mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
d3d12: Add support for indexed draw
This commit is contained in:
parent
5ce0261265
commit
232c97cc82
2 changed files with 110 additions and 124 deletions
|
@ -17,7 +17,7 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value)
|
|||
|
||||
void D3D12GSRender::ResourceStorage::Reset()
|
||||
{
|
||||
m_currentVertexBuffersHeapOffset = 0;
|
||||
m_vertexIndexBuffersHeapFreeSpace = 0;
|
||||
m_constantsBufferIndex = 0;
|
||||
m_currentScaleOffsetBufferIndex = 0;
|
||||
m_constantsBuffersHeapFreeSpace = 0;
|
||||
|
@ -44,50 +44,28 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
|||
// Create heap for vertex and constants buffers
|
||||
D3D12_HEAP_DESC vertexBufferHeapDesc = {};
|
||||
// 16 MB wide
|
||||
vertexBufferHeapDesc.SizeInBytes = 1024 * 1024 * 16;
|
||||
vertexBufferHeapDesc.SizeInBytes = 1024 * 1024 * 256;
|
||||
vertexBufferHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||
vertexBufferHeapDesc.Properties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
check(device->CreateHeap(&vertexBufferHeapDesc, IID_PPV_ARGS(&m_vertexBuffersHeap)));
|
||||
check(device->CreateHeap(&vertexBufferHeapDesc, IID_PPV_ARGS(&m_vertexIndexBuffersHeap)));
|
||||
check(device->CreateHeap(&vertexBufferHeapDesc, IID_PPV_ARGS(&m_constantsBuffersHeap)));
|
||||
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProp = {};
|
||||
heapProp.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
|
||||
D3D12_RESOURCE_DESC resDesc = {};
|
||||
resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resDesc.Width = (UINT)1024 * 1024;
|
||||
resDesc.Height = 1;
|
||||
resDesc.DepthOrArraySize = 1;
|
||||
resDesc.SampleDesc.Count = 1;
|
||||
resDesc.MipLevels = 1;
|
||||
resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
|
||||
check(device->CreateCommittedResource(
|
||||
&heapProp,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&resDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&m_indexBuffer)
|
||||
));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {};
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
descriptorHeapDesc.NumDescriptors = 1000; // For safety
|
||||
descriptorHeapDesc.NumDescriptors = 10000; // For safety
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
check(device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_constantsBufferDescriptorsHeap)));
|
||||
|
||||
|
||||
descriptorHeapDesc = {};
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
descriptorHeapDesc.NumDescriptors = 1000; // For safety
|
||||
descriptorHeapDesc.NumDescriptors = 10000; // For safety
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
check(device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_scaleOffsetDescriptorHeap)));
|
||||
|
||||
// Texture
|
||||
D3D12_HEAP_DESC heapDescription = {};
|
||||
heapDescription.SizeInBytes = 256 * 256 * 256 * 16;
|
||||
heapDescription.SizeInBytes = 1024 * 1024 * 256;
|
||||
heapDescription.Properties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapDescription.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||
check(device->CreateHeap(&heapDescription, IID_PPV_ARGS(&m_uploadTextureHeap)));
|
||||
|
@ -97,7 +75,7 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
|||
check(device->CreateHeap(&heapDescription, IID_PPV_ARGS(&m_textureStorage)));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC textureDescriptorDesc = {};
|
||||
textureDescriptorDesc.NumDescriptors = 1000; // For safety
|
||||
textureDescriptorDesc.NumDescriptors = 2048; // For safety
|
||||
textureDescriptorDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
textureDescriptorDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
check(device->CreateDescriptorHeap(&textureDescriptorDesc, IID_PPV_ARGS(&m_textureDescriptorsHeap)));
|
||||
|
@ -109,12 +87,11 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
|||
void D3D12GSRender::ResourceStorage::Release()
|
||||
{
|
||||
// NOTE: Should be released only if no command are in flight !
|
||||
m_indexBuffer->Release();
|
||||
m_backbufferAsRendertarget->Release();
|
||||
m_constantsBufferDescriptorsHeap->Release();
|
||||
m_scaleOffsetDescriptorHeap->Release();
|
||||
m_constantsBuffersHeap->Release();
|
||||
m_vertexBuffersHeap->Release();
|
||||
m_vertexIndexBuffersHeap->Release();
|
||||
m_backBuffer->Release();
|
||||
for (auto tmp : m_inflightResources)
|
||||
tmp->Release();
|
||||
|
@ -451,9 +428,9 @@ void D3D12GSRender::ExecCMD(u32 cmd)
|
|||
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**) &commandList);
|
||||
}
|
||||
|
||||
std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool indexed_draw)
|
||||
std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool indexed_draw)
|
||||
{
|
||||
std::vector<D3D12_VERTEX_BUFFER_VIEW> result;
|
||||
std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> result;
|
||||
m_IASet = getIALayout(m_device, indexed_draw, m_vertex_data);
|
||||
|
||||
const u32 data_offset = indexed_draw ? 0 : m_draw_array_first;
|
||||
|
@ -464,6 +441,9 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool index
|
|||
const size_t item_size = m_vertex_data[i].GetTypeSize() * m_vertex_data[i].size;
|
||||
const size_t data_size = m_vertex_data[i].data.size() - data_offset * item_size;
|
||||
size_t subBufferSize = (data_offset + data_size) * item_size;
|
||||
// 65536 alignment
|
||||
size_t bufferHeapOffset = getCurrentResourceStorage().m_vertexIndexBuffersHeapFreeSpace;
|
||||
bufferHeapOffset = (bufferHeapOffset + 65536 - 1) & ~65535;
|
||||
|
||||
ID3D12Resource *vertexBuffer;
|
||||
D3D12_RESOURCE_DESC vertexBufferDesc = {};
|
||||
|
@ -475,8 +455,8 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool index
|
|||
vertexBufferDesc.MipLevels = 1;
|
||||
vertexBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
check(m_device->CreatePlacedResource(
|
||||
getCurrentResourceStorage().m_vertexBuffersHeap,
|
||||
getCurrentResourceStorage().m_currentVertexBuffersHeapOffset,
|
||||
getCurrentResourceStorage().m_vertexIndexBuffersHeap,
|
||||
bufferHeapOffset,
|
||||
&vertexBufferDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
|
@ -492,40 +472,11 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool index
|
|||
vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
|
||||
vertexBufferView.SizeInBytes = (UINT)subBufferSize;
|
||||
vertexBufferView.StrideInBytes = (UINT)item_size;
|
||||
result.push_back(vertexBufferView);
|
||||
|
||||
// 65536 alignment
|
||||
getCurrentResourceStorage().m_currentVertexBuffersHeapOffset += (subBufferSize + 65536 - 1) & ~65535;
|
||||
}
|
||||
|
||||
if (indexed_draw)
|
||||
{
|
||||
/* D3D12_RESOURCE_DESC resDesc = {};
|
||||
resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resDesc.Width = (UINT)m_indexed_array.m_data.size();
|
||||
resDesc.Height = 1;
|
||||
resDesc.DepthOrArraySize = 1;
|
||||
resDesc.SampleDesc.Count = 1;
|
||||
resDesc.MipLevels = 1;
|
||||
resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
check(m_device->CreateCommittedResource(
|
||||
&heapProp,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&resDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&m_indexBuffer)
|
||||
));
|
||||
|
||||
check(m_indexBuffer->Map(0, nullptr, (void**)&bufferMap));
|
||||
memcpy(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size());
|
||||
m_indexBuffer->Unmap(0, nullptr);
|
||||
|
||||
D3D12_INDEX_BUFFER_VIEW indexBufferView = {};
|
||||
indexBufferView.SizeInBytes = (UINT)m_indexed_array.m_data.size();
|
||||
indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress();*/
|
||||
result.first.push_back(vertexBufferView);
|
||||
getCurrentResourceStorage().m_vertexIndexBuffersHeapFreeSpace = bufferHeapOffset + subBufferSize;
|
||||
}
|
||||
|
||||
// Only handle quads now
|
||||
switch (m_draw_mode - 1)
|
||||
{
|
||||
default:
|
||||
|
@ -543,26 +494,86 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool index
|
|||
break;
|
||||
}
|
||||
|
||||
if (m_forcedIndexBuffer)
|
||||
if (indexed_draw || m_forcedIndexBuffer)
|
||||
{
|
||||
unsigned short *bufferMap;
|
||||
check(getCurrentResourceStorage().m_indexBuffer->Map(0, nullptr, (void**)&bufferMap));
|
||||
size_t subBufferSize;
|
||||
if (indexed_draw && !m_forcedIndexBuffer)
|
||||
subBufferSize = m_indexed_array.m_data.size();
|
||||
else if (indexed_draw && m_forcedIndexBuffer)
|
||||
subBufferSize = 6 * m_indexed_array.m_data.size() / 4;
|
||||
else
|
||||
subBufferSize = 2 * m_draw_array_count * 6 / 4;
|
||||
// 65536 alignment
|
||||
size_t bufferHeapOffset = getCurrentResourceStorage().m_vertexIndexBuffersHeapFreeSpace;
|
||||
bufferHeapOffset = (bufferHeapOffset + 65536 - 1) & ~65535;
|
||||
|
||||
memcpy(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size());
|
||||
getCurrentResourceStorage().m_indexBufferCount = 0;
|
||||
// QUADS
|
||||
for (unsigned i = 0; i < m_draw_array_count / 4; i++)
|
||||
|
||||
D3D12_RESOURCE_DESC resDesc = {};
|
||||
resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resDesc.Width = (UINT)subBufferSize;
|
||||
resDesc.Height = 1;
|
||||
resDesc.DepthOrArraySize = 1;
|
||||
resDesc.SampleDesc.Count = 1;
|
||||
resDesc.MipLevels = 1;
|
||||
resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
|
||||
ID3D12Resource *indexBuffer;
|
||||
check(m_device->CreatePlacedResource(
|
||||
getCurrentResourceStorage().m_vertexIndexBuffersHeap,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&resDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&indexBuffer)
|
||||
));
|
||||
|
||||
unsigned short *bufferMap;
|
||||
check(indexBuffer->Map(0, nullptr, (void**)&bufferMap));
|
||||
size_t forcedIndexCount = 0;
|
||||
if (indexed_draw && !m_forcedIndexBuffer)
|
||||
memcpy(bufferMap, m_indexed_array.m_data.data(), subBufferSize);
|
||||
else if (indexed_draw && m_forcedIndexBuffer)
|
||||
{
|
||||
// First triangle
|
||||
bufferMap[6 * i] = 4 * i;
|
||||
bufferMap[6 * i + 1] = 4 * i + 1;
|
||||
bufferMap[6 * i + 2] = 4 * i + 2;
|
||||
bufferMap[6 * i + 3] = 4 * i;
|
||||
bufferMap[6 * i + 4] = 4 * i + 2;
|
||||
bufferMap[6 * i + 5] = 4 * i + 3;
|
||||
getCurrentResourceStorage().m_indexBufferCount += 6;
|
||||
size_t indexcount = m_indexed_array.m_data.size() / 2;
|
||||
unsigned short *indexList = (unsigned short*)m_indexed_array.m_data.data();
|
||||
for (unsigned i = 0; i < indexcount / 4; i++)
|
||||
{
|
||||
// First triangle
|
||||
bufferMap[6 * i] = indexList[4 * i];
|
||||
bufferMap[6 * i + 1] = indexList[4 * i + 1];
|
||||
bufferMap[6 * i + 2] = indexList[4 * i + 2];
|
||||
// Second triangle
|
||||
bufferMap[6 * i + 3] = indexList[4 * i];
|
||||
bufferMap[6 * i + 4] = indexList[4 * i + 2];
|
||||
bufferMap[6 * i + 5] = indexList[4 * i + 3];
|
||||
forcedIndexCount += 6;
|
||||
}
|
||||
}
|
||||
getCurrentResourceStorage().m_indexBuffer->Unmap(0, nullptr);
|
||||
else
|
||||
{
|
||||
for (unsigned i = 0; i < m_draw_array_count / 4; i++)
|
||||
{
|
||||
// First triangle
|
||||
bufferMap[6 * i] = 4 * i;
|
||||
bufferMap[6 * i + 1] = 4 * i + 1;
|
||||
bufferMap[6 * i + 2] = 4 * i + 2;
|
||||
// Second triangle
|
||||
bufferMap[6 * i + 3] = 4 * i;
|
||||
bufferMap[6 * i + 4] = 4 * i + 2;
|
||||
bufferMap[6 * i + 5] = 4 * i + 3;
|
||||
forcedIndexCount += 6;
|
||||
}
|
||||
}
|
||||
indexBuffer->Unmap(0, nullptr);
|
||||
getCurrentResourceStorage().m_inflightResources.push_back(indexBuffer);
|
||||
getCurrentResourceStorage().m_vertexIndexBuffersHeapFreeSpace = bufferHeapOffset + subBufferSize;
|
||||
getCurrentResourceStorage().m_indexBufferCount = forcedIndexCount;
|
||||
|
||||
D3D12_INDEX_BUFFER_VIEW indexBufferView = {};
|
||||
indexBufferView.SizeInBytes = (UINT)subBufferSize;
|
||||
indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress();
|
||||
indexBufferView.Format = DXGI_FORMAT_R16_UINT;
|
||||
result.second = indexBufferView;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -901,21 +912,15 @@ void D3D12GSRender::ExecCMD()
|
|||
|
||||
if (m_indexed_array.m_count)
|
||||
{
|
||||
// LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
|
||||
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
|
||||
}
|
||||
|
||||
if (m_indexed_array.m_count || m_draw_array_count)
|
||||
{
|
||||
const std::vector<D3D12_VERTEX_BUFFER_VIEW> &vertexBufferViews = EnableVertexData(m_indexed_array.m_count ? true : false);
|
||||
commandList->IASetVertexBuffers(0, (UINT)vertexBufferViews.size(), vertexBufferViews.data());
|
||||
if (m_forcedIndexBuffer)
|
||||
{
|
||||
D3D12_INDEX_BUFFER_VIEW indexBufferView = {};
|
||||
indexBufferView.SizeInBytes = (UINT)getCurrentResourceStorage().m_indexBufferCount * sizeof(unsigned short);
|
||||
indexBufferView.BufferLocation = getCurrentResourceStorage().m_indexBuffer->GetGPUVirtualAddress();
|
||||
indexBufferView.Format = DXGI_FORMAT_R16_UINT;
|
||||
commandList->IASetIndexBuffer(&indexBufferView);
|
||||
}
|
||||
const std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> &vertexIndexBufferViews = EnableVertexData(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);
|
||||
}
|
||||
|
||||
if (!LoadProgram())
|
||||
|
@ -1031,36 +1036,18 @@ void D3D12GSRender::ExecCMD()
|
|||
break;
|
||||
}
|
||||
|
||||
if (m_forcedIndexBuffer)
|
||||
// Indexed quad
|
||||
if (m_forcedIndexBuffer && m_indexed_array.m_count)
|
||||
commandList->DrawIndexedInstanced((UINT)getCurrentResourceStorage().m_indexBufferCount, 1, 0, 0, 0);
|
||||
// Non indexed quad
|
||||
else if (m_forcedIndexBuffer && !m_indexed_array.m_count)
|
||||
commandList->DrawIndexedInstanced((UINT)getCurrentResourceStorage().m_indexBufferCount, 1, 0, (UINT)m_draw_array_first, 0);
|
||||
// Indexed triangles
|
||||
else if (m_indexed_array.m_count)
|
||||
commandList->DrawIndexedInstanced(m_indexed_array.m_count, 1, 0, (UINT)m_draw_array_first, 0);
|
||||
else if (m_draw_array_count)
|
||||
commandList->DrawInstanced(m_draw_array_count, 1, m_draw_array_first, 0);
|
||||
|
||||
if (m_indexed_array.m_count)
|
||||
{
|
||||
/* switch (m_indexed_array.m_type)
|
||||
{
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||
commandList->DrawIndexedInstanced
|
||||
glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr);
|
||||
checkForGlError("glDrawElements #4");
|
||||
break;
|
||||
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr);
|
||||
checkForGlError("glDrawElements #2");
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR(RSX, "Bad indexed array type (%d)", m_indexed_array.m_type);
|
||||
break;
|
||||
}
|
||||
|
||||
DisableVertexData();
|
||||
m_indexed_array.Reset();*/
|
||||
}
|
||||
|
||||
|
||||
check(commandList->Close());
|
||||
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);
|
||||
|
||||
|
|
|
@ -59,10 +59,9 @@ private:
|
|||
std::vector<ID3D12Resource *> m_inflightResources;
|
||||
|
||||
// Vertex storage
|
||||
size_t m_currentVertexBuffersHeapOffset;
|
||||
ID3D12Heap *m_vertexBuffersHeap;
|
||||
size_t m_vertexIndexBuffersHeapFreeSpace;
|
||||
ID3D12Heap *m_vertexIndexBuffersHeap;
|
||||
size_t m_indexBufferCount;
|
||||
ID3D12Resource *m_indexBuffer;
|
||||
|
||||
// Constants storage
|
||||
ID3D12Heap *m_constantsBuffersHeap;
|
||||
|
@ -121,7 +120,7 @@ private:
|
|||
virtual void Close() override;
|
||||
|
||||
bool LoadProgram();
|
||||
std::vector<D3D12_VERTEX_BUFFER_VIEW> EnableVertexData(bool indexed_draw = false);
|
||||
std::pair<std::vector<D3D12_VERTEX_BUFFER_VIEW>, D3D12_INDEX_BUFFER_VIEW> EnableVertexData(bool indexed_draw = false);
|
||||
void setScaleOffset();
|
||||
void FillVertexShaderConstantsBuffer();
|
||||
void FillPixelShaderConstantsBuffer();
|
||||
|
|
Loading…
Add table
Reference in a new issue