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 struct VertexBufferBind : public CommandBuffer::Command
190 VertexBufferBind(uint32_t pBinding, const VkBuffer pBuffer, const VkDeviceSize pOffset) :
191 binding(pBinding), buffer(pBuffer), offset(pOffset)
195 void play(CommandBuffer::ExecutionState& executionState) override
197 executionState.vertexInputBindings[binding] = { buffer, offset };
201 const VkBuffer buffer;
202 const VkDeviceSize offset;
205 struct IndexBufferBind : public CommandBuffer::Command
207 IndexBufferBind(const VkBuffer buffer, const VkDeviceSize offset, const VkIndexType indexType) :
208 buffer(buffer), offset(offset), indexType(indexType)
213 void play(CommandBuffer::ExecutionState& executionState) override
215 executionState.indexBufferBinding = {buffer, offset};
216 executionState.indexType = indexType;
219 const VkBuffer buffer;
220 const VkDeviceSize offset;
221 const VkIndexType indexType;
224 void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int firstVertex, int firstInstance)
226 for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
228 auto &attrib = context.input[i];
231 const auto &vertexInput = vertexInputBindings[attrib.binding];
232 Buffer *buffer = Cast(vertexInput.buffer);
233 attrib.buffer = buffer ? buffer->getOffsetPointer(
234 attrib.offset + vertexInput.offset + attrib.vertexStride * firstVertex + attrib.instanceStride * firstInstance) : nullptr;
239 void CommandBuffer::ExecutionState::bindAttachments()
241 // Binds all the attachments for the current subpass
242 // Ideally this would be performed by BeginRenderPass and NextSubpass, but
243 // there is too much stomping of the renderer's state by setContext() in
246 for (auto i = 0u; i < renderPass->getCurrentSubpass().colorAttachmentCount; i++)
248 auto attachmentReference = renderPass->getCurrentSubpass().pColorAttachments[i];
249 if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
251 auto attachment = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
252 renderer->setRenderTarget(i, attachment, 0);
256 auto attachmentReference = renderPass->getCurrentSubpass().pDepthStencilAttachment;
257 if (attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED)
259 auto attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
260 if (attachment->hasDepthAspect())
262 renderer->setDepthBuffer(attachment, 0);
264 if (attachment->hasStencilAspect())
266 renderer->setStencilBuffer(attachment, 0);
271 struct Draw : public CommandBuffer::Command
273 Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
274 : vertexCount(vertexCount), instanceCount(instanceCount), firstVertex(firstVertex), firstInstance(firstInstance)
278 void play(CommandBuffer::ExecutionState& executionState) override
280 GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
281 executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
283 sw::Context context = pipeline->getContext();
284 executionState.bindVertexInputs(context, firstVertex, firstInstance);
286 const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
287 for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
289 context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
292 context.pushConstants = executionState.pushConstants;
294 executionState.renderer->setContext(context);
295 executionState.renderer->setScissor(pipeline->getScissor());
296 executionState.renderer->setViewport(pipeline->getViewport());
297 executionState.renderer->setBlendConstant(pipeline->getBlendConstants());
299 executionState.bindAttachments();
301 const uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount);
302 for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
304 executionState.renderer->setInstanceID(instance);
305 executionState.renderer->draw(context.drawType, primitiveCount);
306 executionState.renderer->advanceInstanceAttributes();
310 uint32_t vertexCount;
311 uint32_t instanceCount;
312 uint32_t firstVertex;
313 uint32_t firstInstance;
316 struct DrawIndexed : public CommandBuffer::Command
318 DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
319 : indexCount(indexCount), instanceCount(instanceCount), firstIndex(firstIndex), vertexOffset(vertexOffset), firstInstance(firstInstance)
323 void play(CommandBuffer::ExecutionState& executionState) override
325 GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
326 executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
328 sw::Context context = pipeline->getContext();
330 executionState.bindVertexInputs(context, vertexOffset, firstInstance);
332 const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
333 for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
335 context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
338 context.pushConstants = executionState.pushConstants;
340 context.indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
341 executionState.indexBufferBinding.offset + firstIndex * (executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4));
343 executionState.renderer->setContext(context);
344 executionState.renderer->setScissor(pipeline->getScissor());
345 executionState.renderer->setViewport(pipeline->getViewport());
346 executionState.renderer->setBlendConstant(pipeline->getBlendConstants());
348 executionState.bindAttachments();
350 auto drawType = executionState.indexType == VK_INDEX_TYPE_UINT16
351 ? (context.drawType | sw::DRAW_INDEXED16) : (context.drawType | sw::DRAW_INDEXED32);
353 const uint32_t primitiveCount = pipeline->computePrimitiveCount(indexCount);
354 for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
356 executionState.renderer->setInstanceID(instance);
357 executionState.renderer->draw(static_cast<sw::DrawType>(drawType), primitiveCount);
358 executionState.renderer->advanceInstanceAttributes();
363 uint32_t instanceCount;
365 int32_t vertexOffset;
366 uint32_t firstInstance;
369 struct ImageToImageCopy : public CommandBuffer::Command
371 ImageToImageCopy(VkImage pSrcImage, VkImage pDstImage, const VkImageCopy& pRegion) :
372 srcImage(pSrcImage), dstImage(pDstImage), region(pRegion)
376 void play(CommandBuffer::ExecutionState& executionState) override
378 Cast(srcImage)->copyTo(dstImage, region);
384 const VkImageCopy region;
387 struct BufferToBufferCopy : public CommandBuffer::Command
389 BufferToBufferCopy(VkBuffer pSrcBuffer, VkBuffer pDstBuffer, const VkBufferCopy& pRegion) :
390 srcBuffer(pSrcBuffer), dstBuffer(pDstBuffer), region(pRegion)
394 void play(CommandBuffer::ExecutionState& executionState) override
396 Cast(srcBuffer)->copyTo(Cast(dstBuffer), region);
402 const VkBufferCopy region;
405 struct ImageToBufferCopy : public CommandBuffer::Command
407 ImageToBufferCopy(VkImage pSrcImage, VkBuffer pDstBuffer, const VkBufferImageCopy& pRegion) :
408 srcImage(pSrcImage), dstBuffer(pDstBuffer), region(pRegion)
412 void play(CommandBuffer::ExecutionState& executionState) override
414 Cast(srcImage)->copyTo(dstBuffer, region);
420 const VkBufferImageCopy region;
423 struct BufferToImageCopy : public CommandBuffer::Command
425 BufferToImageCopy(VkBuffer pSrcBuffer, VkImage pDstImage, const VkBufferImageCopy& pRegion) :
426 srcBuffer(pSrcBuffer), dstImage(pDstImage), region(pRegion)
430 void play(CommandBuffer::ExecutionState& executionState) override
432 Cast(dstImage)->copyFrom(srcBuffer, region);
438 const VkBufferImageCopy region;
441 struct FillBuffer : public CommandBuffer::Command
443 FillBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) :
444 dstBuffer(dstBuffer), dstOffset(dstOffset), size(size), data(data)
448 void play(CommandBuffer::ExecutionState& executionState) override
450 Cast(dstBuffer)->fill(dstOffset, size, data);
455 VkDeviceSize dstOffset;
460 struct UpdateBuffer : public CommandBuffer::Command
462 UpdateBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData) :
463 dstBuffer(dstBuffer), dstOffset(dstOffset), dataSize(dataSize), pData(pData)
467 void play(CommandBuffer::ExecutionState& executionState) override
469 Cast(dstBuffer)->update(dstOffset, dataSize, pData);
474 VkDeviceSize dstOffset;
475 VkDeviceSize dataSize;
479 struct ClearColorImage : public CommandBuffer::Command
481 ClearColorImage(VkImage image, const VkClearColorValue& color, const VkImageSubresourceRange& range) :
482 image(image), color(color), range(range)
486 void play(CommandBuffer::ExecutionState& executionState) override
488 Cast(image)->clear(color, range);
493 const VkClearColorValue color;
494 const VkImageSubresourceRange range;
497 struct ClearDepthStencilImage : public CommandBuffer::Command
499 ClearDepthStencilImage(VkImage image, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range) :
500 image(image), depthStencil(depthStencil), range(range)
504 void play(CommandBuffer::ExecutionState& executionState) override
506 Cast(image)->clear(depthStencil, range);
511 const VkClearDepthStencilValue depthStencil;
512 const VkImageSubresourceRange range;
515 struct ClearAttachment : public CommandBuffer::Command
517 ClearAttachment(const VkClearAttachment& attachment, const VkClearRect& rect) :
518 attachment(attachment), rect(rect)
522 void play(CommandBuffer::ExecutionState& executionState) override
524 executionState.renderPassFramebuffer->clear(executionState.renderPass, attachment, rect);
528 const VkClearAttachment attachment;
529 const VkClearRect rect;
532 struct BlitImage : public CommandBuffer::Command
534 BlitImage(VkImage srcImage, VkImage dstImage, const VkImageBlit& region, VkFilter filter) :
535 srcImage(srcImage), dstImage(dstImage), region(region), filter(filter)
539 void play(CommandBuffer::ExecutionState& executionState) override
541 Cast(srcImage)->blit(dstImage, region, filter);
551 struct PipelineBarrier : public CommandBuffer::Command
557 void play(CommandBuffer::ExecutionState& executionState) override
559 // This is a very simple implementation that simply calls sw::Renderer::synchronize(),
560 // since the driver is free to move the source stage towards the bottom of the pipe
561 // and the target stage towards the top, so a full pipeline sync is spec compliant.
562 executionState.renderer->synchronize();
564 // Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs.
566 // Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary.
572 struct SignalEvent : public CommandBuffer::Command
574 SignalEvent(VkEvent ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask)
578 void play(CommandBuffer::ExecutionState& executionState) override
580 if(Cast(ev)->signal())
582 // Was waiting for signal on this event, sync now
583 executionState.renderer->synchronize();
589 VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and signal the event at the last stage
592 struct ResetEvent : public CommandBuffer::Command
594 ResetEvent(VkEvent ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask)
598 void play(CommandBuffer::ExecutionState& executionState) override
605 VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and reset the event at the last stage
608 struct WaitEvent : public CommandBuffer::Command
610 WaitEvent(VkEvent ev) : ev(ev)
614 void play(CommandBuffer::ExecutionState& executionState) override
616 if(!Cast(ev)->wait())
618 // Already signaled, sync now
619 executionState.renderer->synchronize();
627 struct BindDescriptorSet : public CommandBuffer::Command
629 BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet)
630 : pipelineBindPoint(pipelineBindPoint), set(set), descriptorSet(descriptorSet)
634 void play(CommandBuffer::ExecutionState& executionState)
636 ASSERT((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS));
637 executionState.boundDescriptorSets[pipelineBindPoint][set] = descriptorSet;
641 VkPipelineBindPoint pipelineBindPoint;
643 const VkDescriptorSet descriptorSet;
646 struct SetPushConstants : public CommandBuffer::Command
648 SetPushConstants(uint32_t offset, uint32_t size, void const *pValues)
649 : offset(offset), size(size)
651 ASSERT(offset < MAX_PUSH_CONSTANT_SIZE);
652 ASSERT(offset + size <= MAX_PUSH_CONSTANT_SIZE);
654 memcpy(data, pValues, size);
657 void play(CommandBuffer::ExecutionState& executionState)
659 memcpy(&executionState.pushConstants.data[offset], data, size);
665 unsigned char data[MAX_PUSH_CONSTANT_SIZE];
668 CommandBuffer::CommandBuffer(VkCommandBufferLevel pLevel) : level(pLevel)
670 // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
671 commands = new std::vector<std::unique_ptr<Command> >();
674 void CommandBuffer::destroy(const VkAllocationCallbacks* pAllocator)
679 void CommandBuffer::resetState()
681 // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
687 VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo* pInheritanceInfo)
689 ASSERT((state != RECORDING) && (state != PENDING));
691 // Nothing interesting to do based on flags. We don't have any optimizations
692 // to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE
693 // must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
696 // pInheritanceInfo merely contains optimization hints, so we currently ignore it
709 VkResult CommandBuffer::end()
711 ASSERT(state == RECORDING);
718 VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags)
720 ASSERT(state != PENDING);
727 template<typename T, typename... Args>
728 void CommandBuffer::addCommand(Args&&... args)
730 commands->push_back(std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
733 void CommandBuffer::beginRenderPass(VkRenderPass renderPass, VkFramebuffer framebuffer, VkRect2D renderArea,
734 uint32_t clearValueCount, const VkClearValue* clearValues, VkSubpassContents contents)
736 ASSERT(state == RECORDING);
738 addCommand<BeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues);
741 void CommandBuffer::nextSubpass(VkSubpassContents contents)
743 ASSERT(state == RECORDING);
745 addCommand<NextSubpass>();
748 void CommandBuffer::endRenderPass()
750 addCommand<EndRenderPass>();
753 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers)
755 ASSERT(state == RECORDING);
757 for(uint32_t i = 0; i < commandBufferCount; ++i)
759 addCommand<ExecuteCommands>(pCommandBuffers[i]);
763 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
765 UNIMPLEMENTED("setDeviceMask");
768 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
769 uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
771 UNIMPLEMENTED("dispatchBase");
774 void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
775 VkDependencyFlags dependencyFlags,
776 uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
777 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
778 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
780 addCommand<PipelineBarrier>();
783 void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline)
785 switch(pipelineBindPoint)
787 case VK_PIPELINE_BIND_POINT_COMPUTE:
788 case VK_PIPELINE_BIND_POINT_GRAPHICS:
789 addCommand<PipelineBind>(pipelineBindPoint, pipeline);
792 UNIMPLEMENTED("pipelineBindPoint");
796 void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
797 const VkBuffer* pBuffers, const VkDeviceSize* pOffsets)
799 for(uint32_t i = 0; i < bindingCount; ++i)
801 addCommand<VertexBufferBind>(i + firstBinding, pBuffers[i], pOffsets[i]);
805 void CommandBuffer::beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags)
807 UNIMPLEMENTED("beginQuery");
810 void CommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
812 UNIMPLEMENTED("endQuery");
815 void CommandBuffer::resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount)
817 UNIMPLEMENTED("resetQueryPool");
820 void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query)
822 UNIMPLEMENTED("writeTimestamp");
825 void CommandBuffer::copyQueryPoolResults(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
826 VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
828 UNIMPLEMENTED("copyQueryPoolResults");
831 void CommandBuffer::pushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags,
832 uint32_t offset, uint32_t size, const void* pValues)
834 addCommand<SetPushConstants>(offset, size, pValues);
837 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports)
839 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_VIEWPORT dynamic state enabled
840 UNIMPLEMENTED("setViewport");
843 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors)
845 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_SCISSOR dynamic state enabled
846 UNIMPLEMENTED("setScissor");
849 void CommandBuffer::setLineWidth(float lineWidth)
851 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_LINE_WIDTH dynamic state enabled
853 // If the wide lines feature is not enabled, lineWidth must be 1.0
854 ASSERT(lineWidth == 1.0f);
856 UNIMPLEMENTED("setLineWidth");
859 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
861 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state enabled
863 // If the depth bias clamping feature is not enabled, depthBiasClamp must be 0.0
864 ASSERT(depthBiasClamp == 0.0f);
866 UNIMPLEMENTED("setDepthBias");
869 void CommandBuffer::setBlendConstants(const float blendConstants[4])
871 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_BLEND_CONSTANTS dynamic state enabled
873 // blendConstants is an array of four values specifying the R, G, B, and A components
874 // of the blend constant color used in blending, depending on the blend factor.
876 UNIMPLEMENTED("setBlendConstants");
879 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
881 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_DEPTH_BOUNDS dynamic state enabled
883 // Unless the VK_EXT_depth_range_unrestricted extension is enabled minDepthBounds and maxDepthBounds must be between 0.0 and 1.0, inclusive
884 ASSERT(minDepthBounds >= 0.0f && minDepthBounds <= 1.0f);
885 ASSERT(maxDepthBounds >= 0.0f && maxDepthBounds <= 1.0f);
887 UNIMPLEMENTED("setDepthBounds");
890 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
892 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK dynamic state enabled
894 // faceMask must not be 0
895 ASSERT(faceMask != 0);
897 UNIMPLEMENTED("setStencilCompareMask");
900 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
902 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_WRITE_MASK dynamic state enabled
904 // faceMask must not be 0
905 ASSERT(faceMask != 0);
907 UNIMPLEMENTED("setStencilWriteMask");
910 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
912 // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_REFERENCE dynamic state enabled
914 // faceMask must not be 0
915 ASSERT(faceMask != 0);
917 UNIMPLEMENTED("setStencilReference");
920 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
921 uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets,
922 uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets)
924 ASSERT(state == RECORDING);
926 if(dynamicOffsetCount > 0)
928 UNIMPLEMENTED("bindDescriptorSets");
931 for(uint32_t i = 0; i < descriptorSetCount; i++)
933 addCommand<BindDescriptorSet>(pipelineBindPoint, firstSet + i, pDescriptorSets[i]);
937 void CommandBuffer::bindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType)
939 addCommand<IndexBufferBind>(buffer, offset, indexType);
942 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
944 addCommand<Dispatch>(groupCountX, groupCountY, groupCountZ);
947 void CommandBuffer::dispatchIndirect(VkBuffer buffer, VkDeviceSize offset)
949 UNIMPLEMENTED("dispatchIndirect");
952 void CommandBuffer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions)
954 ASSERT(state == RECORDING);
956 for(uint32_t i = 0; i < regionCount; i++)
958 addCommand<BufferToBufferCopy>(srcBuffer, dstBuffer, pRegions[i]);
962 void CommandBuffer::copyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
963 uint32_t regionCount, const VkImageCopy* pRegions)
965 ASSERT(state == RECORDING);
966 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
967 srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
968 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
969 dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
971 for(uint32_t i = 0; i < regionCount; i++)
973 addCommand<ImageToImageCopy>(srcImage, dstImage, pRegions[i]);
977 void CommandBuffer::blitImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
978 uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter)
980 ASSERT(state == RECORDING);
981 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
982 srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
983 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
984 dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
986 for(uint32_t i = 0; i < regionCount; i++)
988 addCommand<BlitImage>(srcImage, dstImage, pRegions[i], filter);
992 void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout,
993 uint32_t regionCount, const VkBufferImageCopy* pRegions)
995 ASSERT(state == RECORDING);
997 for(uint32_t i = 0; i < regionCount; i++)
999 addCommand<BufferToImageCopy>(srcBuffer, dstImage, pRegions[i]);
1003 void CommandBuffer::copyImageToBuffer(VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer,
1004 uint32_t regionCount, const VkBufferImageCopy* pRegions)
1006 ASSERT(state == RECORDING);
1007 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1009 for(uint32_t i = 0; i < regionCount; i++)
1011 addCommand<ImageToBufferCopy>(srcImage, dstBuffer, pRegions[i]);
1015 void CommandBuffer::updateBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData)
1017 ASSERT(state == RECORDING);
1019 addCommand<UpdateBuffer>(dstBuffer, dstOffset, dataSize, pData);
1022 void CommandBuffer::fillBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
1024 ASSERT(state == RECORDING);
1026 addCommand<FillBuffer>(dstBuffer, dstOffset, size, data);
1029 void CommandBuffer::clearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor,
1030 uint32_t rangeCount, const VkImageSubresourceRange* pRanges)
1032 ASSERT(state == RECORDING);
1034 for(uint32_t i = 0; i < rangeCount; i++)
1036 addCommand<ClearColorImage>(image, pColor[i], pRanges[i]);
1040 void CommandBuffer::clearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil,
1041 uint32_t rangeCount, const VkImageSubresourceRange* pRanges)
1043 ASSERT(state == RECORDING);
1045 for(uint32_t i = 0; i < rangeCount; i++)
1047 addCommand<ClearDepthStencilImage>(image, pDepthStencil[i], pRanges[i]);
1051 void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment* pAttachments,
1052 uint32_t rectCount, const VkClearRect* pRects)
1054 ASSERT(state == RECORDING);
1056 for(uint32_t i = 0; i < attachmentCount; i++)
1058 for(uint32_t j = 0; j < rectCount; j++)
1060 addCommand<ClearAttachment>(pAttachments[i], pRects[j]);
1065 void CommandBuffer::resolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
1066 uint32_t regionCount, const VkImageResolve* pRegions)
1068 UNIMPLEMENTED("resolveImage");
1071 void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
1073 ASSERT(state == RECORDING);
1075 addCommand<SignalEvent>(event, stageMask);
1078 void CommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
1080 ASSERT(state == RECORDING);
1082 addCommand<ResetEvent>(event, stageMask);
1085 void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask,
1086 VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
1087 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
1088 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
1090 ASSERT(state == RECORDING);
1092 // TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
1094 // Note: srcStageMask and dstStageMask are currently ignored
1095 for(uint32_t i = 0; i < eventCount; i++)
1097 addCommand<WaitEvent>(pEvents[i]);
1101 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
1103 addCommand<Draw>(vertexCount, instanceCount, firstVertex, firstInstance);
1106 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
1108 addCommand<DrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1111 void CommandBuffer::drawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1113 UNIMPLEMENTED("drawIndirect");
1116 void CommandBuffer::drawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1118 UNIMPLEMENTED("drawIndexedIndirect");
1121 void CommandBuffer::submit(CommandBuffer::ExecutionState& executionState)
1123 // Perform recorded work
1126 for(auto& command : *commands)
1128 command->play(executionState);
1131 // After work is completed
1135 void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState& executionState) const
1137 for(auto& command : *commands)
1139 command->play(executionState);