From c0fd1281713f0ffe8bcfb628f8d328c7a1b5ae09 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Mon, 20 Jun 2022 20:24:36 -0500 Subject: [PATCH] VideoBackends:Metal: Use base vertex --- .../VideoBackends/Metal/MTLStateTracker.h | 7 ++- .../VideoBackends/Metal/MTLStateTracker.mm | 49 +++++++------------ .../VideoBackends/Metal/MTLVertexManager.h | 4 ++ .../VideoBackends/Metal/MTLVertexManager.mm | 25 ++++++---- 4 files changed, 41 insertions(+), 44 deletions(-) diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.h b/Source/Core/VideoBackends/Metal/MTLStateTracker.h index d9c79774e0..ac930767c4 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.h +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.h @@ -46,6 +46,7 @@ public: enum class AlignMask : size_t { + None = 0, Other = 15, Uniform = 255, }; @@ -83,7 +84,7 @@ public: void InvalidateUniforms(bool vertex, bool fragment); void SetUtilityUniform(const void* buffer, size_t size); void SetTexelBuffer(id buffer, u32 offset0, u32 offset1); - void SetVerticesAndIndices(Map vertices, Map indices); + void SetVerticesAndIndices(id vertices, id indices); void SetBBoxBuffer(id bbox, id upload, id download); void SetVertexBufferNow(u32 idx, id buffer, u32 offset); void SetFragmentBufferNow(u32 idx, id buffer, u32 offset); @@ -107,7 +108,7 @@ public: Preallocate(buffer_idx, amt); return CommitPreallocation(buffer_idx, amt, align); } - void* Preallocate(UploadBuffer buffer_idx, size_t amt); + std::pair Preallocate(UploadBuffer buffer_idx, size_t amt); /// Must follow a call to Preallocate where amt is >= to the one provided here Map CommitPreallocation(UploadBuffer buffer_idx, size_t amt, AlignMask align) { @@ -247,8 +248,6 @@ private: id vertices = nullptr; id indices = nullptr; id texels = nullptr; - u32 vertices_offset; - u32 indices_offset; u32 texel_buffer_offset0; u32 texel_buffer_offset1; } m_state; diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm index ea2c8cd328..8451f413da 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm @@ -154,7 +154,7 @@ Metal::StateTracker::Map Metal::StateTracker::AllocateForTextureUpload(size_t am return ret; } -void* Metal::StateTracker::Preallocate(UploadBuffer buffer_idx, size_t amt) +std::pair Metal::StateTracker::Preallocate(UploadBuffer buffer_idx, size_t amt) { BufferPair& buffer = m_upload_buffers[static_cast(buffer_idx)]; u64 last_draw = m_last_finished_draw.load(std::memory_order_acquire); @@ -195,7 +195,8 @@ void* Metal::StateTracker::Preallocate(UploadBuffer buffer_idx, size_t amt) ASSERT_MSG(VIDEO, buffer.gpubuffer, "Failed to allocate MTLBuffer (out of memory?)"); } } - return reinterpret_cast(buffer.buffer) + buffer.usage.Pos(); + size_t pos = buffer.usage.Pos(); + return std::make_pair(reinterpret_cast(buffer.buffer) + pos, pos); } Metal::StateTracker::Map Metal::StateTracker::CommitPreallocation(UploadBuffer buffer_idx, @@ -558,13 +559,14 @@ void Metal::StateTracker::SetTexelBuffer(id buffer, u32 offset0, u32 m_flags.has_texel_buffer = false; } -void Metal::StateTracker::SetVerticesAndIndices(Map vertices, Map indices) +void Metal::StateTracker::SetVerticesAndIndices(id vertices, id indices) { - m_state.vertices = vertices.gpu_buffer; - m_state.indices = indices.gpu_buffer; - m_state.vertices_offset = vertices.gpu_offset; - m_state.indices_offset = indices.gpu_offset; - m_flags.has_vertices = false; + if (m_state.vertices != vertices) + { + m_flags.has_vertices = false; + m_state.vertices = vertices; + } + m_state.indices = indices; } void Metal::StateTracker::SetBBoxBuffer(id bbox, id upload, @@ -691,7 +693,7 @@ void Metal::StateTracker::PrepareRender() { m_flags.has_vertices = true; if (m_state.vertices) - SetVertexBufferNow(0, m_state.vertices, m_state.vertices_offset); + SetVertexBufferNow(0, m_state.vertices, 0); } if (u8 dirty = m_dirty_textures & pipe->GetTextures()) { @@ -801,27 +803,14 @@ void Metal::StateTracker::Draw(u32 base_vertex, u32 num_vertices) void Metal::StateTracker::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) { PrepareRender(); - if (!base_vertex) - { - [m_current_render_encoder - drawIndexedPrimitives:m_state.render_pipeline->Prim() - indexCount:num_indices - indexType:MTLIndexTypeUInt16 - indexBuffer:m_state.indices - indexBufferOffset:m_state.indices_offset + base_index * sizeof(u16)]; - } - else - { - [m_current_render_encoder - drawIndexedPrimitives:m_state.render_pipeline->Prim() - indexCount:num_indices - indexType:MTLIndexTypeUInt16 - indexBuffer:m_state.indices - indexBufferOffset:m_state.indices_offset + base_index * sizeof(u16) - instanceCount:1 - baseVertex:base_vertex - baseInstance:0]; - } + [m_current_render_encoder drawIndexedPrimitives:m_state.render_pipeline->Prim() + indexCount:num_indices + indexType:MTLIndexTypeUInt16 + indexBuffer:m_state.indices + indexBufferOffset:base_index * sizeof(u16) + instanceCount:1 + baseVertex:base_vertex + baseInstance:0]; } void Metal::StateTracker::DispatchComputeShader(u32 groupsize_x, u32 groupsize_y, u32 groupsize_z, diff --git a/Source/Core/VideoBackends/Metal/MTLVertexManager.h b/Source/Core/VideoBackends/Metal/MTLVertexManager.h index 29c715f1fd..8914d5fe84 100644 --- a/Source/Core/VideoBackends/Metal/MTLVertexManager.h +++ b/Source/Core/VideoBackends/Metal/MTLVertexManager.h @@ -26,5 +26,9 @@ protected: void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex, u32* out_base_index) override; void UploadUniforms() override; + +private: + u32 m_vertex_offset; + u32 m_base_vertex; }; } // namespace Metal diff --git a/Source/Core/VideoBackends/Metal/MTLVertexManager.mm b/Source/Core/VideoBackends/Metal/MTLVertexManager.mm index 3683e79ba6..8fb3e25de4 100644 --- a/Source/Core/VideoBackends/Metal/MTLVertexManager.mm +++ b/Source/Core/VideoBackends/Metal/MTLVertexManager.mm @@ -54,31 +54,36 @@ bool Metal::VertexManager::UploadTexelBuffer(const void* data, u32 data_size, void Metal::VertexManager::ResetBuffer(u32 vertex_stride) { const u32 max_vertex_size = 65535 * vertex_stride; - void* vertex = g_state_tracker->Preallocate(StateTracker::UploadBuffer::Vertex, max_vertex_size); - void* index = + const u32 vertex_alloc = max_vertex_size + vertex_stride - 1; // for alignment + auto vertex = g_state_tracker->Preallocate(StateTracker::UploadBuffer::Vertex, vertex_alloc); + auto index = g_state_tracker->Preallocate(StateTracker::UploadBuffer::Index, MAXIBUFFERSIZE * sizeof(u16)); - m_cur_buffer_pointer = m_base_buffer_pointer = static_cast(vertex); + // Align the base vertex + m_base_vertex = (vertex.second + vertex_stride - 1) / vertex_stride; + m_vertex_offset = m_base_vertex * vertex_stride - vertex.second; + m_cur_buffer_pointer = m_base_buffer_pointer = static_cast(vertex.first) + m_vertex_offset; m_end_buffer_pointer = m_base_buffer_pointer + max_vertex_size; - m_index_generator.Start(static_cast(index)); + m_index_generator.Start(static_cast(index.first)); } void Metal::VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex, u32* out_base_index) { - const u32 vsize = num_vertices * vertex_stride; + const u32 vsize = num_vertices * vertex_stride + m_vertex_offset; const u32 isize = num_indices * sizeof(u16); StateTracker::Map vmap = g_state_tracker->CommitPreallocation( - StateTracker::UploadBuffer::Vertex, vsize, StateTracker::AlignMask::Other); + StateTracker::UploadBuffer::Vertex, vsize, StateTracker::AlignMask::None); StateTracker::Map imap = g_state_tracker->CommitPreallocation( - StateTracker::UploadBuffer::Index, isize, StateTracker::AlignMask::Other); + StateTracker::UploadBuffer::Index, isize, StateTracker::AlignMask::None); ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, vsize); ADDSTAT(g_stats.this_frame.bytes_index_streamed, isize); - g_state_tracker->SetVerticesAndIndices(vmap, imap); - *out_base_vertex = 0; - *out_base_index = 0; + DEBUG_ASSERT(vmap.gpu_offset + m_vertex_offset == m_base_vertex * vertex_stride); + g_state_tracker->SetVerticesAndIndices(vmap.gpu_buffer, imap.gpu_buffer); + *out_base_vertex = m_base_vertex; + *out_base_index = imap.gpu_offset / sizeof(u16); } void Metal::VertexManager::UploadUniforms()