d3d12: Add support for indexed draw

This commit is contained in:
vlj 2015-05-25 00:23:08 +02:00 committed by Vincent Lejeune
parent 5ce0261265
commit 232c97cc82
2 changed files with 110 additions and 124 deletions

View file

@ -17,7 +17,7 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value)
void D3D12GSRender::ResourceStorage::Reset() void D3D12GSRender::ResourceStorage::Reset()
{ {
m_currentVertexBuffersHeapOffset = 0; m_vertexIndexBuffersHeapFreeSpace = 0;
m_constantsBufferIndex = 0; m_constantsBufferIndex = 0;
m_currentScaleOffsetBufferIndex = 0; m_currentScaleOffsetBufferIndex = 0;
m_constantsBuffersHeapFreeSpace = 0; m_constantsBuffersHeapFreeSpace = 0;
@ -44,50 +44,28 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
// Create heap for vertex and constants buffers // Create heap for vertex and constants buffers
D3D12_HEAP_DESC vertexBufferHeapDesc = {}; D3D12_HEAP_DESC vertexBufferHeapDesc = {};
// 16 MB wide // 16 MB wide
vertexBufferHeapDesc.SizeInBytes = 1024 * 1024 * 16; vertexBufferHeapDesc.SizeInBytes = 1024 * 1024 * 256;
vertexBufferHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; vertexBufferHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
vertexBufferHeapDesc.Properties.Type = D3D12_HEAP_TYPE_UPLOAD; 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))); 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 = {}; D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {};
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; 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; descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
check(device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_constantsBufferDescriptorsHeap))); check(device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_constantsBufferDescriptorsHeap)));
descriptorHeapDesc = {}; descriptorHeapDesc = {};
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; 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; descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
check(device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_scaleOffsetDescriptorHeap))); check(device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_scaleOffsetDescriptorHeap)));
// Texture // Texture
D3D12_HEAP_DESC heapDescription = {}; D3D12_HEAP_DESC heapDescription = {};
heapDescription.SizeInBytes = 256 * 256 * 256 * 16; heapDescription.SizeInBytes = 1024 * 1024 * 256;
heapDescription.Properties.Type = D3D12_HEAP_TYPE_UPLOAD; heapDescription.Properties.Type = D3D12_HEAP_TYPE_UPLOAD;
heapDescription.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; heapDescription.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
check(device->CreateHeap(&heapDescription, IID_PPV_ARGS(&m_uploadTextureHeap))); 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))); check(device->CreateHeap(&heapDescription, IID_PPV_ARGS(&m_textureStorage)));
D3D12_DESCRIPTOR_HEAP_DESC textureDescriptorDesc = {}; 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.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
textureDescriptorDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; textureDescriptorDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
check(device->CreateDescriptorHeap(&textureDescriptorDesc, IID_PPV_ARGS(&m_textureDescriptorsHeap))); check(device->CreateDescriptorHeap(&textureDescriptorDesc, IID_PPV_ARGS(&m_textureDescriptorsHeap)));
@ -109,12 +87,11 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
void D3D12GSRender::ResourceStorage::Release() void D3D12GSRender::ResourceStorage::Release()
{ {
// NOTE: Should be released only if no command are in flight ! // NOTE: Should be released only if no command are in flight !
m_indexBuffer->Release();
m_backbufferAsRendertarget->Release(); m_backbufferAsRendertarget->Release();
m_constantsBufferDescriptorsHeap->Release(); m_constantsBufferDescriptorsHeap->Release();
m_scaleOffsetDescriptorHeap->Release(); m_scaleOffsetDescriptorHeap->Release();
m_constantsBuffersHeap->Release(); m_constantsBuffersHeap->Release();
m_vertexBuffersHeap->Release(); m_vertexIndexBuffersHeap->Release();
m_backBuffer->Release(); m_backBuffer->Release();
for (auto tmp : m_inflightResources) for (auto tmp : m_inflightResources)
tmp->Release(); tmp->Release();
@ -451,9 +428,9 @@ void D3D12GSRender::ExecCMD(u32 cmd)
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**) &commandList); 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); m_IASet = getIALayout(m_device, indexed_draw, m_vertex_data);
const u32 data_offset = indexed_draw ? 0 : m_draw_array_first; 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 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; const size_t data_size = m_vertex_data[i].data.size() - data_offset * item_size;
size_t subBufferSize = (data_offset + data_size) * 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; ID3D12Resource *vertexBuffer;
D3D12_RESOURCE_DESC vertexBufferDesc = {}; D3D12_RESOURCE_DESC vertexBufferDesc = {};
@ -475,8 +455,8 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool index
vertexBufferDesc.MipLevels = 1; vertexBufferDesc.MipLevels = 1;
vertexBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; vertexBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
check(m_device->CreatePlacedResource( check(m_device->CreatePlacedResource(
getCurrentResourceStorage().m_vertexBuffersHeap, getCurrentResourceStorage().m_vertexIndexBuffersHeap,
getCurrentResourceStorage().m_currentVertexBuffersHeapOffset, bufferHeapOffset,
&vertexBufferDesc, &vertexBufferDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, nullptr,
@ -492,40 +472,11 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool index
vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress(); vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
vertexBufferView.SizeInBytes = (UINT)subBufferSize; vertexBufferView.SizeInBytes = (UINT)subBufferSize;
vertexBufferView.StrideInBytes = (UINT)item_size; vertexBufferView.StrideInBytes = (UINT)item_size;
result.push_back(vertexBufferView); result.first.push_back(vertexBufferView);
getCurrentResourceStorage().m_vertexIndexBuffersHeapFreeSpace = bufferHeapOffset + subBufferSize;
// 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();*/
} }
// Only handle quads now
switch (m_draw_mode - 1) switch (m_draw_mode - 1)
{ {
default: default:
@ -543,26 +494,86 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::EnableVertexData(bool index
break; break;
} }
if (m_forcedIndexBuffer) if (indexed_draw || m_forcedIndexBuffer)
{ {
unsigned short *bufferMap; size_t subBufferSize;
check(getCurrentResourceStorage().m_indexBuffer->Map(0, nullptr, (void**)&bufferMap)); 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; D3D12_RESOURCE_DESC resDesc = {};
// QUADS resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
for (unsigned i = 0; i < m_draw_array_count / 4; i++) 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 size_t indexcount = m_indexed_array.m_data.size() / 2;
bufferMap[6 * i] = 4 * i; unsigned short *indexList = (unsigned short*)m_indexed_array.m_data.data();
bufferMap[6 * i + 1] = 4 * i + 1; for (unsigned i = 0; i < indexcount / 4; i++)
bufferMap[6 * i + 2] = 4 * i + 2; {
bufferMap[6 * i + 3] = 4 * i; // First triangle
bufferMap[6 * i + 4] = 4 * i + 2; bufferMap[6 * i] = indexList[4 * i];
bufferMap[6 * i + 5] = 4 * i + 3; bufferMap[6 * i + 1] = indexList[4 * i + 1];
getCurrentResourceStorage().m_indexBufferCount += 6; 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; return result;
} }
@ -901,21 +912,15 @@ void D3D12GSRender::ExecCMD()
if (m_indexed_array.m_count) 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) 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); 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)vertexBufferViews.size(), vertexBufferViews.data()); commandList->IASetVertexBuffers(0, (UINT)vertexIndexBufferViews.first.size(), vertexIndexBufferViews.first.data());
if (m_forcedIndexBuffer) if (m_forcedIndexBuffer || m_indexed_array.m_count)
{ commandList->IASetIndexBuffer(&vertexIndexBufferViews.second);
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);
}
} }
if (!LoadProgram()) if (!LoadProgram())
@ -1031,36 +1036,18 @@ void D3D12GSRender::ExecCMD()
break; 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); 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) else if (m_draw_array_count)
commandList->DrawInstanced(m_draw_array_count, 1, m_draw_array_first, 0); 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()); check(commandList->Close());
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList); m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);

View file

@ -59,10 +59,9 @@ private:
std::vector<ID3D12Resource *> m_inflightResources; std::vector<ID3D12Resource *> m_inflightResources;
// Vertex storage // Vertex storage
size_t m_currentVertexBuffersHeapOffset; size_t m_vertexIndexBuffersHeapFreeSpace;
ID3D12Heap *m_vertexBuffersHeap; ID3D12Heap *m_vertexIndexBuffersHeap;
size_t m_indexBufferCount; size_t m_indexBufferCount;
ID3D12Resource *m_indexBuffer;
// Constants storage // Constants storage
ID3D12Heap *m_constantsBuffersHeap; ID3D12Heap *m_constantsBuffersHeap;
@ -121,7 +120,7 @@ private:
virtual void Close() override; virtual void Close() override;
bool LoadProgram(); 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 setScaleOffset();
void FillVertexShaderConstantsBuffer(); void FillVertexShaderConstantsBuffer();
void FillPixelShaderConstantsBuffer(); void FillPixelShaderConstantsBuffer();