mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 18:40:36 +00:00
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:
parent
1f3fbe91e2
commit
8801abb93a
@ -275,9 +275,9 @@ isContained(const std::vector<std::pair<u32, u32> > &ranges, const std::pair<u32
|
||||
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);
|
||||
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.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<std::vector<D3D12_VERTEX_BUFFER_VIEW>, 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<unsigned int>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 4);
|
||||
break;
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
expandIndexedQuads<unsigned short>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned short *typedDst = static_cast<unsigned short *>(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<unsigned int>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 4);
|
||||
break;
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
expandIndexedQuads<unsigned short>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned short *typedDst = static_cast<unsigned short *>(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()
|
||||
|
@ -508,10 +508,11 @@ void D3D12GSRender::ExecCMD()
|
||||
std::chrono::time_point<std::chrono::system_clock> startVertexTime = std::chrono::system_clock::now();
|
||||
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);
|
||||
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<D3D12_VERTEX_BUFFER_VIEW> &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<std::chrono::system_clock> endVertexTime = std::chrono::system_clock::now();
|
||||
m_timers.m_vertexUploadDuration += std::chrono::duration_cast<std::chrono::microseconds>(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);
|
||||
|
@ -331,8 +331,12 @@ private:
|
||||
DataHeap<ID3D12Heap, 65536> m_UAVHeap;
|
||||
DataHeap<ID3D12Heap, 65536> 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<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 FillVertexShaderConstantsBuffer();
|
||||
void FillPixelShaderConstantsBuffer();
|
||||
|
Loading…
x
Reference in New Issue
Block a user