aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2017-02-28 10:02:49 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-28 20:59:57 +0000
commit2c2bc11aea4dfcd7ee2f5859838a2aa0a56939e0 (patch)
tree733d0feaee5fa7695cb1b33a5d9ab5d8a1b2a39e /src/gpu
parent585dba831c83447861c1977c2e4896d65d449858 (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.cpp2
-rw-r--r--src/gpu/GrContext.cpp7
-rw-r--r--src/gpu/GrGpu.h4
-rw-r--r--src/gpu/GrGpuResource.cpp11
-rw-r--r--src/gpu/GrTexturePriv.h10
-rw-r--r--src/gpu/gl/GrGLCaps.cpp9
-rw-r--r--src/gpu/gl/GrGLGpu.cpp4
-rw-r--r--src/gpu/gl/GrGLGpu.h2
-rw-r--r--src/gpu/gl/GrGLTexture.cpp19
-rw-r--r--src/gpu/gl/GrGLTexture.h1
-rw-r--r--src/gpu/vk/GrVkCaps.cpp1
-rw-r--r--src/gpu/vk/GrVkGpu.cpp3
-rw-r--r--src/gpu/vk/GrVkGpu.h2
-rw-r--r--src/gpu/vk/GrVkTexture.cpp6
-rw-r--r--src/gpu/vk/GrVkTexture.h1
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 };