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 {
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue