d3d12: Refactor index management

Separates it from vertex management and move all the logic (forced
indexing, index count calculation...) outside of GSRender.
This commit is contained in:
vlj 2015-06-29 19:20:18 +02:00 committed by Vincent Lejeune
parent 1f3fbe91e2
commit 8801abb93a
3 changed files with 151 additions and 135 deletions

View file

@ -275,9 +275,9 @@ isContained(const std::vector<std::pair<u32, u32> > &ranges, const std::pair<u32
return false; return false;
} }
std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool indexed_draw) std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool indexed_draw)
{ {
std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> result; std::vector<D3D12_VERTEX_BUFFER_VIEW> result;
const std::vector<VertexBufferFormat> &vertexBufferFormat = FormatVertexData(m_vertex_data); const std::vector<VertexBufferFormat> &vertexBufferFormat = FormatVertexData(m_vertex_data);
m_IASet = getIALayout(m_device, vertexBufferFormat, m_vertex_data); m_IASet = getIALayout(m_device, vertexBufferFormat, m_vertex_data);
@ -310,10 +310,17 @@ std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> D3D12G
vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress(); vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
vertexBufferView.SizeInBytes = (UINT)subBufferSize; vertexBufferView.SizeInBytes = (UINT)subBufferSize;
vertexBufferView.StrideInBytes = (UINT)vbf.stride; 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 // Only handle quads and triangle fan now
bool forcedIndexBuffer = false;
switch (m_draw_mode - 1) switch (m_draw_mode - 1)
{ {
default: default:
@ -325,19 +332,27 @@ std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> D3D12G
case GL_TRIANGLE_STRIP: case GL_TRIANGLE_STRIP:
case GL_QUAD_STRIP: case GL_QUAD_STRIP:
case GL_POLYGON: case GL_POLYGON:
m_forcedIndexBuffer = false; forcedIndexBuffer = false;
break; break;
case GL_TRIANGLE_FAN: case GL_TRIANGLE_FAN:
case GL_QUADS: case GL_QUADS:
m_forcedIndexBuffer = true; forcedIndexBuffer = true;
break; break;
} }
if (indexed_draw || m_forcedIndexBuffer) // No need for index buffer
if (!indexed_draw && !forcedIndexBuffer)
{ {
D3D12_INDEX_BUFFER_VIEW indexBufferView = {}; m_renderingInfo.m_indexed = false;
size_t indexSize; m_renderingInfo.m_count = m_draw_array_count;
m_renderingInfo.m_baseVertex = m_draw_array_first;
return indexBufferView;
}
m_renderingInfo.m_indexed = true;
// Index type
size_t indexSize;
if (!indexed_draw) if (!indexed_draw)
{ {
indexBufferView.Format = DXGI_FORMAT_R16_UINT; indexBufferView.Format = DXGI_FORMAT_R16_UINT;
@ -359,23 +374,32 @@ std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> D3D12G
} }
} }
if (indexed_draw && !m_forcedIndexBuffer) // Index count
indexCount = m_indexed_array.m_data.size() / indexSize; if (indexed_draw && !forcedIndexBuffer)
else if (indexed_draw && m_forcedIndexBuffer) m_renderingInfo.m_count = m_indexed_array.m_data.size() / indexSize;
indexCount = 6 * m_indexed_array.m_data.size() / (4 * indexSize); else if (indexed_draw && forcedIndexBuffer)
m_renderingInfo.m_count = 6 * m_indexed_array.m_data.size() / (4 * indexSize);
else else
{ {
switch (m_draw_mode - 1) switch (m_draw_mode - 1)
{ {
case GL_TRIANGLE_FAN: case GL_TRIANGLE_FAN:
indexCount = (m_draw_array_count - 2) * 3; m_renderingInfo.m_count = (m_draw_array_count - 2) * 3;
break; break;
case GL_QUADS: case GL_QUADS:
indexCount = m_draw_array_count * 6 / 4; m_renderingInfo.m_count = m_draw_array_count * 6 / 4;
break; break;
} }
} }
size_t subBufferSize = align(indexCount * indexSize, 64);
// 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)); assert(m_vertexIndexData.canAlloc(subBufferSize));
size_t heapOffset = m_vertexIndexData.alloc(subBufferSize); size_t heapOffset = m_vertexIndexData.alloc(subBufferSize);
@ -392,9 +416,9 @@ std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> D3D12G
void *bufferMap; void *bufferMap;
check(indexBuffer->Map(0, nullptr, (void**)&bufferMap)); check(indexBuffer->Map(0, nullptr, (void**)&bufferMap));
if (indexed_draw && !m_forcedIndexBuffer) if (indexed_draw && !forcedIndexBuffer)
streamBuffer(bufferMap, m_indexed_array.m_data.data(), subBufferSize); streamBuffer(bufferMap, m_indexed_array.m_data.data(), subBufferSize);
else if (indexed_draw && m_forcedIndexBuffer) else if (indexed_draw && forcedIndexBuffer)
{ {
// Only quads supported now // Only quads supported now
switch (m_indexed_array.m_type) switch (m_indexed_array.m_type)
@ -441,10 +465,7 @@ std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> D3D12G
indexBufferView.SizeInBytes = (UINT)subBufferSize; indexBufferView.SizeInBytes = (UINT)subBufferSize;
indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress(); indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress();
return indexBufferView;
result.second = indexBufferView;
}
return result;
} }
void D3D12GSRender::setScaleOffset() void D3D12GSRender::setScaleOffset()

