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:
parent
0ebd54cf38
commit
40618d0b93
1
BUILD.gn
1
BUILD.gn
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
Loading…
Reference in New Issue