| /* |
| * Copyright 2019 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrVkSecondaryCBDrawContext_DEFINED |
| #define GrVkSecondaryCBDrawContext_DEFINED |
| |
| #include "include/core/SkRefCnt.h" |
| #include "include/core/SkSurfaceProps.h" |
| #include "include/core/SkTypes.h" |
| |
| #include <memory> |
| |
| class GrBackendSemaphore; |
| class GrDeferredDisplayList; |
| class GrRecordingContext; |
| class GrSurfaceCharacterization; |
| struct GrVkDrawableInfo; |
| namespace skgpu::ganesh { |
| class Device; |
| } |
| class SkCanvas; |
| struct SkImageInfo; |
| class SkSurfaceProps; |
| |
| /** |
| * This class is a private header that is intended to only be used inside of Chromium. This requires |
| * Chromium to burrow in and include this specifically since it is not part of skia's public include |
| * directory. |
| */ |
| |
| /** |
| * This class is used to draw into an external Vulkan secondary command buffer that is imported |
| * by the client. The secondary command buffer that gets imported must already have had begin called |
| * on it with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT. Thus any draws to the imported |
| * command buffer cannot require changing the render pass. This requirement means that certain types |
| * of draws will not be supported when using a GrVkSecondaryCBDrawContext. This includes: |
| * Draws that require a dst copy for blending will be dropped |
| * Text draws will be dropped (these may require intermediate uploads of text data) |
| * Read and Write pixels will not work |
| * Any other draw that requires a copy will fail (this includes using backdrop filter with save |
| * layer). |
| * Stenciling is also disabled, but that should not restrict any actual draws from working. |
| * |
| * While using a GrVkSecondaryCBDrawContext, the client can also draw into normal SkSurfaces and |
| * then draw those SkSufaces (as SkImages) into the GrVkSecondaryCBDrawContext. If any of the |
| * previously mentioned unsupported draws are needed by the client, they can draw them into an |
| * offscreen surface, and then draw that into the GrVkSecondaryCBDrawContext. |
| * |
| * After all drawing to the GrVkSecondaryCBDrawContext has been done, the client must call flush() |
| * on the GrVkSecondaryCBDrawContext to actually fill in the secondary VkCommandBuffer with the |
| * draws. |
| * |
| * Additionally, the client must keep the GrVkSecondaryCBDrawContext alive until the secondary |
| * VkCommandBuffer has been submitted and all work finished on the GPU. Before deleting the |
| * GrVkSecondaryCBDrawContext, the client must call releaseResources() so that Skia can cleanup |
| * any internal objects that were created for the draws into the secondary command buffer. |
| */ |
| class SK_SPI GrVkSecondaryCBDrawContext : public SkRefCnt { |
| public: |
| static sk_sp<GrVkSecondaryCBDrawContext> Make(GrRecordingContext*, |
| const SkImageInfo&, |
| const GrVkDrawableInfo&, |
| const SkSurfaceProps* props); |
| |
| ~GrVkSecondaryCBDrawContext() override; |
| |
| SkCanvas* getCanvas(); |
| |
| // Records all the draws to the imported secondary command buffer and sets any dependent |
| // offscreen draws to the GPU. |
| void flush(); |
| |
| /** Inserts a list of GPU semaphores that Skia will have the driver wait on before executing |
| commands for this secondary CB. The wait semaphores will get added to the VkCommandBuffer |
| owned by this GrContext when flush() is called, and not the command buffer which the |
| Secondary CB is from. This will guarantee that the driver waits on the semaphores before |
| the secondary command buffer gets executed. We will submit the semphore to wait at |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT and VK_PIPELINE_STAGE_TRANSFER_BIT. If this |
| call returns false, then the GPU back end will not wait on any passed in semaphores, and the |
| client will still own the semaphores, regardless of the value of deleteSemaphoresAfterWait. |
| |
| If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case |
| it is the client's responsibility to not destroy or attempt to reuse the semaphores until it |
| knows that Skia has finished waiting on them. This can be done by using finishedProcs |
| on flush calls. |
| |
| @param numSemaphores size of waitSemaphores array |
| @param waitSemaphores array of semaphore containers |
| @paramm deleteSemaphoresAfterWait who owns and should delete the semaphores |
| @return true if GPU is waiting on semaphores |
| */ |
| bool wait(int numSemaphores, |
| const GrBackendSemaphore waitSemaphores[], |
| bool deleteSemaphoresAfterWait = true); |
| |
| // This call will release all resources held by the draw context. The client must call |
| // releaseResources() before deleting the drawing context. However, the resources also include |
| // any Vulkan resources that were created and used for draws. Therefore the client must only |
| // call releaseResources() after submitting the secondary command buffer, and waiting for it to |
| // finish on the GPU. If it is called earlier then some vulkan objects may be deleted while they |
| // are still in use by the GPU. |
| void releaseResources(); |
| |
| const SkSurfaceProps& props() const { return fProps; } |
| |
| // TODO: Fill out these calls to support DDL |
| bool characterize(GrSurfaceCharacterization* characterization) const; |
| |
| #ifndef SK_DDL_IS_UNIQUE_POINTER |
| bool draw(sk_sp<const GrDeferredDisplayList> deferredDisplayList); |
| #else |
| bool draw(const GrDeferredDisplayList* deferredDisplayList); |
| #endif |
| |
| bool isCompatible(const GrSurfaceCharacterization& characterization) const; |
| |
| private: |
| explicit GrVkSecondaryCBDrawContext(sk_sp<skgpu::ganesh::Device>, const SkSurfaceProps*); |
| |
| sk_sp<skgpu::ganesh::Device> fDevice; |
| std::unique_ptr<SkCanvas> fCachedCanvas; |
| const SkSurfaceProps fProps; |
| |
| using INHERITED = SkRefCnt; |
| }; |
| |
| #endif |