1 /* 2 * Copyright 2019 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 GrVkSecondaryCBDrawContext_DEFINED 9 #define GrVkSecondaryCBDrawContext_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "include/core/SkSurfaceProps.h" 13 #include "include/core/SkTypes.h" 14 15 #include <memory> 16 17 class GrBackendSemaphore; 18 class GrDeferredDisplayList; 19 class GrRecordingContext; 20 class GrSurfaceCharacterization; 21 struct GrVkDrawableInfo; 22 namespace skgpu::ganesh { 23 class Device; 24 } 25 class SkCanvas; 26 struct SkImageInfo; 27 class SkSurfaceProps; 28 29 /** 30 * This class is a private header that is intended to only be used inside of Chromium. This requires 31 * Chromium to burrow in and include this specifically since it is not part of skia's public include 32 * directory. 33 */ 34 35 /** 36 * This class is used to draw into an external Vulkan secondary command buffer that is imported 37 * by the client. The secondary command buffer that gets imported must already have had begin called 38 * on it with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT. Thus any draws to the imported 39 * command buffer cannot require changing the render pass. This requirement means that certain types 40 * of draws will not be supported when using a GrVkSecondaryCBDrawContext. This includes: 41 * Draws that require a dst copy for blending will be dropped 42 * Text draws will be dropped (these may require intermediate uploads of text data) 43 * Read and Write pixels will not work 44 * Any other draw that requires a copy will fail (this includes using backdrop filter with save 45 * layer). 46 * Stenciling is also disabled, but that should not restrict any actual draws from working. 47 * 48 * While using a GrVkSecondaryCBDrawContext, the client can also draw into normal SkSurfaces and 49 * then draw those SkSufaces (as SkImages) into the GrVkSecondaryCBDrawContext. If any of the 50 * previously mentioned unsupported draws are needed by the client, they can draw them into an 51 * offscreen surface, and then draw that into the GrVkSecondaryCBDrawContext. 52 * 53 * After all drawing to the GrVkSecondaryCBDrawContext has been done, the client must call flush() 54 * on the GrVkSecondaryCBDrawContext to actually fill in the secondary VkCommandBuffer with the 55 * draws. 56 * 57 * Additionally, the client must keep the GrVkSecondaryCBDrawContext alive until the secondary 58 * VkCommandBuffer has been submitted and all work finished on the GPU. Before deleting the 59 * GrVkSecondaryCBDrawContext, the client must call releaseResources() so that Skia can cleanup 60 * any internal objects that were created for the draws into the secondary command buffer. 61 */ 62 class SK_SPI GrVkSecondaryCBDrawContext : public SkRefCnt { 63 public: 64 static sk_sp<GrVkSecondaryCBDrawContext> Make(GrRecordingContext*, 65 const SkImageInfo&, 66 const GrVkDrawableInfo&, 67 const SkSurfaceProps* props); 68 69 ~GrVkSecondaryCBDrawContext() override; 70 71 SkCanvas* getCanvas(); 72 73 // Records all the draws to the imported secondary command buffer and sets any dependent 74 // offscreen draws to the GPU. 75 void flush(); 76 77 /** Inserts a list of GPU semaphores that Skia will have the driver wait on before executing 78 commands for this secondary CB. The wait semaphores will get added to the VkCommandBuffer 79 owned by this GrContext when flush() is called, and not the command buffer which the 80 Secondary CB is from. This will guarantee that the driver waits on the semaphores before 81 the secondary command buffer gets executed. We will submit the semphore to wait at 82 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT and VK_PIPELINE_STAGE_TRANSFER_BIT. If this 83 call returns false, then the GPU back end will not wait on any passed in semaphores, and the 84 client will still own the semaphores, regardless of the value of deleteSemaphoresAfterWait. 85 86 If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case 87 it is the client's responsibility to not destroy or attempt to reuse the semaphores until it 88 knows that Skia has finished waiting on them. This can be done by using finishedProcs 89 on flush calls. 90 91 @param numSemaphores size of waitSemaphores array 92 @param waitSemaphores array of semaphore containers 93 @paramm deleteSemaphoresAfterWait who owns and should delete the semaphores 94 @return true if GPU is waiting on semaphores 95 */ 96 bool wait(int numSemaphores, 97 const GrBackendSemaphore waitSemaphores[], 98 bool deleteSemaphoresAfterWait = true); 99 100 // This call will release all resources held by the draw context. The client must call 101 // releaseResources() before deleting the drawing context. However, the resources also include 102 // any Vulkan resources that were created and used for draws. Therefore the client must only 103 // call releaseResources() after submitting the secondary command buffer, and waiting for it to 104 // finish on the GPU. If it is called earlier then some vulkan objects may be deleted while they 105 // are still in use by the GPU. 106 void releaseResources(); 107 props()108 const SkSurfaceProps& props() const { return fProps; } 109 110 // TODO: Fill out these calls to support DDL 111 bool characterize(GrSurfaceCharacterization* characterization) const; 112 113 #ifndef SK_DDL_IS_UNIQUE_POINTER 114 bool draw(sk_sp<const GrDeferredDisplayList> deferredDisplayList); 115 #else 116 bool draw(const GrDeferredDisplayList* deferredDisplayList); 117 #endif 118 119 bool isCompatible(const GrSurfaceCharacterization& characterization) const; 120 121 private: 122 explicit GrVkSecondaryCBDrawContext(sk_sp<skgpu::ganesh::Device>, const SkSurfaceProps*); 123 124 sk_sp<skgpu::ganesh::Device> fDevice; 125 std::unique_ptr<SkCanvas> fCachedCanvas; 126 const SkSurfaceProps fProps; 127 128 using INHERITED = SkRefCnt; 129 }; 130 131 #endif 132