From 8801abb93a5d72e70449d077bf0ae4b48e6d8ee8 Mon Sep 17 00:00:00 2001 From: vlj Date: Mon, 29 Jun 2015 19:20:18 +0200 Subject: [PATCH] d3d12: Refactor index management Separates it from vertex management and move all the logic (forced indexing, index count calculation...) outside of GSRender. --- rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp | 241 ++++++++++++++------------ rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 34 ++-- rpcs3/Emu/RSX/D3D12/D3D12GSRender.h | 11 +- 3 files changed, 151 insertions(+), 135 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index c302ba8e0f..db8e577d13 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -275,9 +275,9 @@ isContained(const std::vector > &ranges, const std::pair, D3D12_INDEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool indexed_draw) +std::vector D3D12GSRender::UploadVertexBuffers(bool indexed_draw) { - std::pair, D3D12_INDEX_BUFFER_VIEW> result; + std::vector result; const std::vector &vertexBufferFormat = FormatVertexData(m_vertex_data); m_IASet = getIALayout(m_device, vertexBufferFormat, m_vertex_data); @@ -310,10 +310,17 @@ std::pair, D3D12_INDEX_BUFFER_VIEW> D3D12G vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress(); vertexBufferView.SizeInBytes = (UINT)subBufferSize; vertexBufferView.StrideInBytes = (UINT)vbf.stride; - result.first.push_back(vertexBufferView); + result.push_back(vertexBufferView); } + return result; +} + +D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw) +{ + D3D12_INDEX_BUFFER_VIEW indexBufferView = {}; // Only handle quads and triangle fan now + bool forcedIndexBuffer = false; switch (m_draw_mode - 1) { default: @@ -325,126 +332,140 @@ std::pair, D3D12_INDEX_BUFFER_VIEW> D3D12G case GL_TRIANGLE_STRIP: case GL_QUAD_STRIP: case GL_POLYGON: - m_forcedIndexBuffer = false; + forcedIndexBuffer = false; break; case GL_TRIANGLE_FAN: case GL_QUADS: - m_forcedIndexBuffer = true; + forcedIndexBuffer = true; break; } - if (indexed_draw || m_forcedIndexBuffer) + // No need for index buffer + if (!indexed_draw && !forcedIndexBuffer) { - D3D12_INDEX_BUFFER_VIEW indexBufferView = {}; - size_t indexSize; + m_renderingInfo.m_indexed = false; + m_renderingInfo.m_count = m_draw_array_count; + m_renderingInfo.m_baseVertex = m_draw_array_first; + return indexBufferView; + } - if (!indexed_draw) + m_renderingInfo.m_indexed = true; + + // Index type + size_t indexSize; + if (!indexed_draw) + { + indexBufferView.Format = DXGI_FORMAT_R16_UINT; + indexSize = 2; + } + else + { + switch (m_indexed_array.m_type) { + default: abort(); + case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: indexBufferView.Format = DXGI_FORMAT_R16_UINT; indexSize = 2; + break; + case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: + indexBufferView.Format = DXGI_FORMAT_R32_UINT; + indexSize = 4; + break; } - else - { - switch (m_indexed_array.m_type) - { - default: abort(); - case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: - indexBufferView.Format = DXGI_FORMAT_R16_UINT; - indexSize = 2; - break; - case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: - indexBufferView.Format = DXGI_FORMAT_R32_UINT; - indexSize = 4; - break; - } - } - - if (indexed_draw && !m_forcedIndexBuffer) - indexCount = m_indexed_array.m_data.size() / indexSize; - else if (indexed_draw && m_forcedIndexBuffer) - indexCount = 6 * m_indexed_array.m_data.size() / (4 * indexSize); - else - { - switch (m_draw_mode - 1) - { - case GL_TRIANGLE_FAN: - indexCount = (m_draw_array_count - 2) * 3; - break; - case GL_QUADS: - indexCount = m_draw_array_count * 6 / 4; - break; - } - } - size_t subBufferSize = align(indexCount * indexSize, 64); - - assert(m_vertexIndexData.canAlloc(subBufferSize)); - size_t heapOffset = m_vertexIndexData.alloc(subBufferSize); - - ID3D12Resource *indexBuffer; - check(m_device->CreatePlacedResource( - m_vertexIndexData.m_heap, - heapOffset, - &getBufferResourceDesc(subBufferSize), - D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, - IID_PPV_ARGS(&indexBuffer) - )); - - void *bufferMap; - check(indexBuffer->Map(0, nullptr, (void**)&bufferMap)); - if (indexed_draw && !m_forcedIndexBuffer) - streamBuffer(bufferMap, m_indexed_array.m_data.data(), subBufferSize); - else if (indexed_draw && m_forcedIndexBuffer) - { - // Only quads supported now - switch (m_indexed_array.m_type) - { - case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: - expandIndexedQuads(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 4); - break; - case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: - expandIndexedQuads(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 2); - break; - } - } - else - { - unsigned short *typedDst = static_cast(bufferMap); - switch (m_draw_mode - 1) - { - case GL_TRIANGLE_FAN: - for (unsigned i = 0; i < (m_draw_array_count - 2); i++) - { - typedDst[3 * i] = 0; - typedDst[3 * i + 1] = i + 2 - 1; - typedDst[3 * i + 2] = i + 2; - } - break; - case GL_QUADS: - for (unsigned i = 0; i < m_draw_array_count / 4; i++) - { - // First triangle - typedDst[6 * i] = 4 * i; - typedDst[6 * i + 1] = 4 * i + 1; - typedDst[6 * i + 2] = 4 * i + 2; - // Second triangle - typedDst[6 * i + 3] = 4 * i + 2; - typedDst[6 * i + 4] = 4 * i + 3; - typedDst[6 * i + 5] = 4 * i; - } - break; - } - - } - indexBuffer->Unmap(0, nullptr); - m_vertexIndexData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, subBufferSize, indexBuffer)); - - indexBufferView.SizeInBytes = (UINT)subBufferSize; - indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress(); - - result.second = indexBufferView; } - return result; + + // Index count + if (indexed_draw && !forcedIndexBuffer) + m_renderingInfo.m_count = m_indexed_array.m_data.size() / indexSize; + else if (indexed_draw && forcedIndexBuffer) + m_renderingInfo.m_count = 6 * m_indexed_array.m_data.size() / (4 * indexSize); + else + { + switch (m_draw_mode - 1) + { + case GL_TRIANGLE_FAN: + m_renderingInfo.m_count = (m_draw_array_count - 2) * 3; + break; + case GL_QUADS: + m_renderingInfo.m_count = m_draw_array_count * 6 / 4; + break; + } + } + + // Base vertex + if (!indexed_draw && forcedIndexBuffer) + m_renderingInfo.m_baseVertex = m_draw_array_first; + else + m_renderingInfo.m_baseVertex = 0; + + // Alloc + size_t subBufferSize = align(m_renderingInfo.m_count * indexSize, 64); + + assert(m_vertexIndexData.canAlloc(subBufferSize)); + size_t heapOffset = m_vertexIndexData.alloc(subBufferSize); + + ID3D12Resource *indexBuffer; + check(m_device->CreatePlacedResource( + m_vertexIndexData.m_heap, + heapOffset, + &getBufferResourceDesc(subBufferSize), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&indexBuffer) + )); + + void *bufferMap; + check(indexBuffer->Map(0, nullptr, (void**)&bufferMap)); + if (indexed_draw && !forcedIndexBuffer) + streamBuffer(bufferMap, m_indexed_array.m_data.data(), subBufferSize); + else if (indexed_draw && forcedIndexBuffer) + { + // Only quads supported now + switch (m_indexed_array.m_type) + { + case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: + expandIndexedQuads(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 4); + break; + case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: + expandIndexedQuads(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 2); + break; + } + } + else + { + unsigned short *typedDst = static_cast(bufferMap); + switch (m_draw_mode - 1) + { + case GL_TRIANGLE_FAN: + for (unsigned i = 0; i < (m_draw_array_count - 2); i++) + { + typedDst[3 * i] = 0; + typedDst[3 * i + 1] = i + 2 - 1; + typedDst[3 * i + 2] = i + 2; + } + break; + case GL_QUADS: + for (unsigned i = 0; i < m_draw_array_count / 4; i++) + { + // First triangle + typedDst[6 * i] = 4 * i; + typedDst[6 * i + 1] = 4 * i + 1; + typedDst[6 * i + 2] = 4 * i + 2; + // Second triangle + typedDst[6 * i + 3] = 4 * i + 2; + typedDst[6 * i + 4] = 4 * i + 3; + typedDst[6 * i + 5] = 4 * i; + } + break; + } + + } + indexBuffer->Unmap(0, nullptr); + m_vertexIndexData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, subBufferSize, indexBuffer)); + + indexBufferView.SizeInBytes = (UINT)subBufferSize; + indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress(); + return indexBufferView; } void D3D12GSRender::setScaleOffset() diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 644b3cab6a..92b282bbe4 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -508,10 +508,11 @@ void D3D12GSRender::ExecCMD() std::chrono::time_point startVertexTime = std::chrono::system_clock::now(); if (m_indexed_array.m_count || m_draw_array_count) { - const std::pair, D3D12_INDEX_BUFFER_VIEW> &vertexIndexBufferViews = UploadVertexBuffers(m_indexed_array.m_count ? true : false); - commandList->IASetVertexBuffers(0, (UINT)vertexIndexBufferViews.first.size(), vertexIndexBufferViews.first.data()); - if (m_forcedIndexBuffer || m_indexed_array.m_count) - commandList->IASetIndexBuffer(&vertexIndexBufferViews.second); + const std::vector &vertexBufferViews = UploadVertexBuffers(m_indexed_array.m_count ? true : false); + const D3D12_INDEX_BUFFER_VIEW &indexBufferView = uploadIndexBuffers(m_indexed_array.m_count ? true : false); + commandList->IASetVertexBuffers(0, (UINT)vertexBufferViews.size(), vertexBufferViews.data()); + if (m_renderingInfo.m_indexed) + commandList->IASetIndexBuffer(&indexBufferView); } std::chrono::time_point endVertexTime = std::chrono::system_clock::now(); m_timers.m_vertexUploadDuration += std::chrono::duration_cast(endVertexTime - startVertexTime).count(); @@ -635,14 +636,13 @@ void D3D12GSRender::ExecCMD() D3D12_RECT box = { - 0, + 0, 0, (LONG)m_surface_clip_w, (LONG)m_surface_clip_h, }; commandList->RSSetScissorRects(1, &box); - bool requireIndexBuffer = false; switch (m_draw_mode - 1) { case GL_POINTS: @@ -664,31 +664,21 @@ void D3D12GSRender::ExecCMD() commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); break; case GL_TRIANGLE_FAN: - commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - requireIndexBuffer = true; - break; case GL_QUADS: commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - requireIndexBuffer = true; + break; case GL_QUAD_STRIP: case GL_POLYGON: default: commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); -// LOG_ERROR(RSX, "Unsupported primitive type"); + LOG_ERROR(RSX, "Unsupported primitive type"); break; } - // Indexed quad - if (m_forcedIndexBuffer && m_indexed_array.m_count) - commandList->DrawIndexedInstanced((UINT)indexCount, 1, 0, 0, 0); - // Non indexed quad/triangle fan - else if (m_forcedIndexBuffer && !m_indexed_array.m_count) - commandList->DrawIndexedInstanced((UINT)indexCount, 1, 0, (UINT)m_draw_array_first, 0); - // Indexed triangles - else if (m_indexed_array.m_count) - commandList->DrawIndexedInstanced((UINT)m_indexed_array.m_data.size() / ((m_indexed_array.m_type == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16) ? 2 : 4), 1, 0, 0, 0); - else if (m_draw_array_count) - commandList->DrawInstanced(m_draw_array_count, 1, m_draw_array_first, 0); + if (m_renderingInfo.m_indexed) + commandList->DrawIndexedInstanced((UINT)m_renderingInfo.m_count, 1, 0, m_renderingInfo.m_baseVertex, 0); + else + commandList->DrawInstanced((UINT)m_renderingInfo.m_count, 1, m_renderingInfo.m_baseVertex, 0); check(commandList->Close()); m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 76c09dff3d..5d5dcbd60b 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -331,8 +331,12 @@ private: DataHeap m_UAVHeap; DataHeap m_readbackResources; - bool m_forcedIndexBuffer; - size_t indexCount; + struct + { + bool m_indexed; + size_t m_count; + size_t m_baseVertex; + } m_renderingInfo; RenderTargets m_rtts; @@ -372,7 +376,8 @@ private: virtual void Close() override; bool LoadProgram(); - std::pair, D3D12_INDEX_BUFFER_VIEW> UploadVertexBuffers(bool indexed_draw = false); + std::vector UploadVertexBuffers(bool indexed_draw = false); + D3D12_INDEX_BUFFER_VIEW uploadIndexBuffers(bool indexed_draw = false); void setScaleOffset(); void FillVertexShaderConstantsBuffer(); void FillPixelShaderConstantsBuffer();