diff --git a/examples/Animometer.cpp b/examples/Animometer.cpp index d8b37714fe..cd58968982 100644 --- a/examples/Animometer.cpp +++ b/examples/Animometer.cpp @@ -133,6 +133,7 @@ void frame() { nxt::CommandBufferBuilder builder = device.CreateCommandBufferBuilder() .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(pipeline) .Clone(); @@ -144,6 +145,7 @@ void frame() { i++; } + builder.EndRenderSubpass(); builder.EndRenderPass(); commands[j] = builder.GetResult(); } diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp index 99e93a28cd..518bbbc7c2 100644 --- a/examples/ComputeBoids.cpp +++ b/examples/ComputeBoids.cpp @@ -271,11 +271,13 @@ void initCommandBuffers() { .Dispatch(kNumParticles, 1, 1) .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(renderPipeline) .TransitionBufferUsage(bufferDst, nxt::BufferUsageBit::Vertex) .SetVertexBuffers(0, 1, &bufferDst, zeroOffsets) .SetVertexBuffers(1, 1, &modelBuffer, zeroOffsets) .DrawArrays(3, kNumParticles, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/HelloCompute.cpp b/examples/HelloCompute.cpp index ffebef97fa..0d3d58c896 100644 --- a/examples/HelloCompute.cpp +++ b/examples/HelloCompute.cpp @@ -132,10 +132,12 @@ void frame() { .Dispatch(1, 1, 1) .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(renderPipeline) .TransitionBufferUsage(buffer, nxt::BufferUsageBit::Uniform) .SetBindGroup(0, renderBindGroup) .DrawArrays(3, 1, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/HelloDepthStencil.cpp b/examples/HelloDepthStencil.cpp index 84d1e5e637..f376089a79 100644 --- a/examples/HelloDepthStencil.cpp +++ b/examples/HelloDepthStencil.cpp @@ -272,6 +272,7 @@ void frame() { nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(pipeline) .TransitionBufferUsage(cameraBuffer, nxt::BufferUsageBit::Uniform) .SetBindGroup(0, bindGroup[0]) @@ -288,6 +289,7 @@ void frame() { .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) .SetBindGroup(0, bindGroup[1]) .DrawElements(36, 1, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/HelloIndices.cpp b/examples/HelloIndices.cpp index 96ec0d0e0b..ac0223b699 100644 --- a/examples/HelloIndices.cpp +++ b/examples/HelloIndices.cpp @@ -83,10 +83,12 @@ void frame() { static const uint32_t vertexBufferOffsets[1] = {0}; nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(pipeline) .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) .SetIndexBuffer(indexBuffer, 0, nxt::IndexFormat::Uint32) .DrawElements(3, 1, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/HelloInstancing.cpp b/examples/HelloInstancing.cpp index f6b17de161..136ac218ea 100644 --- a/examples/HelloInstancing.cpp +++ b/examples/HelloInstancing.cpp @@ -89,10 +89,12 @@ void frame() { static const uint32_t vertexBufferOffsets[1] = {0}; nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(pipeline) .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) .SetVertexBuffers(1, 1, &instanceBuffer, vertexBufferOffsets) .DrawArrays(3, 4, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/HelloTriangle.cpp b/examples/HelloTriangle.cpp index 937b0d115d..7c69bf705b 100644 --- a/examples/HelloTriangle.cpp +++ b/examples/HelloTriangle.cpp @@ -144,11 +144,13 @@ void frame() { static const uint32_t vertexBufferOffsets[1] = {0}; nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(pipeline) .SetBindGroup(0, bindGroup) .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) .SetIndexBuffer(indexBuffer, 0, nxt::IndexFormat::Uint32) .DrawElements(3, 1, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/HelloUBO.cpp b/examples/HelloUBO.cpp index 26751d7b36..5ea5ac0b28 100644 --- a/examples/HelloUBO.cpp +++ b/examples/HelloUBO.cpp @@ -94,10 +94,12 @@ void frame() { nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(pipeline) .TransitionBufferUsage(buffer, nxt::BufferUsageBit::Uniform) .SetBindGroup(0, bindGroup) .DrawArrays(3, 1, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/HelloVertices.cpp b/examples/HelloVertices.cpp index 64c00ad036..ad5b7b8083 100644 --- a/examples/HelloVertices.cpp +++ b/examples/HelloVertices.cpp @@ -77,9 +77,11 @@ void frame() { static const uint32_t vertexBufferOffsets[1] = {0}; nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() .BeginRenderPass(renderpass, framebuffer) + .BeginRenderSubpass() .SetPipeline(pipeline) .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) .DrawArrays(3, 1, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/RenderToTexture.cpp b/examples/RenderToTexture.cpp index dfb36f99f9..1ceee3f874 100644 --- a/examples/RenderToTexture.cpp +++ b/examples/RenderToTexture.cpp @@ -187,17 +187,20 @@ void frame() { .BeginRenderPass(renderpass, framebuffer) // renderTarget is not transitioned here because it's implicit in // BeginRenderPass or AdvanceSubpass. - .SetPipeline(pipeline) - .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) - .DrawArrays(3, 1, 0, 0) - .AdvanceSubpass() + .BeginRenderSubpass() + .SetPipeline(pipeline) + .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) + .DrawArrays(3, 1, 0, 0) + .EndRenderSubpass() // renderTarget must be transitioned here because it's Sampled, not // ColorAttachment or InputAttachment. .TransitionTextureUsage(renderTarget, nxt::TextureUsageBit::Sampled) - .SetPipeline(pipelinePost) - .SetBindGroup(0, bindGroup) - .SetVertexBuffers(0, 1, &vertexBufferQuad, vertexBufferOffsets) - .DrawArrays(6, 1, 0, 0) + .BeginRenderSubpass() + .SetPipeline(pipelinePost) + .SetBindGroup(0, bindGroup) + .SetVertexBuffers(0, 1, &vertexBufferQuad, vertexBufferOffsets) + .DrawArrays(6, 1, 0, 0) + .EndRenderSubpass() .EndRenderPass() .GetResult(); diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp index 39337501c9..56189b4dfe 100644 --- a/examples/glTFViewer/glTFViewer.cpp +++ b/examples/glTFViewer/glTFViewer.cpp @@ -496,6 +496,7 @@ namespace { sizeof(u_transform_block) / sizeof(uint32_t), reinterpret_cast(&transforms)); cmd.BeginRenderPass(renderpass, framebuffer); + cmd.BeginRenderSubpass(); cmd.SetPipeline(material.pipeline); cmd.TransitionBufferUsage(material.uniformBuffer, nxt::BufferUsageBit::Uniform); cmd.SetBindGroup(0, material.bindGroup0); @@ -539,6 +540,7 @@ namespace { // DrawArrays cmd.DrawArrays(vertexCount, 1, 0, 0); } + cmd.EndRenderSubpass(); cmd.EndRenderPass(); } auto commands = cmd.GetResult(); diff --git a/next.json b/next.json index cab85a6ea0..718ed87197 100644 --- a/next.json +++ b/next.json @@ -255,10 +255,7 @@ ] }, { - "name": "advance subpass" - }, - { - "name": "end render pass" + "name": "begin render subpass" }, { "name": "copy buffer to buffer", @@ -343,6 +340,12 @@ {"name": "first instance", "type": "uint32_t"} ] }, + { + "name": "end render pass" + }, + { + "name": "end render subpass" + }, { "name": "set stencil reference", "args": [ diff --git a/src/backend/CommandBuffer.cpp b/src/backend/CommandBuffer.cpp index 17c55aee69..b182662128 100644 --- a/src/backend/CommandBuffer.cpp +++ b/src/backend/CommandBuffer.cpp @@ -105,18 +105,18 @@ namespace backend { Command type; while(commands->NextCommandId(&type)) { switch (type) { - case Command::AdvanceSubpass: - { - AdvanceSubpassCmd* cmd = commands->NextCommand(); - cmd->~AdvanceSubpassCmd(); - } - break; case Command::BeginRenderPass: { BeginRenderPassCmd* begin = commands->NextCommand(); begin->~BeginRenderPassCmd(); } break; + case Command::BeginRenderSubpass: + { + BeginRenderSubpassCmd* begin = commands->NextCommand(); + begin->~BeginRenderSubpassCmd(); + } + break; case Command::CopyBufferToBuffer: { CopyBufferToBufferCmd* copy = commands->NextCommand(); @@ -159,6 +159,12 @@ namespace backend { cmd->~EndRenderPassCmd(); } break; + case Command::EndRenderSubpass: + { + EndRenderSubpassCmd* cmd = commands->NextCommand(); + cmd->~EndRenderSubpassCmd(); + } + break; case Command::SetPipeline: { SetPipelineCmd* cmd = commands->NextCommand(); @@ -220,14 +226,14 @@ namespace backend { void SkipCommand(CommandIterator* commands, Command type) { switch (type) { - case Command::AdvanceSubpass: - commands->NextCommand(); - break; - case Command::BeginRenderPass: commands->NextCommand(); break; + case Command::BeginRenderSubpass: + commands->NextCommand(); + break; + case Command::CopyBufferToBuffer: commands->NextCommand(); break; @@ -256,6 +262,10 @@ namespace backend { commands->NextCommand(); break; + case Command::EndRenderSubpass: + commands->NextCommand(); + break; + case Command::SetPipeline: commands->NextCommand(); break; @@ -313,15 +323,6 @@ namespace backend { Command type; while (iterator.NextCommandId(&type)) { switch (type) { - case Command::AdvanceSubpass: - { - iterator.NextCommand(); - if (!state->AdvanceSubpass()) { - return false; - } - } - break; - case Command::BeginRenderPass: { BeginRenderPassCmd* cmd = iterator.NextCommand(); @@ -342,6 +343,15 @@ namespace backend { } break; + case Command::BeginRenderSubpass: + { + iterator.NextCommand(); + if (!state->BeginSubpass()) { + return false; + } + } + break; + case Command::CopyBufferToBuffer: { CopyBufferToBufferCmd* copy = iterator.NextCommand(); @@ -423,6 +433,15 @@ namespace backend { } break; + case Command::EndRenderSubpass: + { + iterator.NextCommand(); + if (!state->EndSubpass()) { + return false; + } + } + break; + case Command::SetPipeline: { SetPipelineCmd* cmd = iterator.NextCommand(); @@ -523,8 +542,8 @@ namespace backend { return device->CreateCommandBuffer(this); } - void CommandBufferBuilder::AdvanceSubpass() { - allocator.Allocate(Command::AdvanceSubpass); + void CommandBufferBuilder::BeginRenderSubpass() { + allocator.Allocate(Command::BeginRenderSubpass); } void CommandBufferBuilder::BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer) { @@ -608,6 +627,10 @@ namespace backend { allocator.Allocate(Command::EndRenderPass); } + void CommandBufferBuilder::EndRenderSubpass() { + allocator.Allocate(Command::EndRenderSubpass); + } + void CommandBufferBuilder::SetPipeline(PipelineBase* pipeline) { SetPipelineCmd* cmd = allocator.Allocate(Command::SetPipeline); new(cmd) SetPipelineCmd; diff --git a/src/backend/CommandBuffer.h b/src/backend/CommandBuffer.h index adc5be7531..4b0c90def2 100644 --- a/src/backend/CommandBuffer.h +++ b/src/backend/CommandBuffer.h @@ -59,8 +59,8 @@ namespace backend { CommandIterator AcquireCommands(); // NXT API - void AdvanceSubpass(); void BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer); + void BeginRenderSubpass(); void CopyBufferToBuffer(BufferBase* source, uint32_t sourceOffset, BufferBase* destination, uint32_t destinationOffset, uint32_t size); void CopyBufferToTexture(BufferBase* buffer, uint32_t bufferOffset, TextureBase* texture, uint32_t x, uint32_t y, uint32_t z, @@ -72,6 +72,7 @@ namespace backend { void DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); void DrawElements(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t firstInstance); void EndRenderPass(); + void EndRenderSubpass(); void SetPushConstants(nxt::ShaderStageBit stage, uint32_t offset, uint32_t count, const void* data); void SetPipeline(PipelineBase* pipeline); void SetStencilReference(uint32_t reference); diff --git a/src/backend/CommandBufferStateTracker.cpp b/src/backend/CommandBufferStateTracker.cpp index 45e5ba2523..535700f877 100644 --- a/src/backend/CommandBufferStateTracker.cpp +++ b/src/backend/CommandBufferStateTracker.cpp @@ -126,7 +126,7 @@ namespace backend { builder->HandleError("Can't begin a subpass without an active render pass"); return false; } - if (subpassActive) { + if (aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) { builder->HandleError("Can't begin a subpass without ending the previous subpass"); return false; } @@ -159,19 +159,16 @@ namespace backend { texturesTransitioned.insert(texture); } - subpassActive = true; + aspects.set(VALIDATION_ASPECT_RENDER_SUBPASS); return true; }; bool CommandBufferStateTracker::EndSubpass() { - if (currentRenderPass == nullptr) { - builder->HandleError("Can't end a subpass without an active render pass"); - return false; - } - if (!subpassActive) { + if (!aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) { builder->HandleError("Can't end a subpass without beginning one"); return false; } + ASSERT(currentRenderPass != nullptr); auto& subpassInfo = currentRenderPass->GetSubpassInfo(currentSubpass); for (auto location : IterateBitSet(subpassInfo.colorAttachmentsSet)) { @@ -194,7 +191,7 @@ namespace backend { } currentSubpass += 1; - subpassActive = false; + aspects.reset(VALIDATION_ASPECT_RENDER_SUBPASS); UnsetPipeline(); return true; }; @@ -204,6 +201,7 @@ namespace backend { builder->HandleError("A render pass is already active"); return false; } + ASSERT(!aspects[VALIDATION_ASPECT_RENDER_SUBPASS]); if (!framebuffer->GetRenderPass()->IsCompatibleWith(renderPass)) { builder->HandleError("Framebuffer is incompatible with this render pass"); return false; @@ -212,32 +210,17 @@ namespace backend { currentRenderPass = renderPass; currentFramebuffer = framebuffer; currentSubpass = 0; - subpassActive = false; - - // TODO(kainino@chromium.org): remove this when AdvanceSubpass is removed. - if (!BeginSubpass()) { - return false; - } UnsetPipeline(); return true; } - bool CommandBufferStateTracker::AdvanceSubpass() { - // TODO(kainino@chromium.org): remove this function when AdvanceSubpass is removed. - return EndSubpass() && BeginSubpass(); - } - bool CommandBufferStateTracker::EndRenderPass() { if (currentRenderPass == nullptr) { builder->HandleError("No render pass is currently active"); return false; } - // TODO(kainino@chromium.org): remove this when AdvanceSubpass is removed. - if (!EndSubpass()) { - return false; - } - if (subpassActive) { + if (aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) { builder->HandleError("Can't end a render pass while a subpass is active"); return false; } @@ -261,8 +244,8 @@ namespace backend { } aspects.set(VALIDATION_ASPECT_COMPUTE_PIPELINE); } else { - if (!currentRenderPass) { - builder->HandleError("A render pass must be active when a render pipeline is set"); + if (!aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) { + builder->HandleError("A render subpass must be active when a render pipeline is set"); return false; } if (!pipeline->GetRenderPass()->IsCompatibleWith(currentRenderPass)) { @@ -504,7 +487,12 @@ namespace backend { } void CommandBufferStateTracker::UnsetPipeline() { - // All of the aspects (currently) are pipeline-dependent. - aspects.reset(); + constexpr ValidationAspects pipelineDependentAspectsInverse = + ~(1 << VALIDATION_ASPECT_RENDER_PIPELINE | + 1 << VALIDATION_ASPECT_COMPUTE_PIPELINE | + 1 << VALIDATION_ASPECT_BIND_GROUPS | + 1 << VALIDATION_ASPECT_VERTEX_BUFFERS | + 1 << VALIDATION_ASPECT_INDEX_BUFFER); + aspects &= pipelineDependentAspectsInverse; } } diff --git a/src/backend/CommandBufferStateTracker.h b/src/backend/CommandBufferStateTracker.h index 290596ea72..2e2a4f2a76 100644 --- a/src/backend/CommandBufferStateTracker.h +++ b/src/backend/CommandBufferStateTracker.h @@ -41,7 +41,6 @@ namespace backend { bool BeginSubpass(); bool EndSubpass(); bool BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer); - bool AdvanceSubpass(); bool EndRenderPass(); bool SetPipeline(PipelineBase* pipeline); bool SetBindGroup(uint32_t index, BindGroupBase* bindgroup); @@ -63,6 +62,7 @@ namespace backend { VALIDATION_ASPECT_BIND_GROUPS, VALIDATION_ASPECT_VERTEX_BUFFERS, VALIDATION_ASPECT_INDEX_BUFFER, + VALIDATION_ASPECT_RENDER_SUBPASS, VALIDATION_ASPECT_COUNT }; @@ -96,7 +96,6 @@ namespace backend { RenderPassBase* currentRenderPass = nullptr; FramebufferBase* currentFramebuffer = nullptr; - bool subpassActive = false; uint32_t currentSubpass = 0; }; } diff --git a/src/backend/Commands.h b/src/backend/Commands.h index c02d955bc8..3e3839cbb3 100644 --- a/src/backend/Commands.h +++ b/src/backend/Commands.h @@ -28,8 +28,8 @@ namespace backend { // dependencies: Ref needs Object to be defined. enum class Command { - AdvanceSubpass, BeginRenderPass, + BeginRenderSubpass, CopyBufferToBuffer, CopyBufferToTexture, CopyTextureToBuffer, @@ -37,6 +37,7 @@ namespace backend { DrawArrays, DrawElements, EndRenderPass, + EndRenderSubpass, SetPipeline, SetPushConstants, SetStencilReference, @@ -47,14 +48,14 @@ namespace backend { TransitionTextureUsage, }; - struct AdvanceSubpassCmd { - }; - struct BeginRenderPassCmd { Ref renderPass; Ref framebuffer; }; + struct BeginRenderSubpassCmd { + }; + struct BufferCopyLocation { Ref buffer; uint32_t offset; @@ -106,6 +107,9 @@ namespace backend { struct EndRenderPassCmd { }; + struct EndRenderSubpassCmd { + }; + struct SetPipelineCmd { Ref pipeline; }; diff --git a/src/backend/d3d12/CommandBufferD3D12.cpp b/src/backend/d3d12/CommandBufferD3D12.cpp index e4197e7e9a..cce134e9f7 100644 --- a/src/backend/d3d12/CommandBufferD3D12.cpp +++ b/src/backend/d3d12/CommandBufferD3D12.cpp @@ -253,12 +253,6 @@ namespace d3d12 { while(commands.NextCommandId(&type)) { switch (type) { - case Command::AdvanceSubpass: - { - commands.NextCommand(); - } - break; - case Command::BeginRenderPass: { BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand(); @@ -275,6 +269,12 @@ namespace d3d12 { } break; + case Command::BeginRenderSubpass: + { + commands.NextCommand(); + } + break; + case Command::CopyBufferToBuffer: { CopyBufferToBufferCmd* copy = commands.NextCommand(); @@ -371,6 +371,12 @@ namespace d3d12 { } break; + case Command::EndRenderSubpass: + { + commands.NextCommand(); + } + break; + case Command::SetPipeline: { SetPipelineCmd* cmd = commands.NextCommand(); diff --git a/src/backend/metal/CommandBufferMTL.mm b/src/backend/metal/CommandBufferMTL.mm index 24fbdd432b..dd4cc37964 100644 --- a/src/backend/metal/CommandBufferMTL.mm +++ b/src/backend/metal/CommandBufferMTL.mm @@ -141,14 +141,6 @@ namespace metal { uint32_t currentSubpass = 0; while (commands.NextCommandId(&type)) { switch (type) { - case Command::AdvanceSubpass: - { - commands.NextCommand(); - currentSubpass += 1; - encoders.BeginSubpass(commandBuffer, currentSubpass); - } - break; - case Command::BeginRenderPass: { BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand(); @@ -156,6 +148,12 @@ namespace metal { encoders.currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get()); encoders.FinishEncoders(); currentSubpass = 0; + } + break; + + case Command::BeginRenderSubpass: + { + commands.NextCommand(); encoders.BeginSubpass(commandBuffer, currentSubpass); } break; @@ -291,6 +289,13 @@ namespace metal { } break; + case Command::EndRenderSubpass: + { + commands.NextCommand(); + currentSubpass += 1; + } + break; + case Command::SetPipeline: { SetPipelineCmd* cmd = commands.NextCommand(); diff --git a/src/backend/opengl/CommandBufferGL.cpp b/src/backend/opengl/CommandBufferGL.cpp index 485035c856..0de3e55518 100644 --- a/src/backend/opengl/CommandBufferGL.cpp +++ b/src/backend/opengl/CommandBufferGL.cpp @@ -65,16 +65,16 @@ namespace opengl { while(commands.NextCommandId(&type)) { switch (type) { - case Command::AdvanceSubpass: + case Command::BeginRenderPass: { - commands.NextCommand(); + commands.NextCommand(); // TODO(kainino@chromium.org): implement } break; - case Command::BeginRenderPass: + case Command::BeginRenderSubpass: { - commands.NextCommand(); + commands.NextCommand(); // TODO(kainino@chromium.org): implement } break; @@ -173,6 +173,13 @@ namespace opengl { } break; + case Command::EndRenderSubpass: + { + commands.NextCommand(); + // TODO(kainino@chromium.org): implement + } + break; + case Command::SetPipeline: { SetPipelineCmd* cmd = commands.NextCommand();