summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2018-11-27 17:16:53 +1000
committerStenzek <stenzek@gmail.com>2018-12-04 17:37:25 +1000
commit7afd5cc2fb7e45f2c497e5aed007a017b8461335 (patch)
tree17f445fc7a686cd28859e6c46fb1a32d64a56123 /Source/Core
parent5ca18ff04e6dd69e09a5675db8f9474a51bdfcc0 (diff)
Use main buffers for utility draws
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp33
-rw-r--r--Source/Core/VideoBackends/D3D/GeometryShaderCache.h3
-rw-r--r--Source/Core/VideoBackends/D3D/PixelShaderCache.cpp34
-rw-r--r--Source/Core/VideoBackends/D3D/PixelShaderCache.h2
-rw-r--r--Source/Core/VideoBackends/D3D/Render.cpp91
-rw-r--r--Source/Core/VideoBackends/D3D/Render.h13
-rw-r--r--Source/Core/VideoBackends/D3D/VertexManager.cpp165
-rw-r--r--Source/Core/VideoBackends/D3D/VertexManager.h36
-rw-r--r--Source/Core/VideoBackends/D3D/VertexShaderCache.cpp31
-rw-r--r--Source/Core/VideoBackends/D3D/VertexShaderCache.h2
-rw-r--r--Source/Core/VideoBackends/Null/VertexManager.cpp19
-rw-r--r--Source/Core/VideoBackends/Null/VertexManager.h9
-rw-r--r--Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp20
-rw-r--r--Source/Core/VideoBackends/OGL/ProgramShaderCache.h2
-rw-r--r--Source/Core/VideoBackends/OGL/Render.cpp69
-rw-r--r--Source/Core/VideoBackends/OGL/Render.h11
-rw-r--r--Source/Core/VideoBackends/OGL/StreamBuffer.h2
-rw-r--r--Source/Core/VideoBackends/OGL/VertexManager.cpp123
-rw-r--r--Source/Core/VideoBackends/OGL/VertexManager.h23
-rw-r--r--Source/Core/VideoBackends/Software/SWVertexLoader.cpp19
-rw-r--r--Source/Core/VideoBackends/Software/SWVertexLoader.h11
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.cpp169
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.h7
-rw-r--r--Source/Core/VideoBackends/Vulkan/StateTracker.cpp95
-rw-r--r--Source/Core/VideoBackends/Vulkan/StateTracker.h13
-rw-r--r--Source/Core/VideoBackends/Vulkan/VertexManager.cpp87
-rw-r--r--Source/Core/VideoBackends/Vulkan/VertexManager.h15
-rw-r--r--Source/Core/VideoCommon/IndexGenerator.cpp8
-rw-r--r--Source/Core/VideoCommon/IndexGenerator.h2
-rw-r--r--Source/Core/VideoCommon/RenderBase.h14
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.cpp58
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.h28
32 files changed, 533 insertions, 681 deletions
diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
index ae807bd6c2..baa444bf47 100644
--- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
+++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
@@ -4,7 +4,6 @@
#include <string>
-#include "Common/Align.h"
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
@@ -18,8 +17,6 @@
#include "VideoCommon/Debugger.h"
#include "VideoCommon/GeometryShaderGen.h"
-#include "VideoCommon/GeometryShaderManager.h"
-#include "VideoCommon/Statistics.h"
#include "VideoCommon/VideoConfig.h"
namespace DX11
@@ -36,25 +33,6 @@ ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader()
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? CopyGeometryShader : nullptr;
}
-ID3D11Buffer* gscbuf = nullptr;
-
-ID3D11Buffer*& GeometryShaderCache::GetConstantBuffer()
-{
- // TODO: divide the global variables of the generated shaders into about 5 constant buffers to
- // speed this up
- if (GeometryShaderManager::dirty)
- {
- D3D11_MAPPED_SUBRESOURCE map;
- D3D::context->Map(gscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
- memcpy(map.pData, &GeometryShaderManager::constants, sizeof(GeometryShaderConstants));
- D3D::context->Unmap(gscbuf, 0);
- GeometryShaderManager::dirty = false;
-
- ADDSTAT(stats.thisFrame.bytesUniformStreamed, sizeof(GeometryShaderConstants));
- }
- return gscbuf;
-}
-
const char clear_shader_code[] = {
"struct VSOUTPUT\n"
"{\n"
@@ -116,15 +94,6 @@ const char copy_shader_code[] = {
void GeometryShaderCache::Init()
{
- unsigned int gbsize = Common::AlignUp(static_cast<unsigned int>(sizeof(GeometryShaderConstants)),
- 16); // must be a multiple of 16
- D3D11_BUFFER_DESC gbdesc = CD3D11_BUFFER_DESC(gbsize, D3D11_BIND_CONSTANT_BUFFER,
- D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
- HRESULT hr = D3D::device->CreateBuffer(&gbdesc, nullptr, &gscbuf);
- CHECK(hr == S_OK, "Create geometry shader constant buffer (size=%u)", gbsize);
- D3D::SetDebugObjectName(gscbuf,
- "geometry shader constant buffer used to emulate the GX pipeline");
-
// used when drawing clear quads
ClearGeometryShader = D3D::CompileAndCreateGeometryShader(clear_shader_code);
CHECK(ClearGeometryShader != nullptr, "Create clear geometry shader");
@@ -138,8 +107,6 @@ void GeometryShaderCache::Init()
void GeometryShaderCache::Shutdown()
{
- SAFE_RELEASE(gscbuf);
-
SAFE_RELEASE(ClearGeometryShader);
SAFE_RELEASE(CopyGeometryShader);
}
diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h
index 28c1ee3680..38ffde1b51 100644
--- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h
+++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h
@@ -20,7 +20,8 @@ public:
static ID3D11GeometryShader* GetClearGeometryShader();
static ID3D11GeometryShader* GetCopyGeometryShader();
- static ID3D11Buffer*& GetConstantBuffer();
+ static ID3D11Buffer* GetConstantBuffer();
+ static void UpdateConstantBuffer(const void* data, u32 data_size);
};
} // namespace DX11
diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp
index e09e32d8a2..c86086614f 100644
--- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp
+++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp
@@ -4,7 +4,6 @@
#include <string>
-#include "Common/Align.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
@@ -20,8 +19,6 @@
#include "VideoCommon/Debugger.h"
#include "VideoCommon/PixelShaderGen.h"
-#include "VideoCommon/PixelShaderManager.h"
-#include "VideoCommon/Statistics.h"
#include "VideoCommon/VideoConfig.h"
namespace DX11
@@ -32,7 +29,6 @@ ID3D11PixelShader* s_AnaglyphProgram = nullptr;
ID3D11PixelShader* s_DepthResolveProgram = nullptr;
ID3D11PixelShader* s_rgba6_to_rgb8[2] = {nullptr};
ID3D11PixelShader* s_rgb8_to_rgba6[2] = {nullptr};
-ID3D11Buffer* pscbuf = nullptr;
const char clear_program_code[] = {"void main(\n"
"out float4 ocol0 : SV_Target,\n"
@@ -277,36 +273,8 @@ ID3D11PixelShader* PixelShaderCache::GetDepthResolveProgram()
return s_DepthResolveProgram;
}
-static void UpdateConstantBuffers()
-{
- if (PixelShaderManager::dirty)
- {
- D3D11_MAPPED_SUBRESOURCE map;
- D3D::context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
- memcpy(map.pData, &PixelShaderManager::constants, sizeof(PixelShaderConstants));
- D3D::context->Unmap(pscbuf, 0);
- PixelShaderManager::dirty = false;
-
- ADDSTAT(stats.thisFrame.bytesUniformStreamed, sizeof(PixelShaderConstants));
- }
-}
-
-ID3D11Buffer* PixelShaderCache::GetConstantBuffer()
-{
- UpdateConstantBuffers();
- return pscbuf;
-}
-
void PixelShaderCache::Init()
{
- unsigned int cbsize = Common::AlignUp(static_cast<unsigned int>(sizeof(PixelShaderConstants)),
- 16); // must be a multiple of 16
- D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER,
- D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
- D3D::device->CreateBuffer(&cbdesc, nullptr, &pscbuf);
- CHECK(pscbuf != nullptr, "Create pixel shader constant buffer");
- D3D::SetDebugObjectName(pscbuf, "pixel shader constant buffer used to emulate the GX pipeline");
-
// used when drawing clear quads
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code);
CHECK(s_ClearProgram != nullptr, "Create clear pixel shader");
@@ -334,8 +302,6 @@ void PixelShaderCache::InvalidateMSAAShaders()
void PixelShaderCache::Shutdown()
{
- SAFE_RELEASE(pscbuf);
-
SAFE_RELEASE(s_ClearProgram);
SAFE_RELEASE(s_AnaglyphProgram);
SAFE_RELEASE(s_DepthResolveProgram);
diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.h b/Source/Core/VideoBackends/D3D/PixelShaderCache.h
index 22b6b0cc0c..da1b3b720d 100644
--- a/Source/Core/VideoBackends/D3D/PixelShaderCache.h
+++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.h
@@ -21,8 +21,6 @@ public:
static void Init();
static void Shutdown();
- static ID3D11Buffer* GetConstantBuffer();
-
static ID3D11PixelShader* GetColorCopyProgram(bool multisampled);
static ID3D11PixelShader* GetClearProgram();
static ID3D11PixelShader* GetAnaglyphProgram();
diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp
index e06a5b4c69..93098f53fe 100644
--- a/Source/Core/VideoBackends/D3D/Render.cpp
+++ b/Source/Core/VideoBackends/D3D/Render.cpp
@@ -167,16 +167,6 @@ void Renderer::SetupDeviceObjects()
D3D::SetDebugObjectName(m_reset_rast_state, "rasterizer state for Renderer::ResetAPIState");
m_screenshot_texture = nullptr;
-
- CD3D11_BUFFER_DESC vbo_desc(UTILITY_VBO_SIZE, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC,
- D3D11_CPU_ACCESS_WRITE);
- hr = D3D::device->CreateBuffer(&vbo_desc, nullptr, &m_utility_vertex_buffer);
- CHECK(SUCCEEDED(hr), "Create utility VBO");
-
- CD3D11_BUFFER_DESC ubo_desc(UTILITY_UBO_SIZE, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC,
- D3D11_CPU_ACCESS_WRITE);
- hr = D3D::device->CreateBuffer(&ubo_desc, nullptr, &m_utility_uniform_buffer);
- CHECK(SUCCEEDED(hr), "Create utility UBO");
}
// Kill off all device objects
@@ -196,8 +186,6 @@ void Renderer::TeardownDeviceObjects()
SAFE_RELEASE(m_reset_rast_state);
SAFE_RELEASE(m_screenshot_texture);
SAFE_RELEASE(m_3d_vision_texture);
- SAFE_RELEASE(m_utility_vertex_buffer);
- SAFE_RELEASE(m_utility_uniform_buffer);
}
void Renderer::Create3DVisionTexture(int width, int height)
@@ -273,25 +261,6 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
return DXPipeline::Create(config);
}
-void Renderer::UpdateUtilityUniformBuffer(const void* uniforms, u32 uniforms_size)
-{
- DEBUG_ASSERT(uniforms_size > 0 && uniforms_size < UTILITY_UBO_SIZE);
- D3D11_MAPPED_SUBRESOURCE mapped;
- HRESULT hr = D3D::context->Map(m_utility_uniform_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
- CHECK(SUCCEEDED(hr), "Map utility UBO");
- std::memcpy(mapped.pData, uniforms, uniforms_size);
- D3D::context->Unmap(m_utility_uniform_buffer, 0);
-}
-
-void Renderer::UpdateUtilityVertexBuffer(const void* vertices, u32 vertex_stride, u32 num_vertices)
-{
- D3D11_MAPPED_SUBRESOURCE mapped;
- HRESULT hr = D3D::context->Map(m_utility_vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
- CHECK(SUCCEEDED(hr), "Map utility VBO");
- std::memcpy(mapped.pData, vertices, num_vertices * vertex_stride);
- D3D::context->Unmap(m_utility_vertex_buffer, 0);
-}
-
void Renderer::SetPipeline(const AbstractPipeline* pipeline)
{
const DXPipeline* dx_pipeline = static_cast<const DXPipeline*>(pipeline);
@@ -308,54 +277,6 @@ void Renderer::SetPipeline(const AbstractPipeline* pipeline)
D3D::stateman->SetPixelShader(dx_pipeline->GetPixelShader());
}
-void Renderer::DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices)
-{
- // Copy in uniforms.
- if (uniforms_size > 0)
- {
- UpdateUtilityUniformBuffer(uniforms, uniforms_size);
- D3D::stateman->SetVertexConstants(m_utility_uniform_buffer);
- D3D::stateman->SetPixelConstants(m_utility_uniform_buffer);
- D3D::stateman->SetGeometryConstants(m_utility_uniform_buffer);
- }
-
- // If the vertices are larger than our buffer, we need to break it up into multiple draws.
- const char* vertices_ptr = static_cast<const char*>(vertices);
- while (num_vertices > 0)
- {
- u32 vertices_this_draw = num_vertices;
- if (vertices_ptr)
- {
- vertices_this_draw = std::min(vertices_this_draw, UTILITY_VBO_SIZE / vertex_stride);
- DEBUG_ASSERT(vertices_this_draw > 0);
- UpdateUtilityVertexBuffer(vertices_ptr, vertex_stride, vertices_this_draw);
- D3D::stateman->SetVertexBuffer(m_utility_vertex_buffer, vertex_stride, 0);
- }
-
- // Apply pending state and draw.
- D3D::stateman->Apply();
- D3D::context->Draw(vertices_this_draw, 0);
- vertices_ptr += vertex_stride * vertices_this_draw;
- num_vertices -= vertices_this_draw;
- }
-}
-
-void Renderer::DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
- u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
-{
- D3D::stateman->SetComputeShader(static_cast<const DXShader*>(shader)->GetD3DComputeShader());
-
- if (uniforms_size > 0)
- {
- UpdateUtilityUniformBuffer(uniforms, uniforms_size);
- D3D::stateman->SetComputeConstants(m_utility_uniform_buffer);
- }
-
- D3D::stateman->Apply();
- D3D::context->Dispatch(groups_x, groups_y, groups_z);
-}
-
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
{
TargetRectangle result;
@@ -560,6 +481,18 @@ void Renderer::SetViewport(float x, float y, float width, float height, float ne
D3D::context->RSSetViewports(1, &vp);
}
+void Renderer::Draw(u32 base_vertex, u32 num_vertices)
+{
+ D3D::stateman->Apply();
+ D3D::context->Draw(num_vertices, base_vertex);
+}
+
+void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
+{
+ D3D::stateman->Apply();
+ D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
+}
+
void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z)
{
diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h
index 24b02af672..4750a0e69a 100644
--- a/Source/Core/VideoBackends/D3D/Render.h
+++ b/Source/Core/VideoBackends/D3D/Render.h
@@ -50,6 +50,8 @@ public:
void SetInterlacingMode() override;
void SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) override;
+ void Draw(u32 base_vertex, u32 num_vertices) override;
+ void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) override;
void SetFullscreen(bool enable_fullscreen) override;
bool IsFullscreen() const override;
@@ -73,11 +75,6 @@ public:
void ReinterpretPixelData(unsigned int convtype) override;
- void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices) override;
- void DispatchComputeShader(const AbstractShader* shader, const void* uniforms, u32 uniforms_size,
- u32 groups_x, u32 groups_y, u32 groups_z) override;
-
private:
void SetupDeviceObjects();
void TeardownDeviceObjects();
@@ -89,9 +86,6 @@ private:
void BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D* src_texture,
u32 src_width, u32 src_height);
- void UpdateUtilityUniformBuffer(const void* uniforms, u32 uniforms_size);
- void UpdateUtilityVertexBuffer(const void* vertices, u32 vertex_stride, u32 num_vertices);
-
StateCache m_state_cache;
std::array<ID3D11BlendState*, 4> m_clear_blend_states{};
@@ -103,9 +97,6 @@ private:
ID3D11Texture2D* m_screenshot_texture = nullptr;
D3DTexture2D* m_3d_vision_texture = nullptr;
- ID3D11Buffer* m_utility_vertex_buffer = nullptr;
- ID3D11Buffer* m_utility_uniform_buffer = nullptr;
-
u32 m_last_multisamples = 1;
bool m_last_stereo_mode = false;
bool m_last_fullscreen_state = false;
diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp
index 9d37aa8bf5..8a84ebadc3 100644
--- a/Source/Core/VideoBackends/D3D/VertexManager.cpp
+++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp
@@ -6,6 +6,7 @@
#include <d3d11.h>
+#include "Common/Align.h"
#include "Common/CommonTypes.h"
#include "VideoBackends/D3D/BoundingBox.h"
@@ -19,11 +20,14 @@
#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/Debugger.h"
+#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/NativeVertexFormat.h"
+#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexLoaderManager.h"
+#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoConfig.h"
namespace DX11
@@ -33,15 +37,34 @@ const u32 MAX_IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
const u32 MAX_VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
const u32 MAX_BUFFER_SIZE = MAX_IBUFFER_SIZE + MAX_VBUFFER_SIZE;
+static ID3D11Buffer* AllocateConstantBuffer(u32 size)
+{
+ const u32 cbsize = Common::AlignUp(size, 16u); // must be a multiple of 16
+ const CD3D11_BUFFER_DESC cbdesc(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC,
+ D3D11_CPU_ACCESS_WRITE);
+ ID3D11Buffer* cbuf;
+ const HRESULT hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &cbuf);
+ CHECK(hr == S_OK, "shader constant buffer (size=%u)", cbsize);
+ D3D::SetDebugObjectName(cbuf, "constant buffer used to emulate the GX pipeline");
+ return cbuf;
+}
+
+static void UpdateConstantBuffer(ID3D11Buffer* const buffer, const void* data, u32 data_size)
+{
+ D3D11_MAPPED_SUBRESOURCE map;
+ D3D::context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+ memcpy(map.pData, data, data_size);
+ D3D::context->Unmap(buffer, 0);
+
+ ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
+}
+
void VertexManager::CreateDeviceObjects()
{
D3D11_BUFFER_DESC bufdesc =
CD3D11_BUFFER_DESC(MAX_BUFFER_SIZE, D3D11_BIND_INDEX_BUFFER | D3D11_BIND_VERTEX_BUFFER,
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
- m_vertexDrawOffset = 0;
- m_indexDrawOffset = 0;
-
for (int i = 0; i < MAX_BUFFER_COUNT; i++)
{
m_buffers[i] = nullptr;
@@ -50,12 +73,18 @@ void VertexManager::CreateDeviceObjects()
D3D::SetDebugObjectName(m_buffers[i], "Buffer of VertexManager");
}
- m_currentBuffer = 0;
- m_bufferCursor = MAX_BUFFER_SIZE;
+ m_buffer_cursor = MAX_BUFFER_SIZE;
+
+ m_vertex_constant_buffer = AllocateConstantBuffer(sizeof(VertexShaderConstants));
+ m_geometry_constant_buffer = AllocateConstantBuffer(sizeof(GeometryShaderConstants));
+ m_pixel_constant_buffer = AllocateConstantBuffer(sizeof(PixelShaderConstants));
}
void VertexManager::DestroyDeviceObjects()
{
+ SAFE_RELEASE(m_pixel_constant_buffer);
+ SAFE_RELEASE(m_geometry_constant_buffer);
+ SAFE_RELEASE(m_vertex_constant_buffer);
for (int i = 0; i < MAX_BUFFER_COUNT; i++)
{
SAFE_RELEASE(m_buffers[i]);
@@ -64,12 +93,12 @@ void VertexManager::DestroyDeviceObjects()
VertexManager::VertexManager()
{
- LocalVBuffer.resize(MAXVBUFFERSIZE);
+ m_staging_vertex_buffer.resize(MAXVBUFFERSIZE);
- m_cur_buffer_pointer = m_base_buffer_pointer = &LocalVBuffer[0];
- m_end_buffer_pointer = m_base_buffer_pointer + LocalVBuffer.size();
+ m_cur_buffer_pointer = m_base_buffer_pointer = &m_staging_vertex_buffer[0];
+ m_end_buffer_pointer = m_base_buffer_pointer + m_staging_vertex_buffer.size();
- LocalIBuffer.resize(MAXIBUFFERSIZE);
+ m_staging_index_buffer.resize(MAXIBUFFERSIZE);
CreateDeviceObjects();
}
@@ -79,71 +108,103 @@ VertexManager::~VertexManager()
DestroyDeviceObjects();
}
-void VertexManager::PrepareDrawBuffers(u32 stride)
+void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
+{
+ // Just use the one buffer for all three.
+ UpdateConstantBuffer(m_vertex_constant_buffer, uniforms, uniforms_size);
+ D3D::stateman->SetVertexConstants(m_vertex_constant_buffer);
+ D3D::stateman->SetGeometryConstants(m_vertex_constant_buffer);
+ D3D::stateman->SetPixelConstants(m_vertex_constant_buffer);
+ VertexShaderManager::dirty = true;
+ GeometryShaderManager::dirty = true;
+ PixelShaderManager::dirty = true;
+}
+
+void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
+{
+ m_cur_buffer_pointer = m_base_buffer_pointer;
+ IndexGenerator::Start(m_staging_index_buffer.data());
+}
+
+void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index)
{
D3D11_MAPPED_SUBRESOURCE map;
- u32 vertexBufferSize = u32(m_cur_buffer_pointer - m_base_buffer_pointer);
- u32 indexBufferSize = IndexGenerator::GetIndexLen() * sizeof(u16);
+ u32 vertexBufferSize = Common::AlignUp(num_vertices * vertex_stride, sizeof(u16));
+ u32 indexBufferSize = num_indices * sizeof(u16);
u32 totalBufferSize = vertexBufferSize + indexBufferSize;
- u32 cursor = m_bufferCursor;
- u32 padding = m_bufferCursor % stride;
+ u32 cursor = m_buffer_cursor;
+ u32 padding = vertex_stride > 0 ? (m_buffer_cursor % vertex_stride) : 0;
if (padding)
{
- cursor += stride - padding;
+ cursor += vertex_stride - padding;
}
D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
if (cursor + totalBufferSize >= MAX_BUFFER_SIZE)
{
// Wrap around
- m_currentBuffer = (m_currentBuffer + 1) % MAX_BUFFER_COUNT;
+ m_current_buffer = (m_current_buffer + 1) % MAX_BUFFER_COUNT;
cursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
- m_vertexDrawOffset = cursor;
- m_indexDrawOffset = cursor + vertexBufferSize;
+ *out_base_vertex = vertex_stride > 0 ? (cursor / vertex_stride) : 0;
+ *out_base_index = (cursor + vertexBufferSize) / sizeof(u16);
- D3D::context->Map(m_buffers[m_currentBuffer], 0, MapType, 0, &map);
+ D3D::context->Map(m_buffers[m_current_buffer], 0, MapType, 0, &map);
u8* mappedData = reinterpret_cast<u8*>(map.pData);
- memcpy(mappedData + m_vertexDrawOffset, m_base_buffer_pointer, vertexBufferSize);
- memcpy(mappedData + m_indexDrawOffset, GetIndexBuffer(), indexBufferSize);
- D3D::context->Unmap(m_buffers[m_currentBuffer], 0);
+ if (vertexBufferSize > 0)
+ std::memcpy(mappedData + cursor, m_base_buffer_pointer, vertexBufferSize);
+ if (indexBufferSize > 0)
+ std::memcpy(mappedData + cursor + vertexBufferSize, m_staging_index_buffer.data(),
+ indexBufferSize);
+ D3D::context->Unmap(m_buffers[m_current_buffer], 0);
- m_bufferCursor = cursor + totalBufferSize;
+ m_buffer_cursor = cursor + totalBufferSize;
ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertexBufferSize);
ADDSTAT(stats.thisFrame.bytesIndexStreamed, indexBufferSize);
+
+ D3D::stateman->SetVertexBuffer(m_buffers[m_current_buffer], vertex_stride, 0);
+ D3D::stateman->SetIndexBuffer(m_buffers[m_current_buffer]);
}
-void VertexManager::Draw(u32 stride)
+void VertexManager::UploadConstants()
{
- u32 indices = IndexGenerator::GetIndexLen();
-
- D3D::stateman->SetVertexBuffer(m_buffers[m_currentBuffer], stride, 0);
- D3D::stateman->SetIndexBuffer(m_buffers[m_currentBuffer]);
-
- u32 baseVertex = m_vertexDrawOffset / stride;
- u32 startIndex = m_indexDrawOffset / sizeof(u16);
-
- D3D::stateman->Apply();
- D3D::context->DrawIndexed(indices, startIndex, baseVertex);
+ if (VertexShaderManager::dirty)
+ {
+ UpdateConstantBuffer(m_vertex_constant_buffer, &VertexShaderManager::constants,
+ sizeof(VertexShaderConstants));
+ VertexShaderManager::dirty = false;
+ }
+ if (GeometryShaderManager::dirty)
+ {
+ UpdateConstantBuffer(m_geometry_constant_buffer, &GeometryShaderManager::constants,
+ sizeof(GeometryShaderConstants));
+ GeometryShaderManager::dirty = false;
+ }
+ if (PixelShaderManager::dirty)
+ {
+ UpdateConstantBuffer(m_pixel_constant_buffer, &PixelShaderManager::constants,
+ sizeof(PixelShaderConstants));
+ PixelShaderManager::dirty = false;
+ }
- INCSTAT(stats.thisFrame.numDrawCalls);
+ D3D::stateman->SetPixelConstants(m_pixel_constant_buffer, g_ActiveConfig.bEnablePixelLighting ?
+ m_vertex_constant_buffer :
+ nullptr);
+ D3D::stateman->SetVertexConstants(m_vertex_constant_buffer);
+ D3D::stateman->SetGeometryConstants(m_geometry_constant_buffer);
}
-void VertexManager::vFlush()
+void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
{
- u32 stride = VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride();
- PrepareDrawBuffers(stride);
-
- if (!m_current_pipeline_object)
- return;
-
FramebufferManager::SetIntegerEFBRenderTarget(
m_current_pipeline_config.blending_state.logicopenable);
+
if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active)
{
D3D::context->OMSetRenderTargetsAndUnorderedAccessViews(
@@ -151,21 +212,7 @@ void VertexManager::vFlush()
nullptr);
}
- g_renderer->SetPipeline(m_current_pipeline_object);
-
- ID3D11Buffer* vertexConstants = VertexShaderCache::GetConstantBuffer();
- D3D::stateman->SetPixelConstants(PixelShaderCache::GetConstantBuffer(),
- g_ActiveConfig.bEnablePixelLighting ? vertexConstants : nullptr);
- D3D::stateman->SetVertexConstants(vertexConstants);
- D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer());
-
- Draw(stride);
-}
-
-void VertexManager::ResetBuffer(u32 stride)
-{
- m_cur_buffer_pointer = m_base_buffer_pointer;
- IndexGenerator::Start(GetIndexBuffer());
+ D3D::stateman->Apply();
+ D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
}
-
-} // namespace
+} // namespace DX11
diff --git a/Source/Core/VideoBackends/D3D/VertexManager.h b/Source/Core/VideoBackends/D3D/VertexManager.h
index 922f854c6b..a7eab78ef5 100644
--- a/Source/Core/VideoBackends/D3D/VertexManager.h
+++ b/Source/Core/VideoBackends/D3D/VertexManager.h
@@ -42,32 +42,32 @@ public:
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
- void CreateDeviceObjects() override;
- void DestroyDeviceObjects() override;
+ void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;
protected:
- void ResetBuffer(u32 stride) override;
- u16* GetIndexBuffer() { return &LocalIBuffer[0]; }
+ void CreateDeviceObjects() override;
+ void DestroyDeviceObjects() override;
+ void ResetBuffer(u32 vertex_stride, bool cull_all) override;
+ void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
+ u32* out_base_index) override;
+ void UploadConstants() override;
+ void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;
private:
- void PrepareDrawBuffers(u32 stride);
- void Draw(u32 stride);
- // temp
- void vFlush() override;
-
- u32 m_vertexDrawOffset;
- u32 m_indexDrawOffset;
- u32 m_currentBuffer;
- u32 m_bufferCursor;
-
enum
{
MAX_BUFFER_COUNT = 2
};
- ID3D11Buffer* m_buffers[MAX_BUFFER_COUNT];
+ ID3D11Buffer* m_buffers[MAX_BUFFER_COUNT] = {};
+ u32 m_current_buffer = 0;
+ u32 m_buffer_cursor = 0;
+
+ std::vector<u8> m_staging_vertex_buffer;
+ std::vector<u16> m_staging_index_buffer;
- std::vector<u8> LocalVBuffer;
- std::vector<u16> LocalIBuffer;
+ ID3D11Buffer* m_vertex_constant_buffer = nullptr;
+ ID3D11Buffer* m_geometry_constant_buffer = nullptr;
+ ID3D11Buffer* m_pixel_constant_buffer = nullptr;
};
-} // namespace
+} // namespace DX11
diff --git a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp
index 2033a38701..b7fc3a2582 100644
--- a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp
+++ b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp
@@ -4,7 +4,6 @@
#include <string>
-#include "Common/Align.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
@@ -23,7 +22,6 @@
#include "VideoCommon/UberShaderVertex.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexShaderGen.h"
-#include "VideoCommon/VertexShaderManager.h"
namespace DX11
{
@@ -49,25 +47,6 @@ ID3D11InputLayout* VertexShaderCache::GetClearInputLayout()
return ClearLayout;
}
-ID3D11Buffer* vscbuf = nullptr;
-
-ID3D11Buffer*& VertexShaderCache::GetConstantBuffer()
-{
- // TODO: divide the global variables of the generated shaders into about 5 constant buffers to
- // speed this up
- if (VertexShaderManager::dirty)
- {
- D3D11_MAPPED_SUBRESOURCE map;
- D3D::context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
- memcpy(map.pData, &VertexShaderManager::constants, sizeof(VertexShaderConstants));
- D3D::context->Unmap(vscbuf, 0);
- VertexShaderManager::dirty = false;
-
- ADDSTAT(stats.thisFrame.bytesUniformStreamed, sizeof(VertexShaderConstants));
- }
- return vscbuf;
-}
-
// this class will load the precompiled shaders into our cache
template <typename UidType>
class VertexShaderCacheInserter : public LinearDiskCacheReader<UidType, u8>
@@ -121,14 +100,6 @@ void VertexShaderCache::Init()
{"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
- unsigned int cbsize = Common::AlignUp(static_cast<unsigned int>(sizeof(VertexShaderConstants)),
- 16); // must be a multiple of 16
- D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER,
- D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
- HRESULT hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &vscbuf);
- CHECK(hr == S_OK, "Create vertex shader constant buffer (size=%u)", cbsize);
- D3D::SetDebugObjectName(vscbuf, "vertex shader constant buffer used to emulate the GX pipeline");
-
D3DBlob* blob;
D3D::CompileVertexShader(simple_shader_code, &blob);
D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout);
@@ -156,8 +127,6 @@ void VertexShaderCache::Init()
void VertexShaderCache::Shutdown()
{
- SAFE_RELEASE(vscbuf);
-
SAFE_RELEASE(SimpleVertexShader);
SAFE_RELEASE(ClearVertexShader);
diff --git a/Source/Core/VideoBackends/D3D/VertexShaderCache.h b/Source/Core/VideoBackends/D3D/VertexShaderCache.h
index b59d75be47..d7f1958806 100644
--- a/Source/Core/VideoBackends/D3D/VertexShaderCache.h
+++ b/Source/Core/VideoBackends/D3D/VertexShaderCache.h
@@ -23,8 +23,6 @@ public:
static void Init();
static void Shutdown();
- static ID3D11Buffer*& GetConstantBuffer();
-
static ID3D11VertexShader* GetSimpleVertexShader();
static ID3D11VertexShader* GetClearVertexShader();
static ID3D11InputLayout* GetSimpleInputLayout();
diff --git a/Source/Core/VideoBackends/Null/VertexManager.cpp b/Source/Core/VideoBackends/Null/VertexManager.cpp
index 0e121ffa0d..872e9c3657 100644
--- a/Source/Core/VideoBackends/Null/VertexManager.cpp
+++ b/Source/Core/VideoBackends/Null/VertexManager.cpp
@@ -22,6 +22,10 @@ VertexManager::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_dec
return std::make_unique<NullNativeVertexFormat>(vtx_decl);
}
+void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
+{
+}
+
VertexManager::VertexManager() : m_local_v_buffer(MAXVBUFFERSIZE), m_local_i_buffer(MAXIBUFFERSIZE)
{
}
@@ -30,15 +34,24 @@ VertexManager::~VertexManager()
{
}
-void VertexManager::ResetBuffer(u32 stride)
+void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
{
m_cur_buffer_pointer = m_base_buffer_pointer = m_local_v_buffer.data();
m_end_buffer_pointer = m_cur_buffer_pointer + m_local_v_buffer.size();
IndexGenerator::Start(&m_local_i_buffer[0]);
}
-void VertexManager::vFlush()
+void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index)
+{
+}
+
+void VertexManager::UploadConstants()
+{
+}
+
+void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
{
}
-} // namespace
+} // namespace Null
diff --git a/Source/Core/VideoBackends/Null/VertexManager.h b/Source/Core/VideoBackends/Null/VertexManager.h
index 863090cab6..1d6a706ec3 100644
--- a/Source/Core/VideoBackends/Null/VertexManager.h
+++ b/Source/Core/VideoBackends/Null/VertexManager.h
@@ -20,11 +20,16 @@ public:
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
+ void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;
+
protected:
- void ResetBuffer(u32 stride) override;
+ void ResetBuffer(u32 vertex_stride, bool cull_all) override;
+ void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
+ u32* out_base_index) override;
+ void UploadConstants() override;
+ void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;
private:
- void vFlush() override;
std::vector<u8> m_local_v_buffer;
std::vector<u16> m_local_i_buffer;
};
diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
index 78458aa3fe..c8d54acd5a 100644
--- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
+++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
@@ -259,6 +259,21 @@ void ProgramShaderCache::UploadConstants()
}
}
+void ProgramShaderCache::UploadConstants(const void* data, u32 data_size)
+{
+ // allocate and copy
+ const u32 alloc_size = Common::AlignUp(data_size, s_ubo_align);
+ auto buffer = s_buffer->Map(alloc_size, s_ubo_align);
+ std::memcpy(buffer.first, data, data_size);
+ s_buffer->Unmap(alloc_size);
+
+ // bind the same sub-buffer to all stages
+ for (u32 index = 1; index <= 3; index++)
+ glBindBufferRange(GL_UNIFORM_BUFFER, index, s_buffer->m_buffer, buffer.second, data_size);
+
+ ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
+}
+
bool ProgramShaderCache::CompileShader(SHADER& shader, const std::string& vcode,
const std::string& pcode, const std::string& gcode)
{
@@ -539,6 +554,11 @@ void ProgramShaderCache::BindVertexFormat(const GLVertexFormat* vertex_format)
s_last_VAO = new_VAO;
}
+bool ProgramShaderCache::IsValidVertexFormatBound()
+{
+ return s_last_VAO != 0 && s_last_VAO != s_attributeless_VAO;
+}
+
void ProgramShaderCache::InvalidateVertexFormat()
{
s_last_VAO = 0;
diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.h b/Source/Core/VideoBackends/OGL/ProgramShaderCache.h
index 0096c6e5b9..b94e733167 100644
--- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.h
+++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.h
@@ -69,6 +69,7 @@ class ProgramShaderCache
{
public:
static void BindVertexFormat(const GLVertexFormat* vertex_format);
+ static bool IsValidVertexFormatBound();
static void InvalidateVertexFormat();
static void InvalidateLastProgram();
@@ -83,6 +84,7 @@ public:
static u32 GetUniformBufferAlignment();
static void InvalidateConstants();
static void UploadConstants();
+ static void UploadConstants(const void* data, u32 data_size);
static void Init();
static void Shutdown();
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp
index c43bb0ac87..55de5ec0dc 100644
--- a/Source/Core/VideoBackends/OGL/Render.cpp
+++ b/Source/Core/VideoBackends/OGL/Render.cpp
@@ -1184,6 +1184,27 @@ void Renderer::SetViewport(float x, float y, float width, float height, float ne
glDepthRangef(near_depth, far_depth);
}
+void Renderer::Draw(u32 base_vertex, u32 num_vertices)
+{
+ glDrawArrays(static_cast<const OGLPipeline*>(m_graphics_pipeline)->GetGLPrimitive(), base_vertex,
+ num_vertices);
+}
+
+void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
+{
+ if (g_ogl_config.bSupportsGLBaseVertex)
+ {
+ glDrawElementsBaseVertex(static_cast<const OGLPipeline*>(m_graphics_pipeline)->GetGLPrimitive(),
+ num_indices, GL_UNSIGNED_SHORT,
+ static_cast<u16*>(nullptr) + base_index, base_vertex);
+ }
+ else
+ {
+ glDrawElements(static_cast<const OGLPipeline*>(m_graphics_pipeline)->GetGLPrimitive(),
+ num_indices, GL_UNSIGNED_SHORT, static_cast<u16*>(nullptr) + base_index);
+ }
+}
+
void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z)
{
@@ -1675,54 +1696,6 @@ void Renderer::SetInterlacingMode()
// TODO
}
-void Renderer::DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices)
-{
- // Copy in uniforms.
- if (uniforms_size > 0)
- UploadUtilityUniforms(uniforms, uniforms_size);
-
- // Draw from base index if there is vertex data.
- if (vertices)
- {
- StreamBuffer* vbuf = static_cast<VertexManager*>(g_vertex_manager.get())->GetVertexBuffer();
- auto buf = vbuf->Map(vertex_stride * num_vertices, vertex_stride);
- std::memcpy(buf.first, vertices, vertex_stride * num_vertices);
- vbuf->Unmap(vertex_stride * num_vertices);
- glDrawArrays(m_graphics_pipeline->GetGLPrimitive(), buf.second / vertex_stride, num_vertices);
- }
- else
- {
- glDrawArrays(m_graphics_pipeline->GetGLPrimitive(), 0, num_vertices);
- }
-}
-
-void Renderer::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
-{
- DEBUG_ASSERT(uniforms_size > 0);
-
- auto buf = ProgramShaderCache::GetUniformBuffer()->Map(
- uniforms_size, ProgramShaderCache::GetUniformBufferAlignment());
- std::memcpy(buf.first, uniforms, uniforms_size);
- ProgramShaderCache::GetUniformBuffer()->Unmap(uniforms_size);
- glBindBufferRange(GL_UNIFORM_BUFFER, 1, ProgramShaderCache::GetUniformBuffer()->m_buffer,
- buf.second, uniforms_size);
-
- // This is rather horrible, but because of how the UBOs are bound, this forces it to rebind.
- ProgramShaderCache::InvalidateConstants();
-}
-
-void Renderer::DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
- u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
-{
- glUseProgram(static_cast<const OGLShader*>(shader)->GetGLComputeProgramID());
- if (uniforms_size > 0)
- UploadUtilityUniforms(uniforms, uniforms_size);
-
- glDispatchCompute(groups_x, groups_y, groups_z);
- ProgramShaderCache::InvalidateLastProgram();
-}
-
std::unique_ptr<VideoCommon::AsyncShaderCompiler> Renderer::CreateAsyncShaderCompiler()
{
return std::make_unique<SharedContextAsyncShaderCompiler>();
diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h
index de051ba0d7..2de8ff01a5 100644
--- a/Source/Core/VideoBackends/OGL/Render.h
+++ b/Source/Core/VideoBackends/OGL/Render.h
@@ -116,6 +116,8 @@ public:
void SetInterlacingMode() override;
void SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) override;
+ void Draw(u32 base_vertex, u32 num_vertices) override;
+ void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) override;
void RenderText(const std::string& text, int left, int top, u32 color) override;
@@ -137,18 +139,14 @@ public:
void ReinterpretPixelData(unsigned int convtype) override;
- void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices) override;
-
- void DispatchComputeShader(const AbstractShader* shader, const void* uniforms, u32 uniforms_size,
- u32 groups_x, u32 groups_y, u32 groups_z) override;
-
std::unique_ptr<VideoCommon::AsyncShaderCompiler> CreateAsyncShaderCompiler() override;
// Only call methods from this on the GPU thread.
GLContext* GetMainGLContext() const { return m_main_gl_context.get(); }
bool IsGLES() const { return m_main_gl_context->IsGLES(); }
+ const OGLPipeline* GetCurrentGraphicsPipeline() const { return m_graphics_pipeline; }
+
private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc,
const TargetRectangle& targetPixelRc, const void* data);
@@ -165,7 +163,6 @@ private:
void ApplyBlendingState(const BlendingState state, bool force = false);
void ApplyRasterizationState(const RasterizationState state, bool force = false);
void ApplyDepthState(const DepthState state, bool force = false);
- void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size);
std::unique_ptr<GLContext> m_main_gl_context;
std::array<const AbstractTexture*, 8> m_bound_textures{};
diff --git a/Source/Core/VideoBackends/OGL/StreamBuffer.h b/Source/Core/VideoBackends/OGL/StreamBuffer.h
index 83b79bd906..2a8efba1af 100644
--- a/Source/Core/VideoBackends/OGL/StreamBuffer.h
+++ b/Source/Core/VideoBackends/OGL/StreamBuffer.h
@@ -19,6 +19,8 @@ public:
static std::unique_ptr<StreamBuffer> Create(u32 type, u32 size);
virtual ~StreamBuffer();
+ u32 GetCurrentOffset() const { return m_iterator; }
+
/* This mapping function will return a pair of:
* - the pointer to the mapped buffer
* - the offset into the real GPU buffer (always multiple of stride)
diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp
index 00cf6b3cfa..3883a13595 100644
--- a/Source/Core/VideoBackends/OGL/VertexManager.cpp
+++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp
@@ -15,6 +15,7 @@
#include "Common/StringUtil.h"
#include "VideoBackends/OGL/BoundingBox.h"
+#include "VideoBackends/OGL/OGLPipeline.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/Render.h"
#include "VideoBackends/OGL/StreamBuffer.h"
@@ -31,11 +32,6 @@ namespace OGL
const u32 MAX_IBUFFER_SIZE = 2 * 1024 * 1024;
const u32 MAX_VBUFFER_SIZE = 32 * 1024 * 1024;
-static std::unique_ptr<StreamBuffer> s_vertexBuffer;
-static std::unique_ptr<StreamBuffer> s_indexBuffer;
-static size_t s_baseVertex;
-static size_t s_index_offset;
-
VertexManager::VertexManager() : m_cpu_v_buffer(MAX_VBUFFER_SIZE), m_cpu_i_buffer(MAX_IBUFFER_SIZE)
{
CreateDeviceObjects();
@@ -48,58 +44,45 @@ VertexManager::~VertexManager()
void VertexManager::CreateDeviceObjects()
{
- s_vertexBuffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
- m_vertex_buffers = s_vertexBuffer->m_buffer;
-
- s_indexBuffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
- m_index_buffers = s_indexBuffer->m_buffer;
+ m_vertex_buffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
+ m_index_buffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
}
void VertexManager::DestroyDeviceObjects()
{
- s_vertexBuffer.reset();
- s_indexBuffer.reset();
+ m_vertex_buffer.reset();
+ m_index_buffer.reset();
}
-StreamBuffer* VertexManager::GetVertexBuffer() const
+void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
{
- return s_vertexBuffer.get();
-}
-
-OGL::StreamBuffer* VertexManager::GetIndexBuffer() const
-{
- return s_indexBuffer.get();
+ ProgramShaderCache::InvalidateConstants();
+ ProgramShaderCache::UploadConstants(uniforms, uniforms_size);
}
GLuint VertexManager::GetVertexBufferHandle() const
{
- return m_vertex_buffers;
+ return m_vertex_buffer->m_buffer;
}
GLuint VertexManager::GetIndexBufferHandle() const
{
- return m_index_buffers;
+ return m_index_buffer->m_buffer;
}
-void VertexManager::PrepareDrawBuffers(u32 stride)
+static void CheckBufferBinding()
{
- u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
- u32 index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16);
-
// The index buffer is part of the VAO state, therefore we need to bind it first.
- const GLVertexFormat* vertex_format =
- static_cast<GLVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat());
- ProgramShaderCache::BindVertexFormat(vertex_format);
- s_vertexBuffer->Unmap(vertex_data_size);
- s_indexBuffer->Unmap(index_data_size);
-
- ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertex_data_size);
- ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_data_size);
+ if (!ProgramShaderCache::IsValidVertexFormatBound())
+ {
+ ProgramShaderCache::BindVertexFormat(
+ static_cast<GLVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat()));
+ }
}
-void VertexManager::ResetBuffer(u32 stride)
+void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
{
- if (m_cull_all)
+ if (cull_all)
{
// This buffer isn't getting sent to the GPU. Just allocate it on the cpu.
m_cur_buffer_pointer = m_base_buffer_pointer = m_cpu_v_buffer.data();
@@ -109,68 +92,41 @@ void VertexManager::ResetBuffer(u32 stride)
}
else
{
- // The index buffer is part of the VAO state, therefore we need to bind it first.
- const GLVertexFormat* vertex_format =
- static_cast<GLVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat());
- ProgramShaderCache::BindVertexFormat(vertex_format);
+ CheckBufferBinding();
- auto buffer = s_vertexBuffer->Map(MAXVBUFFERSIZE, stride);
+ auto buffer = m_vertex_buffer->Map(MAXVBUFFERSIZE, vertex_stride);
m_cur_buffer_pointer = m_base_buffer_pointer = buffer.first;
m_end_buffer_pointer = buffer.first + MAXVBUFFERSIZE;
- s_baseVertex = buffer.second / stride;
- buffer = s_indexBuffer->Map(MAXIBUFFERSIZE * sizeof(u16));
+ buffer = m_index_buffer->Map(MAXIBUFFERSIZE * sizeof(u16));
IndexGenerator::Start((u16*)buffer.first);
- s_index_offset = buffer.second;
}
}
-void VertexManager::Draw(u32 stride)
+void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index)
{
- u32 index_size = IndexGenerator::GetIndexLen();
- u32 max_index = IndexGenerator::GetNumVerts();
- GLenum primitive_mode = 0;
+ u32 vertex_data_size = num_vertices * vertex_stride;
+ u32 index_data_size = num_indices * sizeof(u16);
- switch (m_current_primitive_type)
- {
- case PrimitiveType::Points:
- primitive_mode = GL_POINTS;
- break;
- case PrimitiveType::Lines:
- primitive_mode = GL_LINES;
- break;
- case PrimitiveType::Triangles:
- primitive_mode = GL_TRIANGLES;
- break;
- case PrimitiveType::TriangleStrip:
- primitive_mode = GL_TRIANGLE_STRIP;
- break;
- }
+ *out_base_vertex = vertex_stride > 0 ? (m_vertex_buffer->GetCurrentOffset() / vertex_stride) : 0;
+ *out_base_index = m_index_buffer->GetCurrentOffset() / sizeof(u16);
- if (g_ogl_config.bSupportsGLBaseVertex)
- {
- glDrawRangeElementsBaseVertex(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT,
- (u8*)nullptr + s_index_offset, (GLint)s_baseVertex);
- }
- else
- {
- glDrawRangeElements(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT,
- (u8*)nullptr + s_index_offset);
- }
+ CheckBufferBinding();
+ m_vertex_buffer->Unmap(vertex_data_size);
+ m_index_buffer->Unmap(index_data_size);
- INCSTAT(stats.thisFrame.numDrawCalls);
+ ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertex_data_size);
+ ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_data_size);
}
-void VertexManager::vFlush()
+void VertexManager::UploadConstants()
{
- GLVertexFormat* nativeVertexFmt = (GLVertexFormat*)VertexLoaderManager::GetCurrentVertexFormat();
- u32 stride = nativeVertexFmt->GetVertexStride();
-
- PrepareDrawBuffers(stride);
-
- // upload global constants
ProgramShaderCache::UploadConstants();
+}
+void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
+{
if (::BoundingBox::active && !g_Config.BBoxUseFragmentShaderImplementation())
{
glEnable(GL_STENCIL_TEST);
@@ -178,8 +134,8 @@ void VertexManager::vFlush()
if (m_current_pipeline_object)
{
- g_renderer->SetPipeline(m_current_pipeline_object);
- Draw(stride);
+ static_cast<Renderer*>(g_renderer.get())->SetPipeline(m_current_pipeline_object);
+ static_cast<Renderer*>(g_renderer.get())->DrawIndexed(base_index, num_indices, base_vertex);
}
if (::BoundingBox::active && !g_Config.BBoxUseFragmentShaderImplementation())
@@ -191,5 +147,4 @@ void VertexManager::vFlush()
g_Config.iSaveTargetId++;
ClearEFBCache();
}
-
-} // namespace
+} // namespace OGL
diff --git a/Source/Core/VideoBackends/OGL/VertexManager.h b/Source/Core/VideoBackends/OGL/VertexManager.h
index 39203c5f4c..388c559716 100644
--- a/Source/Core/VideoBackends/OGL/VertexManager.h
+++ b/Source/Core/VideoBackends/OGL/VertexManager.h
@@ -35,27 +35,26 @@ public:
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
- void CreateDeviceObjects() override;
- void DestroyDeviceObjects() override;
+ void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;
- StreamBuffer* GetVertexBuffer() const;
- StreamBuffer* GetIndexBuffer() const;
GLuint GetVertexBufferHandle() const;
GLuint GetIndexBufferHandle() const;
protected:
- void ResetBuffer(u32 stride) override;
+ void CreateDeviceObjects() override;
+ void DestroyDeviceObjects() override;
+ void ResetBuffer(u32 vertex_stride, bool cull_all) override;
+ void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
+ u32* out_base_index) override;
+ void UploadConstants() override;
+ void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;
private:
- void Draw(u32 stride);
- void vFlush() override;
- void PrepareDrawBuffers(u32 stride);
-
- GLuint m_vertex_buffers;
- GLuint m_index_buffers;
+ std::unique_ptr<StreamBuffer> m_vertex_buffer;
+ std::unique_ptr<StreamBuffer> m_index_buffer;
// Alternative buffers in CPU memory for primatives we are going to discard.
std::vector<u8> m_cpu_v_buffer;
std::vector<u16> m_cpu_i_buffer;
};
-}
+} // namespace OGL
diff --git a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp
index e62a0a2348..4a53b4041c 100644
--- a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp
+++ b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp
@@ -48,14 +48,29 @@ SWVertexLoader::~SWVertexLoader()
{
}
-void SWVertexLoader::ResetBuffer(u32 stride)
+void SWVertexLoader::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
+{
+}
+
+void SWVertexLoader::ResetBuffer(u32 vertex_stride, bool cull_all)
{
m_cur_buffer_pointer = m_base_buffer_pointer = m_local_vertex_buffer.data();
m_end_buffer_pointer = m_cur_buffer_pointer + m_local_vertex_buffer.size();
IndexGenerator::Start(m_local_index_buffer.data());
}
-void SWVertexLoader::vFlush()
+void SWVertexLoader::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index)
+{
+ *out_base_vertex = 0;
+ *out_base_index = 0;
+}
+
+void SWVertexLoader::UploadConstants()
+{
+}
+
+void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
{
DebugUtil::OnObjectBegin();
diff --git a/Source/Core/VideoBackends/Software/SWVertexLoader.h b/Source/Core/VideoBackends/Software/SWVertexLoader.h
index abb4c86b7c..dabbdef168 100644
--- a/Source/Core/VideoBackends/Software/SWVertexLoader.h
+++ b/Source/Core/VideoBackends/Software/SWVertexLoader.h
@@ -23,9 +23,14 @@ public:
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vdec) override;
-private:
- void ResetBuffer(u32 stride) override;
- void vFlush() override;
+ void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;
+
+protected:
+ void ResetBuffer(u32 vertex_stride, bool cull_all) override;
+ void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
+ u32* out_base_index) override;
+ void UploadConstants() override;
+ void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;
void SetFormat(u8 attributeIndex, u8 primitiveType);
void ParseVertex(const PortableVertexDeclaration& vdec, int index);
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
index 764250cbe9..6bec599882 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
@@ -259,158 +259,6 @@ void Renderer::SetPipeline(const AbstractPipeline* pipeline)
StateTracker::GetInstance()->SetPipeline(static_cast<const VKPipeline*>(pipeline));
}
-void Renderer::DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices)
-{
- // Binding the utility pipeline layout breaks the standard layout.
- StateTracker::GetInstance()->SetPendingRebind();
-
- // Upload uniforms.
- VkBuffer uniform_buffer = g_object_cache->GetUtilityShaderUniformBuffer()->GetBuffer();
- u32 uniform_buffer_offset = 0;
- if (uniforms_size > 0)
- std::tie(uniform_buffer, uniform_buffer_offset) =
- UpdateUtilityUniformBuffer(uniforms, uniforms_size);
-
- // Upload vertices.
- VkBuffer vertex_buffer = VK_NULL_HANDLE;
- VkDeviceSize vertex_buffer_offset = 0;
- if (vertices)
- {
- u32 vertices_size = vertex_stride * num_vertices;
- StreamBuffer* vbo_buf = g_object_cache->GetUtilityShaderVertexBuffer();
- if (!vbo_buf->ReserveMemory(vertices_size, vertex_stride))
- {
- Util::ExecuteCurrentCommandsAndRestoreState(true);
- if (!vbo_buf->ReserveMemory(vertices_size, vertex_stride))
- {
- PanicAlert("Failed to reserve vertex buffer space for utility draw.");
- return;
- }
- }
-
- vertex_buffer = vbo_buf->GetBuffer();
- vertex_buffer_offset = vbo_buf->GetCurrentOffset();
- std::memcpy(vbo_buf->GetCurrentHostPointer(), vertices, vertices_size);
- vbo_buf->CommitMemory(vertices_size);
- }
-
- // Allocate descriptor sets.
- std::array<VkDescriptorSet, 2> dsets;
- dsets[0] = g_command_buffer_mgr->AllocateDescriptorSet(
- g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_SINGLE_UNIFORM_BUFFER));
- dsets[1] = g_command_buffer_mgr->AllocateDescriptorSet(
- g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_PIXEL_SHADER_SAMPLERS));
-
- // Flush first if failed.
- if (dsets[0] == VK_NULL_HANDLE || dsets[1] == VK_NULL_HANDLE)
- {
- Util::ExecuteCurrentCommandsAndRestoreState(true);
- dsets[0] = g_command_buffer_mgr->AllocateDescriptorSet(
- g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_SINGLE_UNIFORM_BUFFER));
- dsets[1] = g_command_buffer_mgr->AllocateDescriptorSet(
- g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_PIXEL_SHADER_SAMPLERS));
-
- if (dsets[0] == VK_NULL_HANDLE || dsets[1] == VK_NULL_HANDLE)
- {
- PanicAlert("Failed to allocate descriptor sets in utility draw.");
- return;
- }
- }
-
- // Build UBO descriptor set.
- std::array<VkWriteDescriptorSet, 2> dswrites;
- VkDescriptorBufferInfo dsbuffer = {uniform_buffer, 0, std::max(uniforms_size, 4u)};
- dswrites[0] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, dsets[0], 0, 0, 1,
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, nullptr, &dsbuffer, nullptr};
- dswrites[1] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- nullptr,
- dsets[1],
- 0,
- 0,
- NUM_PIXEL_SHADER_SAMPLERS,
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- StateTracker::GetInstance()->GetPSSamplerBindings().data(),
- nullptr,
- nullptr};
-
- // Build commands.
- VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
- vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- StateTracker::GetInstance()->GetPipeline()->GetVkPipeline());
- if (vertex_buffer != VK_NULL_HANDLE)
- vkCmdBindVertexBuffers(command_buffer, 0, 1, &vertex_buffer, &vertex_buffer_offset);
-
- // Update and bind descriptors.
- VkPipelineLayout pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_UTILITY);
- vkUpdateDescriptorSets(g_vulkan_context->GetDevice(), static_cast<u32>(dswrites.size()),
- dswrites.data(), 0, nullptr);
- vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0,
- static_cast<u32>(dsets.size()), dsets.data(), 1, &uniform_buffer_offset);
-
- // Ensure we're in a render pass before drawing, just in case we had to flush.
- StateTracker::GetInstance()->BeginRenderPass();
- vkCmdDraw(command_buffer, num_vertices, 1, 0, 0);
-}
-
-void Renderer::DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
- u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
-{
- // Binding the utility pipeline layout breaks the standard layout.
- StateTracker::GetInstance()->SetPendingRebind();
- StateTracker::GetInstance()->EndRenderPass();
-
- // Upload uniforms.
- VkBuffer uniform_buffer = g_object_cache->GetUtilityShaderUniformBuffer()->GetBuffer();
- u32 uniform_buffer_offset = 0;
- if (uniforms_size > 0)
- std::tie(uniform_buffer, uniform_buffer_offset) =
- UpdateUtilityUniformBuffer(uniforms, uniforms_size);
-
- // Flush first if failed.
- VkDescriptorSet dset = g_command_buffer_mgr->AllocateDescriptorSet(
- g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_COMPUTE));
- if (dset == VK_NULL_HANDLE)
- {
- Util::ExecuteCurrentCommandsAndRestoreState(true);
- dset = g_command_buffer_mgr->AllocateDescriptorSet(
- g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_COMPUTE));
- if (dset == VK_NULL_HANDLE)
- {
- PanicAlert("Failed to allocate descriptor sets in utility dispatch.");
- return;
- }
- }
-
- std::array<VkWriteDescriptorSet, 2> dswrites;
- VkDescriptorBufferInfo dsbuffer = {uniform_buffer, 0, std::max(uniforms_size, 4u)};
- dswrites[0] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, dset, 0, 0, 1,
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, nullptr, &dsbuffer, nullptr};
- dswrites[1] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- nullptr,
- dset,
- 1,
- 0,
- NUM_PIXEL_SHADER_SAMPLERS,
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- StateTracker::GetInstance()->GetPSSamplerBindings().data(),
- nullptr,
- nullptr};
-
- // TODO: Texel buffers, storage images.
-
- // Build commands.
- VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
- VkPipelineLayout pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_UTILITY);
- vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
- static_cast<const VKShader*>(shader)->GetComputePipeline());
- vkUpdateDescriptorSets(g_vulkan_context->GetDevice(), static_cast<u32>(dswrites.size()),
- dswrites.data(), 0, nullptr);
- vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1,
- &dset, 1, &uniform_buffer_offset);
- vkCmdDispatch(command_buffer, groups_x, groups_y, groups_z);
-}
-
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
{
u32 backbuffer_width = m_swap_chain->GetWidth();
@@ -1185,6 +1033,23 @@ void Renderer::SetViewport(float x, float y, float width, float height, float ne
StateTracker::GetInstance()->SetViewport(viewport);
}
+void Renderer::Draw(u32 base_vertex, u32 num_vertices)
+{
+ if (StateTracker::GetInstance()->Bind())
+ return;
+
+ vkCmdDraw(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_vertices, 1, base_vertex, 0);
+}
+
+void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
+{
+ if (!StateTracker::GetInstance()->Bind())
+ return;
+
+ vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_indices, 1, base_index,
+ base_vertex, 0);
+}
+
void Renderer::RecompileShaders()
{
DestroyShaders();
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h
index edb7764a5d..bd7efc88ca 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.h
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.h
@@ -87,11 +87,8 @@ public:
void SetInterlacingMode() override;
void SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) override;
-
- void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices) override;
- void DispatchComputeShader(const AbstractShader* shader, const void* uniforms, u32 uniforms_size,
- u32 groups_x, u32 groups_y, u32 groups_z) override;
+ void Draw(u32 base_vertex, u32 num_vertices) override;
+ void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) override;
private:
bool CreateSemaphores();
diff --git a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp
index f3b2752ddd..471a8b12f5 100644
--- a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp
+++ b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp
@@ -218,6 +218,37 @@ void StateTracker::UpdatePixelShaderConstants()
PixelShaderManager::dirty = false;
}
+void StateTracker::UpdateConstants(const void* data, u32 data_size)
+{
+ if (!m_uniform_stream_buffer->ReserveMemory(
+ data_size, g_vulkan_context->GetUniformBufferAlignment(), true, true, false))
+ {
+ WARN_LOG(VIDEO, "Executing command buffer while waiting for ext space in uniform buffer");
+ Util::ExecuteCurrentCommandsAndRestoreState(false);
+ }
+
+ for (u32 binding = 0; binding < NUM_UBO_DESCRIPTOR_SET_BINDINGS; binding++)
+ {
+ if (m_bindings.uniform_buffer_bindings[binding].buffer != m_uniform_stream_buffer->GetBuffer())
+ {
+ m_bindings.uniform_buffer_bindings[binding].buffer = m_uniform_stream_buffer->GetBuffer();
+ m_dirty_flags |= DIRTY_FLAG_VS_UBO << binding;
+ }
+ m_bindings.uniform_buffer_offsets[binding] =
+ static_cast<uint32_t>(m_uniform_stream_buffer->GetCurrentOffset());
+ }
+ m_dirty_flags |= DIRTY_FLAG_DYNAMIC_OFFSETS;
+
+ std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), data, data_size);
+ ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
+ m_uniform_stream_buffer->CommitMemory(data_size);
+
+ // Cached data is now out-of-sync.
+ VertexShaderManager::dirty = true;
+ GeometryShaderManager::dirty = true;
+ PixelShaderManager::dirty = true;
+}
+
bool StateTracker::ReserveConstantStorage()
{
// Since we invalidate all constants on command buffer execution, it doesn't matter if this
@@ -473,16 +504,16 @@ bool StateTracker::Bind(bool rebind_all /*= false*/)
{
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline->GetVkPipelineLayout(), 0, m_num_active_descriptor_sets,
- m_descriptor_sets.data(), NUM_UBO_DESCRIPTOR_SET_BINDINGS,
+ m_descriptor_sets.data(), m_num_dynamic_offsets,
m_bindings.uniform_buffer_offsets.data());
}
else if (m_dirty_flags & DIRTY_FLAG_DYNAMIC_OFFSETS)
{
- vkCmdBindDescriptorSets(
- command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipelineLayout(),
- DESCRIPTOR_SET_BIND_POINT_UNIFORM_BUFFERS, 1,
- &m_descriptor_sets[DESCRIPTOR_SET_BIND_POINT_UNIFORM_BUFFERS],
- NUM_UBO_DESCRIPTOR_SET_BINDINGS, m_bindings.uniform_buffer_offsets.data());
+ vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ m_pipeline->GetVkPipelineLayout(),
+ DESCRIPTOR_SET_BIND_POINT_UNIFORM_BUFFERS, 1,
+ &m_descriptor_sets[DESCRIPTOR_SET_BIND_POINT_UNIFORM_BUFFERS],
+ m_num_dynamic_offsets, m_bindings.uniform_buffer_offsets.data());
}
if (m_dirty_flags & DIRTY_FLAG_VIEWPORT || rebind_all)
@@ -640,6 +671,14 @@ void StateTracker::EndClearRenderPass()
bool StateTracker::UpdateDescriptorSet()
{
+ if (m_pipeline->GetUsage() == AbstractPipelineUsage::GX)
+ return UpdateGXDescriptorSet();
+ else
+ return UpdateUtilityDescriptorSet();
+}
+
+bool StateTracker::UpdateGXDescriptorSet()
+{
const size_t MAX_DESCRIPTOR_WRITES = NUM_UBO_DESCRIPTOR_SET_BINDINGS + // UBO
1 + // Samplers
1; // SSBO
@@ -729,6 +768,50 @@ bool StateTracker::UpdateDescriptorSet()
vkUpdateDescriptorSets(g_vulkan_context->GetDevice(), num_writes, writes.data(), 0, nullptr);
m_num_active_descriptor_sets = NUM_GX_DRAW_DESCRIPTOR_SETS;
+ m_num_dynamic_offsets = NUM_UBO_DESCRIPTOR_SET_BINDINGS;
+ return true;
+}
+
+bool StateTracker::UpdateUtilityDescriptorSet()
+{
+ // Allocate descriptor sets.
+ m_descriptor_sets[0] = g_command_buffer_mgr->AllocateDescriptorSet(
+ g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_SINGLE_UNIFORM_BUFFER));
+ m_descriptor_sets[1] = g_command_buffer_mgr->AllocateDescriptorSet(
+ g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_PIXEL_SHADER_SAMPLERS));
+ if (m_descriptor_sets[0] == VK_NULL_HANDLE || m_descriptor_sets[1] == VK_NULL_HANDLE)
+ {
+ return false;
+ }
+
+ // Build UBO descriptor set.
+ std::array<VkWriteDescriptorSet, 2> dswrites;
+ dswrites[0] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ nullptr,
+ m_descriptor_sets[0],
+ 0,
+ 0,
+ 1,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ nullptr,
+ &m_bindings.uniform_buffer_bindings[UBO_DESCRIPTOR_SET_BINDING_VS],
+ nullptr};
+ dswrites[1] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ nullptr,
+ m_descriptor_sets[1],
+ 0,
+ 0,
+ NUM_PIXEL_SHADER_SAMPLERS,
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ m_bindings.ps_samplers.data(),
+ nullptr,
+ nullptr};
+
+ vkUpdateDescriptorSets(g_vulkan_context->GetDevice(), static_cast<uint32_t>(dswrites.size()),
+ dswrites.data(), 0, nullptr);
+ m_num_active_descriptor_sets = NUM_UTILITY_DRAW_DESCRIPTOR_SETS;
+ m_num_dynamic_offsets = 1;
+ m_dirty_flags |= DIRTY_FLAG_DESCRIPTOR_SET_BINDING;
return true;
}
diff --git a/Source/Core/VideoBackends/Vulkan/StateTracker.h b/Source/Core/VideoBackends/Vulkan/StateTracker.h
index 895e139756..a3d7a365ae 100644
--- a/Source/Core/VideoBackends/Vulkan/StateTracker.h
+++ b/Source/Core/VideoBackends/Vulkan/StateTracker.h
@@ -30,10 +30,6 @@ public:
static bool CreateInstance();
static void DestroyInstance();
- const std::array<VkDescriptorImageInfo, NUM_PIXEL_SHADER_SAMPLERS>& GetPSSamplerBindings() const
- {
- return m_bindings.ps_samplers;
- }
VkFramebuffer GetFramebuffer() const { return m_framebuffer; }
const VKPipeline* GetPipeline() const { return m_pipeline; }
void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset);
@@ -47,6 +43,9 @@ public:
void UpdateGeometryShaderConstants();
void UpdatePixelShaderConstants();
+ // Updates constants from external data, e.g. utility draws.
+ void UpdateConstants(const void* data, u32 data_size);
+
void SetTexture(size_t index, VkImageView view);
void SetSampler(size_t index, VkSampler sampler);
@@ -104,7 +103,8 @@ private:
// Number of descriptor sets for game draws.
enum
{
- NUM_GX_DRAW_DESCRIPTOR_SETS = DESCRIPTOR_SET_BIND_POINT_STORAGE_OR_TEXEL_BUFFER + 1
+ NUM_GX_DRAW_DESCRIPTOR_SETS = DESCRIPTOR_SET_BIND_POINT_STORAGE_OR_TEXEL_BUFFER + 1,
+ NUM_UTILITY_DRAW_DESCRIPTOR_SETS = 2
};
enum DITRY_FLAG : u32
@@ -133,6 +133,8 @@ private:
bool IsViewportWithinRenderArea() const;
bool UpdateDescriptorSet();
+ bool UpdateGXDescriptorSet();
+ bool UpdateUtilityDescriptorSet();
// Allocates storage in the uniform buffer of the specified size. If this storage cannot be
// allocated immediately, the current command buffer will be submitted and all stage's
@@ -167,6 +169,7 @@ private:
} m_bindings;
size_t m_uniform_buffer_reserve_size = 0;
u32 m_num_active_descriptor_sets = 0;
+ u32 m_num_dynamic_offsets = 0;
// rasterization
VkViewport m_viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
diff --git a/Source/Core/VideoBackends/Vulkan/VertexManager.cpp b/Source/Core/VideoBackends/Vulkan/VertexManager.cpp
index 4fa3a92b09..bd0ab0b54d 100644
--- a/Source/Core/VideoBackends/Vulkan/VertexManager.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VertexManager.cpp
@@ -69,25 +69,14 @@ VertexManager::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_dec
return std::make_unique<VertexFormat>(vtx_decl);
}
-void VertexManager::PrepareDrawBuffers(u32 stride)
+void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
{
- size_t vertex_data_size = IndexGenerator::GetNumVerts() * stride;
- size_t index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16);
-
- m_vertex_stream_buffer->CommitMemory(vertex_data_size);
- m_index_stream_buffer->CommitMemory(index_data_size);
-
- ADDSTAT(stats.thisFrame.bytesVertexStreamed, static_cast<int>(vertex_data_size));
- ADDSTAT(stats.thisFrame.bytesIndexStreamed, static_cast<int>(index_data_size));
-
- StateTracker::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0);
- StateTracker::GetInstance()->SetIndexBuffer(m_index_stream_buffer->GetBuffer(), 0,
- VK_INDEX_TYPE_UINT16);
+ StateTracker::GetInstance()->UpdateConstants(uniforms, uniforms_size);
}
-void VertexManager::ResetBuffer(u32 stride)
+void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
{
- if (m_cull_all)
+ if (cull_all)
{
// Not drawing on the gpu, so store in a heap buffer instead
m_cur_buffer_pointer = m_base_buffer_pointer = m_cpu_vertex_buffer.data();
@@ -97,7 +86,8 @@ void VertexManager::ResetBuffer(u32 stride)
}
// Attempt to allocate from buffers
- bool has_vbuffer_allocation = m_vertex_stream_buffer->ReserveMemory(MAXVBUFFERSIZE, stride);
+ bool has_vbuffer_allocation =
+ m_vertex_stream_buffer->ReserveMemory(MAXVBUFFERSIZE, vertex_stride);
bool has_ibuffer_allocation =
m_index_stream_buffer->ReserveMemory(MAXIBUFFERSIZE * sizeof(u16), sizeof(u16));
if (!has_vbuffer_allocation || !has_ibuffer_allocation)
@@ -108,7 +98,7 @@ void VertexManager::ResetBuffer(u32 stride)
// Attempt to allocate again, this may cause a fence wait
if (!has_vbuffer_allocation)
- has_vbuffer_allocation = m_vertex_stream_buffer->ReserveMemory(MAXVBUFFERSIZE, stride);
+ has_vbuffer_allocation = m_vertex_stream_buffer->ReserveMemory(MAXVBUFFERSIZE, vertex_stride);
if (!has_ibuffer_allocation)
has_ibuffer_allocation =
m_index_stream_buffer->ReserveMemory(MAXIBUFFERSIZE * sizeof(u16), sizeof(u16));
@@ -123,34 +113,40 @@ void VertexManager::ResetBuffer(u32 stride)
m_end_buffer_pointer = m_vertex_stream_buffer->GetCurrentHostPointer() + MAXVBUFFERSIZE;
m_cur_buffer_pointer = m_vertex_stream_buffer->GetCurrentHostPointer();
IndexGenerator::Start(reinterpret_cast<u16*>(m_index_stream_buffer->GetCurrentHostPointer()));
-
- // Update base indices
- m_current_draw_base_vertex =
- static_cast<u32>(m_vertex_stream_buffer->GetCurrentOffset() / stride);
- m_current_draw_base_index =
- static_cast<u32>(m_index_stream_buffer->GetCurrentOffset() / sizeof(u16));
}
-void VertexManager::vFlush()
+void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index)
{
- const VertexFormat* vertex_format =
- static_cast<VertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat());
- u32 vertex_stride = vertex_format->GetVertexStride();
+ const u32 vertex_data_size = num_vertices * vertex_stride;
+ const u32 index_data_size = num_indices * sizeof(u16);
+
+ *out_base_vertex =
+ vertex_stride > 0 ?
+ static_cast<u32>(m_vertex_stream_buffer->GetCurrentOffset() / vertex_stride) :
+ 0;
+ *out_base_index = static_cast<u32>(m_index_stream_buffer->GetCurrentOffset() / sizeof(u16));
- // Figure out the number of indices to draw
- u32 index_count = IndexGenerator::GetIndexLen();
+ m_vertex_stream_buffer->CommitMemory(vertex_data_size);
+ m_index_stream_buffer->CommitMemory(index_data_size);
- // Update tracked state
+ ADDSTAT(stats.thisFrame.bytesVertexStreamed, static_cast<int>(vertex_data_size));
+ ADDSTAT(stats.thisFrame.bytesIndexStreamed, static_cast<int>(index_data_size));
+
+ StateTracker::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0);
+ StateTracker::GetInstance()->SetIndexBuffer(m_index_stream_buffer->GetBuffer(), 0,
+ VK_INDEX_TYPE_UINT16);
+}
+
+void VertexManager::UploadConstants()
+{
StateTracker::GetInstance()->UpdateVertexShaderConstants();
StateTracker::GetInstance()->UpdateGeometryShaderConstants();
StateTracker::GetInstance()->UpdatePixelShaderConstants();
+}
- // Commit memory to device.
- // NOTE: This must be done after constant upload, as a constant buffer overrun can cause
- // the current command buffer to be executed, and we want the buffer space to be associated
- // with the command buffer that has the corresponding draw.
- PrepareDrawBuffers(vertex_stride);
-
+void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
+{
// Flush all EFB pokes and invalidate the peek cache.
FramebufferManager::GetInstance()->InvalidatePeekCache();
FramebufferManager::GetInstance()->FlushEFBPokes();
@@ -168,19 +164,14 @@ void VertexManager::vFlush()
}
// Bind all pending state to the command buffer
- if (m_current_pipeline_object)
+ if (StateTracker::GetInstance()->Bind())
{
- g_renderer->SetPipeline(m_current_pipeline_object);
- if (!StateTracker::GetInstance()->Bind())
- {
- WARN_LOG(VIDEO, "Skipped draw of %u indices", index_count);
- return;
- }
-
- // Execute the draw
- vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), index_count, 1,
- m_current_draw_base_index, m_current_draw_base_vertex, 0);
- INCSTAT(stats.thisFrame.numDrawCalls);
+ vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_indices, 1, base_index,
+ base_vertex, 0);
+ }
+ else
+ {
+ WARN_LOG(VIDEO, "Skipped draw of %u indices", num_indices);
}
StateTracker::GetInstance()->OnDraw();
diff --git a/Source/Core/VideoBackends/Vulkan/VertexManager.h b/Source/Core/VideoBackends/Vulkan/VertexManager.h
index 1f892e4151..65c31e11f4 100644
--- a/Source/Core/VideoBackends/Vulkan/VertexManager.h
+++ b/Source/Core/VideoBackends/Vulkan/VertexManager.h
@@ -27,20 +27,19 @@ public:
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
-protected:
- void PrepareDrawBuffers(u32 stride);
- void ResetBuffer(u32 stride) override;
+ void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;
-private:
- void vFlush() override;
+protected:
+ void ResetBuffer(u32 vertex_stride, bool cull_all) override;
+ void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
+ u32* out_base_index) override;
+ void UploadConstants() override;
+ void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;
std::vector<u8> m_cpu_vertex_buffer;
std::vector<u16> m_cpu_index_buffer;
std::unique_ptr<StreamBuffer> m_vertex_stream_buffer;
std::unique_ptr<StreamBuffer> m_index_stream_buffer;
-
- u32 m_current_draw_base_vertex = 0;
- u32 m_current_draw_base_index = 0;
};
}
diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp
index 6cb49aceba..5e45cc6a5f 100644
--- a/Source/Core/VideoCommon/IndexGenerator.cpp
+++ b/Source/Core/VideoCommon/IndexGenerator.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <cstddef>
+#include <cstring>
#include "Common/CommonTypes.h"
#include "Common/Compiler.h"
@@ -56,6 +57,13 @@ void IndexGenerator::AddIndices(int primitive, u32 numVerts)
base_index += numVerts;
}
+void IndexGenerator::AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices)
+{
+ std::memcpy(index_buffer_current, indices, sizeof(u16) * num_indices);
+ index_buffer_current += num_indices;
+ base_index += num_vertices;
+}
+
// Triangles
template <bool pr>
DOLPHIN_FORCE_INLINE u16* IndexGenerator::WriteTriangle(u16* Iptr, u32 index1, u32 index2,
diff --git a/Source/Core/VideoCommon/IndexGenerator.h b/Source/Core/VideoCommon/IndexGenerator.h
index 8d2a5e8700..67f16b66c1 100644
--- a/Source/Core/VideoCommon/IndexGenerator.h
+++ b/Source/Core/VideoCommon/IndexGenerator.h
@@ -18,6 +18,8 @@ public:
static void AddIndices(int primitive, u32 numVertices);
+ static void AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices);
+
// returns numprimitives
static u32 GetNumVerts() { return base_index; }
static u32 GetIndexLen() { return (u32)(index_buffer_current - BASEIptr); }
diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h
index 9fa1beb772..bea1f5ba0a 100644
--- a/Source/Core/VideoCommon/RenderBase.h
+++ b/Source/Core/VideoCommon/RenderBase.h
@@ -114,6 +114,10 @@ public:
{
}
+ // Drawing with currently-bound pipeline state.
+ virtual void Draw(u32 base_vertex, u32 num_vertices) {}
+ virtual void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) {}
+
// Shader modules/objects.
virtual std::unique_ptr<AbstractShader>
CreateShaderFromSource(ShaderStage stage, const char* source, size_t length) = 0;
@@ -192,16 +196,6 @@ public:
virtual std::unique_ptr<VideoCommon::AsyncShaderCompiler> CreateAsyncShaderCompiler();
- // Drawing utility shaders.
- virtual void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices)
- {
- }
- virtual void DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
- u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
- {
- }
-
void ShowOSDMessage(OSDMessage message);
protected:
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp
index 8364b039c5..0e178e4d9b 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/VertexManagerBase.cpp
@@ -27,6 +27,7 @@
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/SamplerCommon.h"
+#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexShaderManager.h"
@@ -131,7 +132,7 @@ DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count,
// need to alloc new buffer
if (m_is_flushed)
{
- g_vertex_manager->ResetBuffer(stride);
+ g_vertex_manager->ResetBuffer(stride, cullall);
m_is_flushed = false;
}
@@ -209,6 +210,28 @@ std::pair<size_t, size_t> VertexManagerBase::ResetFlushAspectRatioCount()
return val;
}
+void VertexManagerBase::UploadUtilityVertices(const void* vertices, u32 vertex_stride,
+ u32 num_vertices, const u16* indices, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index)
+{
+ // The GX vertex list should be flushed before any utility draws occur.
+ ASSERT(m_is_flushed);
+
+ // Copy into the buffers usually used for GX drawing.
+ ResetBuffer(std::max(vertex_stride, 1u), false);
+ if (vertices)
+ {
+ const u32 copy_size = vertex_stride * num_vertices;
+ ASSERT((m_cur_buffer_pointer + copy_size) <= m_end_buffer_pointer);
+ std::memcpy(m_cur_buffer_pointer, vertices, copy_size);
+ m_cur_buffer_pointer += copy_size;
+ }
+ if (indices)
+ IndexGenerator::AddExternalIndices(indices, num_indices, num_vertices);
+
+ CommitBuffer(num_vertices, vertex_stride, num_indices, out_base_vertex, out_base_index);
+}
+
static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex,
bool has_arbitrary_mips)
{
@@ -384,19 +407,35 @@ void VertexManagerBase::Flush()
if (!m_cull_all)
{
+ // Update and upload constants. Note for the Vulkan backend, this must occur before the
+ // vertex/index buffer is committed, otherwise the data will be associated with the
+ // previous command buffer, instead of the one with the draw if there is an overflow.
+ GeometryShaderManager::SetConstants();
+ PixelShaderManager::SetConstants();
+ UploadConstants();
+
+ // Now the vertices can be flushed to the GPU.
+ const u32 num_indices = IndexGenerator::GetIndexLen();
+ u32 base_vertex, base_index;
+ CommitBuffer(IndexGenerator::GetNumVerts(),
+ VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride(), num_indices,
+ &base_vertex, &base_index);
+
// Update the pipeline, or compile one if needed.
UpdatePipelineConfig();
UpdatePipelineObject();
+ if (m_current_pipeline_object)
+ {
+ g_renderer->SetPipeline(m_current_pipeline_object);
+ if (PerfQueryBase::ShouldEmulate())
+ g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
- // set the rest of the global constants
- GeometryShaderManager::SetConstants();
- PixelShaderManager::SetConstants();
+ DrawCurrentBatch(base_index, num_indices, base_vertex);
+ INCSTAT(stats.thisFrame.numDrawCalls);
- if (PerfQueryBase::ShouldEmulate())
- g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
- g_vertex_manager->vFlush();
- if (PerfQueryBase::ShouldEmulate())
- g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ if (PerfQueryBase::ShouldEmulate())
+ g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ }
}
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
@@ -413,7 +452,6 @@ void VertexManagerBase::Flush()
void VertexManagerBase::DoState(PointerWrap& p)
{
p.Do(m_zslope);
- g_vertex_manager->vDoState(p);
}
void VertexManagerBase::CalculateZSlope(NativeVertexFormat* format)
diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h
index 88d9d9fbe0..cd3e4ed552 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.h
+++ b/Source/Core/VideoCommon/VertexManagerBase.h
@@ -69,9 +69,29 @@ public:
m_pipeline_config_changed = true;
}
+ // Utility pipeline drawing (e.g. EFB copies, post-processing, UI).
+ virtual void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) = 0;
+ void UploadUtilityVertices(const void* vertices, u32 vertex_stride, u32 num_vertices,
+ const u16* indices, u32 num_indices, u32* out_base_vertex,
+ u32* out_base_index);
+
protected:
- virtual void vDoState(PointerWrap& p) {}
- virtual void ResetBuffer(u32 stride) = 0;
+ // Vertex buffers/index buffer creation.
+ virtual void CreateDeviceObjects() {}
+ virtual void DestroyDeviceObjects() {}
+
+ // Prepares the buffer for the next batch of vertices.
+ virtual void ResetBuffer(u32 vertex_stride, bool cull_all) = 0;
+
+ // Commits/uploads the current batch of vertices.
+ virtual void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index) = 0;
+
+ // Uploads uniform buffers for GX draws.
+ virtual void UploadConstants() = 0;
+
+ // Issues the draw call for the current batch in the backend.
+ virtual void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) = 0;
u8* m_cur_buffer_pointer = nullptr;
u8* m_base_buffer_pointer = nullptr;
@@ -98,10 +118,6 @@ private:
size_t m_flush_count_4_3 = 0;
size_t m_flush_count_anamorphic = 0;
- virtual void vFlush() = 0;
-
- virtual void CreateDeviceObjects() {}
- virtual void DestroyDeviceObjects() {}
void UpdatePipelineConfig();
void UpdatePipelineObject();
};