| 1 | // Copyright 2018 The SwiftShader Authors. All Rights Reserved. |
| 2 | // |
| 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 |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 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. |
| 14 | |
| 15 | #ifndef VK_COMMAND_BUFFER_HPP_ |
| 16 | #define VK_COMMAND_BUFFER_HPP_ |
| 17 | |
| 18 | #include "VkConfig.h" |
| 19 | #include "VkObject.hpp" |
| 20 | #include "VkDescriptorSet.hpp" |
| 21 | #include "Device/Color.hpp" |
| 22 | #include "Device/Context.hpp" |
| 23 | #include <memory> |
| 24 | #include <vector> |
| 25 | |
| 26 | namespace sw |
| 27 | { |
| 28 | class Context; |
| 29 | class Renderer; |
| 30 | class TaskEvents; |
| 31 | } |
| 32 | |
| 33 | namespace vk |
| 34 | { |
| 35 | |
| 36 | class Buffer; |
| 37 | class Event; |
| 38 | class Framebuffer; |
| 39 | class Image; |
| 40 | class Pipeline; |
| 41 | class PipelineLayout; |
| 42 | class QueryPool; |
| 43 | class RenderPass; |
| 44 | |
| 45 | class CommandBuffer |
| 46 | { |
| 47 | public: |
| 48 | static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; } |
| 49 | |
| 50 | CommandBuffer(VkCommandBufferLevel pLevel); |
| 51 | |
| 52 | static inline CommandBuffer* Cast(VkCommandBuffer object) |
| 53 | { |
| 54 | return reinterpret_cast<CommandBuffer*>(object); |
| 55 | } |
| 56 | |
| 57 | void destroy(const VkAllocationCallbacks* pAllocator); |
| 58 | |
| 59 | VkResult begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo* pInheritanceInfo); |
| 60 | VkResult end(); |
| 61 | VkResult reset(VkCommandPoolResetFlags flags); |
| 62 | |
| 63 | void beginRenderPass(RenderPass* renderPass, Framebuffer* framebuffer, VkRect2D renderArea, |
| 64 | uint32_t clearValueCount, const VkClearValue* pClearValues, VkSubpassContents contents); |
| 65 | void nextSubpass(VkSubpassContents contents); |
| 66 | void endRenderPass(); |
| 67 | void executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); |
| 68 | |
| 69 | void setDeviceMask(uint32_t deviceMask); |
| 70 | void dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, |
| 71 | uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); |
| 72 | |
| 73 | void pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, |
| 74 | uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, |
| 75 | uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, |
| 76 | uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); |
| 77 | void bindPipeline(VkPipelineBindPoint pipelineBindPoint, Pipeline* pipeline); |
| 78 | void bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, |
| 79 | const VkBuffer* pBuffers, const VkDeviceSize* pOffsets); |
| 80 | |
| 81 | void beginQuery(QueryPool* queryPool, uint32_t query, VkQueryControlFlags flags); |
| 82 | void endQuery(QueryPool* queryPool, uint32_t query); |
| 83 | void resetQueryPool(QueryPool* queryPool, uint32_t firstQuery, uint32_t queryCount); |
| 84 | void writeTimestamp(VkPipelineStageFlagBits pipelineStage, QueryPool* queryPool, uint32_t query); |
| 85 | void copyQueryPoolResults(const QueryPool* queryPool, uint32_t firstQuery, uint32_t queryCount, |
| 86 | Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); |
| 87 | void pushConstants(PipelineLayout* layout, VkShaderStageFlags stageFlags, |
| 88 | uint32_t offset, uint32_t size, const void* pValues); |
| 89 | |
| 90 | void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports); |
| 91 | void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors); |
| 92 | void setLineWidth(float lineWidth); |
| 93 | void setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor); |
| 94 | void setBlendConstants(const float blendConstants[4]); |
| 95 | void setDepthBounds(float minDepthBounds, float maxDepthBounds); |
| 96 | void setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask); |
| 97 | void setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask); |
| 98 | void setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference); |
| 99 | void bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, const PipelineLayout* layout, |
| 100 | uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, |
| 101 | uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets); |
| 102 | void bindIndexBuffer(Buffer* buffer, VkDeviceSize offset, VkIndexType indexType); |
| 103 | void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); |
| 104 | void dispatchIndirect(Buffer* buffer, VkDeviceSize offset); |
| 105 | void copyBuffer(const Buffer* srcBuffer, Buffer* dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions); |
| 106 | void copyImage(const Image* srcImage, VkImageLayout srcImageLayout, Image* dstImage, VkImageLayout dstImageLayout, |
| 107 | uint32_t regionCount, const VkImageCopy* pRegions); |
| 108 | void blitImage(const Image* srcImage, VkImageLayout srcImageLayout, Image* dstImage, VkImageLayout dstImageLayout, |
| 109 | uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter); |
| 110 | void copyBufferToImage(Buffer* srcBuffer, Image* dstImage, VkImageLayout dstImageLayout, |
| 111 | uint32_t regionCount, const VkBufferImageCopy* pRegions); |
| 112 | void copyImageToBuffer(Image* srcImage, VkImageLayout srcImageLayout, Buffer* dstBuffer, |
| 113 | uint32_t regionCount, const VkBufferImageCopy* pRegions); |
| 114 | void updateBuffer(Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); |
| 115 | void fillBuffer(Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); |
| 116 | void clearColorImage(Image* image, VkImageLayout imageLayout, const VkClearColorValue* pColor, |
| 117 | uint32_t rangeCount, const VkImageSubresourceRange* pRanges); |
| 118 | void clearDepthStencilImage(Image* image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, |
| 119 | uint32_t rangeCount, const VkImageSubresourceRange* pRanges); |
| 120 | void clearAttachments(uint32_t attachmentCount, const VkClearAttachment* pAttachments, |
| 121 | uint32_t rectCount, const VkClearRect* pRects); |
| 122 | void resolveImage(const Image* srcImage, VkImageLayout srcImageLayout, Image* dstImage, VkImageLayout dstImageLayout, |
| 123 | uint32_t regionCount, const VkImageResolve* pRegions); |
| 124 | void setEvent(Event* event, VkPipelineStageFlags stageMask); |
| 125 | void resetEvent(Event* event, VkPipelineStageFlags stageMask); |
| 126 | void waitEvents(uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, |
| 127 | VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, |
| 128 | uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, |
| 129 | uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); |
| 130 | |
| 131 | void draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); |
| 132 | void drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); |
| 133 | void drawIndirect(Buffer* buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); |
| 134 | void drawIndexedIndirect(Buffer* buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); |
| 135 | |
| 136 | // TODO(sugoi): Move ExecutionState out of CommandBuffer (possibly into Device) |
| 137 | struct ExecutionState |
| 138 | { |
| 139 | struct PipelineState |
| 140 | { |
| 141 | Pipeline *pipeline = nullptr; |
| 142 | vk::DescriptorSet::Bindings descriptorSets = {}; |
| 143 | vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {}; |
| 144 | }; |
| 145 | |
| 146 | sw::Renderer* renderer = nullptr; |
| 147 | sw::TaskEvents* events = nullptr; |
| 148 | RenderPass* renderPass = nullptr; |
| 149 | Framebuffer* renderPassFramebuffer = nullptr; |
| 150 | std::array<PipelineState, VK_PIPELINE_BIND_POINT_RANGE_SIZE> pipelineState; |
| 151 | |
| 152 | struct DynamicState |
| 153 | { |
| 154 | VkViewport viewport; |
| 155 | VkRect2D scissor; |
| 156 | sw::Color<float> blendConstants; |
| 157 | float depthBiasConstantFactor = 0.0f; |
| 158 | float depthBiasClamp = 0.0f; |
| 159 | float depthBiasSlopeFactor = 0.0f; |
| 160 | float minDepthBounds = 0.0f; |
| 161 | float maxDepthBounds = 0.0f; |
| 162 | |
| 163 | uint32_t compareMask[2] = { 0 }; |
| 164 | uint32_t writeMask[2] = { 0 }; |
| 165 | uint32_t reference[2] = { 0 }; |
| 166 | }; |
| 167 | DynamicState dynamicState; |
| 168 | |
| 169 | sw::PushConstantStorage pushConstants; |
| 170 | |
| 171 | struct VertexInputBinding |
| 172 | { |
| 173 | Buffer* buffer; |
| 174 | VkDeviceSize offset; |
| 175 | }; |
| 176 | VertexInputBinding vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS] = {}; |
| 177 | VertexInputBinding indexBufferBinding; |
| 178 | VkIndexType indexType; |
| 179 | |
| 180 | uint32_t subpassIndex = 0; |
| 181 | |
| 182 | void bindAttachments(sw::Context& context); |
| 183 | void bindVertexInputs(sw::Context& context, int firstInstance); |
| 184 | }; |
| 185 | |
| 186 | void submit(CommandBuffer::ExecutionState& executionState); |
| 187 | void submitSecondary(CommandBuffer::ExecutionState& executionState) const; |
| 188 | |
| 189 | class Command; |
| 190 | private: |
| 191 | void resetState(); |
| 192 | template<typename T, typename... Args> void addCommand(Args&&... args); |
| 193 | |
| 194 | enum State { INITIAL, RECORDING, EXECUTABLE, PENDING, INVALID }; |
| 195 | State state = INITIAL; |
| 196 | VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; |
| 197 | |
| 198 | // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations |
| 199 | std::vector<std::unique_ptr<Command>>* commands; |
| 200 | }; |
| 201 | |
| 202 | using DispatchableCommandBuffer = DispatchableObject<CommandBuffer, VkCommandBuffer>; |
| 203 | |
| 204 | static inline CommandBuffer* Cast(VkCommandBuffer object) |
| 205 | { |
| 206 | return DispatchableCommandBuffer::Cast(object); |
| 207 | } |
| 208 | |
| 209 | } // namespace vk |
| 210 | |
| 211 | #endif // VK_COMMAND_BUFFER_HPP_ |
| 212 | |