Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 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 | |
Antonio Maiorano | 42fd159 | 2020-04-27 11:30:40 -0400 | [diff] [blame] | 18 | #include "VkConfig.hpp" |
Ben Clayton | 225a130 | 2019-04-02 12:28:22 +0100 | [diff] [blame] | 19 | #include "VkDescriptorSet.hpp" |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 20 | #include "VkObject.hpp" |
Chris Forbes | a30de54 | 2019-03-18 18:51:55 -0700 | [diff] [blame] | 21 | #include "Device/Context.hpp" |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 22 | |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 23 | #include <memory> |
| 24 | #include <vector> |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 25 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 26 | namespace sw { |
Alexis Hetu | c65473d | 2018-12-07 16:26:05 -0500 | [diff] [blame] | 27 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 28 | class Context; |
| 29 | class Renderer; |
| 30 | class TaskEvents; |
| 31 | |
| 32 | } // namespace sw |
| 33 | |
| 34 | namespace vk { |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 35 | |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 36 | namespace dbg { |
| 37 | class File; |
| 38 | } // namespace dbg |
| 39 | |
| 40 | class Device; |
Alexis Hetu | 63ae924 | 2019-06-06 13:52:15 -0400 | [diff] [blame] | 41 | class Buffer; |
Alexis Hetu | 7d96f51 | 2019-06-13 18:23:56 -0400 | [diff] [blame] | 42 | class Event; |
Alexis Hetu | 1cd31ea | 2019-01-17 17:14:57 -0500 | [diff] [blame] | 43 | class Framebuffer; |
Alexis Hetu | 7d96f51 | 2019-06-13 18:23:56 -0400 | [diff] [blame] | 44 | class Image; |
Alexis Hetu | 1cd31ea | 2019-01-17 17:14:57 -0500 | [diff] [blame] | 45 | class Pipeline; |
Alexis Hetu | 7d96f51 | 2019-06-13 18:23:56 -0400 | [diff] [blame] | 46 | class PipelineLayout; |
| 47 | class QueryPool; |
Alexis Hetu | 1cd31ea | 2019-01-17 17:14:57 -0500 | [diff] [blame] | 48 | class RenderPass; |
| 49 | |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 50 | class CommandBuffer |
| 51 | { |
| 52 | public: |
| 53 | static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; } |
| 54 | |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 55 | CommandBuffer(Device *device, VkCommandBufferLevel pLevel); |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 56 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 57 | void destroy(const VkAllocationCallbacks *pAllocator); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 58 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 59 | VkResult begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo *pInheritanceInfo); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 60 | VkResult end(); |
| 61 | VkResult reset(VkCommandPoolResetFlags flags); |
| 62 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 63 | void beginRenderPass(RenderPass *renderPass, Framebuffer *framebuffer, VkRect2D renderArea, |
| 64 | uint32_t clearValueCount, const VkClearValue *pClearValues, VkSubpassContents contents); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 65 | void nextSubpass(VkSubpassContents contents); |
| 66 | void endRenderPass(); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 67 | void executeCommands(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 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, |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 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); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 78 | void bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 79 | const VkBuffer *pBuffers, const VkDeviceSize *pOffsets); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 80 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 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); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 89 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 90 | void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports); |
| 91 | void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 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); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 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); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 103 | void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 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); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 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); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 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); |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 135 | |
Alexis Hetu | 9bc7a81 | 2018-12-07 16:13:34 -0500 | [diff] [blame] | 136 | // TODO(sugoi): Move ExecutionState out of CommandBuffer (possibly into Device) |
| 137 | struct ExecutionState |
| 138 | { |
Ben Clayton | 225a130 | 2019-04-02 12:28:22 +0100 | [diff] [blame] | 139 | struct PipelineState |
| 140 | { |
| 141 | Pipeline *pipeline = nullptr; |
Alexis Hetu | 4f438a5 | 2020-06-15 16:13:51 -0400 | [diff] [blame] | 142 | vk::DescriptorSet::Array descriptorSetObjects = {}; |
Ben Clayton | 225a130 | 2019-04-02 12:28:22 +0100 | [diff] [blame] | 143 | vk::DescriptorSet::Bindings descriptorSets = {}; |
| 144 | vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {}; |
| 145 | }; |
| 146 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 147 | sw::Renderer *renderer = nullptr; |
| 148 | sw::TaskEvents *events = nullptr; |
| 149 | RenderPass *renderPass = nullptr; |
| 150 | Framebuffer *renderPassFramebuffer = nullptr; |
Antonio Maiorano | 941293d | 2020-04-27 10:22:49 -0400 | [diff] [blame] | 151 | std::array<PipelineState, vk::VK_PIPELINE_BIND_POINT_RANGE_SIZE> pipelineState; |
Alexis Hetu | 7383243 | 2019-04-11 16:43:18 -0400 | [diff] [blame] | 152 | |
| 153 | struct DynamicState |
| 154 | { |
| 155 | VkViewport viewport; |
| 156 | VkRect2D scissor; |
Nicolas Capens | 68d9ad8 | 2020-04-02 05:22:04 -0400 | [diff] [blame] | 157 | sw::float4 blendConstants; |
Alexis Hetu | 7383243 | 2019-04-11 16:43:18 -0400 | [diff] [blame] | 158 | float depthBiasConstantFactor = 0.0f; |
| 159 | float depthBiasClamp = 0.0f; |
| 160 | float depthBiasSlopeFactor = 0.0f; |
| 161 | float minDepthBounds = 0.0f; |
| 162 | float maxDepthBounds = 0.0f; |
| 163 | |
| 164 | uint32_t compareMask[2] = { 0 }; |
| 165 | uint32_t writeMask[2] = { 0 }; |
| 166 | uint32_t reference[2] = { 0 }; |
| 167 | }; |
| 168 | DynamicState dynamicState; |
| 169 | |
Chris Forbes | a30de54 | 2019-03-18 18:51:55 -0700 | [diff] [blame] | 170 | sw::PushConstantStorage pushConstants; |
Alexis Hetu | 9bc7a81 | 2018-12-07 16:13:34 -0500 | [diff] [blame] | 171 | |
| 172 | struct VertexInputBinding |
| 173 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 174 | Buffer *buffer; |
Alexis Hetu | 9bc7a81 | 2018-12-07 16:13:34 -0500 | [diff] [blame] | 175 | VkDeviceSize offset; |
| 176 | }; |
| 177 | VertexInputBinding vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS] = {}; |
Chris Forbes | baf7ad3 | 2019-02-25 18:14:42 -0800 | [diff] [blame] | 178 | VertexInputBinding indexBufferBinding; |
| 179 | VkIndexType indexType; |
Chris Forbes | 2995dc2 | 2019-03-02 14:57:20 -0800 | [diff] [blame] | 180 | |
Chris Forbes | d6dc4b7 | 2019-08-23 08:23:27 -0700 | [diff] [blame] | 181 | uint32_t subpassIndex = 0; |
| 182 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 183 | void bindAttachments(sw::Context &context); |
| 184 | void bindVertexInputs(sw::Context &context, int firstInstance); |
Alexis Hetu | 9bc7a81 | 2018-12-07 16:13:34 -0500 | [diff] [blame] | 185 | }; |
| 186 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 187 | void submit(CommandBuffer::ExecutionState &executionState); |
| 188 | void submitSecondary(CommandBuffer::ExecutionState &executionState) const; |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 189 | |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 190 | class Command; |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 191 | |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 192 | private: |
Alexis Hetu | d2791c2 | 2018-12-10 14:41:03 -0500 | [diff] [blame] | 193 | void resetState(); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 194 | template<typename T, typename... Args> |
| 195 | void addCommand(Args &&... args); |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 196 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 197 | enum State |
| 198 | { |
| 199 | INITIAL, |
| 200 | RECORDING, |
| 201 | EXECUTABLE, |
| 202 | PENDING, |
| 203 | INVALID |
| 204 | }; |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 205 | |
| 206 | Device *const device; |
Alexis Hetu | a9999ce | 2018-10-17 08:00:43 -0400 | [diff] [blame] | 207 | State state = INITIAL; |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 208 | VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 209 | |
| 210 | // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 211 | std::vector<std::unique_ptr<Command>> *commands; |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 212 | |
| 213 | #ifdef ENABLE_VK_DEBUGGER |
| 214 | std::shared_ptr<vk::dbg::File> debuggerFile; |
| 215 | #endif // ENABLE_VK_DEBUGGER |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 216 | }; |
| 217 | |
| 218 | using DispatchableCommandBuffer = DispatchableObject<CommandBuffer, VkCommandBuffer>; |
| 219 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 220 | static inline CommandBuffer *Cast(VkCommandBuffer object) |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 221 | { |
| 222 | return DispatchableCommandBuffer::Cast(object); |
| 223 | } |
| 224 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 225 | } // namespace vk |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 226 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 227 | #endif // VK_COMMAND_BUFFER_HPP_ |