diff options
author | 2017-02-28 10:02:49 -0500 | |
---|---|---|
committer | 2017-02-28 20:59:57 +0000 | |
commit | 2c2bc11aea4dfcd7ee2f5859838a2aa0a56939e0 (patch) | |
tree | 733d0feaee5fa7695cb1b33a5d9ab5d8a1b2a39e /src/gpu | |
parent | 585dba831c83447861c1977c2e4896d65d449858 (diff) |
Add GrExternalTextureData and SkCrossContextImageData
GrExternalTextureData is an API for exporting the backend-specific
information about a texture in a type-safe way, and without pointing
into the GrTexture. The new detachBackendTexture API lets us release
ownership of a texture to the client.
SkCrossContextImageData is the public API that lets clients upload
textures on one thread/GrContext, then safely transfer ownership to
another thread and GrContext for rendering.
Only GL is implemented/supported right now. Vulkan support requires
that we add thread-safe memory pools, or otherwise transfer the
actual memory block containing the texture to the new context.
Re-land of https://skia-review.googlesource.com/c/8529/
BUG=skia:
Change-Id: I48ebd57d1ea0cfd3a1db10c475f2903afb821966
Reviewed-on: https://skia-review.googlesource.com/8960
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrCaps.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 7 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 4 | ||||
-rw-r--r-- | src/gpu/GrGpuResource.cpp | 11 | ||||
-rw-r--r-- | src/gpu/GrTexturePriv.h | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTexture.cpp | 19 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTexture.h | 1 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 1 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 3 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.h | 2 | ||||
-rw-r--r-- | src/gpu/vk/GrVkTexture.cpp | 6 | ||||
-rw-r--r-- | src/gpu/vk/GrVkTexture.h | 1 |
15 files changed, 82 insertions, 0 deletions
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp index 1efea17bdc..ade64d6588 100644 --- a/src/gpu/GrCaps.cpp +++ b/src/gpu/GrCaps.cpp @@ -53,6 +53,7 @@ GrCaps::GrCaps(const GrContextOptions& options) { fMustClearUploadedBufferData = false; fSampleShadingSupport = false; fFenceSyncSupport = false; + fCrossContextTextureSupport = false; fUseDrawInsteadOfClear = false; @@ -141,6 +142,7 @@ SkString GrCaps::dump() const { r.appendf("Must clear buffer memory : %s\n", gNY[fMustClearUploadedBufferData]); r.appendf("Sample shading support : %s\n", gNY[fSampleShadingSupport]); r.appendf("Fence sync support : %s\n", gNY[fFenceSyncSupport]); + r.appendf("Cross context texture support : %s\n", gNY[fCrossContextTextureSupport]); r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); r.appendf("Draw Instead of TexSubImage [workaround] : %s\n", diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 4b1324e33e..e816687b0b 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -545,6 +545,13 @@ void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) { fDrawingManager->prepareSurfaceForExternalIO(surface); } +GrFence GrContext::prepareSurfaceForExternalIOAndFlush(GrSurface* surface) { + this->prepareSurfaceForExternalIO(surface); + GrFence fence = fGpu->insertFence(); + fGpu->flush(); + return fence; +} + void GrContext::flushSurfaceWrites(GrSurface* surface) { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 0aed3d2c74..f710810650 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -382,6 +382,10 @@ public: virtual bool waitFence(GrFence, uint64_t timeout = 1000) const = 0; virtual void deleteFence(GrFence) const = 0; + // Ensures that all queued up driver-level commands have been sent to the GPU. For example, on + // OpenGL, this calls glFlush. + virtual void flush() = 0; + /////////////////////////////////////////////////////////////////////////// // Debugging and Stats diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp index c3a9556588..dcc4e62282 100644 --- a/src/gpu/GrGpuResource.cpp +++ b/src/gpu/GrGpuResource.cpp @@ -43,6 +43,17 @@ void GrGpuResource::registerWithCacheWrapped() { get_resource_cache(fGpu)->resourceAccess().insertResource(this); } +void GrGpuResource::detachFromCache() { + if (this->wasDestroyed()) { + return; + } + if (fUniqueKey.isValid()) { + this->removeUniqueKey(); + } + this->removeScratchKey(); + this->makeUnbudgeted(); +} + GrGpuResource::~GrGpuResource() { // The cache should have released or destroyed this resource. SkASSERT(this->wasDestroyed()); diff --git a/src/gpu/GrTexturePriv.h b/src/gpu/GrTexturePriv.h index 042061129d..cc0a05edfd 100644 --- a/src/gpu/GrTexturePriv.h +++ b/src/gpu/GrTexturePriv.h @@ -8,6 +8,7 @@ #ifndef GrTexturePriv_DEFINED #define GrTexturePriv_DEFINED +#include "GrExternalTextureData.h" #include "GrTexture.h" /** Class that adds methods to GrTexture that are only intended for use internal to Skia. @@ -67,6 +68,15 @@ public: } SkDestinationSurfaceColorMode mipColorMode() const { return fTexture->fMipColorMode; } + /** + * Return the native bookkeeping data for this texture, and detach the backend object from + * this GrTexture. It's lifetime will no longer be managed by Ganesh, and this GrTexture will + * no longer refer to it. Leaves this GrTexture in an orphan state. + */ + std::unique_ptr<GrExternalTextureData> detachBackendTexture() { + return fTexture->detachBackendTexture(); + } + static void ComputeScratchKey(const GrSurfaceDesc&, GrScratchKey*); private: diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index ddf225213e..0bcb7e817b 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -603,6 +603,15 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, fFenceSyncSupport = true; } + // Safely moving textures between contexts requires fences. The Windows Intel driver has a + // bug with deleting and reusing texture IDs across contexts, so disallow this feature. + fCrossContextTextureSupport = fFenceSyncSupport; +#ifdef SK_BUILD_FOR_WIN + if (kIntel_GrGLVendor == ctxInfo.vendor()) { + fCrossContextTextureSupport = false; + } +#endif + // We support manual mip-map generation (via iterative downsampling draw calls). This fixes // bugs on some cards/drivers that produce incorrect mip-maps for sRGB textures when using // glGenerateMipmap. Our implementation requires mip-level sampling control. Additionally, diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index ad00b0a90c..5dce7d1e2b 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -4741,3 +4741,7 @@ bool GrGLGpu::waitFence(GrFence fence, uint64_t timeout) const { void GrGLGpu::deleteFence(GrFence fence) const { GL_CALL(DeleteSync((GrGLsync)fence)); } + +void GrGLGpu::flush() { + GL_CALL(Flush()); +} diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index fdc2ebbfa9..b6ca4f6fd6 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -150,6 +150,8 @@ public: bool waitFence(GrFence, uint64_t timeout) const override; void deleteFence(GrFence) const override; + void flush() override; + private: GrGLGpu(GrGLContext* ctx, GrContext* context); diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp index edce7b1f33..a5609887c0 100644 --- a/src/gpu/gl/GrGLTexture.cpp +++ b/src/gpu/gl/GrGLTexture.cpp @@ -5,9 +5,11 @@ * found in the LICENSE file. */ +#include "GrContext.h" #include "GrGLTexture.h" #include "GrGLGpu.h" #include "GrShaderCaps.h" +#include "SkMakeUnique.h" #include "SkTraceMemoryDump.h" #define GPUGL static_cast<GrGLGpu*>(this->getGpu()) @@ -111,6 +113,23 @@ GrBackendObject GrGLTexture::getTextureHandle() const { return reinterpret_cast<GrBackendObject>(&fInfo); } +std::unique_ptr<GrExternalTextureData> GrGLTexture::detachBackendTexture() { + // Flush any pending writes to this texture, as well GL itself + GrFence fence = this->getContext()->prepareSurfaceForExternalIOAndFlush(this); + + // Make a copy of our GL-specific information + auto data = skstd::make_unique<GrGLExternalTextureData>(fInfo, fence); + + // Ensure the cache can't reach this texture anymore + this->detachFromCache(); + + // Detach from the GL object, so we don't use it (or try to delete it when we're freed) + fInfo.fTarget = 0; + fInfo.fID = 0; + + return std::move(data); +} + void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, const SkString& dumpName) const { SkString texture_id; diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h index 029fd87a1a..16b47f1f07 100644 --- a/src/gpu/gl/GrGLTexture.h +++ b/src/gpu/gl/GrGLTexture.h @@ -71,6 +71,7 @@ protected: void onRelease() override; void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, const SkString& dumpName) const override; + std::unique_ptr<GrExternalTextureData> detachBackendTexture() override; private: TexParams fTexParams; diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp index 94c1a50d2b..fd454ad544 100644 --- a/src/gpu/vk/GrVkCaps.cpp +++ b/src/gpu/vk/GrVkCaps.cpp @@ -37,6 +37,7 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* fUseDrawInsteadOfClear = false; fFenceSyncSupport = true; // always available in Vulkan + fCrossContextTextureSupport = false; // TODO: Add thread-safe memory pools so we can enable this fMapBufferFlags = kNone_MapFlags; //TODO: figure this out fBufferMapThreshold = SK_MaxS32; //TODO: figure this out diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 915ac9747e..8569c9367f 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -1860,3 +1860,6 @@ void GrVkGpu::deleteFence(GrFence fence) const { GR_VK_CALL(this->vkInterface(), DestroyFence(this->device(), (VkFence)fence, nullptr)); } +void GrVkGpu::flush() { + // We submit the command buffer to the queue whenever Ganesh is flushed, so nothing is needed +} diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index 18059b9682..c935945bd1 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -133,6 +133,8 @@ public: bool waitFence(GrFence, uint64_t timeout) const override; void deleteFence(GrFence) const override; + void flush() override; + void generateMipmap(GrVkTexture* tex); bool updateBuffer(GrVkBuffer* buffer, const void* src, VkDeviceSize offset, VkDeviceSize size); diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp index 7f0cf8d1d8..a8f1bf00dc 100644 --- a/src/gpu/vk/GrVkTexture.cpp +++ b/src/gpu/vk/GrVkTexture.cpp @@ -144,6 +144,12 @@ GrBackendObject GrVkTexture::getTextureHandle() const { return (GrBackendObject)&fInfo; } +std::unique_ptr<GrExternalTextureData> GrVkTexture::detachBackendTexture() { + // Not supported on Vulkan yet + // TODO: Add thread-safe memory pools, and implement this. + return nullptr; +} + GrVkGpu* GrVkTexture::getVkGpu() const { SkASSERT(!this->wasDestroyed()); return static_cast<GrVkGpu*>(this->getGpu()); diff --git a/src/gpu/vk/GrVkTexture.h b/src/gpu/vk/GrVkTexture.h index 70db54838d..db7124e2b8 100644 --- a/src/gpu/vk/GrVkTexture.h +++ b/src/gpu/vk/GrVkTexture.h @@ -42,6 +42,7 @@ protected: void onAbandon() override; void onRelease() override; + std::unique_ptr<GrExternalTextureData> detachBackendTexture() override; private: enum Wrapped { kWrapped }; |