D3D12: Add IndexBufferTracker

Setting an index buffer is dependent on getting the index format
from the pipeline. This adds a tracker to lazily apply the index
format before a draw call if it changes.

Bug: dawn:201
Change-Id: I83c87cc950bf6c93637dd14765c340c97b461061
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11001
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Austin Eng 2019-09-09 21:26:01 +00:00 committed by Commit Bot service account
parent 8e37315012
commit f35420dfca
1 changed files with 35 additions and 11 deletions

View File

@ -448,6 +448,36 @@ namespace dawn_native { namespace d3d12 {
std::array<D3D12_VERTEX_BUFFER_VIEW, kMaxVertexBuffers> mD3D12BufferViews = {}; std::array<D3D12_VERTEX_BUFFER_VIEW, kMaxVertexBuffers> mD3D12BufferViews = {};
}; };
class IndexBufferTracker {
public:
void OnSetIndexBuffer(Buffer* buffer, uint64_t offset) {
mD3D12BufferView.BufferLocation = buffer->GetVA() + offset;
mD3D12BufferView.SizeInBytes = buffer->GetSize() - offset;
// We don't need to dirty the state unless BufferLocation or SizeInBytes
// change, but most of the time this will always be the case.
mLastAppliedIndexFormat = DXGI_FORMAT_UNKNOWN;
}
void OnSetPipeline(const RenderPipelineBase* pipeline) {
mD3D12BufferView.Format =
DXGIIndexFormat(pipeline->GetVertexInputDescriptor()->indexFormat);
}
void Apply(ID3D12GraphicsCommandList* commandList) {
if (mD3D12BufferView.Format == mLastAppliedIndexFormat) {
return;
}
commandList->IASetIndexBuffer(&mD3D12BufferView);
mLastAppliedIndexFormat = mD3D12BufferView.Format;
}
private:
DXGI_FORMAT mLastAppliedIndexFormat = DXGI_FORMAT_UNKNOWN;
D3D12_INDEX_BUFFER_VIEW mD3D12BufferView = {};
};
void AllocateAndSetDescriptorHeaps(Device* device, void AllocateAndSetDescriptorHeaps(Device* device,
BindGroupStateTracker* bindingTracker, BindGroupStateTracker* bindingTracker,
RenderPassDescriptorHeapTracker* renderPassTracker, RenderPassDescriptorHeapTracker* renderPassTracker,
@ -997,6 +1027,7 @@ namespace dawn_native { namespace d3d12 {
RenderPipeline* lastPipeline = nullptr; RenderPipeline* lastPipeline = nullptr;
PipelineLayout* lastLayout = nullptr; PipelineLayout* lastLayout = nullptr;
VertexBufferTracker vertexBufferTracker = {}; VertexBufferTracker vertexBufferTracker = {};
IndexBufferTracker indexBufferTracker = {};
auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) { auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) { switch (type) {
@ -1011,6 +1042,7 @@ namespace dawn_native { namespace d3d12 {
case Command::DrawIndexed: { case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>(); DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
indexBufferTracker.Apply(commandList.Get());
vertexBufferTracker.Apply(commandList.Get(), lastPipeline); vertexBufferTracker.Apply(commandList.Get(), lastPipeline);
commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount, commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount,
draw->firstIndex, draw->baseVertex, draw->firstIndex, draw->baseVertex,
@ -1032,6 +1064,7 @@ namespace dawn_native { namespace d3d12 {
case Command::DrawIndexedIndirect: { case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>(); DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
indexBufferTracker.Apply(commandList.Get());
vertexBufferTracker.Apply(commandList.Get(), lastPipeline); vertexBufferTracker.Apply(commandList.Get(), lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get()); Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature = ComPtr<ID3D12CommandSignature> signature =
@ -1086,6 +1119,7 @@ namespace dawn_native { namespace d3d12 {
commandList->SetPipelineState(pipeline->GetPipelineState().Get()); commandList->SetPipelineState(pipeline->GetPipelineState().Get());
commandList->IASetPrimitiveTopology(pipeline->GetD3D12PrimitiveTopology()); commandList->IASetPrimitiveTopology(pipeline->GetD3D12PrimitiveTopology());
indexBufferTracker.OnSetPipeline(pipeline);
bindingTracker->SetInheritedBindGroups(commandList, lastLayout, layout); bindingTracker->SetInheritedBindGroups(commandList, lastLayout, layout);
lastPipeline = pipeline; lastPipeline = pipeline;
@ -1108,17 +1142,7 @@ namespace dawn_native { namespace d3d12 {
case Command::SetIndexBuffer: { case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>(); SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get()); indexBufferTracker.OnSetIndexBuffer(ToBackend(cmd->buffer.Get()), cmd->offset);
D3D12_INDEX_BUFFER_VIEW bufferView;
bufferView.BufferLocation = buffer->GetVA() + cmd->offset;
bufferView.SizeInBytes = buffer->GetSize() - cmd->offset;
// TODO(cwallez@chromium.org): Make index buffers lazily applied, right now
// this will break if the pipeline is changed for one with a different index
// format after SetIndexBuffer
bufferView.Format =
DXGIIndexFormat(lastPipeline->GetVertexInputDescriptor()->indexFormat);
commandList->IASetIndexBuffer(&bufferView);
} break; } break;
case Command::SetVertexBuffers: { case Command::SetVertexBuffers: {