1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrVkGpuCommandBuffer_DEFINED 9 #define GrVkGpuCommandBuffer_DEFINED 10 11 #include "src/gpu/GrGpuCommandBuffer.h" 12 13 #include "include/gpu/GrTypes.h" 14 #include "include/gpu/vk/GrVkTypes.h" 15 #include "src/gpu/GrColor.h" 16 #include "src/gpu/GrMesh.h" 17 #include "src/gpu/GrTRecorder.h" 18 #include "src/gpu/vk/GrVkPipelineState.h" 19 20 class GrVkGpu; 21 class GrVkImage; 22 class GrVkRenderPass; 23 class GrVkRenderTarget; 24 class GrVkSecondaryCommandBuffer; 25 26 /** Base class for tasks executed on primary command buffer, between secondary command buffers. */ 27 class GrVkPrimaryCommandBufferTask { 28 public: 29 virtual ~GrVkPrimaryCommandBufferTask(); 30 31 struct Args { 32 GrGpu* fGpu; 33 GrSurface* fSurface; 34 }; 35 36 virtual void execute(const Args& args) = 0; 37 38 protected: 39 GrVkPrimaryCommandBufferTask(); 40 GrVkPrimaryCommandBufferTask(const GrVkPrimaryCommandBufferTask&) = delete; 41 GrVkPrimaryCommandBufferTask& operator=(const GrVkPrimaryCommandBufferTask&) = delete; 42 }; 43 44 class GrVkGpuTextureCommandBuffer : public GrGpuTextureCommandBuffer { 45 public: GrVkGpuTextureCommandBuffer(GrVkGpu * gpu)46 GrVkGpuTextureCommandBuffer(GrVkGpu* gpu) : fGpu(gpu) {} 47 48 void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override; 49 void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType, 50 GrColorType bufferColorType, GrGpuBuffer* transferBuffer, 51 size_t offset) override; 52 53 void insertEventMarker(const char*) override; 54 reset()55 void reset() { 56 fTasks.reset(); 57 fTexture = nullptr; 58 #ifdef SK_DEBUG 59 fIsActive = false; 60 #endif 61 } 62 setVk(GrTexture * tex,GrSurfaceOrigin origin)63 void setVk(GrTexture* tex, GrSurfaceOrigin origin) { 64 #ifdef SK_DEBUG 65 fIsActive = true; 66 #endif 67 this->INHERITED::set(tex, origin); 68 } 69 70 #ifdef SK_DEBUG isActive()71 bool isActive() const { return fIsActive; } 72 #endif 73 74 void submit(); 75 76 private: 77 GrVkGpu* fGpu; 78 GrTRecorder<GrVkPrimaryCommandBufferTask> fTasks{1024}; 79 80 #ifdef SK_DEBUG 81 // When we are actively recording into the GrVkGpuCommandBuffer we set this flag to true. This 82 // then allows us to assert that we never submit a primary command buffer to the queue while in 83 // a recording state. This is needed since when we submit to the queue we change command pools 84 // and may trigger the old one to be reset, but a recording GrVkGpuCommandBuffer may still have 85 // a outstanding secondary command buffer allocated from that pool that we'll try to access 86 // after the pool as been reset. 87 bool fIsActive = false; 88 #endif 89 90 typedef GrGpuTextureCommandBuffer INHERITED; 91 }; 92 93 class GrVkGpuRTCommandBuffer : public GrGpuRTCommandBuffer, private GrMesh::SendToGpuImpl { 94 public: 95 GrVkGpuRTCommandBuffer(GrVkGpu*); 96 97 ~GrVkGpuRTCommandBuffer() override; 98 begin()99 void begin() override { } 100 void end() override; 101 102 void insertEventMarker(const char*) override; 103 104 void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override; 105 106 void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override; 107 void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType, 108 GrColorType bufferColorType, GrGpuBuffer* transferBuffer, 109 size_t offset) override; 110 111 void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override; 112 113 void set(GrRenderTarget*, GrSurfaceOrigin, 114 const GrGpuRTCommandBuffer::LoadAndStoreInfo&, 115 const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&); 116 void reset(); 117 118 void submit(); 119 120 #ifdef SK_DEBUG isActive()121 bool isActive() const { return fIsActive; } 122 #endif 123 124 private: 125 void init(); 126 127 // Called instead of init when we are drawing to a render target that already wraps a secondary 128 // command buffer. 129 void initWrapped(); 130 131 bool wrapsSecondaryCommandBuffer() const; 132 133 GrGpu* gpu() override; 134 135 // Bind vertex and index buffers 136 void bindGeometry(const GrGpuBuffer* indexBuffer, 137 const GrGpuBuffer* vertexBuffer, 138 const GrGpuBuffer* instanceBuffer); 139 140 GrVkPipelineState* prepareDrawState(const GrPrimitiveProcessor&, 141 const GrPipeline&, 142 const GrPipeline::FixedDynamicState*, 143 const GrPipeline::DynamicStateArrays*, 144 GrPrimitiveType); 145 146 void onDraw(const GrPrimitiveProcessor&, 147 const GrPipeline&, 148 const GrPipeline::FixedDynamicState*, 149 const GrPipeline::DynamicStateArrays*, 150 const GrMesh[], 151 int meshCount, 152 const SkRect& bounds) override; 153 154 // GrMesh::SendToGpuImpl methods. These issue the actual Vulkan draw commands. 155 // Marked final as a hint to the compiler to not use virtual dispatch. sendMeshToGpu(GrPrimitiveType primType,const GrBuffer * vertexBuffer,int vertexCount,int baseVertex)156 void sendMeshToGpu(GrPrimitiveType primType, const GrBuffer* vertexBuffer, int vertexCount, 157 int baseVertex) final { 158 this->sendInstancedMeshToGpu(primType, vertexBuffer, vertexCount, baseVertex, nullptr, 1, 159 0); 160 } 161 sendIndexedMeshToGpu(GrPrimitiveType primType,const GrBuffer * indexBuffer,int indexCount,int baseIndex,uint16_t,uint16_t,const GrBuffer * vertexBuffer,int baseVertex,GrPrimitiveRestart restart)162 void sendIndexedMeshToGpu(GrPrimitiveType primType, const GrBuffer* indexBuffer, int indexCount, 163 int baseIndex, uint16_t /*minIndexValue*/, uint16_t /*maxIndexValue*/, 164 const GrBuffer* vertexBuffer, int baseVertex, 165 GrPrimitiveRestart restart) final { 166 SkASSERT(restart == GrPrimitiveRestart::kNo); 167 this->sendIndexedInstancedMeshToGpu(primType, indexBuffer, indexCount, baseIndex, 168 vertexBuffer, baseVertex, nullptr, 1, 0, 169 GrPrimitiveRestart::kNo); 170 } 171 172 void sendInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount, 173 int baseVertex, const GrBuffer* instanceBuffer, int instanceCount, 174 int baseInstance) final; 175 176 void sendIndexedInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer, int indexCount, 177 int baseIndex, const GrBuffer* vertexBuffer, int baseVertex, 178 const GrBuffer* instanceBuffer, int instanceCount, 179 int baseInstance, GrPrimitiveRestart) final; 180 181 void onClear(const GrFixedClip&, const SkPMColor4f& color) override; 182 183 void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override; 184 185 void addAdditionalRenderPass(); 186 187 enum class LoadStoreState { 188 kUnknown, 189 kStartsWithClear, 190 kStartsWithDiscard, 191 kLoadAndStore, 192 }; 193 194 struct CommandBufferInfo { 195 using SampledTexture = GrPendingIOResource<GrVkTexture, kRead_GrIOType>; 196 const GrVkRenderPass* fRenderPass; 197 std::unique_ptr<GrVkSecondaryCommandBuffer> fCommandBuffer; 198 int fNumPreCmds = 0; 199 VkClearValue fColorClearValue; 200 SkRect fBounds; 201 bool fIsEmpty = true; 202 LoadStoreState fLoadStoreState = LoadStoreState::kUnknown; 203 // Array of images that will be sampled and thus need to be transferred to sampled layout 204 // before submitting the secondary command buffers. This must happen after we do any predraw 205 // uploads or copies. 206 SkTArray<SampledTexture> fSampledTextures; 207 currentCmdBufCommandBufferInfo208 GrVkSecondaryCommandBuffer* currentCmdBuf() { 209 return fCommandBuffer.get(); 210 } 211 }; 212 213 SkTArray<CommandBufferInfo> fCommandBufferInfos; 214 GrTRecorder<GrVkPrimaryCommandBufferTask> fPreCommandBufferTasks{1024}; 215 GrVkGpu* fGpu; 216 GrVkPipelineState* fLastPipelineState = nullptr; 217 SkPMColor4f fClearColor; 218 VkAttachmentLoadOp fVkColorLoadOp; 219 VkAttachmentStoreOp fVkColorStoreOp; 220 VkAttachmentLoadOp fVkStencilLoadOp; 221 VkAttachmentStoreOp fVkStencilStoreOp; 222 int fCurrentCmdInfo = -1; 223 224 #ifdef SK_DEBUG 225 // When we are actively recording into the GrVkGpuCommandBuffer we set this flag to true. This 226 // then allows us to assert that we never submit a primary command buffer to the queue while in 227 // a recording state. This is needed since when we submit to the queue we change command pools 228 // and may trigger the old one to be reset, but a recording GrVkGpuCommandBuffer may still have 229 // a outstanding secondary command buffer allocated from that pool that we'll try to access 230 // after the pool as been reset. 231 bool fIsActive = false; 232 #endif 233 234 typedef GrGpuRTCommandBuffer INHERITED; 235 }; 236 237 #endif 238