aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2016-04-11 14:47:28 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-11 14:47:28 -0700
commit74b8d323323c8533e3e5cc7719e0bd127aacd829 (patch)
tree114f32ebe9adc4a27285aeb0304ff8daa6b4f972 /src
parentfda880710c28a1b0ff0c8c88f90a7659a7ce553f (diff)
Implement texel buffers
Adds a mechanism for processors to add buffer accesses and implements them in the GL backend. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1870893002 Review URL: https://codereview.chromium.org/1870893002
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrBuffer.h141
-rw-r--r--src/gpu/GrFragmentProcessor.cpp11
-rw-r--r--src/gpu/GrProcessor.cpp14
-rw-r--r--src/gpu/gl/GrGLBuffer.cpp4
-rw-r--r--src/gpu/gl/GrGLBuffer.h13
-rw-r--r--src/gpu/gl/GrGLCaps.cpp18
-rw-r--r--src/gpu/gl/GrGLCaps.h9
-rw-r--r--src/gpu/gl/GrGLGpu.cpp124
-rw-r--r--src/gpu/gl/GrGLGpu.h24
-rw-r--r--src/gpu/gl/GrGLProgram.cpp42
-rw-r--r--src/gpu/gl/GrGLProgram.h15
-rw-r--r--src/gpu/gl/GrGLProgramDataManager.cpp3
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp29
-rw-r--r--src/gpu/glsl/GrGLSL.h4
-rw-r--r--src/gpu/glsl/GrGLSLFragmentProcessor.cpp16
-rw-r--r--src/gpu/glsl/GrGLSLFragmentProcessor.h7
-rw-r--r--src/gpu/glsl/GrGLSLPrimitiveProcessor.h3
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.cpp84
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.h9
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.h1
-rw-r--r--src/gpu/glsl/GrGLSLXferProcessor.h3
-rw-r--r--src/gpu/vk/GrVkProgramDesc.cpp1
22 files changed, 333 insertions, 242 deletions
diff --git a/src/gpu/GrBuffer.h b/src/gpu/GrBuffer.h
deleted file mode 100644
index 7e04577543..0000000000
--- a/src/gpu/GrBuffer.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrBuffer_DEFINED
-#define GrBuffer_DEFINED
-
-#include "GrGpuResource.h"
-
-class GrGpu;
-
-class GrBuffer : public GrGpuResource {
-public:
- /**
- * Computes a scratch key for a buffer with a "dynamic" access pattern. (Buffers with "static"
- * and "stream" access patterns are disqualified by nature from being cached and reused.)
- */
- static void ComputeScratchKeyForDynamicBuffer(size_t size, GrBufferType intendedType,
- GrScratchKey* key) {
- static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType();
- GrScratchKey::Builder builder(key, kType, 1 + (sizeof(size_t) + 3) / 4);
- // TODO: There's not always reason to cache a buffer by type. In some (all?) APIs it's just
- // a chunk of memory we can use/reuse for any type of data. We really only need to
- // differentiate between the "read" types (e.g. kGpuToCpu_BufferType) and "draw" types.
- builder[0] = intendedType;
- builder[1] = (uint32_t)size;
- if (sizeof(size_t) > 4) {
- builder[2] = (uint32_t)((uint64_t)size >> 32);
- }
- }
-
- GrAccessPattern accessPattern() const { return fAccessPattern; }
-
- /**
- * Returns true if the buffer is a wrapper around a CPU array. If true it
- * indicates that map will always succeed and will be free.
- */
- bool isCPUBacked() const { return fCPUBacked; }
-
- /**
- * Maps the buffer to be written by the CPU.
- *
- * The previous content of the buffer is invalidated. It is an error
- * to draw from the buffer while it is mapped. It may fail if the backend
- * doesn't support mapping the buffer. If the buffer is CPU backed then
- * it will always succeed and is a free operation. Once a buffer is mapped,
- * subsequent calls to map() are ignored.
- *
- * Note that buffer mapping does not go through GrContext and therefore is
- * not serialized with other operations.
- *
- * @return a pointer to the data or nullptr if the map fails.
- */
- void* map() {
- if (!fMapPtr) {
- this->onMap();
- }
- return fMapPtr;
- }
-
- /**
- * Unmaps the buffer.
- *
- * The pointer returned by the previous map call will no longer be valid.
- */
- void unmap() {
- SkASSERT(fMapPtr);
- this->onUnmap();
- fMapPtr = nullptr;
- }
-
- /**
- * Returns the same ptr that map() returned at time of map or nullptr if the
- * is not mapped.
- *
- * @return ptr to mapped buffer data or nullptr if buffer is not mapped.
- */
- void* mapPtr() const { return fMapPtr; }
-
- /**
- Queries whether the buffer has been mapped.
-
- @return true if the buffer is mapped, false otherwise.
- */
- bool isMapped() const { return SkToBool(fMapPtr); }
-
- /**
- * Updates the buffer data.
- *
- * The size of the buffer will be preserved. The src data will be
- * placed at the beginning of the buffer and any remaining contents will
- * be undefined. srcSizeInBytes must be <= to the buffer size.
- *
- * The buffer must not be mapped.
- *
- * Note that buffer updates do not go through GrContext and therefore are
- * not serialized with other operations.
- *
- * @return returns true if the update succeeds, false otherwise.
- */
- bool updateData(const void* src, size_t srcSizeInBytes) {
- SkASSERT(!this->isMapped());
- SkASSERT(srcSizeInBytes <= fGpuMemorySize);
- return this->onUpdateData(src, srcSizeInBytes);
- }
-
-protected:
- GrBuffer(GrGpu* gpu, size_t gpuMemorySize, GrBufferType intendedType,
- GrAccessPattern accessPattern, bool cpuBacked)
- : INHERITED(gpu, kCached_LifeCycle),
- fMapPtr(nullptr),
- fGpuMemorySize(gpuMemorySize), // TODO: Zero for cpu backed buffers?
- fAccessPattern(accessPattern),
- fCPUBacked(cpuBacked) {
- if (!fCPUBacked && SkIsPow2(fGpuMemorySize) && kDynamic_GrAccessPattern == fAccessPattern) {
- GrScratchKey key;
- ComputeScratchKeyForDynamicBuffer(fGpuMemorySize, intendedType, &key);
- this->setScratchKey(key);
- }
- }
-
- void* fMapPtr;
-
-private:
- virtual size_t onGpuMemorySize() const { return fGpuMemorySize; }
-
- virtual void onMap() = 0;
- virtual void onUnmap() = 0;
- virtual bool onUpdateData(const void* src, size_t srcSizeInBytes) = 0;
-
- size_t fGpuMemorySize;
- GrAccessPattern fAccessPattern;
- bool fCPUBacked;
-
- typedef GrGpuResource INHERITED;
-};
-
-#endif
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 46efd80690..9524c84df1 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -27,7 +27,7 @@ GrFragmentProcessor::~GrFragmentProcessor() {
bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that,
bool ignoreCoordTransforms) const {
if (this->classID() != that.classID() ||
- !this->hasSameTextureAccesses(that)) {
+ !this->hasSameSamplers(that)) {
return false;
}
if (ignoreCoordTransforms) {
@@ -69,6 +69,15 @@ void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess)
fNumTexturesExclChildren++;
}
+void GrFragmentProcessor::addBufferAccess(const GrBufferAccess* bufferAccess) {
+ // Can't add buffer accesses after registering any children since their buffer accesses have
+ // already been bubbled up into our fBufferAccesses array
+ SkASSERT(fChildProcessors.empty());
+
+ INHERITED::addBufferAccess(bufferAccess);
+ fNumBuffersExclChildren++;
+}
+
void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
// Can't add transforms after registering any children since their transforms have already been
// bubbled up into our fCoordTransforms array
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index fdfbbb5713..0d3f8d9166 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -106,6 +106,11 @@ void GrProcessor::addTextureAccess(const GrTextureAccess* access) {
this->addGpuResource(access->getProgramTexture());
}
+void GrProcessor::addBufferAccess(const GrBufferAccess* access) {
+ fBufferAccesses.push_back(access);
+ this->addGpuResource(access->getProgramBuffer());
+}
+
void* GrProcessor::operator new(size_t size) {
return MemoryPoolAccessor().pool()->allocate(size);
}
@@ -114,8 +119,8 @@ void GrProcessor::operator delete(void* target) {
return MemoryPoolAccessor().pool()->release(target);
}
-bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const {
- if (this->numTextures() != that.numTextures()) {
+bool GrProcessor::hasSameSamplers(const GrProcessor& that) const {
+ if (this->numTextures() != that.numTextures() || this->numBuffers() != that.numBuffers()) {
return false;
}
for (int i = 0; i < this->numTextures(); ++i) {
@@ -123,6 +128,11 @@ bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const {
return false;
}
}
+ for (int i = 0; i < this->numBuffers(); ++i) {
+ if (this->bufferAccess(i) != that.bufferAccess(i)) {
+ return false;
+ }
+ }
return true;
}
diff --git a/src/gpu/gl/GrGLBuffer.cpp b/src/gpu/gl/GrGLBuffer.cpp
index 6e1ce58588..24fd59267d 100644
--- a/src/gpu/gl/GrGLBuffer.cpp
+++ b/src/gpu/gl/GrGLBuffer.cpp
@@ -96,7 +96,8 @@ GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrBufferType intendedType,
fBufferID(0),
fSizeInBytes(size),
fUsage(gr_to_gl_access_pattern(intendedType, accessPattern)),
- fGLSizeInBytes(0) {
+ fGLSizeInBytes(0),
+ fHasAttachedToTexture(false) {
if (this->isCPUBacked()) {
// Core profile uses vertex array objects, which disallow client side arrays.
SkASSERT(!gpu->glCaps().isCoreProfile());
@@ -151,6 +152,7 @@ void GrGLBuffer::onRelease() {
GL_CALL(DeleteBuffers(1, &fBufferID));
fBufferID = 0;
fGLSizeInBytes = 0;
+ this->glGpu()->notifyBufferReleased(this);
}
fMapPtr = nullptr;
VALIDATE();
diff --git a/src/gpu/gl/GrGLBuffer.h b/src/gpu/gl/GrGLBuffer.h
index b3b4feb002..84d05be382 100644
--- a/src/gpu/gl/GrGLBuffer.h
+++ b/src/gpu/gl/GrGLBuffer.h
@@ -27,6 +27,15 @@ public:
GrGLuint bufferID() const { return fBufferID; }
size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); }
+ /**
+ * Returns the actual size of the underlying GL buffer object. In certain cases we may make this
+ * smaller than the size reported by GrBuffer.
+ */
+ size_t glSizeInBytes() const { return fGLSizeInBytes; }
+
+ void setHasAttachedToTexture() { fHasAttachedToTexture = true; }
+ bool hasAttachedToTexture() const { return fHasAttachedToTexture; }
+
protected:
GrGLBuffer(GrGLGpu*, size_t size, GrBufferType intendedType, GrAccessPattern, bool cpuBacked,
const void* data);
@@ -53,8 +62,8 @@ private:
GrGLuint fBufferID;
size_t fSizeInBytes;
GrGLenum fUsage;
- size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object
- // smaller or larger than the size in fDesc.
+ size_t fGLSizeInBytes;
+ bool fHasAttachedToTexture;
typedef GrBuffer INHERITED;
};
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 0322a0f57c..f3e494acb9 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1382,6 +1382,8 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
texStorageSupported = false;
}
+ bool texelBufferSupport = this->shaderCaps()->texelBufferSupport();
+
fConfigTable[kUnknown_GrPixelConfig].fFormats.fBaseInternalFormat = 0;
fConfigTable[kUnknown_GrPixelConfig].fFormats.fSizedInternalFormat = 0;
fConfigTable[kUnknown_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] = 0;
@@ -1408,6 +1410,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
if (texStorageSupported) {
fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
}
+ if (texelBufferSupport) {
+ fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
fConfigTable[kRGBA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] =
@@ -1567,6 +1572,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kAlpha_8_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] =
GR_GL_RED;
fConfigTable[kAlpha_8_GrPixelConfig].fSwizzle = GrSwizzle::RRRR();
+ if (texelBufferSupport) {
+ fConfigTable[kAlpha_8_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
} else {
fConfigTable[kAlpha_8_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_ALPHA;
fConfigTable[kAlpha_8_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_ALPHA8;
@@ -1635,6 +1643,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
if (texStorageSupported) {
fConfigTable[kRGBA_float_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
}
+ if (texelBufferSupport) {
+ fConfigTable[kRGBA_float_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
fConfigTable[kRGBA_float_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
if (this->textureRedSupport()) {
@@ -1643,6 +1654,10 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kAlpha_half_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage]
= GR_GL_RED;
fConfigTable[kAlpha_half_GrPixelConfig].fSwizzle = GrSwizzle::RRRR();
+ if (texelBufferSupport) {
+ fConfigTable[kAlpha_half_GrPixelConfig].fFlags |=
+ ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
} else {
fConfigTable[kAlpha_half_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_ALPHA;
fConfigTable[kAlpha_half_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_ALPHA16F;
@@ -1691,6 +1706,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
if (texStorageSupported) {
fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
}
+ if (texelBufferSupport) {
+ fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
fConfigTable[kRGBA_half_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
// Compressed texture support
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index e2bc100cae..1602a0f63d 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -135,11 +135,19 @@ public:
return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseTexStorage_Flag);
}
+ bool canUseConfigWithTexelBuffer(GrPixelConfig config) const {
+ return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseWithTexelBuffer_Flag);
+ }
+
/** Returns the mapping between GrPixelConfig components and GL internal format components. */
const GrSwizzle& configSwizzle(GrPixelConfig config) const {
return fConfigTable[config].fSwizzle;
}
+ GrGLenum configSizedInternalFormat(GrPixelConfig config) const {
+ return fConfigTable[config].fFormats.fSizedInternalFormat;
+ }
+
bool getTexImageFormats(GrPixelConfig surfaceConfig, GrPixelConfig externalConfig,
GrGLenum* internalFormat, GrGLenum* externalFormat,
GrGLenum* externalType) const;
@@ -468,6 +476,7 @@ private:
kRenderable_Flag = 0x4,
kRenderableWithMSAA_Flag = 0x8,
kCanUseTexStorage_Flag = 0x10,
+ kCanUseWithTexelBuffer_Flag = 0x20,
};
uint32_t fFlags;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index e8b5755849..af5955014a 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -194,6 +194,7 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
, fTempSrcFBOID(0)
, fTempDstFBOID(0)
, fStencilClearFBOID(0)
+ , fHWMaxUsedBufferTextureUnit(-1)
, fHWPLSEnabled(false)
, fPLSHasBeenUsed(false)
, fHWMinSampleShading(0.0) {
@@ -223,6 +224,10 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
}
GR_STATIC_ASSERT(6 == SK_ARRAY_COUNT(fHWBufferState));
+ if (this->caps()->shaderCaps()->texelBufferSupport()) {
+ fHWBufferTextures.reset(this->glCaps().glslCaps()->maxCombinedSamplers());
+ }
+
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
fPathRendering.reset(new GrGLPathRendering(this));
}
@@ -522,6 +527,10 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
for (int s = 0; s < fHWBoundTextureUniqueIDs.count(); ++s) {
fHWBoundTextureUniqueIDs[s] = SK_InvalidUniqueID;
}
+ for (int b = 0; b < fHWBufferTextures.count(); ++b) {
+ SkASSERT(this->caps()->shaderCaps()->texelBufferSupport());
+ fHWBufferTextures[b].fKnownBound = false;
+ }
}
if (resetBits & kBlend_GrGLBackendState) {
@@ -2052,14 +2061,7 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso
this->flushBlend(blendInfo, swizzle);
}
- SkSTArray<8, const GrTextureAccess*> textureAccesses;
- program->setData(primProc, pipeline, &textureAccesses);
-
- int numTextureAccesses = textureAccesses.count();
- for (int i = 0; i < numTextureAccesses; i++) {
- this->bindTexture(i, textureAccesses[i]->getParams(), pipeline.getAllowSRGBInputs(),
- static_cast<GrGLTexture*>(textureAccesses[i]->getTexture()));
- }
+ program->setData(primProc, pipeline);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
this->flushStencil(pipeline.getStencil());
@@ -2147,6 +2149,31 @@ GrGLenum GrGLGpu::bindBuffer(GrBufferType type, const GrGLBuffer* buffer) {
return bufferState.fGLTarget;
}
+void GrGLGpu::notifyBufferReleased(const GrGLBuffer* buffer) {
+ if (buffer->hasAttachedToTexture()) {
+ // Detach this buffer from any textures to ensure the underlying memory is freed.
+ uint32_t uniqueID = buffer->getUniqueID();
+ for (int i = fHWMaxUsedBufferTextureUnit; i >= 0; --i) {
+ auto& buffTex = fHWBufferTextures[i];
+ if (uniqueID != buffTex.fAttachedBufferUniqueID) {
+ continue;
+ }
+ if (i == fHWMaxUsedBufferTextureUnit) {
+ --fHWMaxUsedBufferTextureUnit;
+ }
+
+ this->setTextureUnit(i);
+ if (!buffTex.fKnownBound) {
+ SkASSERT(buffTex.fTextureID);
+ GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
+ buffTex.fKnownBound = true;
+ }
+ GL_CALL(TexBuffer(GR_GL_TEXTURE_BUFFER,
+ this->glCaps().configSizedInternalFormat(buffTex.fTexelConfig), 0));
+ }
+ }
+}
+
void GrGLGpu::disableScissor() {
if (kNo_TriState != fHWScissorSettings.fEnabled) {
GL_CALL(Disable(GR_GL_SCISSOR_TEST));
@@ -3264,21 +3291,78 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, bool dstCo
(setAll || memcmp(newTexParams.fSwizzleRGBA,
oldTexParams.fSwizzleRGBA,
sizeof(newTexParams.fSwizzleRGBA)))) {
+ this->setTextureSwizzle(unitIdx, target, newTexParams.fSwizzleRGBA);
+ }
+ texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
+}
+
+void GrGLGpu::bindTexelBuffer(int unitIdx, intptr_t offsetInBytes, GrPixelConfig texelConfig,
+ GrGLBuffer* buffer) {
+ SkASSERT(this->glCaps().canUseConfigWithTexelBuffer(texelConfig));
+ SkASSERT(unitIdx >= 0 && unitIdx < fHWBufferTextures.count());
+ SkASSERT(offsetInBytes >= 0 && offsetInBytes < (intptr_t) buffer->glSizeInBytes());
+
+ BufferTexture& buffTex = fHWBufferTextures[unitIdx];
+
+ if (!buffTex.fKnownBound) {
+ if (!buffTex.fTextureID) {
+ GL_CALL(GenTextures(1, &buffTex.fTextureID));
+ if (!buffTex.fTextureID) {
+ return;
+ }
+ }
+
this->setTextureUnit(unitIdx);
- if (this->glStandard() == kGLES_GrGLStandard) {
- // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
- const GrGLenum* swizzle = newTexParams.fSwizzleRGBA;
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
- } else {
- GR_STATIC_ASSERT(sizeof(newTexParams.fSwizzleRGBA[0]) == sizeof(GrGLint));
- const GrGLint* swizzle = reinterpret_cast<const GrGLint*>(newTexParams.fSwizzleRGBA);
- GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA, swizzle));
+ GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
+
+ buffTex.fKnownBound = true;
+ }
+
+ if (buffer->getUniqueID() != buffTex.fAttachedBufferUniqueID ||
+ buffTex.fOffsetInBytes != offsetInBytes ||
+ buffTex.fTexelConfig != texelConfig ||
+ buffTex.fAttachedSizeInBytes != buffer->glSizeInBytes() - offsetInBytes) {
+
+ size_t attachmentSizeInBytes = buffer->glSizeInBytes() - offsetInBytes;
+
+ this->setTextureUnit(unitIdx);
+ GL_CALL(TexBufferRange(GR_GL_TEXTURE_BUFFER,
+ this->glCaps().configSizedInternalFormat(texelConfig),
+ buffer->bufferID(),
+ offsetInBytes,
+ attachmentSizeInBytes));
+
+ buffTex.fOffsetInBytes = offsetInBytes;
+ buffTex.fTexelConfig = texelConfig;
+ buffTex.fAttachedSizeInBytes = attachmentSizeInBytes;
+ buffTex.fAttachedBufferUniqueID = buffer->getUniqueID();
+
+ if (this->glCaps().textureSwizzleSupport() &&
+ this->glCaps().configSwizzle(texelConfig) != buffTex.fSwizzle) {
+ GrGLenum glSwizzle[4];
+ get_tex_param_swizzle(texelConfig, this->glCaps(), glSwizzle);
+ this->setTextureSwizzle(unitIdx, GR_GL_TEXTURE_BUFFER, glSwizzle);
+ buffTex.fSwizzle = this->glCaps().configSwizzle(texelConfig);
}
+
+ buffer->setHasAttachedToTexture();
+ fHWMaxUsedBufferTextureUnit = SkTMax(unitIdx, fHWMaxUsedBufferTextureUnit);
+ }
+}
+
+void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]) {
+ this->setTextureUnit(unitIdx);
+ if (this->glStandard() == kGLES_GrGLStandard) {
+ // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
+ } else {
+ GR_STATIC_ASSERT(sizeof(swizzle[0]) == sizeof(GrGLint));
+ GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
+ reinterpret_cast<const GrGLint*>(swizzle)));
}
- texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
}
void GrGLGpu::flushColorWrite(bool writeColor) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index c2dda0a222..c8b5d70f1b 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -60,6 +60,8 @@ public:
void bindTexture(int unitIdx, const GrTextureParams& params, bool dstConfigAllowsSRGB,
GrGLTexture* texture);
+ void bindTexelBuffer(int unitIdx, intptr_t offsetInBytes, GrPixelConfig, GrGLBuffer*);
+
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
GrPixelConfig readConfig, DrawPreference*,
ReadPixelTempDrawInfo*) override;
@@ -88,6 +90,9 @@ public:
// If the caller wishes to bind an index buffer to a specific VAO, it can call glBind directly.
GrGLenum bindBuffer(GrBufferType type, const GrGLBuffer*);
+ // Called by GrGLBuffer after its buffer object has been destroyed.
+ void notifyBufferReleased(const GrGLBuffer*);
+
const GrGLContext* glContextForTesting() const override {
return &this->glContext();
}
@@ -206,6 +211,8 @@ private:
// binds texture unit in GL
void setTextureUnit(int unitIdx);
+ void setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]);
+
// Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
bool flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc);
@@ -498,6 +505,23 @@ private:
TriState fHWSRGBFramebuffer;
SkTArray<uint32_t, true> fHWBoundTextureUniqueIDs;
+ struct BufferTexture {
+ BufferTexture() : fTextureID(0), fKnownBound(false),
+ fAttachedBufferUniqueID(SK_InvalidUniqueID),
+ fSwizzle(GrSwizzle::RGBA()) {}
+
+ GrGLuint fTextureID;
+ bool fKnownBound;
+ intptr_t fOffsetInBytes;
+ GrPixelConfig fTexelConfig;
+ size_t fAttachedSizeInBytes;
+ uint32_t fAttachedBufferUniqueID;
+ GrSwizzle fSwizzle;
+ };
+
+ SkTArray<BufferTexture, true> fHWBufferTextures;
+ int fHWMaxUsedBufferTextureUnit;
+
// EXT_raster_multisample.
TriState fHWRasterMultisampleEnabled;
int fHWNumRasterSamples;
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index aa828a24c4..6a433e17c5 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -11,6 +11,7 @@
#include "GrProcessor.h"
#include "GrCoordTransform.h"
#include "GrGLGpu.h"
+#include "GrGLBuffer.h"
#include "GrGLPathRendering.h"
#include "GrPathProcessor.h"
#include "GrPipeline.h"
@@ -66,46 +67,34 @@ void GrGLProgram::abandon() {
///////////////////////////////////////////////////////////////////////////////
-static void append_texture_bindings(const GrProcessor& processor,
- SkTArray<const GrTextureAccess*>* textureBindings) {
- if (int numTextures = processor.numTextures()) {
- const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures);
- int i = 0;
- do {
- bindings[i] = &processor.textureAccess(i);
- } while (++i < numTextures);
- }
-}
-
-void GrGLProgram::setData(const GrPrimitiveProcessor& primProc,
- const GrPipeline& pipeline,
- SkTArray<const GrTextureAccess*>* textureBindings) {
+void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) {
this->setRenderTargetState(primProc, pipeline);
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
+ int nextSamplerIdx = 0;
fGeometryProcessor->setData(fProgramDataManager, primProc);
- append_texture_bindings(primProc, textureBindings);
+ this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
- this->setFragmentData(primProc, pipeline, textureBindings);
+ this->setFragmentData(primProc, pipeline, &nextSamplerIdx);
if (primProc.getPixelLocalStorageState() !=
GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
const GrXferProcessor& xp = pipeline.getXferProcessor();
fXferProcessor->setData(fProgramDataManager, xp);
- append_texture_bindings(xp, textureBindings);
+ this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
}
}
void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
- SkTArray<const GrTextureAccess*>* textureBindings) {
+ int* nextSamplerIdx) {
int numProcessors = fFragmentProcessors.count();
for (int i = 0; i < numProcessors; ++i) {
const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
fFragmentProcessors[i]->setData(fProgramDataManager, processor);
this->setTransformData(primProc, processor, i);
- append_texture_bindings(processor, textureBindings);
+ this->bindTextures(processor, pipeline.getAllowSRGBInputs(), nextSamplerIdx);
}
}
void GrGLProgram::setTransformData(const GrPrimitiveProcessor& primProc,
@@ -145,3 +134,18 @@ void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
size, rt->origin());
}
}
+
+void GrGLProgram::bindTextures(const GrProcessor& processor,
+ bool allowSRGBInputs,
+ int* nextSamplerIdx) {
+ for (int i = 0; i < processor.numTextures(); ++i) {
+ const GrTextureAccess& access = processor.textureAccess(i);
+ fGpu->bindTexture((*nextSamplerIdx)++, access.getParams(),
+ allowSRGBInputs, static_cast<GrGLTexture*>(access.getTexture()));
+ }
+ for (int i = 0; i < processor.numBuffers(); ++i) {
+ const GrBufferAccess& access = processor.bufferAccess(i);
+ fGpu->bindTexelBuffer((*nextSamplerIdx)++, access.offsetInBytes(), access.texelConfig(),
+ static_cast<GrGLBuffer*>(access.buffer()));
+ }
+}
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 22678cb6a3..c70b1bd0e2 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -94,8 +94,7 @@ public:
* the program is bound before calling, and to bind the outgoing textures to their respective
* units upon return. (Each index in the array corresponds to its matching GL texture unit.)
*/
- void setData(const GrPrimitiveProcessor&, const GrPipeline&,
- SkTArray<const GrTextureAccess*>* textureBindings);
+ void setData(const GrPrimitiveProcessor&, const GrPipeline&);
protected:
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
@@ -113,16 +112,16 @@ protected:
const GrGLSLFragProcs& fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms);
- // A templated helper to loop over effects, set the transforms(via subclass) and bind textures
- void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&,
- SkTArray<const GrTextureAccess*>* textureBindings);
- void setTransformData(const GrPrimitiveProcessor&,
- const GrFragmentProcessor&,
- int index);
+ // A helper to loop over effects, set the transforms (via subclass) and bind textures
+ void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&, int* nextSamplerIdx);
+ void setTransformData(const GrPrimitiveProcessor&, const GrFragmentProcessor&, int index);
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setRenderTargetState(const GrPrimitiveProcessor&, const GrPipeline&);
+ // Helper for setData() that binds textures and texel buffers to the appropriate texture units
+ void bindTextures(const GrProcessor&, bool allowSRGBInputs, int* nextSamplerIdx);
+
// these reflect the current values of uniforms (GL uniform values travel with program)
RenderTargetState fRenderTargetState;
BuiltinUniformHandles fBuiltinUniformHandles;
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index d5b48f7061..6b2e1118cb 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -63,8 +63,7 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, GrGLuint programID,
void GrGLProgramDataManager::setSampler(UniformHandle u, int texUnit) const {
const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kSampler2D_GrSLType || uni.fType == kSamplerExternal_GrSLType ||
- uni.fType == kSampler2DRect_GrSLType);
+ SkASSERT(GrSLTypeIsSamplerType(uni.fType));
SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
// FIXME: We still insert a single sampler uniform for every stage. If the shader does not
// reference the sampler then the compiler may have optimized it out. Uncomment this assert
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 5e9fe5fcc6..801224c9b6 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -17,11 +17,11 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLCaps.h"
-static uint16_t texture_key(GrSLType samplerType, GrPixelConfig config, GrShaderFlags visibility,
+static uint16_t sampler_key(GrSLType samplerType, GrPixelConfig config, GrShaderFlags visibility,
const GrGLSLCaps& caps) {
enum {
kFirstSamplerType = kSampler2D_GrSLType,
- kLastSamplerType = kSampler2DRect_GrSLType,
+ kLastSamplerType = kSamplerBuffer_GrSLType,
kSamplerTypeKeyBits = 4
};
GR_STATIC_ASSERT(kLastSamplerType - kFirstSamplerType < (1 << kSamplerTypeKeyBits));
@@ -34,23 +34,30 @@ static uint16_t texture_key(GrSLType samplerType, GrPixelConfig config, GrShader
(caps.samplerPrecision(config, visibility) << (8 + kSamplerTypeKeyBits)));
}
-static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
- const GrGLSLCaps& caps) {
+static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrProcessor& proc,
+ const GrGLSLCaps& caps) {
int numTextures = proc.numTextures();
+ int numSamplers = numTextures + proc.numBuffers();
// Need two bytes per key (swizzle, sampler type, and precision).
- int word32Count = (proc.numTextures() + 1) / 2;
+ int word32Count = (numSamplers + 1) / 2;
if (0 == word32Count) {
return;
}
uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
- for (int i = 0; i < numTextures; ++i) {
+ int i = 0;
+ for (; i < numTextures; ++i) {
const GrTextureAccess& access = proc.textureAccess(i);
const GrTexture* tex = access.getTexture();
- k16[i] = texture_key(tex->samplerType(), tex->config(), access.getVisibility(), caps);
+ k16[i] = sampler_key(tex->samplerType(), tex->config(), access.getVisibility(), caps);
+ }
+ for (; i < numSamplers; ++i) {
+ const GrBufferAccess& access = proc.bufferAccess(i - numTextures);
+ k16[i] = sampler_key(kSamplerBuffer_GrSLType, access.texelConfig(), access.visibility(),
+ caps);
}
- // zero the last 16 bits if the number of textures is odd.
- if (numTextures & 0x1) {
- k16[numTextures] = 0;
+ // zero the last 16 bits if the number of samplers is odd.
+ if (numSamplers & 0x1) {
+ k16[numSamplers] = 0;
}
}
@@ -76,7 +83,7 @@ static bool gen_meta_key(const GrProcessor& proc,
return false;
}
- add_texture_key(b, proc, glslCaps);
+ add_sampler_keys(b, proc, glslCaps);
uint32_t* key = b->add32n(2);
key[0] = (classID << 16) | SkToU32(processorKeySize);
diff --git a/src/gpu/glsl/GrGLSL.h b/src/gpu/glsl/GrGLSL.h
index 9f5f2b05b4..844b7c76db 100644
--- a/src/gpu/glsl/GrGLSL.h
+++ b/src/gpu/glsl/GrGLSL.h
@@ -58,7 +58,7 @@ bool GrGLSLSupportsNamedFragmentShaderOutputs(GrGLSLGeneration);
*/
inline const char* GrGLSLTexture2DFunctionName(GrSLType coordType, GrSLType samplerType,
GrGLSLGeneration glslGen) {
- SkASSERT(GrSLTypeIsSamplerType(samplerType));
+ SkASSERT(GrSLTypeIs2DTextureType(samplerType));
SkASSERT(kVec2f_GrSLType == coordType || kVec3f_GrSLType == coordType);
// GL_TEXTURE_RECTANGLE_ARB is written against OpenGL 2.0/GLSL 1.10. At that time there were
// separate texture*() functions. In OpenGL 3.0/GLSL 1.30 the different texture*() functions
@@ -127,6 +127,8 @@ static inline const char* GrGLSLTypeString(GrSLType t) {
return "samplerExternalOES";
case kSampler2DRect_GrSLType:
return "sampler2DRect";
+ case kSamplerBuffer_GrSLType:
+ return "samplerBuffer";
case kBool_GrSLType:
return "bool";
case kInt_GrSLType:
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index c3e57bc314..42538eaf0f 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -75,18 +75,25 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
* Textures work the same way as transforms.
*/
int firstCoordAt = args.fFp.numTransformsExclChildren();
- int firstSamplerAt = args.fFp.numTexturesExclChildren();
+ int firstTextureAt = args.fFp.numTexturesExclChildren();
+ int firstBufferAt = args.fFp.numBuffersExclChildren();
for (int i = 0; i < childIndex; ++i) {
firstCoordAt += args.fFp.childProcessor(i).numTransforms();
- firstSamplerAt += args.fFp.childProcessor(i).numTextures();
+ firstTextureAt += args.fFp.childProcessor(i).numTextures();
+ firstBufferAt += args.fFp.childProcessor(i).numBuffers();
}
GrGLSLTransformedCoordsArray childCoords;
SamplerArray childTexSamplers;
+ SamplerArray childBufferSamplers;
if (childProc.numTransforms() > 0) {
childCoords.push_back_n(childProc.numTransforms(), &args.fCoords[firstCoordAt]);
}
if (childProc.numTextures() > 0) {
- childTexSamplers.push_back_n(childProc.numTextures(), &args.fTexSamplers[firstSamplerAt]);
+ childTexSamplers.push_back_n(childProc.numTextures(), &args.fTexSamplers[firstTextureAt]);
+ }
+ if (childProc.numBuffers() > 0) {
+ childBufferSamplers.push_back_n(childProc.numBuffers(),
+ &args.fBufferSamplers[firstBufferAt]);
}
// emit the code for the child in its own scope
@@ -100,7 +107,8 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
outputColor,
inputColor,
childCoords,
- childTexSamplers);
+ childTexSamplers,
+ childBufferSamplers);
this->childProcessor(childIndex)->emitCode(childArgs);
fragBuilder->codeAppend("}\n");
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h
index 5c71340a1c..9fc4a8c436 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h
@@ -60,7 +60,8 @@ public:
const char* outputColor,
const char* inputColor,
const GrGLSLTransformedCoordsArray& coords,
- const SamplerArray& texSamplers)
+ const SamplerArray& texSamplers,
+ const SamplerArray& bufferSamplers)
: fFragBuilder(fragBuilder)
, fUniformHandler(uniformHandler)
, fGLSLCaps(caps)
@@ -68,7 +69,8 @@ public:
, fOutputColor(outputColor)
, fInputColor(inputColor)
, fCoords(coords)
- , fTexSamplers(texSamplers) {}
+ , fTexSamplers(texSamplers)
+ , fBufferSamplers(bufferSamplers) {}
GrGLSLFPFragmentBuilder* fFragBuilder;
GrGLSLUniformHandler* fUniformHandler;
const GrGLSLCaps* fGLSLCaps;
@@ -77,6 +79,7 @@ public:
const char* fInputColor;
const GrGLSLTransformedCoordsArray& fCoords;
const SamplerArray& fTexSamplers;
+ const SamplerArray& fBufferSamplers;
};
virtual void emitCode(EmitArgs&) = 0;
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
index fc0c4788b5..4bd5fefd9f 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
@@ -43,6 +43,7 @@ public:
const char* outputColor,
const char* outputCoverage,
const SamplerArray& texSamplers,
+ const SamplerArray& bufferSamplers,
const TransformsIn& transformsIn,
TransformsOut* transformsOut)
: fVertBuilder(vertBuilder)
@@ -54,6 +55,7 @@ public:
, fOutputColor(outputColor)
, fOutputCoverage(outputCoverage)
, fTexSamplers(texSamplers)
+ , fBufferSamplers(bufferSamplers)
, fTransformsIn(transformsIn)
, fTransformsOut(transformsOut) {}
GrGLSLVertexBuilder* fVertBuilder;
@@ -65,6 +67,7 @@ public:
const char* fOutputColor;
const char* fOutputCoverage;
const SamplerArray& fTexSamplers;
+ const SamplerArray& fBufferSamplers;
const TransformsIn& fTransformsIn;
TransformsOut* fTransformsOut;
};
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index ccb078b144..88ef5b9245 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -98,7 +98,8 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
fGeometryProcessor = proc.createGLSLInstance(*this->glslCaps());
SkSTArray<4, GrGLSLSampler> texSamplers(proc.numTextures());
- this->emitSamplers(proc, &texSamplers);
+ SkSTArray<2, GrGLSLSampler> bufferSamplers(proc.numBuffers());
+ this->emitSamplers(proc, &texSamplers, &bufferSamplers);
GrGLSLGeometryProcessor::EmitArgs args(&fVS,
&fFS,
@@ -109,6 +110,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
outputColor->c_str(),
outputCoverage->c_str(),
texSamplers,
+ bufferSamplers,
fCoordTransforms,
&fOutCoords);
fGeometryProcessor->emitCode(args);
@@ -149,7 +151,8 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();
SkSTArray<4, GrGLSLSampler> texSamplers(fp.numTextures());
- this->emitSamplers(fp, &texSamplers);
+ SkSTArray<2, GrGLSLSampler> bufferSamplers(fp.numBuffers());
+ this->emitSamplers(fp, &texSamplers, &bufferSamplers);
GrGLSLFragmentProcessor::EmitArgs args(&fFS,
this->uniformHandler(),
@@ -158,7 +161,8 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
output->c_str(),
input.isOnes() ? nullptr : input.c_str(),
fOutCoords[index],
- texSamplers);
+ texSamplers,
+ bufferSamplers);
fragProc->emitCode(args);
// We have to check that effects and the code they emit are consistent, ie if an effect
@@ -194,7 +198,8 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
fFS.codeAppend(openBrace.c_str());
SkSTArray<4, GrGLSLSampler> texSamplers(xp.numTextures());
- this->emitSamplers(xp, &texSamplers);
+ SkSTArray<2, GrGLSLSampler> bufferSamplers(xp.numBuffers());
+ this->emitSamplers(xp, &texSamplers, &bufferSamplers);
bool usePLSDstRead = (plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState);
GrGLSLXferProcessor::EmitArgs args(&fFS,
@@ -205,6 +210,7 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
fFS.getPrimaryColorOutputName(),
fFS.getSecondaryColorOutputName(),
texSamplers,
+ bufferSamplers,
usePLSDstRead);
fXferProcessor->emitCode(args);
@@ -215,41 +221,65 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
}
void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
- GrGLSLSampler::SamplerArray* outTexSamplers) {
- int numTextures = processor.numTextures();
- UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures);
+ GrGLSLSampler::SamplerArray* outTexSamplers,
+ GrGLSLSampler::SamplerArray* outBufferSamplers) {
SkString name;
+ int numTextures = processor.numTextures();
for (int t = 0; t < numTextures; ++t) {
const GrTextureAccess& access = processor.textureAccess(t);
- GrShaderFlags visibility = access.getVisibility();
- if (visibility & kVertex_GrShaderFlag) {
- ++fNumVertexSamplers;
- }
- if (visibility & kGeometry_GrShaderFlag) {
- SkASSERT(this->primitiveProcessor().willUseGeoShader());
- ++fNumGeometrySamplers;
- }
- if (visibility & kFragment_GrShaderFlag) {
- ++fNumFragmentSamplers;
- }
GrSLType samplerType = access.getTexture()->samplerType();
if (kSamplerExternal_GrSLType == samplerType) {
const char* externalFeatureString = this->glslCaps()->externalTextureExtensionString();
// We shouldn't ever create a GrGLTexture that requires external sampler type
SkASSERT(externalFeatureString);
- this->addFeature(visibility,
+ this->addFeature(access.getVisibility(),
1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
externalFeatureString);
}
- GrSLPrecision precision = this->glslCaps()->samplerPrecision(access.getTexture()->config(),
- visibility);
- name.printf("Sampler%d", t);
- localSamplerUniforms[t] = this->uniformHandler()->addUniform(visibility,
- samplerType,
- precision,
- name.c_str());
- outTexSamplers->emplace_back(localSamplerUniforms[t], access.getTexture()->config());
+ name.printf("TextureSampler%d", t);
+ this->emitSampler(samplerType, access.getTexture()->config(),
+ name.c_str(), access.getVisibility(), outTexSamplers);
+ }
+
+ if (int numBuffers = processor.numBuffers()) {
+ SkASSERT(this->glslCaps()->texelBufferSupport());
+ GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags;
+
+ for (int b = 0; b < numBuffers; ++b) {
+ const GrBufferAccess& access = processor.bufferAccess(b);
+ name.printf("BufferSampler%d", b);
+ this->emitSampler(kSamplerBuffer_GrSLType, access.texelConfig(), name.c_str(),
+ access.visibility(), outBufferSamplers);
+ texelBufferVisibility |= access.visibility();
+ }
+
+ if (const char* extension = this->glslCaps()->texelBufferExtensionString()) {
+ this->addFeature(texelBufferVisibility,
+ 1 << GrGLSLShaderBuilder::kTexelBuffer_GLSLPrivateFeature,
+ extension);
+ }
+ }
+}
+
+void GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
+ GrPixelConfig config,
+ const char* name,
+ GrShaderFlags visibility,
+ GrGLSLSampler::SamplerArray* outSamplers) {
+ if (visibility & kVertex_GrShaderFlag) {
+ ++fNumVertexSamplers;
+ }
+ if (visibility & kGeometry_GrShaderFlag) {
+ SkASSERT(this->primitiveProcessor().willUseGeoShader());
+ ++fNumGeometrySamplers;
+ }
+ if (visibility & kFragment_GrShaderFlag) {
+ ++fNumFragmentSamplers;
}
+ GrSLPrecision precision = this->glslCaps()->samplerPrecision(config, visibility);
+ UniformHandle u = this->uniformHandler()->addUniform(visibility, samplerType, precision, name);
+ fSamplerUniforms.push_back(u);
+ outSamplers->emplace_back(u, config);
}
void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 4d253c73bf..3ce7daf349 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -146,7 +146,14 @@ private:
const GrGLSLExpr4& coverageIn,
bool ignoresCoverage,
GrPixelLocalStorageState plsState);
- void emitSamplers(const GrProcessor& processor, GrGLSLSampler::SamplerArray* outTexSamplers);
+ void emitSamplers(const GrProcessor& processor,
+ GrGLSLSampler::SamplerArray* outTexSamplers,
+ GrGLSLSampler::SamplerArray* outBufferSamplers);
+ void emitSampler(GrSLType samplerType,
+ GrPixelConfig,
+ const char* name,
+ GrShaderFlags visibility,
+ GrGLSLSampler::SamplerArray* outSamplers);
void emitFSOutputSwizzle(bool hasSecondaryOutput);
bool checkSamplerCounts();
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index c14df53915..ef7963f83a 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -153,6 +153,7 @@ protected:
kBlendEquationAdvanced_GLSLPrivateFeature,
kBlendFuncExtended_GLSLPrivateFeature,
kExternalTexture_GLSLPrivateFeature,
+ kTexelBuffer_GLSLPrivateFeature,
kFramebufferFetch_GLSLPrivateFeature,
kNoPerspectiveInterpolation_GLSLPrivateFeature,
kSampleVariables_GLSLPrivateFeature,
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.h b/src/gpu/glsl/GrGLSLXferProcessor.h
index 3f190ce82f..adc3d41765 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.h
+++ b/src/gpu/glsl/GrGLSLXferProcessor.h
@@ -33,6 +33,7 @@ public:
const char* outputPrimary,
const char* outputSecondary,
const SamplerArray& texSamplers,
+ const SamplerArray& bufferSamplers,
const bool usePLSDstRead)
: fXPFragBuilder(fragBuilder)
, fUniformHandler(uniformHandler)
@@ -43,6 +44,7 @@ public:
, fOutputPrimary(outputPrimary)
, fOutputSecondary(outputSecondary)
, fTexSamplers(texSamplers)
+ , fBufferSamplers(bufferSamplers)
, fUsePLSDstRead(usePLSDstRead) {}
GrGLSLXPFragmentBuilder* fXPFragBuilder;
@@ -54,6 +56,7 @@ public:
const char* fOutputPrimary;
const char* fOutputSecondary;
const SamplerArray& fTexSamplers;
+ const SamplerArray& fBufferSamplers;
bool fUsePLSDstRead;
};
/**
diff --git a/src/gpu/vk/GrVkProgramDesc.cpp b/src/gpu/vk/GrVkProgramDesc.cpp
index f4bd2bf506..4619bcfded 100644
--- a/src/gpu/vk/GrVkProgramDesc.cpp
+++ b/src/gpu/vk/GrVkProgramDesc.cpp
@@ -22,6 +22,7 @@
static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
const GrGLSLCaps& caps) {
int numTextures = proc.numTextures();
+ SkASSERT(0 == proc.numBuffers());
// Need two bytes per key (swizzle, sampler type, and precision).
int word32Count = (proc.numTextures() + 1) / 2;
if (0 == word32Count) {