diff options
Diffstat (limited to 'Source')
10 files changed, 111 insertions, 19 deletions
diff --git a/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp b/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp index c88fee33ee..d9be7faf2f 100644 --- a/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp @@ -255,7 +255,10 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, vertexBufferSize); ADDSTAT(g_stats.this_frame.bytes_index_streamed, indexBufferSize); +} +void VertexManager::BindCommittedBuffer(u32 vertex_stride) +{ D3D::stateman->SetVertexBuffer(m_buffers[m_current_buffer].Get(), vertex_stride, 0); D3D::stateman->SetIndexBuffer(m_buffers[m_current_buffer].Get()); } diff --git a/Source/Core/VideoBackends/D3D/D3DVertexManager.h b/Source/Core/VideoBackends/D3D/D3DVertexManager.h index ef7c4a9191..37374f6ec3 100644 --- a/Source/Core/VideoBackends/D3D/D3DVertexManager.h +++ b/Source/Core/VideoBackends/D3D/D3DVertexManager.h @@ -51,6 +51,7 @@ protected: void ResetBuffer(u32 vertex_stride) override; void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex, u32* out_base_index) override; + void BindCommittedBuffer(u32 vertex_stride) override; void UploadUniforms() override; private: diff --git a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp index 4565db29bd..5366110ecc 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp @@ -128,7 +128,10 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, static_cast<int>(vertex_data_size)); ADDSTAT(g_stats.this_frame.bytes_index_streamed, static_cast<int>(index_data_size)); +} +void VertexManager::BindCommittedBuffer(u32 vertex_stride) +{ Gfx::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer.GetGPUPointer(), m_vertex_srv.cpu_handle, vertex_stride, m_vertex_stream_buffer.GetSize()); diff --git a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h index 76c0c6d7cb..d7479b0c56 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h +++ b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h @@ -30,6 +30,7 @@ protected: void ResetBuffer(u32 vertex_stride) override; void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex, u32* out_base_index) override; + void BindCommittedBuffer(u32 vertex_stride) override; void UploadUniforms() override; void UpdateVertexShaderConstants(); diff --git a/Source/Core/VideoBackends/OGL/OGLVertexManager.cpp b/Source/Core/VideoBackends/OGL/OGLVertexManager.cpp index c5382cf358..614d066a5b 100644 --- a/Source/Core/VideoBackends/OGL/OGLVertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/OGLVertexManager.cpp @@ -177,7 +177,6 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in *out_base_vertex = vertex_stride > 0 ? (m_vertex_buffer->GetCurrentOffset() / vertex_stride) : 0; *out_base_index = m_index_buffer->GetCurrentOffset() / sizeof(u16); - CheckBufferBinding(); m_vertex_buffer->Unmap(vertex_data_size); m_index_buffer->Unmap(index_data_size); @@ -185,6 +184,11 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in ADDSTAT(g_stats.this_frame.bytes_index_streamed, index_data_size); } +void VertexManager::BindCommittedBuffer(u32 /*vertex_stride*/) +{ + CheckBufferBinding(); +} + void VertexManager::UploadUniforms() { ProgramShaderCache::UploadConstants(); diff --git a/Source/Core/VideoBackends/OGL/OGLVertexManager.h b/Source/Core/VideoBackends/OGL/OGLVertexManager.h index 55a3ef14ad..14111693f4 100644 --- a/Source/Core/VideoBackends/OGL/OGLVertexManager.h +++ b/Source/Core/VideoBackends/OGL/OGLVertexManager.h @@ -47,6 +47,7 @@ protected: void ResetBuffer(u32 vertex_stride) override; void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex, u32* out_base_index) override; + void BindCommittedBuffer(u32 vertex_stride) override; void UploadUniforms() override; private: diff --git a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp index 18c5ad560c..ea8a1d090a 100644 --- a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp @@ -184,7 +184,10 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, static_cast<int>(vertex_data_size)); ADDSTAT(g_stats.this_frame.bytes_index_streamed, static_cast<int>(index_data_size)); +} +void VertexManager::BindCommittedBuffer(u32 /*vertex_stride*/) +{ StateTracker::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0, VERTEX_STREAM_BUFFER_SIZE); StateTracker::GetInstance()->SetIndexBuffer(m_index_stream_buffer->GetBuffer(), 0, diff --git a/Source/Core/VideoBackends/Vulkan/VKVertexManager.h b/Source/Core/VideoBackends/Vulkan/VKVertexManager.h index 75d35c0d32..f00ac47e93 100644 --- a/Source/Core/VideoBackends/Vulkan/VKVertexManager.h +++ b/Source/Core/VideoBackends/Vulkan/VKVertexManager.h @@ -33,6 +33,7 @@ protected: void ResetBuffer(u32 vertex_stride) override; void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex, u32* out_base_index) override; + void BindCommittedBuffer(u32 vertex_stride) override; void UploadUniforms() override; void DestroyTexelBufferViews(); diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index f3f27518bf..7c1f9166ce 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -343,6 +343,10 @@ void VertexManagerBase::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 nu *out_base_index = 0; } +void VertexManagerBase::BindCommittedBuffer(u32) +{ +} + void VertexManagerBase::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) { // If bounding box is enabled, we need to flush any changes first, then invalidate what we have. @@ -393,6 +397,7 @@ void VertexManagerBase::UploadUtilityVertices(const void* vertices, u32 vertex_s m_index_generator.AddExternalIndices(indices, num_indices, num_vertices); CommitBuffer(num_vertices, vertex_stride, num_indices, out_base_vertex, out_base_index); + BindCommittedBuffer(vertex_stride); } u32 VertexManagerBase::GetTexelBufferElementSize(TexelBufferFormat buffer_format) @@ -560,6 +565,7 @@ void VertexManagerBase::Flush() std::vector<std::string> texture_names; Common::SmallVector<u32, 8> texture_units; std::array<SamplerState, 8> samplers; + Common::SmallVector<SubmittedSampledTexture, 8> sampled_textures; if (!m_cull_all) { if (!g_ActiveConfig.bGraphicMods) @@ -572,6 +578,9 @@ void VertexManagerBase::Flush() const float custom_tex_scale = cache_entry->GetWidth() / float(cache_entry->native_width); samplers[i] = TextureCacheBase::GetSamplerState( i, custom_tex_scale, cache_entry->is_custom_tex, cache_entry->has_arbitrary_mips); + + sampled_textures.push_back( + SubmittedSampledTexture{.entry = cache_entry, .sampler = samplers[i], .index = i}); } } else @@ -590,6 +599,9 @@ void VertexManagerBase::Flush() const float custom_tex_scale = cache_entry->GetWidth() / float(cache_entry->native_width); samplers[i] = TextureCacheBase::GetSamplerState( i, custom_tex_scale, cache_entry->is_custom_tex, cache_entry->has_arbitrary_mips); + + sampled_textures.push_back( + SubmittedSampledTexture{.entry = cache_entry, .sampler = samplers[i], .index = i}); } } } @@ -633,8 +645,8 @@ void VertexManagerBase::Flush() UpdatePipelineObject(); if (m_current_pipeline_object) { - RenderDrawCall(pixel_shader_manager, geometry_shader_manager, m_current_primitive_type, - m_current_pipeline_object); + ProcessEmulatedMesh(pixel_shader_manager, geometry_shader_manager, + m_current_pipeline_object, sampled_textures); } } @@ -1023,25 +1035,54 @@ void VertexManagerBase::OnEndFrame() InvalidatePipelineObject(); } -void VertexManagerBase::RenderDrawCall(PixelShaderManager& pixel_shader_manager, - GeometryShaderManager& geometry_shader_manager, - PrimitiveType primitive_type, - const AbstractPipeline* current_pipeline) +void VertexManagerBase::ProcessEmulatedMesh( + PixelShaderManager& pixel_shader_manager, GeometryShaderManager& geometry_shader_manager, + const AbstractPipeline* pipeline, std::span<const SubmittedSampledTexture> sampled_textures) { - // Now we can upload uniforms, as nothing else will override them. - geometry_shader_manager.SetConstants(primitive_type); + geometry_shader_manager.SetConstants(m_current_primitive_type); pixel_shader_manager.SetConstants(); - UploadUniforms(); - g_gfx->SetPipeline(current_pipeline); + const u32 vertex_stride = VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride(); + const u32 index_size = m_index_generator.GetIndexLen(); u32 base_vertex, base_index; - CommitBuffer(m_index_generator.GetNumVerts(), - VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride(), - m_index_generator.GetIndexLen(), &base_vertex, &base_index); + CommitBuffer(m_index_generator.GetNumVerts(), vertex_stride, index_size, &base_vertex, + &base_index); + + SubmittedDrawCallData draw_call_data; + draw_call_data.pipeline = pipeline; + draw_call_data.frame_buffer = g_gfx->GetCurrentFramebuffer(); + draw_call_data.base_index = base_index; + draw_call_data.base_vertex = base_vertex; + draw_call_data.index_size = index_size; + draw_call_data.vertex_stride = vertex_stride; + draw_call_data.primitive_type = m_current_primitive_type; + for (const SubmittedSampledTexture& texture : sampled_textures) + draw_call_data.textures.emplace_back(texture); + + DrawSubmittedDrawData(g_framebuffer_manager.get(), draw_call_data); +} + +void VertexManagerBase::DrawSubmittedDrawData(FramebufferManager* /*framebuffer_manager*/, + const SubmittedDrawCallData& draw_call_data) +{ + BindCommittedBuffer(draw_call_data.vertex_stride); + + // Now we can upload uniforms, as nothing else will override them. + UploadUniforms(); + + g_gfx->SetPipeline(draw_call_data.pipeline); + + for (const SubmittedSampledTexture& texture : draw_call_data.textures) + { + g_gfx->SetTexture(texture.index, texture.entry->texture.get()); + g_gfx->SetSamplerState(texture.index, texture.sampler); + } + u32 base_vertex = draw_call_data.base_vertex; if (g_backend_info.api_type != APIType::D3D && g_ActiveConfig.UseVSForLinePointExpand() && - (primitive_type == PrimitiveType::Points || primitive_type == PrimitiveType::Lines)) + (draw_call_data.primitive_type == PrimitiveType::Points || + draw_call_data.primitive_type == PrimitiveType::Lines)) { // VS point/line expansion puts the vertex id at gl_VertexID << 2 // That means the base vertex has to be adjusted to match @@ -1052,7 +1093,7 @@ void VertexManagerBase::RenderDrawCall(PixelShaderManager& pixel_shader_manager, if (PerfQueryBase::ShouldEmulate()) g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); - DrawCurrentBatch(base_index, m_index_generator.GetIndexLen(), base_vertex); + DrawCurrentBatch(draw_call_data.base_index, draw_call_data.index_size, base_vertex); // Track the total emulated state draws INCSTAT(g_stats.this_frame.num_draw_calls); diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index 8397efe707..84d0c54460 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -4,18 +4,23 @@ #pragma once #include <memory> +#include <span> #include <vector> #include "Common/BitSet.h" #include "Common/CommonTypes.h" #include "Common/MathUtil.h" +#include "Common/SmallVector.h" #include "VideoCommon/CPUCull.h" #include "VideoCommon/IndexGenerator.h" #include "VideoCommon/RenderState.h" #include "VideoCommon/ShaderCache.h" +#include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/VideoEvents.h" +class AbstractFramebuffer; class DataReader; +class FramebufferManager; class GeometryShaderManager; class NativeVertexFormat; class PixelShaderManager; @@ -168,6 +173,29 @@ public: // Call at the end of a frame. void OnEndFrame(); + struct SubmittedSampledTexture + { + RcTcacheEntry entry; + SamplerState sampler; + u32 index = 0; + }; + + struct SubmittedDrawCallData + { + const AbstractPipeline* pipeline = nullptr; + AbstractFramebuffer* frame_buffer = nullptr; + u32 base_index = 0; + u32 base_vertex = 0; + u32 index_size = 0; + u32 vertex_stride = 0; + PrimitiveType primitive_type = PrimitiveType::Points; + Common::SmallVector<SubmittedSampledTexture, 8> textures; + }; + + // Executes a previously captured draw call. + void DrawSubmittedDrawData(FramebufferManager* framebuffer_manager, + const SubmittedDrawCallData& draw_call_data); + protected: // When utility uniforms are used, the GX uniforms need to be re-written afterwards. static void InvalidateConstants(); @@ -179,6 +207,11 @@ protected: virtual void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex, u32* out_base_index); + // Binds the buffers most recently committed, so that a draw can be issued against them. + // Separated from CommitBuffer so that draws can rebind the buffers if the draws + // are triggered independently + virtual void BindCommittedBuffer(u32 vertex_stride); + // Uploads uniform buffers for GX draws. virtual void UploadUniforms(); @@ -220,9 +253,10 @@ private: // Minimum number of draws per command buffer when attempting to preempt a readback operation. static constexpr u32 MINIMUM_DRAW_CALLS_PER_COMMAND_BUFFER_FOR_READBACK = 10; - void RenderDrawCall(PixelShaderManager& pixel_shader_manager, - GeometryShaderManager& geometry_shader_manager, PrimitiveType primitive_type, - const AbstractPipeline* current_pipeline); + void ProcessEmulatedMesh(PixelShaderManager& pixel_shader_manager, + GeometryShaderManager& geometry_shader_manager, + const AbstractPipeline* pipeline, + std::span<const SubmittedSampledTexture> sampled_textures); void UpdatePipelineConfig(); void UpdatePipelineObject(); |