View file

@ -508,10 +508,11 @@ void D3D12GSRender::ExecCMD()
std::chrono::time_point<std::chrono::system_clock> startVertexTime = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> startVertexTime = std::chrono::system_clock::now();
if (m_indexed_array.m_count || m_draw_array_count) if (m_indexed_array.m_count || m_draw_array_count)
{ {
const std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> &vertexIndexBufferViews = UploadVertexBuffers(m_indexed_array.m_count ? true : false); const std::vector<D3D12_VERTEX_BUFFER_VIEW> &vertexBufferViews = UploadVertexBuffers(m_indexed_array.m_count ? true : false);
commandList->IASetVertexBuffers(0, (UINT)vertexIndexBufferViews.first.size(), vertexIndexBufferViews.first.data()); const D3D12_INDEX_BUFFER_VIEW &indexBufferView = uploadIndexBuffers(m_indexed_array.m_count ? true : false);
if (m_forcedIndexBuffer || m_indexed_array.m_count) commandList->IASetVertexBuffers(0, (UINT)vertexBufferViews.size(), vertexBufferViews.data());
commandList->IASetIndexBuffer(&vertexIndexBufferViews.second); if (m_renderingInfo.m_indexed)
commandList->IASetIndexBuffer(&indexBufferView);
} }
std::chrono::time_point<std::chrono::system_clock> endVertexTime = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> endVertexTime = std::chrono::system_clock::now();
m_timers.m_vertexUploadDuration += std::chrono::duration_cast<std::chrono::microseconds>(endVertexTime - startVertexTime).count(); m_timers.m_vertexUploadDuration += std::chrono::duration_cast<std::chrono::microseconds>(endVertexTime - startVertexTime).count();
@ -642,7 +643,6 @@ void D3D12GSRender::ExecCMD()
}; };
commandList->RSSetScissorRects(1, &box); commandList->RSSetScissorRects(1, &box);
bool requireIndexBuffer = false;
switch (m_draw_mode - 1) switch (m_draw_mode - 1)
{ {
case GL_POINTS: case GL_POINTS:
@ -664,31 +664,21 @@ void D3D12GSRender::ExecCMD()
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
break; break;
case GL_TRIANGLE_FAN: case GL_TRIANGLE_FAN:
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
requireIndexBuffer = true;
break;
case GL_QUADS: case GL_QUADS:
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
requireIndexBuffer = true; break;
case GL_QUAD_STRIP: case GL_QUAD_STRIP:
case GL_POLYGON: case GL_POLYGON:
default: default:
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// LOG_ERROR(RSX, "Unsupported primitive type"); LOG_ERROR(RSX, "Unsupported primitive type");
break; break;
} }
// Indexed quad if (m_renderingInfo.m_indexed)
if (m_forcedIndexBuffer && m_indexed_array.m_count) commandList->DrawIndexedInstanced((UINT)m_renderingInfo.m_count, 1, 0, m_renderingInfo.m_baseVertex, 0);
commandList->DrawIndexedInstanced((UINT)indexCount, 1, 0, 0, 0); else
// Non indexed quad/triangle fan commandList->DrawInstanced((UINT)m_renderingInfo.m_count, 1, m_renderingInfo.m_baseVertex, 0);
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);
check(commandList->Close()); check(commandList->Close());
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList); m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);

View file

@ -331,8 +331,12 @@ private:
DataHeap<ID3D12Heap, 65536> m_UAVHeap; DataHeap<ID3D12Heap, 65536> m_UAVHeap;
DataHeap<ID3D12Heap, 65536> m_readbackResources; DataHeap<ID3D12Heap, 65536> m_readbackResources;
bool m_forcedIndexBuffer; struct
size_t indexCount; {
bool m_indexed;
size_t m_count;
size_t m_baseVertex;
} m_renderingInfo;
RenderTargets m_rtts; RenderTargets m_rtts;
@ -372,7 +376,8 @@ private:
virtual void Close() override; virtual void Close() override;
bool LoadProgram(); bool LoadProgram();
std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> UploadVertexBuffers(bool indexed_draw = false); std::vector<D3D12_VERTEX_BUFFER_VIEW> UploadVertexBuffers(bool indexed_draw = false);
D3D12_INDEX_BUFFER_VIEW uploadIndexBuffers(bool indexed_draw = false);
void setScaleOffset(); void setScaleOffset();
void FillVertexShaderConstantsBuffer(); void FillVertexShaderConstantsBuffer();
void FillPixelShaderConstantsBuffer(); void FillPixelShaderConstantsBuffer();