d3d11: CommandBuffer: implement render pass

Bug: dawn:1705
Change-Id: I21c6a8550f098cb1e97d5f0c9a93da53600fa8a3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/127700
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Auto-Submit: Peng Huang <penghuang@chromium.org>
This commit is contained in:
Peng Huang 2023-04-20 18:07:20 +00:00 committed by Dawn LUCI CQ
parent ce2cdb4b4d
commit 91a23a3ac3
2 changed files with 328 additions and 2 deletions

View File

@ -41,6 +41,17 @@
namespace dawn::native::d3d11 {
namespace {
DXGI_FORMAT DXGIIndexFormat(wgpu::IndexFormat format) {
switch (format) {
case wgpu::IndexFormat::Uint16:
return DXGI_FORMAT_R16_UINT;
case wgpu::IndexFormat::Uint32:
return DXGI_FORMAT_R32_UINT;
default:
UNREACHABLE();
}
}
class BindGroupTracker : public BindGroupTrackerBase<false, uint64_t> {
public:
MaybeError Apply(CommandRecordingContext* commandContext) {
@ -245,6 +256,7 @@ MaybeError CommandBuffer::Execute() {
};
size_t nextComputePassNumber = 0;
size_t nextRenderPassNumber = 0;
Command type;
while (mCommands.NextCommandId(&type)) {
@ -262,8 +274,14 @@ MaybeError CommandBuffer::Execute() {
}
case Command::BeginRenderPass: {
[[maybe_unused]] auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
return DAWN_UNIMPLEMENTED_ERROR("Render pass not implemented");
auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
DAWN_TRY(
LazyClearSyncScope(GetResourceUsages().renderPasses[nextRenderPassNumber]));
LazyClearRenderPassAttachments(cmd);
DAWN_TRY(ExecuteRenderPass(cmd, commandContext));
nextRenderPassNumber++;
break;
}
case Command::CopyBufferToBuffer: {
@ -553,6 +571,285 @@ MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandCon
UNREACHABLE();
}
MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass,
CommandRecordingContext* commandContext) {
ID3D11DeviceContext1* d3d11DeviceContext1 = commandContext->GetD3D11DeviceContext1();
// Hold ID3D11RenderTargetView ComPtr to make attachments alive.
ityp::array<ColorAttachmentIndex, ComPtr<ID3D11RenderTargetView>, kMaxColorAttachments>
d3d11RenderTargetViews = {};
ityp::array<ColorAttachmentIndex, ID3D11RenderTargetView*, kMaxColorAttachments>
d3d11RenderTargetViewPtrs = {};
ColorAttachmentIndex attachmentCount(uint8_t(0));
for (ColorAttachmentIndex i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
TextureView* colorTextureView = ToBackend(renderPass->colorAttachments[i].view.Get());
DAWN_TRY_ASSIGN(d3d11RenderTargetViews[i], colorTextureView->CreateD3D11RenderTargetView());
d3d11RenderTargetViewPtrs[i] = d3d11RenderTargetViews[i].Get();
if (renderPass->colorAttachments[i].loadOp == wgpu::LoadOp::Clear) {
d3d11DeviceContext1->ClearRenderTargetView(
d3d11RenderTargetViews[i].Get(),
ConvertToFloatColor(renderPass->colorAttachments[i].clearColor).data());
}
attachmentCount = i;
attachmentCount++;
}
ComPtr<ID3D11DepthStencilView> d3d11DepthStencilView;
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto* attachmentInfo = &renderPass->depthStencilAttachment;
const Format& attachmentFormat = attachmentInfo->view->GetTexture()->GetFormat();
TextureView* depthStencilTextureView =
ToBackend(renderPass->depthStencilAttachment.view.Get());
DAWN_TRY_ASSIGN(d3d11DepthStencilView,
depthStencilTextureView->CreateD3D11DepthStencilView(false, false));
UINT clearFlags = 0;
if (attachmentFormat.HasDepth() &&
renderPass->depthStencilAttachment.depthLoadOp == wgpu::LoadOp::Clear) {
clearFlags |= D3D11_CLEAR_DEPTH;
}
if (attachmentFormat.HasStencil() &&
renderPass->depthStencilAttachment.stencilLoadOp == wgpu::LoadOp::Clear) {
clearFlags |= D3D11_CLEAR_STENCIL;
}
d3d11DeviceContext1->ClearDepthStencilView(d3d11DepthStencilView.Get(), clearFlags,
attachmentInfo->clearDepth,
attachmentInfo->clearStencil);
}
d3d11DeviceContext1->OMSetRenderTargets(static_cast<uint8_t>(attachmentCount),
d3d11RenderTargetViewPtrs.data(),
d3d11DepthStencilView.Get());
// Set viewport
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = renderPass->width;
viewport.Height = renderPass->height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
d3d11DeviceContext1->RSSetViewports(1, &viewport);
// Set scissor
D3D11_RECT scissor;
scissor.left = 0;
scissor.top = 0;
scissor.right = renderPass->width;
scissor.bottom = renderPass->height;
d3d11DeviceContext1->RSSetScissorRects(1, &scissor);
RenderPipeline* lastPipeline = nullptr;
BindGroupTracker bindGroupTracker = {};
std::array<float, 4> blendColor = {0.0f, 0.0f, 0.0f, 0.0f};
uint32_t stencilReference = 0;
auto DoRenderBundleCommand = [&](CommandIterator* iter, Command type) -> MaybeError {
switch (type) {
case Command::Draw: {
DrawCmd* draw = iter->NextCommand<DrawCmd>();
DAWN_TRY(bindGroupTracker.Apply(commandContext));
DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->firstVertex,
draw->firstInstance));
commandContext->GetD3D11DeviceContext()->DrawInstanced(
draw->vertexCount, draw->instanceCount, draw->firstVertex, draw->firstInstance);
break;
}
case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
DAWN_TRY(bindGroupTracker.Apply(commandContext));
DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->baseVertex,
draw->firstInstance));
commandContext->GetD3D11DeviceContext()->DrawIndexedInstanced(
draw->indexCount, draw->instanceCount, draw->firstIndex, draw->baseVertex,
draw->firstInstance);
break;
}
case Command::DrawIndirect: {
// TODO(dawn:1716): figure how to setup built-in variables for indirect draw.
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
DAWN_TRY(bindGroupTracker.Apply(commandContext));
uint64_t indirectBufferOffset = draw->indirectOffset;
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
ASSERT(indirectBuffer != nullptr);
commandContext->GetD3D11DeviceContext()->DrawInstancedIndirect(
indirectBuffer->GetD3D11Buffer(), indirectBufferOffset);
break;
}
case Command::DrawIndexedIndirect: {
// TODO(dawn:1716): figure how to setup built-in variables for indirect draw.
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
DAWN_TRY(bindGroupTracker.Apply(commandContext));
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
ASSERT(indirectBuffer != nullptr);
commandContext->GetD3D11DeviceContext()->DrawIndexedInstancedIndirect(
indirectBuffer->GetD3D11Buffer(), draw->indirectOffset);
break;
}
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();
lastPipeline->ApplyNow(commandContext, blendColor, stencilReference);
bindGroupTracker.OnSetPipeline(lastPipeline);
break;
}
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
uint32_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = iter->NextData<uint32_t>(cmd->dynamicOffsetCount);
}
bindGroupTracker.OnSetBindGroup(cmd->index, cmd->group.Get(),
cmd->dynamicOffsetCount, dynamicOffsets);
break;
}
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
UINT indexBufferBaseOffset = cmd->offset;
DXGI_FORMAT indexBufferFormat = DXGIIndexFormat(cmd->format);
commandContext->GetD3D11DeviceContext()->IASetIndexBuffer(
ToBackend(cmd->buffer)->GetD3D11Buffer(), indexBufferFormat,
indexBufferBaseOffset);
break;
}
case Command::SetVertexBuffer: {
SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
ASSERT(lastPipeline);
const VertexBufferInfo& info = lastPipeline->GetVertexBuffer(cmd->slot);
// TODO(dawn:1705): should we set vertex back to nullptr after the draw call?
UINT slot = static_cast<uint8_t>(cmd->slot);
ID3D11Buffer* buffer = ToBackend(cmd->buffer)->GetD3D11Buffer();
UINT arrayStride = info.arrayStride;
UINT offset = cmd->offset;
commandContext->GetD3D11DeviceContext()->IASetVertexBuffers(slot, 1, &buffer,
&arrayStride, &offset);
break;
}
case Command::InsertDebugMarker:
case Command::PopDebugGroup:
case Command::PushDebugGroup: {
HandleDebugCommands(commandContext, type);
break;
}
default:
UNREACHABLE();
break;
}
return {};
};
Command type;
while (mCommands.NextCommandId(&type)) {
switch (type) {
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
// TODO(dawn:1705): resolve MSAA
return {};
}
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
stencilReference = cmd->reference;
return {};
}
case Command::SetViewport: {
SetViewportCmd* cmd = mCommands.NextCommand<SetViewportCmd>();
D3D11_VIEWPORT viewport;
viewport.TopLeftX = cmd->x;
viewport.TopLeftY = cmd->y;
viewport.Width = cmd->width;
viewport.Height = cmd->height;
viewport.MinDepth = cmd->minDepth;
viewport.MaxDepth = cmd->maxDepth;
commandContext->GetD3D11DeviceContext()->RSSetViewports(1, &viewport);
break;
}
case Command::SetScissorRect: {
SetScissorRectCmd* cmd = mCommands.NextCommand<SetScissorRectCmd>();
D3D11_RECT scissorRect = {static_cast<LONG>(cmd->x), static_cast<LONG>(cmd->y),
static_cast<LONG>(cmd->x + cmd->width),
static_cast<LONG>(cmd->y + cmd->height)};
commandContext->GetD3D11DeviceContext()->RSSetScissorRects(1, &scissorRect);
break;
}
case Command::SetBlendConstant: {
SetBlendConstantCmd* cmd = mCommands.NextCommand<SetBlendConstantCmd>();
blendColor = ConvertToFloatColor(cmd->color);
break;
}
case Command::ExecuteBundles: {
ExecuteBundlesCmd* cmd = mCommands.NextCommand<ExecuteBundlesCmd>();
auto bundles = mCommands.NextData<Ref<RenderBundleBase>>(cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
CommandIterator* iter = bundles[i]->GetCommands();
iter->Reset();
while (iter->NextCommandId(&type)) {
DAWN_TRY(DoRenderBundleCommand(iter, type));
}
}
break;
}
case Command::BeginOcclusionQuery: {
return DAWN_UNIMPLEMENTED_ERROR("BeginOcclusionQuery unimplemented.");
}
case Command::EndOcclusionQuery: {
return DAWN_UNIMPLEMENTED_ERROR("EndOcclusionQuery unimplemented.");
}
case Command::WriteTimestamp:
return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");
default: {
DAWN_TRY(DoRenderBundleCommand(&mCommands, type));
}
}
}
// EndRenderPass should have been called
UNREACHABLE();
}
void CommandBuffer::HandleDebugCommands(CommandRecordingContext* commandContext, Command command) {
switch (command) {
case Command::InsertDebugMarker: {
@ -579,6 +876,28 @@ void CommandBuffer::HandleDebugCommands(CommandRecordingContext* commandContext,
}
}
MaybeError CommandBuffer::RecordFirstIndexOffset(RenderPipeline* renderPipeline,
CommandRecordingContext* commandContext,
uint32_t firstVertex,
uint32_t firstInstance) {
if (!renderPipeline->GetUsesVertexOrInstanceIndex()) {
// Vertex and instance index are not used in shader, so we don't need to update the uniform
// buffer. The original value in the uniform buffer will not be used, so we don't need to
// clear it.
return {};
}
// TODO(dawn:1705): only update the uniform buffer when the value changes.
uint32_t offsets[] = {
firstVertex,
firstInstance,
};
DAWN_TRY(
commandContext->GetUniformBuffer()->Write(commandContext, 0, offsets, sizeof(offsets)));
return {};
}
MaybeError CommandBuffer::RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline,
CommandRecordingContext* commandContext,
DispatchCmd* dispatchCmd) {

View File

@ -27,6 +27,7 @@ namespace dawn::native::d3d11 {
class CommandRecordingContext;
class ComputePipeline;
class RenderPipeline;
class CommandBuffer final : public CommandBufferBase {
public:
@ -38,8 +39,14 @@ class CommandBuffer final : public CommandBufferBase {
using CommandBufferBase::CommandBufferBase;
MaybeError ExecuteComputePass(CommandRecordingContext* commandContext);
MaybeError ExecuteRenderPass(BeginRenderPassCmd* renderPass,
CommandRecordingContext* commandContext);
void HandleDebugCommands(CommandRecordingContext* commandContext, Command command);
MaybeError RecordFirstIndexOffset(RenderPipeline* renderPipeline,
CommandRecordingContext* commandContext,
uint32_t firstVertex,
uint32_t firstInstance);
MaybeError RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline,
CommandRecordingContext* commandContext,
DispatchCmd* dispatchCmd);