Implement RenderBundle in the backend

Bug: dawn:154
Change-Id: I45496fb2103150dabe32fbc7cb5856dc40c9339f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9222
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2019-08-14 02:01:14 +00:00 committed by Commit Bot service account
parent 0ebd54cf38
commit 40618d0b93
6 changed files with 590 additions and 272 deletions

View File

@ -769,6 +769,7 @@ source_set("dawn_end2end_tests_sources") {
"src/tests/end2end/ObjectCachingTests.cpp",
"src/tests/end2end/OpArrayLengthTests.cpp",
"src/tests/end2end/PrimitiveTopologyTests.cpp",
"src/tests/end2end/RenderBundleTests.cpp",
"src/tests/end2end/RenderPassLoadOpTests.cpp",
"src/tests/end2end/RenderPassTests.cpp",
"src/tests/end2end/SamplerTests.cpp",

View File

@ -17,6 +17,7 @@
#include "common/Assert.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/RenderBundle.h"
#include "dawn_native/d3d12/BindGroupD3D12.h"
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
#include "dawn_native/d3d12/BufferD3D12.h"
@ -398,7 +399,7 @@ namespace dawn_native { namespace d3d12 {
Command type;
PipelineLayout* lastLayout = nullptr;
while (commands->NextCommandId(&type)) {
auto HandleCommand = [&](CommandIterator* commands, Command type) {
switch (type) {
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd =
@ -431,6 +432,26 @@ namespace dawn_native { namespace d3d12 {
default:
SkipCommand(commands, type);
}
};
while (commands->NextCommandId(&type)) {
switch (type) {
case Command::ExecuteBundles: {
ExecuteBundlesCmd* cmd = commands->NextCommand<ExecuteBundlesCmd>();
auto bundles = commands->NextData<Ref<RenderBundleBase>>(cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
CommandIterator* commands = bundles[i]->GetCommands();
commands->Reset();
while (commands->NextCommandId(&type)) {
HandleCommand(commands, type);
}
}
} break;
default:
HandleCommand(commands, type);
break;
}
}
commands->Reset();
@ -987,6 +1008,155 @@ namespace dawn_native { namespace d3d12 {
PipelineLayout* lastLayout = nullptr;
VertexBuffersInfo vertexBuffersInfo = {};
auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
case Command::Draw: {
DrawCmd* draw = iter->NextCommand<DrawCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
commandList->DrawInstanced(draw->vertexCount, draw->instanceCount,
draw->firstVertex, draw->firstInstance);
} break;
case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount,
draw->firstIndex, draw->baseVertex,
draw->firstInstance);
} break;
case Command::DrawIndirect: {
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature =
ToBackend(GetDevice())->GetDrawIndirectSignature();
commandList->ExecuteIndirect(signature.Get(), 1,
buffer->GetD3D12Resource().Get(),
draw->indirectOffset, nullptr, 0);
} break;
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature =
ToBackend(GetDevice())->GetDrawIndexedIndirectSignature();
commandList->ExecuteIndirect(signature.Get(), 1,
buffer->GetD3D12Resource().Get(),
draw->indirectOffset, nullptr, 0);
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
const char* label = iter->NextData<char>(cmd->length + 1);
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
// PIX color is 1 byte per channel in ARGB format
constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice())
->GetFunctions()
->pixSetMarkerOnCommandList(commandList.Get(), kPIXBlackColor, label);
}
} break;
case Command::PopDebugGroup: {
iter->NextCommand<PopDebugGroupCmd>();
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
ToBackend(GetDevice())
->GetFunctions()
->pixEndEventOnCommandList(commandList.Get());
}
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
const char* label = iter->NextData<char>(cmd->length + 1);
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
// PIX color is 1 byte per channel in ARGB format
constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice())
->GetFunctions()
->pixBeginEventOnCommandList(commandList.Get(), kPIXBlackColor, label);
}
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
commandList->SetGraphicsRootSignature(layout->GetRootSignature().Get());
commandList->SetPipelineState(pipeline->GetPipelineState().Get());
commandList->IASetPrimitiveTopology(pipeline->GetD3D12PrimitiveTopology());
bindingTracker->SetInheritedBindGroups(commandList, lastLayout, layout);
lastPipeline = pipeline;
lastLayout = layout;
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
BindGroup* group = ToBackend(cmd->group.Get());
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
bindingTracker->SetBindGroup(commandList, lastLayout, group, cmd->index,
cmd->dynamicOffsetCount, dynamicOffsets);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get());
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;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
auto buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
auto offsets = iter->NextData<uint64_t>(cmd->count);
vertexBuffersInfo.startSlot =
std::min(vertexBuffersInfo.startSlot, cmd->startSlot);
vertexBuffersInfo.endSlot =
std::max(vertexBuffersInfo.endSlot, cmd->startSlot + cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
Buffer* buffer = ToBackend(buffers[i].Get());
auto* d3d12BufferView =
&vertexBuffersInfo.d3d12BufferViews[cmd->startSlot + i];
d3d12BufferView->BufferLocation = buffer->GetVA() + offsets[i];
d3d12BufferView->SizeInBytes = buffer->GetSize() - offsets[i];
// The bufferView stride is set based on the input state before a draw.
}
} break;
default:
UNREACHABLE();
break;
}
};
Command type;
while (mCommands.NextCommandId(&type)) {
switch (type) {
@ -1001,98 +1171,6 @@ namespace dawn_native { namespace d3d12 {
return;
} break;
case Command::Draw: {
DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
commandList->DrawInstanced(draw->vertexCount, draw->instanceCount,
draw->firstVertex, draw->firstInstance);
} break;
case Command::DrawIndexed: {
DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount,
draw->firstIndex, draw->baseVertex,
draw->firstInstance);
} break;
case Command::DrawIndirect: {
DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature =
ToBackend(GetDevice())->GetDrawIndirectSignature();
commandList->ExecuteIndirect(signature.Get(), 1,
buffer->GetD3D12Resource().Get(),
draw->indirectOffset, nullptr, 0);
} break;
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = mCommands.NextCommand<DrawIndexedIndirectCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature =
ToBackend(GetDevice())->GetDrawIndexedIndirectSignature();
commandList->ExecuteIndirect(signature.Get(), 1,
buffer->GetD3D12Resource().Get(),
draw->indirectOffset, nullptr, 0);
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1);
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
// PIX color is 1 byte per channel in ARGB format
constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice())
->GetFunctions()
->pixSetMarkerOnCommandList(commandList.Get(), kPIXBlackColor, label);
}
} break;
case Command::PopDebugGroup: {
mCommands.NextCommand<PopDebugGroupCmd>();
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
ToBackend(GetDevice())
->GetFunctions()
->pixEndEventOnCommandList(commandList.Get());
}
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1);
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
// PIX color is 1 byte per channel in ARGB format
constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice())
->GetFunctions()
->pixBeginEventOnCommandList(commandList.Get(), kPIXBlackColor, label);
}
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
commandList->SetGraphicsRootSignature(layout->GetRootSignature().Get());
commandList->SetPipelineState(pipeline->GetPipelineState().Get());
commandList->IASetPrimitiveTopology(pipeline->GetD3D12PrimitiveTopology());
bindingTracker->SetInheritedBindGroups(commandList, lastLayout, layout);
lastPipeline = pipeline;
lastLayout = layout;
} break;
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
@ -1128,56 +1206,20 @@ namespace dawn_native { namespace d3d12 {
commandList->OMSetBlendFactor(static_cast<const FLOAT*>(&cmd->color.r));
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
BindGroup* group = ToBackend(cmd->group.Get());
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
}
bindingTracker->SetBindGroup(commandList, lastLayout, group, cmd->index,
cmd->dynamicOffsetCount, dynamicOffsets);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get());
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;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = mCommands.NextData<uint64_t>(cmd->count);
vertexBuffersInfo.startSlot =
std::min(vertexBuffersInfo.startSlot, cmd->startSlot);
vertexBuffersInfo.endSlot =
std::max(vertexBuffersInfo.endSlot, cmd->startSlot + cmd->count);
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) {
Buffer* buffer = ToBackend(buffers[i].Get());
auto* d3d12BufferView =
&vertexBuffersInfo.d3d12BufferViews[cmd->startSlot + i];
d3d12BufferView->BufferLocation = buffer->GetVA() + offsets[i];
d3d12BufferView->SizeInBytes = buffer->GetSize() - offsets[i];
// The bufferView stride is set based on the input state before a draw.
CommandIterator* iter = bundles[i]->GetCommands();
iter->Reset();
while (iter->NextCommandId(&type)) {
EncodeRenderBundleCommand(iter, type);
}
}
} break;
default: { UNREACHABLE(); } break;
default: { EncodeRenderBundleCommand(&mCommands, type); } break;
}
}
}

