Remove deferred BufferLocation updates for drawIndexedIndirect Instead of using BufferLocation as another layer of indirection, the indirectBuffer can be set directly on the indirect command. This makes the indirect validation a bit simpler, but introduces additional lifetime dependencies in that the indirect draw validation MUST be encoded while the DrawIndexedIndirectCmds it references are still valid. Bug: dawn:809 Change-Id: I1ef084622d8737ad5ec1b0247bf9062712e35008 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/67241 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn index 979c7c4..cfea707 100644 --- a/src/dawn_native/BUILD.gn +++ b/src/dawn_native/BUILD.gn
@@ -205,8 +205,6 @@ "BuddyMemoryAllocator.h", "Buffer.cpp", "Buffer.h", - "BufferLocation.cpp", - "BufferLocation.h", "CachedObject.cpp", "CachedObject.h", "CallbackTaskManager.cpp",
diff --git a/src/dawn_native/BufferLocation.cpp b/src/dawn_native/BufferLocation.cpp deleted file mode 100644 index 5ee24f2..0000000 --- a/src/dawn_native/BufferLocation.cpp +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2021 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 "dawn_native/BufferLocation.h" - -namespace dawn_native { - - BufferLocation::BufferLocation() = default; - - BufferLocation::BufferLocation(BufferBase* buffer, uint64_t offset) - : mBuffer(buffer), mOffset(offset) { - } - - BufferLocation::~BufferLocation() = default; - - // static - Ref<BufferLocation> BufferLocation::New() { - return AcquireRef(new BufferLocation()); - } - - // static - Ref<BufferLocation> BufferLocation::New(BufferBase* buffer, uint64_t offset) { - return AcquireRef(new BufferLocation(buffer, offset)); - } - - bool BufferLocation::IsNull() const { - return mBuffer.Get() == nullptr; - } - - BufferBase* BufferLocation::GetBuffer() const { - return mBuffer.Get(); - } - - uint64_t BufferLocation::GetOffset() const { - return mOffset; - } - - void BufferLocation::Set(BufferBase* buffer, uint64_t offset) { - mBuffer = buffer; - mOffset = offset; - } - -} // namespace dawn_native
diff --git a/src/dawn_native/BufferLocation.h b/src/dawn_native/BufferLocation.h deleted file mode 100644 index 4ff733d..0000000 --- a/src/dawn_native/BufferLocation.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2021 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. - -#ifndef DAWNNATIVE_BUFFERLOCATION_H_ -#define DAWNNATIVE_BUFFERLOCATION_H_ - -#include "common/RefCounted.h" -#include "dawn_native/Buffer.h" - -#include <cstdint> - -namespace dawn_native { - - // A ref-counted wrapper around a Buffer ref and an offset into the buffer. - class BufferLocation : public RefCounted { - public: - BufferLocation(); - BufferLocation(BufferBase* buffer, uint64_t offset = 0); - ~BufferLocation(); - - static Ref<BufferLocation> New(); - static Ref<BufferLocation> New(BufferBase* buffer, uint64_t offset = 0); - - bool IsNull() const; - - BufferBase* GetBuffer() const; - uint64_t GetOffset() const; - - void Set(BufferBase* buffer, uint64_t offset); - - private: - Ref<BufferBase> mBuffer; - uint64_t mOffset = 0; - }; - -} // namespace dawn_native - -#endif // DAWNNATIVE_BUFFERLOCATION_H_
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt index 6b90e2c..2c2ead4 100644 --- a/src/dawn_native/CMakeLists.txt +++ b/src/dawn_native/CMakeLists.txt
@@ -50,8 +50,6 @@ "BuddyMemoryAllocator.h" "Buffer.cpp" "Buffer.h" - "BufferLocation.cpp" - "BufferLocation.h" "CachedObject.cpp" "CachedObject.h" "CallbackTaskManager.cpp"
diff --git a/src/dawn_native/CommandBuffer.cpp b/src/dawn_native/CommandBuffer.cpp index a964f40..3fadb1a 100644 --- a/src/dawn_native/CommandBuffer.cpp +++ b/src/dawn_native/CommandBuffer.cpp
@@ -39,14 +39,6 @@ Destroy(); } - void CommandBufferBase::DoNextSetValidatedBufferLocationsInternal() { - SetValidatedBufferLocationsInternalCmd* cmd = - mCommands.NextCommand<SetValidatedBufferLocationsInternalCmd>(); - for (const DeferredBufferLocationUpdate& update : cmd->updates) { - update.location->Set(update.buffer.Get(), update.offset); - } - } - // static CommandBufferBase* CommandBufferBase::MakeError(DeviceBase* device) { return new CommandBufferBase(device, ObjectBase::kError);
diff --git a/src/dawn_native/CommandBuffer.h b/src/dawn_native/CommandBuffer.h index c6d47ae..023208b 100644 --- a/src/dawn_native/CommandBuffer.h +++ b/src/dawn_native/CommandBuffer.h
@@ -48,8 +48,6 @@ protected: ~CommandBufferBase() override; - void DoNextSetValidatedBufferLocationsInternal(); - CommandIterator mCommands; private:
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp index c9510d0..153ef7b 100644 --- a/src/dawn_native/CommandEncoder.cpp +++ b/src/dawn_native/CommandEncoder.cpp
@@ -1018,18 +1018,6 @@ return commandBuffer.Detach(); } - void CommandEncoder::EncodeSetValidatedBufferLocationsInternal( - std::vector<DeferredBufferLocationUpdate> updates) { - ASSERT(GetDevice()->IsValidationEnabled()); - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - SetValidatedBufferLocationsInternalCmd* cmd = - allocator->Allocate<SetValidatedBufferLocationsInternalCmd>( - Command::SetValidatedBufferLocationsInternal); - cmd->updates = std::move(updates); - return {}; - }); - } - ResultOrError<Ref<CommandBufferBase>> CommandEncoder::FinishInternal( const CommandBufferDescriptor* descriptor) { DeviceBase* device = GetDevice();
diff --git a/src/dawn_native/CommandEncoder.h b/src/dawn_native/CommandEncoder.h index 6547e7d..d390d70 100644 --- a/src/dawn_native/CommandEncoder.h +++ b/src/dawn_native/CommandEncoder.h
@@ -78,9 +78,6 @@ CommandBufferBase* APIFinish(const CommandBufferDescriptor* descriptor = nullptr); - void EncodeSetValidatedBufferLocationsInternal( - std::vector<DeferredBufferLocationUpdate> updates); - private: ResultOrError<Ref<CommandBufferBase>> FinishInternal( const CommandBufferDescriptor* descriptor);
diff --git a/src/dawn_native/Commands.cpp b/src/dawn_native/Commands.cpp index ea122e7..c2bd0dd 100644 --- a/src/dawn_native/Commands.cpp +++ b/src/dawn_native/Commands.cpp
@@ -158,12 +158,6 @@ cmd->~SetStencilReferenceCmd(); break; } - case Command::SetValidatedBufferLocationsInternal: { - SetValidatedBufferLocationsInternalCmd* cmd = - commands->NextCommand<SetValidatedBufferLocationsInternalCmd>(); - cmd->~SetValidatedBufferLocationsInternalCmd(); - break; - } case Command::SetViewport: { SetViewportCmd* cmd = commands->NextCommand<SetViewportCmd>(); cmd->~SetViewportCmd(); @@ -319,10 +313,6 @@ commands->NextCommand<SetStencilReferenceCmd>(); break; - case Command::SetValidatedBufferLocationsInternal: - commands->NextCommand<SetValidatedBufferLocationsInternalCmd>(); - break; - case Command::SetViewport: commands->NextCommand<SetViewportCmd>(); break;
diff --git a/src/dawn_native/Commands.h b/src/dawn_native/Commands.h index 09acd10..cee9bbd 100644 --- a/src/dawn_native/Commands.h +++ b/src/dawn_native/Commands.h
@@ -19,7 +19,6 @@ #include "dawn_native/AttachmentState.h" #include "dawn_native/BindingInfo.h" -#include "dawn_native/BufferLocation.h" #include "dawn_native/Texture.h" #include "dawn_native/dawn_platform.h" @@ -63,7 +62,6 @@ SetBlendConstant, SetBindGroup, SetIndexBuffer, - SetValidatedBufferLocationsInternal, SetVertexBuffer, WriteBuffer, WriteTimestamp, @@ -179,7 +177,8 @@ }; struct DrawIndexedIndirectCmd { - Ref<BufferLocation> indirectBufferLocation; + Ref<BufferBase> indirectBuffer; + uint64_t indirectOffset; }; struct EndComputePassCmd {}; @@ -225,16 +224,6 @@ uint32_t reference; }; - struct DeferredBufferLocationUpdate { - Ref<BufferLocation> location; - Ref<BufferBase> buffer; - uint64_t offset; - }; - - struct SetValidatedBufferLocationsInternalCmd { - std::vector<DeferredBufferLocationUpdate> updates; - }; - struct SetViewportCmd { float x, y, width, height, minDepth, maxDepth; };
diff --git a/src/dawn_native/IndirectDrawMetadata.cpp b/src/dawn_native/IndirectDrawMetadata.cpp index e150d78..9d514f3 100644 --- a/src/dawn_native/IndirectDrawMetadata.cpp +++ b/src/dawn_native/IndirectDrawMetadata.cpp
@@ -159,12 +159,11 @@ } } - void IndirectDrawMetadata::AddIndexedIndirectDraw( - wgpu::IndexFormat indexFormat, - uint64_t indexBufferSize, - BufferBase* indirectBuffer, - uint64_t indirectOffset, - BufferLocation* drawCmdIndirectBufferLocation) { + void IndirectDrawMetadata::AddIndexedIndirectDraw(wgpu::IndexFormat indexFormat, + uint64_t indexBufferSize, + BufferBase* indirectBuffer, + uint64_t indirectOffset, + DrawIndexedIndirectCmd* cmd) { uint64_t numIndexBufferElements; switch (indexFormat) { case wgpu::IndexFormat::Uint16: @@ -187,7 +186,7 @@ IndexedIndirectDraw draw; draw.clientBufferOffset = indirectOffset; - draw.bufferLocation = drawCmdIndirectBufferLocation; + draw.cmd = cmd; it->second.AddIndexedIndirectDraw(mMaxDrawCallsPerBatch, mMaxBatchOffsetRange, std::move(draw)); }
diff --git a/src/dawn_native/IndirectDrawMetadata.h b/src/dawn_native/IndirectDrawMetadata.h index f55f3d3..e652750 100644 --- a/src/dawn_native/IndirectDrawMetadata.h +++ b/src/dawn_native/IndirectDrawMetadata.h
@@ -18,7 +18,6 @@ #include "common/NonCopyable.h" #include "common/RefCounted.h" #include "dawn_native/Buffer.h" -#include "dawn_native/BufferLocation.h" #include "dawn_native/CommandBufferStateTracker.h" #include "dawn_native/Commands.h" @@ -45,7 +44,10 @@ public: struct IndexedIndirectDraw { uint64_t clientBufferOffset; - Ref<BufferLocation> bufferLocation; + // This is a pointer to the command that should be populated with the validated + // indirect scratch buffer. It is only valid up until the encoded command buffer + // is submitted. + DrawIndexedIndirectCmd* cmd; }; struct IndexedIndirectValidationBatch { @@ -109,7 +111,7 @@ uint64_t indexBufferSize, BufferBase* indirectBuffer, uint64_t indirectOffset, - BufferLocation* drawCmdIndirectBufferLocation); + DrawIndexedIndirectCmd* cmd); private: IndexedIndirectBufferValidationInfoMap mIndexedIndirectBufferValidationInfo;
diff --git a/src/dawn_native/IndirectDrawValidationEncoder.cpp b/src/dawn_native/IndirectDrawValidationEncoder.cpp index 1eba1ba..02cef8e 100644 --- a/src/dawn_native/IndirectDrawValidationEncoder.cpp +++ b/src/dawn_native/IndirectDrawValidationEncoder.cpp
@@ -226,7 +226,6 @@ // single pass as possible. Batches can be grouped together as long as they're validating // data from the same indirect buffer, but they may still be split into multiple passes if // the number of draw calls in a pass would exceed some (very high) upper bound. - uint64_t numTotalDrawCalls = 0; size_t validatedParamsSize = 0; std::vector<Pass> passes; IndirectDrawMetadata::IndexedIndirectBufferValidationInfoMap& bufferInfoMap = @@ -257,7 +256,6 @@ newBatch.clientIndirectOffset = minOffsetAlignedDown; newBatch.clientIndirectSize = batch.maxOffset + kDrawIndexedIndirectSize - minOffsetAlignedDown; - numTotalDrawCalls += batch.draws.size(); newBatch.validatedParamsSize = batch.draws.size() * kDrawIndexedIndirectSize; newBatch.validatedParamsOffset = @@ -306,10 +304,7 @@ DAWN_TRY(validatedParamsBuffer.EnsureCapacity(validatedParamsSize)); usageTracker->BufferUsedAs(validatedParamsBuffer.GetBuffer(), wgpu::BufferUsage::Indirect); - // Now we allocate and populate host-side batch data to be copied to the GPU, and prepare to - // update all DrawIndexedIndirectCmd buffer references. - std::vector<DeferredBufferLocationUpdate> deferredBufferLocationUpdates; - deferredBufferLocationUpdates.reserve(numTotalDrawCalls); + // Now we allocate and populate host-side batch data to be copied to the GPU. for (Pass& pass : passes) { // We use std::malloc here because it guarantees maximal scalar alignment. pass.batchData = {std::malloc(pass.batchDataSize), std::free}; @@ -322,16 +317,13 @@ uint32_t* indirectOffsets = reinterpret_cast<uint32_t*>(batch.batchInfo + 1); uint64_t validatedParamsOffset = batch.validatedParamsOffset; - for (const auto& draw : batch.metadata->draws) { + for (auto& draw : batch.metadata->draws) { // The shader uses this to index an array of u32, hence the division by 4 bytes. *indirectOffsets++ = static_cast<uint32_t>( (draw.clientBufferOffset - batch.clientIndirectOffset) / 4); - DeferredBufferLocationUpdate deferredUpdate; - deferredUpdate.location = draw.bufferLocation; - deferredUpdate.buffer = validatedParamsBuffer.GetBuffer(); - deferredUpdate.offset = validatedParamsOffset; - deferredBufferLocationUpdates.push_back(std::move(deferredUpdate)); + draw.cmd->indirectBuffer = validatedParamsBuffer.GetBuffer(); + draw.cmd->indirectOffset = validatedParamsOffset; validatedParamsOffset += kDrawIndexedIndirectSize; } @@ -364,8 +356,6 @@ // Finally, we can now encode our validation passes. Each pass first does a single // WriteBuffer to get batch data over to the GPU, followed by a single compute pass. The // compute pass encodes a separate SetBindGroup and Dispatch command for each batch. - commandEncoder->EncodeSetValidatedBufferLocationsInternal( - std::move(deferredBufferLocationUpdates)); for (const Pass& pass : passes) { commandEncoder->APIWriteBuffer(batchDataBuffer.GetBuffer(), 0, static_cast<const uint8_t*>(pass.batchData.get()),
diff --git a/src/dawn_native/RenderEncoderBase.cpp b/src/dawn_native/RenderEncoderBase.cpp index a8ef2ff..f2a8dce 100644 --- a/src/dawn_native/RenderEncoderBase.cpp +++ b/src/dawn_native/RenderEncoderBase.cpp
@@ -17,7 +17,6 @@ #include "common/Constants.h" #include "common/Log.h" #include "dawn_native/Buffer.h" -#include "dawn_native/BufferLocation.h" #include "dawn_native/CommandEncoder.h" #include "dawn_native/CommandValidation.h" #include "dawn_native/Commands.h" @@ -198,14 +197,20 @@ DrawIndexedIndirectCmd* cmd = allocator->Allocate<DrawIndexedIndirectCmd>(Command::DrawIndexedIndirect); if (IsValidationEnabled()) { - cmd->indirectBufferLocation = BufferLocation::New(); + // Later, EncodeIndirectDrawValidationCommands will allocate a scratch storage + // buffer which will store the validated indirect data. The buffer and offset + // will be updated to point to it. + // |EncodeIndirectDrawValidationCommands| is called at the end of encoding the + // render pass, while the |cmd| pointer is still valid. + cmd->indirectBuffer = nullptr; + mIndirectDrawMetadata.AddIndexedIndirectDraw( mCommandBufferState.GetIndexFormat(), mCommandBufferState.GetIndexBufferSize(), indirectBuffer, indirectOffset, - cmd->indirectBufferLocation.Get()); + cmd); } else { - cmd->indirectBufferLocation = - BufferLocation::New(indirectBuffer, indirectOffset); + cmd->indirectBuffer = indirectBuffer; + cmd->indirectOffset = indirectOffset; } // TODO(crbug.com/dawn/1166): Adding the indirectBuffer is needed for correct usage
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index e7d12a5..445c781 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -993,10 +993,6 @@ break; } - case Command::SetValidatedBufferLocationsInternal: - DoNextSetValidatedBufferLocationsInternal(); - break; - case Command::WriteBuffer: { WriteBufferCmd* write = mCommands.NextCommand<WriteBufferCmd>(); const uint64_t offset = write->offset; @@ -1414,7 +1410,6 @@ case Command::DrawIndexedIndirect: { DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>(); - ASSERT(!draw->indirectBufferLocation->IsNull()); DAWN_TRY(bindingTracker->Apply(commandContext)); vertexBufferTracker.Apply(commandList, lastPipeline); @@ -1423,12 +1418,13 @@ // Zero the index offset values to avoid reusing values from the previous draw RecordFirstIndexOffset(commandList, lastPipeline, 0, 0); - Buffer* buffer = ToBackend(draw->indirectBufferLocation->GetBuffer()); + Buffer* buffer = ToBackend(draw->indirectBuffer.Get()); + ASSERT(buffer != nullptr); + ComPtr<ID3D12CommandSignature> signature = ToBackend(GetDevice())->GetDrawIndexedIndirectSignature(); commandList->ExecuteIndirect(signature.Get(), 1, buffer->GetD3D12Resource(), - draw->indirectBufferLocation->GetOffset(), nullptr, - 0); + draw->indirectOffset, nullptr, 0); break; }
diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm index cacefa0..f1be722 100644 --- a/src/dawn_native/metal/CommandBufferMTL.mm +++ b/src/dawn_native/metal/CommandBufferMTL.mm
@@ -986,10 +986,6 @@ break; } - case Command::SetValidatedBufferLocationsInternal: - DoNextSetValidatedBufferLocationsInternal(); - break; - case Command::WriteBuffer: { WriteBufferCmd* write = mCommands.NextCommand<WriteBufferCmd>(); const uint64_t offset = write->offset; @@ -1341,15 +1337,16 @@ bindGroups.Apply(encoder); storageBufferLengths.Apply(encoder, lastPipeline, enableVertexPulling); - ASSERT(!draw->indirectBufferLocation->IsNull()); - Buffer* buffer = ToBackend(draw->indirectBufferLocation->GetBuffer()); + Buffer* buffer = ToBackend(draw->indirectBuffer.Get()); + ASSERT(buffer != nullptr); + id<MTLBuffer> indirectBuffer = buffer->GetMTLBuffer(); [encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology() indexType:indexBufferType indexBuffer:indexBuffer indexBufferOffset:indexBufferBaseOffset indirectBuffer:indirectBuffer - indirectBufferOffset:draw->indirectBufferLocation->GetOffset()]; + indirectBufferOffset:draw->indirectOffset]; break; }
diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index b34935a..f6b80ab 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -844,10 +844,6 @@ break; } - case Command::SetValidatedBufferLocationsInternal: - DoNextSetValidatedBufferLocationsInternal(); - break; - case Command::WriteBuffer: { WriteBufferCmd* write = mCommands.NextCommand<WriteBufferCmd>(); uint64_t offset = write->offset; @@ -1187,17 +1183,17 @@ case Command::DrawIndexedIndirect: { DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>(); - ASSERT(!draw->indirectBufferLocation->IsNull()); vertexStateBufferBindingTracker.Apply(gl); bindGroupTracker.Apply(gl); - Buffer* indirectBuffer = ToBackend(draw->indirectBufferLocation->GetBuffer()); + Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get()); + ASSERT(indirectBuffer != nullptr); + gl.BindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle()); gl.DrawElementsIndirect( lastPipeline->GetGLPrimitiveTopology(), indexBufferFormat, - reinterpret_cast<void*>( - static_cast<intptr_t>(draw->indirectBufferLocation->GetOffset()))); + reinterpret_cast<void*>(static_cast<intptr_t>(draw->indirectOffset))); break; }
diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index 30fd55e..cfcdb36 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp
@@ -826,10 +826,6 @@ break; } - case Command::SetValidatedBufferLocationsInternal: - DoNextSetValidatedBufferLocationsInternal(); - break; - case Command::WriteBuffer: { WriteBufferCmd* write = mCommands.NextCommand<WriteBufferCmd>(); const uint64_t offset = write->offset; @@ -1075,10 +1071,10 @@ case Command::DrawIndirect: { DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>(); - VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle(); + Buffer* buffer = ToBackend(draw->indirectBuffer.Get()); descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS); - device->fn.CmdDrawIndirect(commands, indirectBuffer, + device->fn.CmdDrawIndirect(commands, buffer->GetHandle(), static_cast<VkDeviceSize>(draw->indirectOffset), 1, 0); break; @@ -1086,14 +1082,13 @@ case Command::DrawIndexedIndirect: { DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>(); - ASSERT(!draw->indirectBufferLocation->IsNull()); - VkBuffer indirectBuffer = - ToBackend(draw->indirectBufferLocation->GetBuffer())->GetHandle(); + Buffer* buffer = ToBackend(draw->indirectBuffer.Get()); + ASSERT(buffer != nullptr); descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS); device->fn.CmdDrawIndexedIndirect( - commands, indirectBuffer, - static_cast<VkDeviceSize>(draw->indirectBufferLocation->GetOffset()), 1, 0); + commands, buffer->GetHandle(), + static_cast<VkDeviceSize>(draw->indirectOffset), 1, 0); break; }