1 /*
2 * Copyright 2015 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 #include "GrVkCommandBuffer.h"
9
10 #include "GrVkFramebuffer.h"
11 #include "GrVkImageView.h"
12 #include "GrVkRenderPass.h"
13 #include "GrVkRenderTarget.h"
14 #include "GrVkProgram.h"
15 #include "GrVkTransferBuffer.h"
16 #include "GrVkUtil.h"
17
Create(const GrVkGpu * gpu,VkCommandPool cmdPool)18 GrVkCommandBuffer* GrVkCommandBuffer::Create(const GrVkGpu* gpu, VkCommandPool cmdPool) {
19 const VkCommandBufferAllocateInfo cmdInfo = {
20 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
21 NULL, // pNext
22 cmdPool, // commandPool
23 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
24 1 // bufferCount
25 };
26
27 VkCommandBuffer cmdBuffer;
28 VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(),
29 &cmdInfo,
30 &cmdBuffer));
31 if (err) {
32 return nullptr;
33 }
34 return new GrVkCommandBuffer(cmdBuffer);
35 }
36
~GrVkCommandBuffer()37 GrVkCommandBuffer::~GrVkCommandBuffer() {
38 // Should have ended any render pass we're in the middle of
39 SkASSERT(!fActiveRenderPass);
40 }
41
invalidateState()42 void GrVkCommandBuffer::invalidateState() {
43 fBoundVertexBuffer = 0;
44 fBoundVertexBufferIsValid = false;
45 fBoundIndexBuffer = 0;
46 fBoundIndexBufferIsValid = false;
47 }
48
freeGPUData(const GrVkGpu * gpu) const49 void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const {
50 SkASSERT(!fIsActive);
51 SkASSERT(!fActiveRenderPass);
52 for (int i = 0; i < fTrackedResources.count(); ++i) {
53 fTrackedResources[i]->unref(gpu);
54 }
55
56 // Destroy the fence, if any
57 if (VK_NULL_HANDLE != fSubmitFence) {
58 GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
59 }
60
61 GR_VK_CALL(gpu->vkInterface(), FreeCommandBuffers(gpu->device(), gpu->cmdPool(),
62 1, &fCmdBuffer));
63 }
64
abandonSubResources() const65 void GrVkCommandBuffer::abandonSubResources() const {
66 for (int i = 0; i < fTrackedResources.count(); ++i) {
67 fTrackedResources[i]->unrefAndAbandon();
68 }
69 }
70
begin(const GrVkGpu * gpu)71 void GrVkCommandBuffer::begin(const GrVkGpu* gpu) {
72 SkASSERT(!fIsActive);
73 VkCommandBufferBeginInfo cmdBufferBeginInfo;
74 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
75 cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
76 cmdBufferBeginInfo.pNext = nullptr;
77 cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
78 cmdBufferBeginInfo.pInheritanceInfo = nullptr;
79
80 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), BeginCommandBuffer(fCmdBuffer,
81 &cmdBufferBeginInfo));
82 fIsActive = true;
83 }
84
end(const GrVkGpu * gpu)85 void GrVkCommandBuffer::end(const GrVkGpu* gpu) {
86 SkASSERT(fIsActive);
87 SkASSERT(!fActiveRenderPass);
88 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer));
89 this->invalidateState();
90 fIsActive = false;
91 }
92
93 ///////////////////////////////////////////////////////////////////////////////
94
beginRenderPass(const GrVkGpu * gpu,const GrVkRenderPass * renderPass,const GrVkRenderTarget & target)95 void GrVkCommandBuffer::beginRenderPass(const GrVkGpu* gpu,
96 const GrVkRenderPass* renderPass,
97 const GrVkRenderTarget& target) {
98 SkASSERT(fIsActive);
99 SkASSERT(!fActiveRenderPass);
100 VkRenderPassBeginInfo beginInfo;
101 VkSubpassContents contents;
102 renderPass->getBeginInfo(target, &beginInfo, &contents);
103 GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents));
104 fActiveRenderPass = renderPass;
105 this->addResource(renderPass);
106 target.addResources(*this);
107
108 }
109
endRenderPass(const GrVkGpu * gpu)110 void GrVkCommandBuffer::endRenderPass(const GrVkGpu* gpu) {
111 SkASSERT(fIsActive);
112 SkASSERT(fActiveRenderPass);
113 GR_VK_CALL(gpu->vkInterface(), CmdEndRenderPass(fCmdBuffer));
114 fActiveRenderPass = nullptr;
115 }
116
submitToQueue(const GrVkGpu * gpu,VkQueue queue,GrVkGpu::SyncQueue sync)117 void GrVkCommandBuffer::submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync) {
118 SkASSERT(!fIsActive);
119
120 VkResult err;
121 VkFenceCreateInfo fenceInfo;
122 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
123 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
124 err = GR_VK_CALL(gpu->vkInterface(), CreateFence(gpu->device(), &fenceInfo, nullptr,
125 &fSubmitFence));
126 SkASSERT(!err);
127
128 VkSubmitInfo submitInfo;
129 memset(&submitInfo, 0, sizeof(VkSubmitInfo));
130 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
131 submitInfo.pNext = nullptr;
132 submitInfo.waitSemaphoreCount = 0;
133 submitInfo.pWaitSemaphores = nullptr;
134 submitInfo.commandBufferCount = 1;
135 submitInfo.pCommandBuffers = &fCmdBuffer;
136 submitInfo.signalSemaphoreCount = 0;
137 submitInfo.pSignalSemaphores = nullptr;
138 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), QueueSubmit(queue, 1, &submitInfo, fSubmitFence));
139
140 if (GrVkGpu::kForce_SyncQueue == sync) {
141 err = GR_VK_CALL(gpu->vkInterface(),
142 WaitForFences(gpu->device(), 1, &fSubmitFence, true, UINT64_MAX));
143 if (VK_TIMEOUT == err) {
144 SkDebugf("Fence failed to signal: %d\n", err);
145 SkFAIL("failing");
146 }
147 SkASSERT(!err);
148
149 // Destroy the fence
150 GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
151 fSubmitFence = VK_NULL_HANDLE;
152 }
153 }
154
finished(const GrVkGpu * gpu) const155 bool GrVkCommandBuffer::finished(const GrVkGpu* gpu) const {
156 if (VK_NULL_HANDLE == fSubmitFence) {
157 return true;
158 }
159
160 VkResult err = GR_VK_CALL(gpu->vkInterface(), GetFenceStatus(gpu->device(), fSubmitFence));
161 switch (err) {
162 case VK_SUCCESS:
163 return true;
164
165 case VK_NOT_READY:
166 return false;
167
168 default:
169 SkDebugf("Error getting fence status: %d\n", err);
170 SkFAIL("failing");
171 break;
172 }
173
174 return false;
175 }
176
177 ////////////////////////////////////////////////////////////////////////////////
178 // CommandBuffer commands
179 ////////////////////////////////////////////////////////////////////////////////
180
pipelineBarrier(const GrVkGpu * gpu,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,bool byRegion,BarrierType barrierType,void * barrier) const181 void GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu,
182 VkPipelineStageFlags srcStageMask,
183 VkPipelineStageFlags dstStageMask,
184 bool byRegion,
185 BarrierType barrierType,
186 void* barrier) const {
187 SkASSERT(fIsActive);
188 VkDependencyFlags dependencyFlags = byRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0;
189
190 switch (barrierType) {
191 case kMemory_BarrierType: {
192 const VkMemoryBarrier* barrierPtr = reinterpret_cast<VkMemoryBarrier*>(barrier);
193 GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask,
194 dstStageMask, dependencyFlags,
195 1, barrierPtr,
196 0, nullptr,
197 0, nullptr));
198 break;
199 }
200
201 case kBufferMemory_BarrierType: {
202 const VkBufferMemoryBarrier* barrierPtr =
203 reinterpret_cast<VkBufferMemoryBarrier*>(barrier);
204 GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask,
205 dstStageMask, dependencyFlags,
206 0, nullptr,
207 1, barrierPtr,
208 0, nullptr));
209 break;
210 }
211
212 case kImageMemory_BarrierType: {
213 const VkImageMemoryBarrier* barrierPtr =
214 reinterpret_cast<VkImageMemoryBarrier*>(barrier);
215 GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask,
216 dstStageMask, dependencyFlags,
217 0, nullptr,
218 0, nullptr,
219 1, barrierPtr));
220 break;
221 }
222 }
223
224 }
225
copyImage(const GrVkGpu * gpu,GrVkImage * srcImage,VkImageLayout srcLayout,GrVkImage * dstImage,VkImageLayout dstLayout,uint32_t copyRegionCount,const VkImageCopy * copyRegions)226 void GrVkCommandBuffer::copyImage(const GrVkGpu* gpu,
227 GrVkImage* srcImage,
228 VkImageLayout srcLayout,
229 GrVkImage* dstImage,
230 VkImageLayout dstLayout,
231 uint32_t copyRegionCount,
232 const VkImageCopy* copyRegions) {
233 SkASSERT(fIsActive);
234 SkASSERT(!fActiveRenderPass);
235 this->addResource(srcImage->resource());
236 this->addResource(dstImage->resource());
237 GR_VK_CALL(gpu->vkInterface(), CmdCopyImage(fCmdBuffer,
238 srcImage->textureImage(),
239 srcLayout,
240 dstImage->textureImage(),
241 dstLayout,
242 copyRegionCount,
243 copyRegions));
244 }
245
copyImageToBuffer(const GrVkGpu * gpu,GrVkImage * srcImage,VkImageLayout srcLayout,GrVkTransferBuffer * dstBuffer,uint32_t copyRegionCount,const VkBufferImageCopy * copyRegions)246 void GrVkCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu,
247 GrVkImage* srcImage,
248 VkImageLayout srcLayout,
249 GrVkTransferBuffer* dstBuffer,
250 uint32_t copyRegionCount,
251 const VkBufferImageCopy* copyRegions) {
252 SkASSERT(fIsActive);
253 SkASSERT(!fActiveRenderPass);
254 this->addResource(srcImage->resource());
255 this->addResource(dstBuffer->resource());
256 GR_VK_CALL(gpu->vkInterface(), CmdCopyImageToBuffer(fCmdBuffer,
257 srcImage->textureImage(),
258 srcLayout,
259 dstBuffer->buffer(),
260 copyRegionCount,
261 copyRegions));
262 }
263
copyBufferToImage(const GrVkGpu * gpu,GrVkTransferBuffer * srcBuffer,GrVkImage * dstImage,VkImageLayout dstLayout,uint32_t copyRegionCount,const VkBufferImageCopy * copyRegions)264 void GrVkCommandBuffer::copyBufferToImage(const GrVkGpu* gpu,
265 GrVkTransferBuffer* srcBuffer,
266 GrVkImage* dstImage,
267 VkImageLayout dstLayout,
268 uint32_t copyRegionCount,
269 const VkBufferImageCopy* copyRegions) {
270 SkASSERT(fIsActive);
271 SkASSERT(!fActiveRenderPass);
272 this->addResource(srcBuffer->resource());
273 this->addResource(dstImage->resource());
274 GR_VK_CALL(gpu->vkInterface(), CmdCopyBufferToImage(fCmdBuffer,
275 srcBuffer->buffer(),
276 dstImage->textureImage(),
277 dstLayout,
278 copyRegionCount,
279 copyRegions));
280 }
281
clearColorImage(const GrVkGpu * gpu,GrVkImage * image,const VkClearColorValue * color,uint32_t subRangeCount,const VkImageSubresourceRange * subRanges)282 void GrVkCommandBuffer::clearColorImage(const GrVkGpu* gpu,
283 GrVkImage* image,
284 const VkClearColorValue* color,
285 uint32_t subRangeCount,
286 const VkImageSubresourceRange* subRanges) {
287 SkASSERT(fIsActive);
288 SkASSERT(!fActiveRenderPass);
289 this->addResource(image->resource());
290 GR_VK_CALL(gpu->vkInterface(), CmdClearColorImage(fCmdBuffer,
291 image->textureImage(),
292 image->currentLayout(),
293 color,
294 subRangeCount,
295 subRanges));
296 }
297
clearAttachments(const GrVkGpu * gpu,int numAttachments,const VkClearAttachment * attachments,int numRects,const VkClearRect * clearRects) const298 void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu,
299 int numAttachments,
300 const VkClearAttachment* attachments,
301 int numRects,
302 const VkClearRect* clearRects) const {
303 SkASSERT(fIsActive);
304 SkASSERT(fActiveRenderPass);
305 SkASSERT(numAttachments > 0);
306 SkASSERT(numRects > 0);
307 #ifdef SK_DEBUG
308 for (int i = 0; i < numAttachments; ++i) {
309 if (attachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
310 uint32_t testIndex;
311 SkAssertResult(fActiveRenderPass->colorAttachmentIndex(&testIndex));
312 SkASSERT(testIndex == attachments[i].colorAttachment);
313 }
314 }
315 #endif
316 GR_VK_CALL(gpu->vkInterface(), CmdClearAttachments(fCmdBuffer,
317 numAttachments,
318 attachments,
319 numRects,
320 clearRects));
321 }
322
bindDescriptorSets(const GrVkGpu * gpu,GrVkProgram * program,VkPipelineLayout layout,uint32_t firstSet,uint32_t setCount,const VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets)323 void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
324 GrVkProgram* program,
325 VkPipelineLayout layout,
326 uint32_t firstSet,
327 uint32_t setCount,
328 const VkDescriptorSet* descriptorSets,
329 uint32_t dynamicOffsetCount,
330 const uint32_t* dynamicOffsets) {
331 SkASSERT(fIsActive);
332 GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer,
333 VK_PIPELINE_BIND_POINT_GRAPHICS,
334 layout,
335 firstSet,
336 setCount,
337 descriptorSets,
338 dynamicOffsetCount,
339 dynamicOffsets));
340 program->addUniformResources(*this);
341 }
342
drawIndexed(const GrVkGpu * gpu,uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance) const343 void GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu,
344 uint32_t indexCount,
345 uint32_t instanceCount,
346 uint32_t firstIndex,
347 int32_t vertexOffset,
348 uint32_t firstInstance) const {
349 SkASSERT(fIsActive);
350 SkASSERT(fActiveRenderPass);
351 GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexed(fCmdBuffer,
352 indexCount,
353 instanceCount,
354 firstIndex,
355 vertexOffset,
356 firstInstance));
357 }
358
draw(const GrVkGpu * gpu,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance) const359 void GrVkCommandBuffer::draw(const GrVkGpu* gpu,
360 uint32_t vertexCount,
361 uint32_t instanceCount,
362 uint32_t firstVertex,
363 uint32_t firstInstance) const {
364 SkASSERT(fIsActive);
365 SkASSERT(fActiveRenderPass);
366 GR_VK_CALL(gpu->vkInterface(), CmdDraw(fCmdBuffer,
367 vertexCount,
368 instanceCount,
369 firstVertex,
370 firstInstance));
371 }
372