View File

@ -17,6 +17,7 @@
#include "dawn_native/BindGroup.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/RenderBundle.h"
#include "dawn_native/metal/BufferMTL.h"
#include "dawn_native/metal/ComputePipelineMTL.h"
#include "dawn_native/metal/DeviceMTL.h"
@ -871,17 +872,10 @@ namespace dawn_native { namespace metal {
id<MTLRenderCommandEncoder> encoder =
[commandBuffer renderCommandEncoderWithDescriptor:mtlRenderPass];
Command type;
while (mCommands.NextCommandId(&type)) {
auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
[encoder endEncoding];
return;
} break;
case Command::Draw: {
DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
DrawCmd* draw = iter->NextCommand<DrawCmd>();
vertexInputBuffers.Apply(encoder, lastPipeline);
storageBufferLengths.Apply(lastPipeline, encoder);
@ -897,7 +891,7 @@ namespace dawn_native { namespace metal {
} break;
case Command::DrawIndexed: {
DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
size_t formatSize =
IndexFormatSize(lastPipeline->GetVertexInputDescriptor()->indexFormat);
@ -919,7 +913,7 @@ namespace dawn_native { namespace metal {
} break;
case Command::DrawIndirect: {
DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
vertexInputBuffers.Apply(encoder, lastPipeline);
storageBufferLengths.Apply(lastPipeline, encoder);
@ -932,7 +926,7 @@ namespace dawn_native { namespace metal {
} break;
case Command::DrawIndexedIndirect: {
DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
vertexInputBuffers.Apply(encoder, lastPipeline);
storageBufferLengths.Apply(lastPipeline, encoder);
@ -948,8 +942,8 @@ namespace dawn_native { namespace metal {
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
char* label = mCommands.NextData<char>(cmd->length + 1);
InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
char* label = iter->NextData<char>(cmd->length + 1);
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
[encoder insertDebugSignpost:mtlLabel];
@ -957,14 +951,14 @@ namespace dawn_native { namespace metal {
} break;
case Command::PopDebugGroup: {
mCommands.NextCommand<PopDebugGroupCmd>();
iter->NextCommand<PopDebugGroupCmd>();
[encoder popDebugGroup];
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
char* label = mCommands.NextData<char>(cmd->length + 1);
PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
char* label = iter->NextData<char>(cmd->length + 1);
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
[encoder pushDebugGroup:mtlLabel];
@ -972,7 +966,7 @@ namespace dawn_native { namespace metal {
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
RenderPipeline* newPipeline = ToBackend(cmd->pipeline).Get();
vertexInputBuffers.OnSetPipeline(lastPipeline, newPipeline);
@ -984,6 +978,49 @@ namespace dawn_native { namespace metal {
lastPipeline = newPipeline;
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
ApplyBindGroup(cmd->index, ToBackend(cmd->group.Get()), cmd->dynamicOffsetCount,
dynamicOffsets, ToBackend(lastPipeline->GetLayout()),
&storageBufferLengths, encoder, nil);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
auto b = ToBackend(cmd->buffer.Get());
indexBuffer = b->GetMTLBuffer();
indexBufferBaseOffset = cmd->offset;
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
const Ref<BufferBase>* buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
const uint64_t* offsets = iter->NextData<uint64_t>(cmd->count);
vertexInputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers,
offsets);
} break;
default:
UNREACHABLE();
break;
}
};
Command type;
while (mCommands.NextCommandId(&type)) {
switch (type) {
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
[encoder endEncoding];
return;
} break;
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
[encoder setStencilReferenceValue:cmd->reference];
@ -1030,36 +1067,20 @@ namespace dawn_native { namespace metal {
alpha:cmd->color.a];
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
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)) {
EncodeRenderBundleCommand(iter, type);
}
}
ApplyBindGroup(cmd->index, ToBackend(cmd->group.Get()), cmd->dynamicOffsetCount,
dynamicOffsets, ToBackend(lastPipeline->GetLayout()),
&storageBufferLengths, encoder, nil);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
auto b = ToBackend(cmd->buffer.Get());
indexBuffer = b->GetMTLBuffer();
indexBufferBaseOffset = cmd->offset;
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
const Ref<BufferBase>* buffers =
mCommands.NextData<Ref<BufferBase>>(cmd->count);
const uint64_t* offsets = mCommands.NextData<uint64_t>(cmd->count);
vertexInputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers,
offsets);
} break;
default: { UNREACHABLE(); } break;
default: { EncodeRenderBundleCommand(&mCommands, type); } break;
}
}

View File

@ -17,6 +17,7 @@
#include "dawn_native/BindGroup.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/RenderBundle.h"
#include "dawn_native/opengl/BufferGL.h"
#include "dawn_native/opengl/ComputePipelineGL.h"
#include "dawn_native/opengl/DeviceGL.h"
@ -735,21 +736,10 @@ namespace dawn_native { namespace opengl {
InputBufferTracker inputBuffers;
Command type;
while (mCommands.NextCommandId(&type)) {
auto DoRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
if (renderPass->attachmentState->GetSampleCount() > 1) {
ResolveMultisampledRenderTargets(gl, renderPass);
}
gl.DeleteFramebuffers(1, &fbo);
return;
} break;
case Command::Draw: {
DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
DrawCmd* draw = iter->NextCommand<DrawCmd>();
inputBuffers.Apply(gl);
if (draw->firstInstance > 0) {
@ -765,7 +755,7 @@ namespace dawn_native { namespace opengl {
} break;
case Command::DrawIndexed: {
DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
inputBuffers.Apply(gl);
dawn::IndexFormat indexFormat =
@ -790,7 +780,7 @@ namespace dawn_native { namespace opengl {
} break;
case Command::DrawIndirect: {
DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
inputBuffers.Apply(gl);
uint64_t indirectBufferOffset = draw->indirectOffset;
@ -803,7 +793,7 @@ namespace dawn_native { namespace opengl {
} break;
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = mCommands.NextCommand<DrawIndexedIndirectCmd>();
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
inputBuffers.Apply(gl);
dawn::IndexFormat indexFormat =
@ -824,17 +814,60 @@ namespace dawn_native { namespace opengl {
case Command::PushDebugGroup: {
// Due to lack of linux driver support for GL_EXT_debug_marker
// extension these functions are skipped.
SkipCommand(&mCommands, type);
SkipCommand(iter, type);
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();
lastPipeline->ApplyNow(persistentPipelineState);
inputBuffers.OnSetPipeline(lastPipeline);
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
ToBackend(lastPipeline->GetLayout()), lastPipeline,
cmd->dynamicOffsetCount, dynamicOffsets);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
indexBufferBaseOffset = cmd->offset;
inputBuffers.OnSetIndexBuffer(cmd->buffer.Get());
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
auto buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
auto offsets = iter->NextData<uint64_t>(cmd->count);
inputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers, offsets);
} break;
default:
UNREACHABLE();
break;
}
};
Command type;
while (mCommands.NextCommandId(&type)) {
switch (type) {
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
if (renderPass->attachmentState->GetSampleCount() > 1) {
ResolveMultisampledRenderTargets(gl, renderPass);
}
gl.DeleteFramebuffers(1, &fbo);
return;
} break;
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
persistentPipelineState.SetStencilReference(gl, cmd->reference);
@ -856,31 +889,20 @@ namespace dawn_native { namespace opengl {
gl.BlendColor(cmd->color.r, cmd->color.g, cmd->color.b, cmd->color.a);
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
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)) {
DoRenderBundleCommand(iter, type);
}
}
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
ToBackend(lastPipeline->GetLayout()), lastPipeline,
cmd->dynamicOffsetCount, dynamicOffsets);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
indexBufferBaseOffset = cmd->offset;
inputBuffers.OnSetIndexBuffer(cmd->buffer.Get());
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = mCommands.NextData<uint64_t>(cmd->count);
inputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers, offsets);
} break;
default: { UNREACHABLE(); } break;
default: { DoRenderBundleCommand(&mCommands, type); } break;
}
}

View File

@ -16,6 +16,7 @@
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/RenderBundle.h"
#include "dawn_native/vulkan/BindGroupVk.h"
#include "dawn_native/vulkan/BufferVk.h"
#include "dawn_native/vulkan/CommandRecordingContext.h"
@ -671,17 +672,10 @@ namespace dawn_native { namespace vulkan {
DescriptorSetTracker descriptorSets;
RenderPipeline* lastPipeline = nullptr;
Command type;
while (mCommands.NextCommandId(&type)) {
auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
device->fn.CmdEndRenderPass(commands);
return;
} break;
case Command::Draw: {
DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
DrawCmd* draw = iter->NextCommand<DrawCmd>();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
device->fn.CmdDraw(commands, draw->vertexCount, draw->instanceCount,
@ -689,7 +683,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::DrawIndexed: {
DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
device->fn.CmdDrawIndexed(commands, draw->indexCount, draw->instanceCount,
@ -698,7 +692,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::DrawIndirect: {
DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
@ -708,7 +702,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::DrawIndexedIndirect: {
DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
@ -719,8 +713,8 @@ namespace dawn_native { namespace vulkan {
case Command::InsertDebugMarker: {
if (device->GetDeviceInfo().debugMarker) {
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1);
InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
const char* label = iter->NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo;
markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
markerInfo.pNext = nullptr;
@ -732,23 +726,23 @@ namespace dawn_native { namespace vulkan {
markerInfo.color[3] = 1.0;
device->fn.CmdDebugMarkerInsertEXT(commands, &markerInfo);
} else {
SkipCommand(&mCommands, Command::InsertDebugMarker);
SkipCommand(iter, Command::InsertDebugMarker);
}
} break;
case Command::PopDebugGroup: {
if (device->GetDeviceInfo().debugMarker) {
mCommands.NextCommand<PopDebugGroupCmd>();
iter->NextCommand<PopDebugGroupCmd>();
device->fn.CmdDebugMarkerEndEXT(commands);
} else {
SkipCommand(&mCommands, Command::PopDebugGroup);
SkipCommand(iter, Command::PopDebugGroup);
}
} break;
case Command::PushDebugGroup: {
if (device->GetDeviceInfo().debugMarker) {
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1);
PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
const char* label = iter->NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo;
markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
markerInfo.pNext = nullptr;
@ -760,35 +754,24 @@ namespace dawn_native { namespace vulkan {
markerInfo.color[3] = 1.0;
device->fn.CmdDebugMarkerBeginEXT(commands, &markerInfo);
} else {
SkipCommand(&mCommands, Command::PushDebugGroup);
SkipCommand(iter, Command::PushDebugGroup);
}
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle();
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
descriptorSets.OnSetBindGroup(cmd->index, set, cmd->dynamicOffsetCount,
dynamicOffsets);
} break;
case Command::SetBlendColor: {
SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
float blendConstants[4] = {
cmd->color.r,
cmd->color.g,
cmd->color.b,
cmd->color.a,
};
device->fn.CmdSetBlendConstants(commands, blendConstants);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
VkBuffer indexBuffer = ToBackend(cmd->buffer)->GetHandle();
// TODO(cwallez@chromium.org): get the index type from the last render pipeline
@ -801,7 +784,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
@ -811,6 +794,50 @@ namespace dawn_native { namespace vulkan {
descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout()));
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
auto buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
auto offsets = iter->NextData<uint64_t>(cmd->count);
std::array<VkBuffer, kMaxVertexBuffers> vkBuffers;
std::array<VkDeviceSize, kMaxVertexBuffers> vkOffsets;
for (uint32_t i = 0; i < cmd->count; ++i) {
Buffer* buffer = ToBackend(buffers[i].Get());
vkBuffers[i] = buffer->GetHandle();
vkOffsets[i] = static_cast<VkDeviceSize>(offsets[i]);
}
device->fn.CmdBindVertexBuffers(commands, cmd->startSlot, cmd->count,
vkBuffers.data(), vkOffsets.data());
} break;
default:
UNREACHABLE();
break;
}
};
Command type;
while (mCommands.NextCommandId(&type)) {
switch (type) {
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
device->fn.CmdEndRenderPass(commands);
return;
} break;
case Command::SetBlendColor: {
SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
float blendConstants[4] = {
cmd->color.r,
cmd->color.g,
cmd->color.b,
cmd->color.a,
};
device->fn.CmdSetBlendConstants(commands, blendConstants);
} break;
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK,
@ -841,25 +868,20 @@ namespace dawn_native { namespace vulkan {
device->fn.CmdSetScissor(commands, 0, 1, &rect);
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = mCommands.NextData<uint64_t>(cmd->count);
std::array<VkBuffer, kMaxVertexBuffers> vkBuffers;
std::array<VkDeviceSize, kMaxVertexBuffers> vkOffsets;
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) {
Buffer* buffer = ToBackend(buffers[i].Get());
vkBuffers[i] = buffer->GetHandle();
vkOffsets[i] = static_cast<VkDeviceSize>(offsets[i]);
CommandIterator* iter = bundles[i]->GetCommands();
iter->Reset();
while (iter->NextCommandId(&type)) {
EncodeRenderBundleCommand(iter, type);
}
}
device->fn.CmdBindVertexBuffers(commands, cmd->startSlot, cmd->count,
vkBuffers.data(), vkOffsets.data());
} break;
default: { UNREACHABLE(); } break;
default: { EncodeRenderBundleCommand(&mCommands, type); } break;
}
}

View File

@ -0,0 +1,210 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tests/DawnTest.h"
#include "utils/ComboRenderBundleEncoderDescriptor.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
constexpr uint32_t kRTSize = 4;
constexpr RGBA8 kColors[2] = {RGBA8(0, 255, 0, 255), RGBA8(0, 0, 255, 255)};
// RenderBundleTest tests simple usage of RenderBundles to draw. The implementaiton
// of RenderBundle is shared significantly with render pass execution which is
// tested in all other rendering tests.
class RenderBundleTest : public DawnTest {
protected:
void SetUp() override {
DawnTest::SetUp();
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
dawn::ShaderModule vsModule =
utils::CreateShaderModule(device, utils::ShaderStage::Vertex, R"(
#version 450
layout(location = 0) in vec4 pos;
void main() {
gl_Position = pos;
})");
dawn::ShaderModule fsModule =
utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
#version 450
layout(location = 0) out vec4 fragColor;
layout (set = 0, binding = 0) uniform fragmentUniformBuffer {
vec4 color;
};
void main() {
fragColor = color;
})");
dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
device, {{0, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer}});
float colors0[] = {kColors[0].r / 255.f, kColors[0].g / 255.f, kColors[0].b / 255.f,
kColors[0].a / 255.f};
float colors1[] = {kColors[1].r / 255.f, kColors[1].g / 255.f, kColors[1].b / 255.f,
kColors[1].a / 255.f};
dawn::Buffer buffer0 = utils::CreateBufferFromData(device, colors0, 4 * sizeof(float),
dawn::BufferUsageBit::Uniform);
dawn::Buffer buffer1 = utils::CreateBufferFromData(device, colors1, 4 * sizeof(float),
dawn::BufferUsageBit::Uniform);
bindGroups[0] = utils::MakeBindGroup(device, bgl, {{0, buffer0, 0, 4 * sizeof(float)}});
bindGroups[1] = utils::MakeBindGroup(device, bgl, {{0, buffer1, 0, 4 * sizeof(float)}});
dawn::PipelineLayoutDescriptor pipelineLayoutDesc;
pipelineLayoutDesc.bindGroupLayoutCount = 1;
pipelineLayoutDesc.bindGroupLayouts = &bgl;
dawn::PipelineLayout pipelineLayout = device.CreatePipelineLayout(&pipelineLayoutDesc);
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.layout = pipelineLayout;
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.bufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4;
descriptor.cColorStates[0]->format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor);
vertexBuffer = utils::CreateBufferFromData<float>(
device, dawn::BufferUsageBit::Vertex,
{// The bottom left triangle
-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
// The top right triangle
-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f});
}
utils::BasicRenderPass renderPass;
dawn::RenderPipeline pipeline;
dawn::Buffer vertexBuffer;
dawn::BindGroup bindGroups[2];
};
// Basic test of RenderBundle.
TEST_P(RenderBundleTest, Basic) {
utils::ComboRenderBundleEncoderDescriptor desc = {};
desc.colorFormatsCount = 1;
desc.cColorFormats[0] = renderPass.colorFormat;
dawn::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
uint64_t zeroOffset = 0;
renderBundleEncoder.SetPipeline(pipeline);
renderBundleEncoder.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
renderBundleEncoder.SetBindGroup(0, bindGroups[0], 0, nullptr);
renderBundleEncoder.Draw(6, 1, 0, 0);
dawn::RenderBundle renderBundle = renderBundleEncoder.Finish();
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
pass.ExecuteBundles(1, &renderBundle);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(kColors[0], renderPass.color, 1, 3);
EXPECT_PIXEL_RGBA8_EQ(kColors[0], renderPass.color, 3, 1);
}
// Test execution of multiple render bundles
TEST_P(RenderBundleTest, MultipleBundles) {
utils::ComboRenderBundleEncoderDescriptor desc = {};
desc.colorFormatsCount = 1;
desc.cColorFormats[0] = renderPass.colorFormat;
dawn::RenderBundle renderBundles[2];
uint64_t zeroOffset = 0;
{
dawn::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
renderBundleEncoder.SetPipeline(pipeline);
renderBundleEncoder.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
renderBundleEncoder.SetBindGroup(0, bindGroups[0], 0, nullptr);
renderBundleEncoder.Draw(3, 1, 0, 0);
renderBundles[0] = renderBundleEncoder.Finish();
}
{
dawn::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
renderBundleEncoder.SetPipeline(pipeline);
renderBundleEncoder.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
renderBundleEncoder.SetBindGroup(0, bindGroups[1], 0, nullptr);
renderBundleEncoder.Draw(3, 1, 3, 0);
renderBundles[1] = renderBundleEncoder.Finish();
}
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
pass.ExecuteBundles(2, renderBundles);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(kColors[0], renderPass.color, 1, 3);
EXPECT_PIXEL_RGBA8_EQ(kColors[1], renderPass.color, 3, 1);
}
// Test execution of a bundle along with render pass commands.
TEST_P(RenderBundleTest, BundleAndRenderPassCommands) {
utils::ComboRenderBundleEncoderDescriptor desc = {};
desc.colorFormatsCount = 1;
desc.cColorFormats[0] = renderPass.colorFormat;
dawn::RenderBundleEncoder renderBundleEncoder = device.CreateRenderBundleEncoder(&desc);
uint64_t zeroOffset = 0;
renderBundleEncoder.SetPipeline(pipeline);
renderBundleEncoder.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
renderBundleEncoder.SetBindGroup(0, bindGroups[0], 0, nullptr);
renderBundleEncoder.Draw(3, 1, 0, 0);
dawn::RenderBundle renderBundle = renderBundleEncoder.Finish();
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
pass.ExecuteBundles(1, &renderBundle);
pass.SetPipeline(pipeline);
pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
pass.SetBindGroup(0, bindGroups[1], 0, nullptr);
pass.Draw(3, 1, 3, 0);
pass.ExecuteBundles(1, &renderBundle);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(kColors[0], renderPass.color, 1, 3);
EXPECT_PIXEL_RGBA8_EQ(kColors[1], renderPass.color, 3, 1);
}
DAWN_INSTANTIATE_TEST(RenderBundleTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);