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:
parent
ce2cdb4b4d
commit
91a23a3ac3
|
@ -41,6 +41,17 @@
|
||||||
namespace dawn::native::d3d11 {
|
namespace dawn::native::d3d11 {
|
||||||
namespace {
|
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> {
|
class BindGroupTracker : public BindGroupTrackerBase<false, uint64_t> {
|
||||||
public:
|
public:
|
||||||
MaybeError Apply(CommandRecordingContext* commandContext) {
|
MaybeError Apply(CommandRecordingContext* commandContext) {
|
||||||
|
@ -245,6 +256,7 @@ MaybeError CommandBuffer::Execute() {
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t nextComputePassNumber = 0;
|
size_t nextComputePassNumber = 0;
|
||||||
|
size_t nextRenderPassNumber = 0;
|
||||||
|
|
||||||
Command type;
|
Command type;
|
||||||
while (mCommands.NextCommandId(&type)) {
|
while (mCommands.NextCommandId(&type)) {
|
||||||
|
@ -262,8 +274,14 @@ MaybeError CommandBuffer::Execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::BeginRenderPass: {
|
case Command::BeginRenderPass: {
|
||||||
[[maybe_unused]] auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
|
auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
|
||||||
return DAWN_UNIMPLEMENTED_ERROR("Render pass not implemented");
|
DAWN_TRY(
|
||||||
|
LazyClearSyncScope(GetResourceUsages().renderPasses[nextRenderPassNumber]));
|
||||||
|
LazyClearRenderPassAttachments(cmd);
|
||||||
|
DAWN_TRY(ExecuteRenderPass(cmd, commandContext));
|
||||||
|
|
||||||
|
nextRenderPassNumber++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::CopyBufferToBuffer: {
|
case Command::CopyBufferToBuffer: {
|
||||||
|
@ -553,6 +571,285 @@ MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandCon
|
||||||
UNREACHABLE();
|
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) {
|
void CommandBuffer::HandleDebugCommands(CommandRecordingContext* commandContext, Command command) {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case Command::InsertDebugMarker: {
|
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,
|
MaybeError CommandBuffer::RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline,
|
||||||
CommandRecordingContext* commandContext,
|
CommandRecordingContext* commandContext,
|
||||||
DispatchCmd* dispatchCmd) {
|
DispatchCmd* dispatchCmd) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace dawn::native::d3d11 {
|
||||||
|
|
||||||
class CommandRecordingContext;
|
class CommandRecordingContext;
|
||||||
class ComputePipeline;
|
class ComputePipeline;
|
||||||
|
class RenderPipeline;
|
||||||
|
|
||||||
class CommandBuffer final : public CommandBufferBase {
|
class CommandBuffer final : public CommandBufferBase {
|
||||||
public:
|
public:
|
||||||
|
@ -38,8 +39,14 @@ class CommandBuffer final : public CommandBufferBase {
|
||||||
using CommandBufferBase::CommandBufferBase;
|
using CommandBufferBase::CommandBufferBase;
|
||||||
|
|
||||||
MaybeError ExecuteComputePass(CommandRecordingContext* commandContext);
|
MaybeError ExecuteComputePass(CommandRecordingContext* commandContext);
|
||||||
|
MaybeError ExecuteRenderPass(BeginRenderPassCmd* renderPass,
|
||||||
|
CommandRecordingContext* commandContext);
|
||||||
void HandleDebugCommands(CommandRecordingContext* commandContext, Command command);
|
void HandleDebugCommands(CommandRecordingContext* commandContext, Command command);
|
||||||
|
|
||||||
|
MaybeError RecordFirstIndexOffset(RenderPipeline* renderPipeline,
|
||||||
|
CommandRecordingContext* commandContext,
|
||||||
|
uint32_t firstVertex,
|
||||||
|
uint32_t firstInstance);
|
||||||
MaybeError RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline,
|
MaybeError RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline,
|
||||||
CommandRecordingContext* commandContext,
|
CommandRecordingContext* commandContext,
|
||||||
DispatchCmd* dispatchCmd);
|
DispatchCmd* dispatchCmd);
|
||||||
|
|
Loading…
Reference in New Issue