1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "VkCommandBuffer.hpp"
16 #include "VkBuffer.hpp"
17 #include "VkEvent.hpp"
18 #include "VkFramebuffer.hpp"
19 #include "VkImage.hpp"
20 #include "VkImageView.hpp"
21 #include "VkPipeline.hpp"
22 #include "VkPipelineLayout.hpp"
23 #include "VkRenderPass.hpp"
24 #include "Device/Renderer.hpp"
31 class CommandBuffer::Command
34 // FIXME (b/119421344): change the commandBuffer argument to a CommandBuffer state
35 virtual void play(CommandBuffer::ExecutionState& executionState) = 0;
39 class BeginRenderPass : public CommandBuffer::Command
42 BeginRenderPass(VkRenderPass renderPass, VkFramebuffer framebuffer, VkRect2D renderArea,
43 uint32_t clearValueCount, const VkClearValue* pClearValues) :
44 renderPass(Cast(renderPass)), framebuffer(Cast(framebuffer)), renderArea(renderArea),
45 clearValueCount(clearValueCount)
47 // FIXME (b/119409619): use an allocator here so we can control all memory allocations
48 clearValues = new VkClearValue[clearValueCount];
49 memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue));
52 ~BeginRenderPass() override
54 delete [] clearValues;
58 void play(CommandBuffer::ExecutionState& executionState) override
60 executionState.renderPass = renderPass;
61 executionState.renderPassFramebuffer = framebuffer;
63 framebuffer->clear(executionState.renderPass, clearValueCount, clearValues, renderArea);
67 RenderPass* renderPass;
68 Framebuffer* framebuffer;
70 uint32_t clearValueCount;
71 VkClearValue* clearValues;
74 class NextSubpass : public CommandBuffer::Command
82 void play(CommandBuffer::ExecutionState& executionState) override
84 bool hasResolveAttachments = (executionState.renderPass->getCurrentSubpass().pResolveAttachments != nullptr);
85 if(hasResolveAttachments)
87 // FIXME(sugoi): remove the following lines and resolve in Renderer::finishRendering()
88 // for a Draw command or after the last command of the current subpass
89 // which modifies pixels.
90 executionState.renderer->synchronize();
91 executionState.renderPassFramebuffer->resolve(executionState.renderPass);
94 executionState.renderPass->nextSubpass();
100 class EndRenderPass : public CommandBuffer::Command
108 void play(CommandBuffer::ExecutionState& executionState) override
110 // Execute (implicit or explicit) VkSubpassDependency to VK_SUBPASS_EXTERNAL
111 // This is somewhat heavier than the actual ordering required.
112 executionState.renderer->synchronize();
114 // FIXME(sugoi): remove the following line and resolve in Renderer::finishRendering()
115 // for a Draw command or after the last command of the current subpass
116 // which modifies pixels.
117 executionState.renderPassFramebuffer->resolve(executionState.renderPass);
119 executionState.renderPass->end();
120 executionState.renderPass = nullptr;
121 executionState.renderPassFramebuffer = nullptr;
127 class ExecuteCommands : public CommandBuffer::Command
130 ExecuteCommands(const VkCommandBuffer& commandBuffer) : commandBuffer(commandBuffer)
135 void play(CommandBuffer::ExecutionState& executionState) override
137 Cast(commandBuffer)->submitSecondary(executionState);
141 const VkCommandBuffer commandBuffer;
144 class PipelineBind : public CommandBuffer::Command
147 PipelineBind(VkPipelineBindPoint pPipelineBindPoint, VkPipeline pPipeline) :
148 pipelineBindPoint(pPipelineBindPoint), pipeline(pPipeline)
153 void play(CommandBuffer::ExecutionState& executionState) override
155 executionState.pipelines[pipelineBindPoint] = Cast(pipeline);
159 VkPipelineBindPoint pipelineBindPoint;
163 class Dispatch : public CommandBuffer::Command
166 Dispatch(uint32_t pGroupCountX, uint32_t pGroupCountY, uint32_t pGroupCountZ) :
167 groupCountX(pGroupCountX), groupCountY(pGroupCountY), groupCountZ(pGroupCountZ)
172 void play(CommandBuffer::ExecutionState& executionState) override
174 ComputePipeline* pipeline = static_cast<ComputePipeline*>(
175 executionState.pipelines[VK_PIPELINE_BIND_POINT_COMPUTE]);
176 pipeline->run(groupCountX, groupCountY, groupCountZ,
177 MAX_BOUND_DESCRIPTOR_SETS,
178 executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_COMPUTE],
179 executionState.pushConstants);
183 uint32_t groupCountX;
184 uint32_t groupCountY;
185 uint32_t groupCountZ;
188 class DispatchIndirect : public CommandBuffer::Command
191 DispatchIndirect(VkBuffer buffer, VkDeviceSize offset) :
192 buffer(buffer), offset(offset)
197 void play(CommandBuffer::ExecutionState& executionState) override
199 auto cmd = reinterpret_cast<VkDispatchIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset));
201 ComputePipeline* pipeline = static_cast<ComputePipeline*>(
202 executionState.pipelines[VK_PIPELINE_BIND_POINT_COMPUTE]);
203 pipeline->run(cmd->x, cmd->y, cmd->z,
204 MAX_BOUND_DESCRIPTOR_SETS,
205 executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_COMPUTE],
206 executionState.pushConstants);
214 struct VertexBufferBind : public CommandBuffer::Command
216 VertexBufferBind(uint32_t pBinding, const VkBuffer pBuffer, const VkDeviceSize pOffset) :
217 binding(pBinding), buffer(pBuffer), offset(pOffset)
221 void play(CommandBuffer::ExecutionState& executionState) override
223 executionState.vertexInputBindings[binding] = { buffer, offset };
227 const VkBuffer buffer;
228 const VkDeviceSize offset;
231 struct IndexBufferBind : public CommandBuffer::Command
233 IndexBufferBind(const VkBuffer buffer, const VkDeviceSize offset, const VkIndexType indexType) :
234 buffer(buffer), offset(offset), indexType(indexType)
239 void play(CommandBuffer::ExecutionState& executionState) override
241 executionState.indexBufferBinding = {buffer, offset};
242 executionState.indexType = indexType;
245 const VkBuffer buffer;
246 const VkDeviceSize offset;
247 const VkIndexType indexType;
250 void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int firstVertex, int firstInstance)
252 for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
254 auto &attrib = context.input[i];
257 const auto &vertexInput = vertexInputBindings[attrib.binding];
258 Buffer *buffer = Cast(vertexInput.buffer);
259 attrib.buffer = buffer ? buffer->getOffsetPointer(
260 attrib.offset + vertexInput.offset + attrib.vertexStride * firstVertex + attrib.instanceStride * firstInstance) : nullptr;
265 void CommandBuffer::ExecutionState::bindAttachments()
267 // Binds all the attachments for the current subpass
268 // Ideally this would be performed by BeginRenderPass and NextSubpass, but
269 // there is too much stomping of the renderer's state by setContext() in
272 for (auto i = 0u; i < renderPass->getCurrentSubpass().colorAttachmentCount; i++)
274 auto attachmentReference = renderPass->getCurrentSubpass().pColorAttachments[i];
275 if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
277 auto attachment = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
278 renderer->setRenderTarget(i, attachment, 0);
282 auto attachmentReference = renderPass->getCurrentSubpass().pDepthStencilAttachment;
283 if (attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED)
285 auto attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
286 if (attachment->hasDepthAspect())
288 renderer->setDepthBuffer(attachment, 0);
290 if (attachment->hasStencilAspect())
292 renderer->setStencilBuffer(attachment, 0);
297 struct DrawBase : public CommandBuffer::Command
299 int bytesPerIndex(CommandBuffer::ExecutionState const& executionState)
301 return executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4;
304 void draw(CommandBuffer::ExecutionState& executionState, bool indexed,
305 uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
307 GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
308 executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
310 sw::Context context = pipeline->getContext();
312 executionState.bindVertexInputs(context, vertexOffset, firstInstance);
314 const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
315 for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
317 context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
320 context.pushConstants = executionState.pushConstants;
321 auto drawType = context.drawType;
325 context.indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
326 executionState.indexBufferBinding.offset + first * bytesPerIndex(executionState));
328 drawType = static_cast<sw::DrawType>(executionState.indexType == VK_INDEX_TYPE_UINT16
329 ? (context.drawType | sw::DRAW_INDEXED16) : (context.drawType | sw::DRAW_INDEXED32));
332 executionState.renderer->setContext(context);
333 executionState.renderer->setScissor(pipeline->getScissor());
334 executionState.renderer->setViewport(pipeline->getViewport());
335 executionState.renderer->setBlendConstant(pipeline->getBlendConstants());
337 executionState.bindAttachments();
339 const uint32_t primitiveCount = pipeline->computePrimitiveCount(count);
340 for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
342 executionState.renderer->setInstanceID(instance);
343 executionState.renderer->draw(drawType, primitiveCount);
344 executionState.renderer->advanceInstanceAttributes();
349 struct Draw : public DrawBase
351 Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
352 : vertexCount(vertexCount), instanceCount(instanceCount), firstVertex(firstVertex), firstInstance(firstInstance)
356 void play(CommandBuffer::ExecutionState& executionState) override
358 draw(executionState, false, vertexCount, instanceCount, 0, firstVertex, firstInstance);
361 uint32_t vertexCount;
362 uint32_t instanceCount;
363 uint32_t firstVertex;
364 uint32_t firstInstance;
367 struct DrawIndexed : public DrawBase
369 DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
370 : indexCount(indexCount), instanceCount(instanceCount), firstIndex(firstIndex), vertexOffset(vertexOffset), firstInstance(firstInstance)
374 void play(CommandBuffer::ExecutionState& executionState) override
376 draw(executionState, true, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
380 uint32_t instanceCount;
382 int32_t vertexOffset;
383 uint32_t firstInstance;
386 struct DrawIndirect : public DrawBase
388 DrawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
389 : buffer(buffer), offset(offset), drawCount(drawCount), stride(stride)
393 void play(CommandBuffer::ExecutionState& executionState) override
395 for (auto drawId = 0u; drawId < drawCount; drawId++)
397 auto cmd = reinterpret_cast<VkDrawIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset + drawId * stride));
398 draw(executionState, false, cmd->vertexCount, cmd->instanceCount, 0, cmd->firstVertex, cmd->firstInstance);
408 struct DrawIndexedIndirect : public DrawBase
410 DrawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
411 : buffer(buffer), offset(offset), drawCount(drawCount), stride(stride)
415 void play(CommandBuffer::ExecutionState& executionState) override
417 for (auto drawId = 0u; drawId < drawCount; drawId++)
419 auto cmd = reinterpret_cast<VkDrawIndexedIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset + drawId * stride));
420 draw(executionState, true, cmd->indexCount, cmd->instanceCount, cmd->firstIndex, cmd->vertexOffset, cmd->firstInstance);
430 struct ImageToImageCopy : public CommandBuffer::Command
432 ImageToImageCopy(VkImage pSrcImage, VkImage pDstImage, const VkImageCopy& pRegion) :
433 srcImage(pSrcImage), dstImage(pDstImage), region(pRegion)
437 void play(CommandBuffer::ExecutionState& executionState) override
439 Cast(srcImage)->copyTo(dstImage, region);
445 const VkImageCopy region;
448 struct BufferToBufferCopy : public CommandBuffer::Command
450 BufferToBufferCopy(VkBuffer pSrcBuffer, VkBuffer pDstBuffer, const VkBufferCopy& pRegion) :
451 srcBuffer(pSrcBuffer), dstBuffer(pDstBuffer), region(pRegion)
455 void play(CommandBuffer::ExecutionState& executionState) override
457 Cast(srcBuffer)->copyTo(Cast(dstBuffer), region);
463 const VkBufferCopy region;
466 struct ImageToBufferCopy : public CommandBuffer::Command
468 ImageToBufferCopy(VkImage pSrcImage, VkBuffer pDstBuffer, const VkBufferImageCopy& pRegion) :
469 srcImage(pSrcImage), dstBuffer(pDstBuffer), region(pRegion)
473 void play(CommandBuffer::ExecutionState& executionState) override
475 Cast(srcImage)->copyTo(dstBuffer, region);
481 const VkBufferImageCopy region;
484 struct BufferToImageCopy : public CommandBuffer::Command
486 BufferToImageCopy(VkBuffer pSrcBuffer, VkImage pDstImage, const VkBufferImageCopy& pRegion) :
487 srcBuffer(pSrcBuffer), dstImage(pDstImage), region(pRegion)
491 void play(CommandBuffer::ExecutionState& executionState) override
493 Cast(dstImage)->copyFrom(srcBuffer, region);
499 const VkBufferImageCopy region;
502 struct FillBuffer : public CommandBuffer::Command
504 FillBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) :
505 dstBuffer(dstBuffer), dstOffset(dstOffset), size(size), data(data)
509 void play(CommandBuffer::ExecutionState& executionState) override
511 Cast(dstBuffer)->fill(dstOffset, size, data);
516 VkDeviceSize dstOffset;
521 struct UpdateBuffer : public CommandBuffer::Command
523 UpdateBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData) :
524 dstBuffer(dstBuffer), dstOffset(dstOffset), dataSize(dataSize), pData(pData)
528 void play(CommandBuffer::ExecutionState& executionState) override
530 Cast(dstBuffer)->update(dstOffset, dataSize, pData);
535 VkDeviceSize dstOffset;
536 VkDeviceSize dataSize;
540 struct ClearColorImage : public CommandBuffer::Command
542 ClearColorImage(VkImage image, const VkClearColorValue& color, const VkImageSubresourceRange& range) :
543 image(image), color(color), range(range)
547 void play(CommandBuffer::ExecutionState& executionState) override
549 Cast(image)->clear(color, range);
554 const VkClearColorValue color;
555 const VkImageSubresourceRange range;
558 struct ClearDepthStencilImage : public CommandBuffer::Command
560 ClearDepthStencilImage(VkImage image, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range) :
561 image(image), depthStencil(depthStencil), range(range)
565 void play(CommandBuffer::ExecutionState& executionState) override
567 Cast(image)->clear(depthStencil, range);
572 const VkClearDepthStencilValue depthStencil;
573 const VkImageSubresourceRange range;
576 struct ClearAttachment : public CommandBuffer::Command
578 ClearAttachment(const VkClearAttachment& attachment, const VkClearRect& rect) :
579 attachment(attachment), rect(rect)
583 void play(CommandBuffer::ExecutionState& executionState) override
585 executionState.renderPassFramebuffer->clear(executionState.renderPass, attachment, rect);
589 const VkClearAttachment attachment;
590 const VkClearRect rect;
593 struct BlitImage : public CommandBuffer::Command
595 BlitImage(VkImage srcImage, VkImage dstImage, const VkImageBlit& region, VkFilter filter) :
596 srcImage(srcImage), dstImage(dstImage), region(region), filter(filter)
600 void play(CommandBuffer::ExecutionState& executionState) override
602 Cast(srcImage)->blit(dstImage, region, filter);
612 struct PipelineBarrier : public CommandBuffer::Command
618 void play(CommandBuffer::ExecutionState& executionState) override
620 // This is a very simple implementation that simply calls sw::Renderer::synchronize(),
621 // since the driver is free to move the source stage towards the bottom of the pipe
622 // and the target stage towards the top, so a full pipeline sync is spec compliant.
623 executionState.renderer->synchronize();
625 // Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs.
627 // Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary.
633 struct SignalEvent : public CommandBuffer::Command
635 SignalEvent(VkEvent ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask)
639 void play(CommandBuffer::ExecutionState& executionState) override
641 if(Cast(ev)->signal())
643 // Was waiting for signal on this event, sync now
644 executionState.renderer->synchronize();
650 VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and signal the event at the last stage
653 struct ResetEvent : public CommandBuffer::Command
655 ResetEvent(VkEvent ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask)
659 void play(CommandBuffer::ExecutionState& executionState) override
666 VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and reset the event at the last stage
669 struct WaitEvent : public CommandBuffer::Command
671 WaitEvent(VkEvent ev) : ev(ev)
675 void play(CommandBuffer::ExecutionState& executionState) override
677 if(!Cast(ev)->wait())
679 // Already signaled, sync now
680 executionState.renderer->synchronize();
688 struct BindDescriptorSet : public CommandBuffer::Command
690 BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet)
691 : pipelineBindPoint(pipelineBindPoint), set(set), descriptorSet(descriptorSet)
695 void play(CommandBuffer::ExecutionState& executionState)
697 ASSERT((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS));
698 executionState.boundDescriptorSets[pipelineBindPoint][set] = descriptorSet;
702 VkPipelineBindPoint pipelineBindPoint;
704 const VkDescriptorSet descriptorSet;
707 struct SetPushConstants : public CommandBuffer::Command
709 SetPushConstants(uint32_t offset, uint32_t size, void const *pValues)
710 : offset(offset), size(size)
712 ASSERT(offset < MAX_PUSH_CONSTANT_SIZE);
713 ASSERT(offset + size <= MAX_PUSH_CONSTANT_SIZE);
715 memcpy(data, pValues, size);
718 void play(CommandBuffer::ExecutionState& executionState)
720 memcpy(&executionState.pushConstants.data[offset], data, size);
726 unsigned char data[MAX_PUSH_CONSTANT_SIZE];
729 CommandBuffer::CommandBuffer(VkCommandBufferLevel pLevel) : level(pLevel)
731 // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
732 commands = new std::vector<std::unique_ptr<Command> >();
735 void CommandBuffer::destroy(const VkAllocationCallbacks* pAllocator)
740 void CommandBuffer::resetState()
742 // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
748 VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo* pInheritanceInfo)
750 ASSERT((state != RECORDING) && (state != PENDING));
752 // Nothing interesting to do based on flags. We don't have any optimizations
753 // to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE
754 // must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
757 // pInheritanceInfo merely contains optimization hints, so we currently ignore it
770 VkResult CommandBuffer::end()
772 ASSERT(state == RECORDING);
779 VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags)
781 ASSERT(state != PENDING);
788 template<typename T, typename... Args>
789 void CommandBuffer::addCommand(Args&&... args)
791 commands->push_back(std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
794 void CommandBuffer::beginRenderPass(VkRenderPass renderPass, VkFramebuffer framebuffer, VkRect2D renderArea,
795 uint32_t clearValueCount, const VkClearValue* clearValues, VkSubpassContents contents)
797 ASSERT(state == RECORDING);
799 addCommand<BeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues);
802 void CommandBuffer::nextSubpass(VkSubpassContents contents)
804 ASSERT(state == RECORDING);
806 addCommand<NextSubpass>();
809 void CommandBuffer::endRenderPass()
811 addCommand<EndRenderPass>();
814 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers)
816 ASSERT(state == RECORDING);
818 for(uint32_t i = 0; i < commandBufferCount; ++i)
820 addCommand<ExecuteCommands>(pCommandBuffers[i]);
824 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
826 UNIMPLEMENTED("setDeviceMask");
829 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
830 uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
832 UNIMPLEMENTED("dispatchBase");
835 void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
836 VkDependencyFlags dependencyFlags,
837 uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
838 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
839 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
841 addCommand<PipelineBarrier>();
844 void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline)
846 switch(pipelineBindPoint)
848 case VK_PIPELINE_BIND_POINT_COMPUTE:
849 case VK_PIPELINE_BIND_POINT_GRAPHICS:
850 addCommand<PipelineBind>(pipelineBindPoint, pipeline);
853 UNIMPLEMENTED("pipelineBindPoint");
857 void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
858 const VkBuffer* pBuffers, const VkDeviceSize* pOffsets)
860 for(uint32_t i = 0; i < bindingCount; ++i)
862 addCommand<VertexBufferBind>(i + firstBinding, pBuffers[i], pOffsets[i]);
866 void CommandBuffer::beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags)
868 UNIMPLEMENTED("beginQuery");
871 void CommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
873 UNIMPLEMENTED("endQuery");
876 void CommandBuffer::resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount)
878 UNIMPLEMENTED("resetQueryPool");
881 void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query)
883 UNIMPLEMENTED("writeTimestamp");
886 void CommandBuffer::copyQueryPoolResults(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
887 VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
889 UNIMPLEMENTED("copyQueryPoolResults");
892 void CommandBuffer::pushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags,
893 uint32_t offset, uint32_t size, const void* pValues)
895 addCommand<SetPushConstants>(offset, size, pValues);
898 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports)
900 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_VIEWPORT dynamic state enabled
901 UNIMPLEMENTED("setViewport");
904 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors)
906 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_SCISSOR dynamic state enabled
907 UNIMPLEMENTED("setScissor");
910 void CommandBuffer::setLineWidth(float lineWidth)
912 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_LINE_WIDTH dynamic state enabled
914 // If the wide lines feature is not enabled, lineWidth must be 1.0
915 ASSERT(lineWidth == 1.0f);
917 UNIMPLEMENTED("setLineWidth");
920 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
922 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state enabled
924 // If the depth bias clamping feature is not enabled, depthBiasClamp must be 0.0
925 ASSERT(depthBiasClamp == 0.0f);
927 UNIMPLEMENTED("setDepthBias");
930 void CommandBuffer::setBlendConstants(const float blendConstants[4])
932 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_BLEND_CONSTANTS dynamic state enabled
934 // blendConstants is an array of four values specifying the R, G, B, and A components
935 // of the blend constant color used in blending, depending on the blend factor.
937 UNIMPLEMENTED("setBlendConstants");
940 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
942 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_DEPTH_BOUNDS dynamic state enabled
944 // Unless the VK_EXT_depth_range_unrestricted extension is enabled minDepthBounds and maxDepthBounds must be between 0.0 and 1.0, inclusive
945 ASSERT(minDepthBounds >= 0.0f && minDepthBounds <= 1.0f);
946 ASSERT(maxDepthBounds >= 0.0f && maxDepthBounds <= 1.0f);
948 UNIMPLEMENTED("setDepthBounds");
951 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
953 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK dynamic state enabled
955 // faceMask must not be 0
956 ASSERT(faceMask != 0);
958 UNIMPLEMENTED("setStencilCompareMask");
961 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
963 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_WRITE_MASK dynamic state enabled
965 // faceMask must not be 0
966 ASSERT(faceMask != 0);
968 UNIMPLEMENTED("setStencilWriteMask");
971 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
973 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_REFERENCE dynamic state enabled
975 // faceMask must not be 0
976 ASSERT(faceMask != 0);
978 UNIMPLEMENTED("setStencilReference");
981 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
982 uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets,
983 uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets)
985 ASSERT(state == RECORDING);
987 if(dynamicOffsetCount > 0)
989 UNIMPLEMENTED("bindDescriptorSets");
992 for(uint32_t i = 0; i < descriptorSetCount; i++)
994 addCommand<BindDescriptorSet>(pipelineBindPoint, firstSet + i, pDescriptorSets[i]);
998 void CommandBuffer::bindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType)
1000 addCommand<IndexBufferBind>(buffer, offset, indexType);
1003 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
1005 addCommand<Dispatch>(groupCountX, groupCountY, groupCountZ);
1008 void CommandBuffer::dispatchIndirect(VkBuffer buffer, VkDeviceSize offset)
1010 addCommand<DispatchIndirect>(buffer, offset);
1013 void CommandBuffer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions)
1015 ASSERT(state == RECORDING);
1017 for(uint32_t i = 0; i < regionCount; i++)
1019 addCommand<BufferToBufferCopy>(srcBuffer, dstBuffer, pRegions[i]);
1023 void CommandBuffer::copyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
1024 uint32_t regionCount, const VkImageCopy* pRegions)
1026 ASSERT(state == RECORDING);
1027 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1028 srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1029 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1030 dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1032 for(uint32_t i = 0; i < regionCount; i++)
1034 addCommand<ImageToImageCopy>(srcImage, dstImage, pRegions[i]);
1038 void CommandBuffer::blitImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
1039 uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter)
1041 ASSERT(state == RECORDING);
1042 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1043 srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1044 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1045 dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1047 for(uint32_t i = 0; i < regionCount; i++)
1049 addCommand<BlitImage>(srcImage, dstImage, pRegions[i], filter);
1053 void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout,
1054 uint32_t regionCount, const VkBufferImageCopy* pRegions)
1056 ASSERT(state == RECORDING);
1058 for(uint32_t i = 0; i < regionCount; i++)
1060 addCommand<BufferToImageCopy>(srcBuffer, dstImage, pRegions[i]);
1064 void CommandBuffer::copyImageToBuffer(VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer,
1065 uint32_t regionCount, const VkBufferImageCopy* pRegions)
1067 ASSERT(state == RECORDING);
1068 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1070 for(uint32_t i = 0; i < regionCount; i++)
1072 addCommand<ImageToBufferCopy>(srcImage, dstBuffer, pRegions[i]);
1076 void CommandBuffer::updateBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData)
1078 ASSERT(state == RECORDING);
1080 addCommand<UpdateBuffer>(dstBuffer, dstOffset, dataSize, pData);
1083 void CommandBuffer::fillBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
1085 ASSERT(state == RECORDING);
1087 addCommand<FillBuffer>(dstBuffer, dstOffset, size, data);
1090 void CommandBuffer::clearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor,
1091 uint32_t rangeCount, const VkImageSubresourceRange* pRanges)
1093 ASSERT(state == RECORDING);
1095 for(uint32_t i = 0; i < rangeCount; i++)
1097 addCommand<ClearColorImage>(image, pColor[i], pRanges[i]);
1101 void CommandBuffer::clearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil,
1102 uint32_t rangeCount, const VkImageSubresourceRange* pRanges)
1104 ASSERT(state == RECORDING);
1106 for(uint32_t i = 0; i < rangeCount; i++)
1108 addCommand<ClearDepthStencilImage>(image, pDepthStencil[i], pRanges[i]);
1112 void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment* pAttachments,
1113 uint32_t rectCount, const VkClearRect* pRects)
1115 ASSERT(state == RECORDING);
1117 for(uint32_t i = 0; i < attachmentCount; i++)
1119 for(uint32_t j = 0; j < rectCount; j++)
1121 addCommand<ClearAttachment>(pAttachments[i], pRects[j]);
1126 void CommandBuffer::resolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
1127 uint32_t regionCount, const VkImageResolve* pRegions)
1129 UNIMPLEMENTED("resolveImage");
1132 void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
1134 ASSERT(state == RECORDING);
1136 addCommand<SignalEvent>(event, stageMask);
1139 void CommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
1141 ASSERT(state == RECORDING);
1143 addCommand<ResetEvent>(event, stageMask);
1146 void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask,
1147 VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
1148 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
1149 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
1151 ASSERT(state == RECORDING);
1153 // TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
1155 // Note: srcStageMask and dstStageMask are currently ignored
1156 for(uint32_t i = 0; i < eventCount; i++)
1158 addCommand<WaitEvent>(pEvents[i]);
1162 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
1164 addCommand<Draw>(vertexCount, instanceCount, firstVertex, firstInstance);
1167 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
1169 addCommand<DrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1172 void CommandBuffer::drawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1174 addCommand<DrawIndirect>(buffer, offset, drawCount, stride);
1177 void CommandBuffer::drawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1179 addCommand<DrawIndexedIndirect>(buffer, offset, drawCount, stride);
1182 void CommandBuffer::submit(CommandBuffer::ExecutionState& executionState)
1184 // Perform recorded work
1187 for(auto& command : *commands)
1189 command->play(executionState);
1192 // After work is completed
1196 void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState& executionState) const
1198 for(auto& command : *commands)
1200 command->play(executionState);