aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2016-11-22 15:56:30 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-22 21:35:11 +0000
commitbe34882042048db096baca32ddf4a8b472529804 (patch)
tree2676dc4a9e6506f19728eddfe011ba4465f1c3ab /src/gpu
parent030cbd5f3cc60255b887fb88920fb655c8a2a9be (diff)
Initial OpenGL Image support.
This change along with recently landed changes is enough to make the new unit test work and not much else. imageLoad is support but not stores or any other image functions (atomics). Barriers in the shading language or the GL API are not yet hooked up. GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4182 Change-Id: I5958b7c89e40ae5ee05f7bbaca3b3738162fe5ce Reviewed-on: https://skia-review.googlesource.com/4182 Reviewed-by: Greg Daniel <egdaniel@google.com> Reviewed-by: Chris Dalton <csmartdalton@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrFragmentProcessor.cpp2
-rw-r--r--src/gpu/GrProcessor.cpp45
-rw-r--r--src/gpu/GrProgramDesc.cpp104
-rw-r--r--src/gpu/GrShaderVar.cpp35
-rw-r--r--src/gpu/GrTexturePriv.h8
-rw-r--r--src/gpu/gl/GrGLCaps.cpp23
-rw-r--r--src/gpu/gl/GrGLCaps.h6
-rw-r--r--src/gpu/gl/GrGLGpu.cpp26
-rw-r--r--src/gpu/gl/GrGLGpu.h8
-rw-r--r--src/gpu/gl/GrGLProgram.cpp7
-rw-r--r--src/gpu/gl/GrGLProgram.h7
-rw-r--r--src/gpu/gl/GrGLProgramDataManager.cpp10
-rw-r--r--src/gpu/gl/GrGLProgramDataManager.h1
-rw-r--r--src/gpu/gl/GrGLUniformHandler.cpp56
-rw-r--r--src/gpu/gl/GrGLUniformHandler.h13
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp1
-rw-r--r--src/gpu/glsl/GrGLSL.h4
-rw-r--r--src/gpu/glsl/GrGLSLCaps.cpp16
-rw-r--r--src/gpu/glsl/GrGLSLCaps.h16
-rw-r--r--src/gpu/glsl/GrGLSLFragmentProcessor.cpp2
-rw-r--r--src/gpu/glsl/GrGLSLFragmentProcessor.h18
-rw-r--r--src/gpu/glsl/GrGLSLPrimitiveProcessor.h10
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.cpp111
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.h32
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.cpp10
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.h8
-rw-r--r--src/gpu/glsl/GrGLSLUniformHandler.h9
-rw-r--r--src/gpu/glsl/GrGLSLXferProcessor.h8
-rw-r--r--src/gpu/vk/GrVkPipelineState.cpp2
-rw-r--r--src/gpu/vk/GrVkUniformHandler.cpp6
-rw-r--r--src/gpu/vk/GrVkUniformHandler.h12
-rw-r--r--src/gpu/vk/GrVkVaryingHandler.cpp4
32 files changed, 495 insertions, 125 deletions
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 820b428313..de4ab9e860 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -27,7 +27,7 @@ GrFragmentProcessor::~GrFragmentProcessor() {
bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
if (this->classID() != that.classID() ||
- !this->hasSameSamplers(that)) {
+ !this->hasSameSamplersAndAccesses(that)) {
return false;
}
if (!this->hasSameTransforms(that)) {
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 1e100e41fa..738ff13e51 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -122,7 +122,12 @@ void GrProcessor::addTextureSampler(const TextureSampler* access) {
void GrProcessor::addBufferAccess(const BufferAccess* access) {
fBufferAccesses.push_back(access);
- this->addGpuResource(access->getProgramBuffer());
+ this->addGpuResource(access->programBuffer());
+}
+
+void GrProcessor::addImageStorageAccess(const ImageStorageAccess* access) {
+ fImageStorageAccesses.push_back(access);
+ this->addGpuResource(access->programTexture());
}
void* GrProcessor::operator new(size_t size) {
@@ -133,9 +138,10 @@ void GrProcessor::operator delete(void* target) {
return MemoryPoolAccessor().pool()->release(target);
}
-bool GrProcessor::hasSameSamplers(const GrProcessor& that) const {
+bool GrProcessor::hasSameSamplersAndAccesses(const GrProcessor &that) const {
if (this->numTextureSamplers() != that.numTextureSamplers() ||
- this->numBuffers() != that.numBuffers()) {
+ this->numBuffers() != that.numBuffers() ||
+ this->numImageStorages() != that.numImageStorages()) {
return false;
}
for (int i = 0; i < this->numTextureSamplers(); ++i) {
@@ -148,6 +154,11 @@ bool GrProcessor::hasSameSamplers(const GrProcessor& that) const {
return false;
}
}
+ for (int i = 0; i < this->numImageStorages(); ++i) {
+ if (this->imageStorageAccess(i) != that.imageStorageAccess(i)) {
+ return false;
+ }
+ }
return true;
}
@@ -189,6 +200,34 @@ void GrProcessor::TextureSampler::reset(GrTexture* texture,
///////////////////////////////////////////////////////////////////////////////////////////////////
+GrProcessor::ImageStorageAccess::ImageStorageAccess(sk_sp<GrTexture> texture, GrIOType ioType,
+ GrShaderFlags visibility) {
+ SkASSERT(texture);
+ fTexture.set(texture.release(), ioType);
+ fVisibility = visibility;
+ // We currently infer this from the config. However, we could allow the client to specify
+ // a format that is different but compatible with the config.
+ switch (fTexture.get()->config()) {
+ case kRGBA_8888_GrPixelConfig:
+ fFormat = GrImageStorageFormat::kRGBA8;
+ break;
+ case kRGBA_8888_sint_GrPixelConfig:
+ fFormat = GrImageStorageFormat::kRGBA8i;
+ break;
+ case kRGBA_half_GrPixelConfig:
+ fFormat = GrImageStorageFormat::kRGBA16f;
+ break;
+ case kRGBA_float_GrPixelConfig:
+ fFormat = GrImageStorageFormat::kRGBA32f;
+ break;
+ default:
+ SkFAIL("Config is not (yet) supported as image storage.");
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
// Initial static variable from GrXPFactory
int32_t GrXPFactory::gCurrXPFClassID =
GrXPFactory::kIllegalXPFClassID;
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index cdbbc23534..9f3278c927 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -15,48 +15,88 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLCaps.h"
+enum {
+ kSamplerOrImageTypeKeyBits = 4
+};
+
+static inline uint16_t image_storage_or_sampler_uniform_type_key(GrSLType type ) {
+ int value = UINT16_MAX;
+ switch (type) {
+ case kTexture2DSampler_GrSLType:
+ value = 0;
+ break;
+ case kITexture2DSampler_GrSLType:
+ value = 1;
+ break;
+ case kTextureExternalSampler_GrSLType:
+ value = 2;
+ break;
+ case kTexture2DRectSampler_GrSLType:
+ value = 3;
+ break;
+ case kBufferSampler_GrSLType:
+ value = 4;
+ break;
+ case kImageStorage2D_GrSLType:
+ value = 5;
+ break;
+ case kIImageStorage2D_GrSLType:
+ value = 6;
+ break;
+
+ default:
+ break;
+ }
+ SkASSERT((value & ((1 << kSamplerOrImageTypeKeyBits) - 1)) == value);
+ return value;
+}
+
static uint16_t sampler_key(GrSLType samplerType, GrPixelConfig config, GrShaderFlags visibility,
const GrGLSLCaps& caps) {
- enum {
- kFirstSamplerType = kTexture2DSampler_GrSLType,
- kLastSamplerType = kBufferSampler_GrSLType,
- kSamplerTypeKeyBits = 4
- };
- GR_STATIC_ASSERT(kLastSamplerType - kFirstSamplerType < (1 << kSamplerTypeKeyBits));
-
- SkASSERT((int)samplerType >= kFirstSamplerType && (int)samplerType <= kLastSamplerType);
- int samplerTypeKey = samplerType - kFirstSamplerType;
-
- return SkToU16(caps.configTextureSwizzle(config).asKey() |
- (samplerTypeKey << 8) |
- (caps.samplerPrecision(config, visibility) << (8 + kSamplerTypeKeyBits)));
+ int samplerTypeKey = image_storage_or_sampler_uniform_type_key(samplerType);
+
+ GR_STATIC_ASSERT(1 == sizeof(caps.configTextureSwizzle(config).asKey()));
+ return SkToU16(samplerTypeKey |
+ caps.configTextureSwizzle(config).asKey() << kSamplerOrImageTypeKeyBits |
+ (caps.samplerPrecision(config, visibility) << (8 + kSamplerOrImageTypeKeyBits)));
}
-static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrProcessor& proc,
- const GrGLSLCaps& caps) {
+static uint16_t storage_image_key(const GrProcessor::ImageStorageAccess& imageAccess) {
+ GrSLType type = imageAccess.texture()->texturePriv().imageStorageType();
+ return image_storage_or_sampler_uniform_type_key(type) |
+ (int)imageAccess.format() << kSamplerOrImageTypeKeyBits;
+}
+
+static void add_sampler_and_image_keys(GrProcessorKeyBuilder* b, const GrProcessor& proc,
+ const GrGLSLCaps& caps) {
int numTextureSamplers = proc.numTextureSamplers();
- int numSamplers = numTextureSamplers + proc.numBuffers();
- // Need two bytes per key (swizzle, sampler type, and precision).
- int word32Count = (numSamplers + 1) / 2;
+ int numBuffers = proc.numBuffers();
+ int numImageStorages = proc.numImageStorages();
+ int numUniforms = numTextureSamplers + numBuffers + numImageStorages;
+ // Need two bytes per key.
+ int word32Count = (numUniforms + 1) / 2;
if (0 == word32Count) {
return;
}
uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
- int i = 0;
- for (; i < numTextureSamplers; ++i) {
- const GrProcessor::TextureSampler& textureSampler = proc.textureSampler(i);
- const GrTexture* tex = textureSampler.texture();
- k16[i] = sampler_key(tex->texturePriv().samplerType(), tex->config(),
- textureSampler.visibility(), caps);
+ int j = 0;
+ for (int i = 0; i < numTextureSamplers; ++i, ++j) {
+ const GrProcessor::TextureSampler& sampler = proc.textureSampler(i);
+ const GrTexture* tex = sampler.texture();
+ k16[j] = sampler_key(tex->texturePriv().samplerType(), tex->config(), sampler.visibility(),
+ caps);
+ }
+ for (int i = 0; i < numBuffers; ++i, ++j) {
+ const GrProcessor::BufferAccess& access = proc.bufferAccess(i);
+ k16[j] = sampler_key(kBufferSampler_GrSLType, access.texelConfig(), access.visibility(),
+ caps);
}
- for (; i < numSamplers; ++i) {
- const GrProcessor::BufferAccess& access = proc.bufferAccess(i - numTextureSamplers);
- k16[i] = sampler_key(kBufferSampler_GrSLType, access.texelConfig(),
- access.visibility(), caps);
+ for (int i = 0; i < numImageStorages; ++i, ++j) {
+ k16[j] = storage_image_key(proc.imageStorageAccess(i));
}
- // zero the last 16 bits if the number of samplers is odd.
- if (numSamplers & 0x1) {
- k16[numSamplers] = 0;
+ // zero the last 16 bits if the number of uniforms for samplers and image storages is odd.
+ if (numUniforms & 0x1) {
+ k16[numUniforms] = 0;
}
}
@@ -82,7 +122,7 @@ static bool gen_meta_key(const GrProcessor& proc,
return false;
}
- add_sampler_keys(b, proc, glslCaps);
+ add_sampler_and_image_keys(b, proc, glslCaps);
uint32_t* key = b->add32n(2);
key[0] = (classID << 16) | SkToU32(processorKeySize);
diff --git a/src/gpu/GrShaderVar.cpp b/src/gpu/GrShaderVar.cpp
index ef305cbfc9..e1ea207e81 100644
--- a/src/gpu/GrShaderVar.cpp
+++ b/src/gpu/GrShaderVar.cpp
@@ -9,14 +9,47 @@
#include "GrShaderVar.h"
#include "glsl/GrGLSLCaps.h"
+static const char* type_modifier_string(GrShaderVar::TypeModifier t) {
+ switch (t) {
+ case GrShaderVar::kNone_TypeModifier: return "";
+ case GrShaderVar::kIn_TypeModifier: return "in";
+ case GrShaderVar::kInOut_TypeModifier: return "inout";
+ case GrShaderVar::kOut_TypeModifier: return "out";
+ case GrShaderVar::kUniform_TypeModifier: return "uniform";
+ }
+ SkFAIL("Unknown shader variable type modifier.");
+ return "";
+}
+
+void GrShaderVar::setImageStorageFormat(GrImageStorageFormat format) {
+ const char* formatStr = nullptr;
+ switch (format) {
+ case GrImageStorageFormat::kRGBA8:
+ formatStr = "rgba8";
+ break;
+ case GrImageStorageFormat::kRGBA8i:
+ formatStr = "rgba8i";
+ break;
+ case GrImageStorageFormat::kRGBA16f:
+ formatStr = "rgba16f";
+ break;
+ case GrImageStorageFormat::kRGBA32f:
+ formatStr = "rgba32f";
+ break;
+ }
+ this->addLayoutQualifier(formatStr);
+ SkASSERT(formatStr);
+}
+
void GrShaderVar::appendDecl(const GrGLSLCaps* glslCaps, SkString* out) const {
SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeAcceptsPrecision(fType));
+ SkString layout = fLayoutQualifier;
if (!fLayoutQualifier.isEmpty()) {
out->appendf("layout(%s) ", fLayoutQualifier.c_str());
}
out->append(fExtraModifiers);
if (this->getTypeModifier() != kNone_TypeModifier) {
- out->append(TypeModifierString(this->getTypeModifier()));
+ out->append(type_modifier_string(this->getTypeModifier()));
out->append(" ");
}
GrSLType effectiveType = this->getType();
diff --git a/src/gpu/GrTexturePriv.h b/src/gpu/GrTexturePriv.h
index d68eb799e8..042061129d 100644
--- a/src/gpu/GrTexturePriv.h
+++ b/src/gpu/GrTexturePriv.h
@@ -49,6 +49,14 @@ public:
return fTexture->fMaxMipMapLevel;
}
+ GrSLType imageStorageType() const {
+ if (GrPixelConfigIsSint(fTexture->config())) {
+ return kIImageStorage2D_GrSLType;
+ } else {
+ return kImageStorage2D_GrSLType;
+ }
+ }
+
GrSLType samplerType() const { return fTexture->fSamplerType; }
/** The filter used is clamped to this value in GrProcessor::TextureSampler. */
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 9f24e5099d..0e6007b11a 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -324,16 +324,21 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
static constexpr int kMaxSaneImages = 4;
GrGLint maxUnits;
GR_GL_GetIntegerv(gli, GR_GL_MAX_IMAGE_UNITS, &maxUnits);
- GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_IMAGE_UNIFORMS, &glslCaps->fMaxVertexImages);
- GR_GL_GetIntegerv(gli, GR_GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &glslCaps->fMaxGeometryImages);
- GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &glslCaps->fMaxFragmentImages);
- GR_GL_GetIntegerv(gli, GR_GL_MAX_COMBINED_IMAGE_UNIFORMS, &glslCaps->fMaxCombinedImages);
+ GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_IMAGE_UNIFORMS,
+ &glslCaps->fMaxVertexImageStorages);
+ GR_GL_GetIntegerv(gli, GR_GL_MAX_GEOMETRY_IMAGE_UNIFORMS,
+ &glslCaps->fMaxGeometryImageStorages);
+ GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
+ &glslCaps->fMaxFragmentImageStorages);
+ GR_GL_GetIntegerv(gli, GR_GL_MAX_COMBINED_IMAGE_UNIFORMS,
+ &glslCaps->fMaxCombinedImageStorages);
// We use one unit for every image uniform
- glslCaps->fMaxCombinedImages = SkTMin(SkTMin(glslCaps->fMaxCombinedImages, maxUnits),
- kMaxSaneImages);
- glslCaps->fMaxVertexImages = SkTMin(maxUnits, glslCaps->fMaxVertexImages);
- glslCaps->fMaxGeometryImages = SkTMin(maxUnits, glslCaps->fMaxGeometryImages);
- glslCaps->fMaxFragmentImages = SkTMin(maxUnits, glslCaps->fMaxFragmentImages);
+ glslCaps->fMaxCombinedImageStorages = SkTMin(SkTMin(glslCaps->fMaxCombinedImageStorages,
+ maxUnits), kMaxSaneImages);
+ glslCaps->fMaxVertexImageStorages = SkTMin(maxUnits, glslCaps->fMaxVertexImageStorages);
+ glslCaps->fMaxGeometryImageStorages = SkTMin(maxUnits, glslCaps->fMaxGeometryImageStorages);
+ glslCaps->fMaxFragmentImageStorages = SkTMin(maxUnits,
+ glslCaps->fMaxFragmentImageStorages);
}
/**************************************************************************
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 496635d766..c96275fc17 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -159,6 +159,11 @@ public:
bool getRenderbufferFormat(GrPixelConfig config, GrGLenum* internalFormat) const;
+ /** The format to use read/write a texture as an image in a shader */
+ GrGLenum getImageFormat(GrPixelConfig config) const {
+ return fConfigTable[config].fFormats.fSizedInternalFormat;
+ }
+
/**
* Gets an array of legal stencil formats. These formats are not guaranteed
* to be supported by the driver but are legal GLenum names given the GL
@@ -451,7 +456,6 @@ private:
GrGLenum fExternalFormat[kExternalFormatUsageCnt];
GrGLenum fExternalType;
-
// Either the base or sized internal format depending on the GL and config.
GrGLenum fInternalFormatTexImage;
GrGLenum fInternalFormatRenderbuffer;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 9c25602187..776405267d 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -217,6 +217,7 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
fCaps.reset(SkRef(ctx->caps()));
fHWBoundTextureUniqueIDs.reset(this->glCaps().glslCaps()->maxCombinedSamplers());
+ fHWBoundImageStorages.reset(this->glCaps().glslCaps()->maxCombinedImageStorages());
fHWBufferState[kVertex_GrBufferType].fGLTarget = GR_GL_ARRAY_BUFFER;
fHWBufferState[kIndex_GrBufferType].fGLTarget = GR_GL_ELEMENT_ARRAY_BUFFER;
@@ -557,6 +558,10 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
SkASSERT(this->caps()->shaderCaps()->texelBufferSupport());
fHWBufferTextures[b].fKnownBound = false;
}
+ for (int i = 0; i < fHWBoundImageStorages.count(); ++i) {
+ SkASSERT(this->caps()->shaderCaps()->imageLoadStoreSupport());
+ fHWBoundImageStorages[i].fTextureUniqueID.makeInvalid();
+ }
}
if (resetBits & kBlend_GrGLBackendState) {
@@ -3342,6 +3347,27 @@ void GrGLGpu::bindTexelBuffer(int unitIdx, GrPixelConfig texelConfig, GrGLBuffer
}
}
+void GrGLGpu::bindImageStorage(int unitIdx, GrIOType ioType, GrGLTexture *texture) {
+ SkASSERT(texture);
+ if (texture->uniqueID() != fHWBoundImageStorages[unitIdx].fTextureUniqueID ||
+ ioType != fHWBoundImageStorages[unitIdx].fIOType) {
+ GrGLenum access;
+ switch (ioType) {
+ case kRead_GrIOType:
+ access = GR_GL_READ_ONLY;
+ break;
+ case kWrite_GrIOType:
+ access = GR_GL_WRITE_ONLY;
+ break;
+ case kRW_GrIOType:
+ access = GR_GL_READ_WRITE;
+ break;
+ }
+ GrGLenum format = this->glCaps().getImageFormat(texture->config());
+ GL_CALL(BindImageTexture(unitIdx, texture->textureID(), 0, GR_GL_FALSE, 0, access, format));
+ }
+}
+
void GrGLGpu::generateMipmaps(const GrSamplerParams& params, bool allowSRGBInputs,
GrGLTexture* texture) {
SkASSERT(texture);
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index dff342d823..c6e7935ed0 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -62,6 +62,8 @@ public:
void bindTexelBuffer(int unitIdx, GrPixelConfig, GrGLBuffer*);
+ void bindImageStorage(int unitIdx, GrIOType, GrGLTexture *);
+
void generateMipmaps(const GrSamplerParams& params, bool allowSRGBInputs, GrGLTexture* texture);
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
@@ -569,6 +571,12 @@ private:
TriState fHWSRGBFramebuffer;
SkTArray<GrGpuResource::UniqueID, true> fHWBoundTextureUniqueIDs;
+ struct Image {
+ GrGpuResource::UniqueID fTextureUniqueID;
+ GrIOType fIOType;
+ };
+ SkTArray<Image, true> fHWBoundImageStorages;
+
struct BufferTexture {
BufferTexture() : fTextureID(0), fKnownBound(false),
fAttachedBufferUniqueID(SK_InvalidUniqueID),
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 1f2e1c8446..8a61ecafa7 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -32,6 +32,7 @@ GrGLProgram::GrGLProgram(GrGLGpu* gpu,
GrGLuint programID,
const UniformInfoArray& uniforms,
const UniformInfoArray& samplers,
+ const UniformInfoArray& imageStorages,
const VaryingInfoArray& pathProcVaryings,
GrGLSLPrimitiveProcessor* geometryProcessor,
GrGLSLXferProcessor* xferProcessor,
@@ -47,6 +48,7 @@ GrGLProgram::GrGLProgram(GrGLGpu* gpu,
// Assign texture units to sampler uniforms one time up front.
GL_CALL(UseProgram(fProgramID));
fProgramDataManager.setSamplers(samplers);
+ fProgramDataManager.setImageStorages(imageStorages);
}
GrGLProgram::~GrGLProgram() {
@@ -162,6 +164,11 @@ void GrGLProgram::bindTextures(const GrProcessor& processor,
fGpu->bindTexelBuffer((*nextSamplerIdx)++, access.texelConfig(),
static_cast<GrGLBuffer*>(access.buffer()));
}
+ for (int i = 0; i < processor.numImageStorages(); ++i) {
+ const GrProcessor::ImageStorageAccess& access = processor.imageStorageAccess(i);
+ fGpu->bindImageStorage((*nextSamplerIdx)++, access.ioType(),
+ static_cast<GrGLTexture *>(access.texture()));
+ }
}
void GrGLProgram::generateMipmaps(const GrProcessor& processor,
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 3b0940e0d2..ea00df2f1e 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -103,9 +103,9 @@ public:
void generateMipmaps(const GrPrimitiveProcessor&, const GrPipeline&);
protected:
- typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
- typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
- typedef GrGLProgramDataManager::VaryingInfoArray VaryingInfoArray;
+ using UniformHandle = GrGLSLProgramDataManager::UniformHandle ;
+ using UniformInfoArray = GrGLProgramDataManager::UniformInfoArray;
+ using VaryingInfoArray = GrGLProgramDataManager::VaryingInfoArray;
GrGLProgram(GrGLGpu*,
const GrProgramDesc&,
@@ -113,6 +113,7 @@ protected:
GrGLuint programID,
const UniformInfoArray& uniforms,
const UniformInfoArray& samplers,
+ const UniformInfoArray& imageStorages,
const VaryingInfoArray&, // used for NVPR only currently
GrGLSLPrimitiveProcessor* geometryProcessor,
GrGLSLXferProcessor* xferProcessor,
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index 3245bd7185..863eab7abf 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -65,6 +65,16 @@ void GrGLProgramDataManager::setSamplers(const UniformInfoArray& samplers) const
}
}
+void GrGLProgramDataManager::setImageStorages(const UniformInfoArray& images) const {
+ for (int i = 0; i < images.count(); ++i) {
+ const UniformInfo& image = images[i];
+ SkASSERT(image.fVisibility);
+ if (kUnusedUniform != image.fLocation) {
+ GR_GL_CALL(fGpu->glInterface(), Uniform1i(image.fLocation, i));
+ }
+ }
+}
+
void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kInt_GrSLType);
diff --git a/src/gpu/gl/GrGLProgramDataManager.h b/src/gpu/gl/GrGLProgramDataManager.h
index 0ef902c10b..62af4b8cc0 100644
--- a/src/gpu/gl/GrGLProgramDataManager.h
+++ b/src/gpu/gl/GrGLProgramDataManager.h
@@ -47,6 +47,7 @@ public:
void setSamplers(const UniformInfoArray& samplers) const;
+ void setImageStorages(const UniformInfoArray &images) const;
/** Functions for uploading uniform values. The varities ending in v can be used to upload to an
* array of uniforms. arrayCount must be <= the array count of the uniform.
diff --git a/src/gpu/gl/GrGLUniformHandler.cpp b/src/gpu/gl/GrGLUniformHandler.cpp
index 2def001f43..6a2e21fb5c 100644
--- a/src/gpu/gl/GrGLUniformHandler.cpp
+++ b/src/gpu/gl/GrGLUniformHandler.cpp
@@ -80,11 +80,33 @@ GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(uint32_t visi
return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
}
+GrGLSLUniformHandler::ImageStorageHandle GrGLUniformHandler::addImageStorage(
+ uint32_t visibility, GrSLType type, GrImageStorageFormat format, const char* name) {
+ SkASSERT(name && strlen(name));
+ SkDEBUGCODE(static const uint32_t kVisMask = kVertex_GrShaderFlag | kFragment_GrShaderFlag);
+ SkASSERT(0 == (~kVisMask & visibility));
+ SkASSERT(0 != visibility);
+ SkString mangleName;
+ char prefix = 'u';
+ fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
+
+ UniformInfo& imageStorage = fImageStorages.push_back();
+ imageStorage.fVariable.setName(mangleName);
+
+ SkASSERT(GrSLTypeIsImageStorage(type));
+ imageStorage.fVariable.setType(type);
+ imageStorage.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
+ imageStorage.fVariable.setImageStorageFormat(format);
+ imageStorage.fLocation = -1;
+ imageStorage.fVisibility = visibility;
+ return GrGLSLUniformHandler::ImageStorageHandle(fImageStorages.count() - 1);
+}
+
void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
for (int i = 0; i < fUniforms.count(); ++i) {
if (fUniforms[i].fVisibility & visibility) {
fUniforms[i].fVariable.appendDecl(fProgramBuilder->glslCaps(), out);
- out->append(";\n");
+ out->append(";");
}
}
for (int i = 0; i < fSamplers.count(); ++i) {
@@ -93,19 +115,29 @@ void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString*
out->append(";\n");
}
}
+ for (int i = 0; i < fImageStorages.count(); ++i) {
+ if (fImageStorages[i].fVisibility & visibility) {
+ fImageStorages[i].fVariable.appendDecl(fProgramBuilder->glslCaps(), out);
+ out->append(";");
+ }
+ }
}
void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
if (caps.bindUniformLocationSupport()) {
- int uniformCnt = fUniforms.count();
- for (int i = 0; i < uniformCnt; ++i) {
- GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
- fUniforms[i].fLocation = i;
+ int currUniform = 0;
+ for (int i = 0; i < fUniforms.count(); ++i, ++currUniform) {
+ GL_CALL(BindUniformLocation(programID, currUniform, fUniforms[i].fVariable.c_str()));
+ fUniforms[i].fLocation = currUniform;
}
- for (int i = 0; i < fSamplers.count(); ++i) {
- GrGLint location = i + uniformCnt;
- GL_CALL(BindUniformLocation(programID, location, fSamplers[i].fVariable.c_str()));
- fSamplers[i].fLocation = location;
+ for (int i = 0; i < fSamplers.count(); ++i, ++currUniform) {
+ GL_CALL(BindUniformLocation(programID, currUniform, fSamplers[i].fVariable.c_str()));
+ fSamplers[i].fLocation = currUniform;
+ }
+ for (int i = 0; i < fImageStorages.count(); ++i) {
+ GL_CALL(BindUniformLocation(programID, currUniform,
+ fImageStorages[i].fVariable.c_str()));
+ fImageStorages[i].fLocation = currUniform;
}
}
}
@@ -123,6 +155,12 @@ void GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps&
GL_CALL_RET(location, GetUniformLocation(programID, fSamplers[i].fVariable.c_str()));
fSamplers[i].fLocation = location;
}
+ for (int i = 0; i < fImageStorages.count(); ++i) {
+ GrGLint location;
+ GL_CALL_RET(location, GetUniformLocation(programID,
+ fImageStorages[i].fVariable.c_str()));
+ fImageStorages[i].fLocation = location;
+ }
}
}
diff --git a/src/gpu/gl/GrGLUniformHandler.h b/src/gpu/gl/GrGLUniformHandler.h
index d3aa2f8358..32663a42ef 100644
--- a/src/gpu/gl/GrGLUniformHandler.h
+++ b/src/gpu/gl/GrGLUniformHandler.h
@@ -29,7 +29,8 @@ private:
explicit GrGLUniformHandler(GrGLSLProgramBuilder* program)
: INHERITED(program)
, fUniforms(kUniformsPerBlock)
- , fSamplers(kUniformsPerBlock) {}
+ , fSamplers(kUniformsPerBlock)
+ , fImageStorages(kUniformsPerBlock) {}
UniformHandle internalAddUniformArray(uint32_t visibility,
GrSLType type,
@@ -46,10 +47,19 @@ private:
return fSamplers[handle.toIndex()].fVariable;
}
+ ImageStorageHandle addImageStorage(uint32_t visibility,
+ GrSLType,
+ GrImageStorageFormat,
+ const char* name) override;
+
GrSwizzle samplerSwizzle(SamplerHandle handle) const override {
return fSamplerSwizzles[handle.toIndex()];
}
+ const GrShaderVar& imageStorageVariable(ImageStorageHandle handle) const override {
+ return fImageStorages[handle.toIndex()].fVariable;
+ }
+
void appendUniformDecls(GrShaderFlags visibility, SkString*) const override;
// Manually set uniform locations for all our uniforms.
@@ -66,6 +76,7 @@ private:
UniformInfoArray fUniforms;
UniformInfoArray fSamplers;
SkTArray<GrSwizzle> fSamplerSwizzles;
+ UniformInfoArray fImageStorages;
friend class GrGLProgramBuilder;
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index a1ad572a86..a774570b68 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -237,6 +237,7 @@ GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
programID,
fUniformHandler.fUniforms,
fUniformHandler.fSamplers,
+ fUniformHandler.fImageStorages,
fVaryingHandler.fPathProcVaryingInfos,
fGeometryProcessor,
fXferProcessor,
diff --git a/src/gpu/glsl/GrGLSL.h b/src/gpu/glsl/GrGLSL.h
index 4461f4c60f..bc5b319465 100644
--- a/src/gpu/glsl/GrGLSL.h
+++ b/src/gpu/glsl/GrGLSL.h
@@ -146,6 +146,10 @@ static inline const char* GrGLSLTypeString(GrSLType t) {
return "texture2D";
case kSampler_GrSLType:
return "sampler";
+ case kImageStorage2D_GrSLType:
+ return "image2D";
+ case kIImageStorage2D_GrSLType:
+ return "iimage2D";
}
SkFAIL("Unknown shader var type.");
return ""; // suppress warning
diff --git a/src/gpu/glsl/GrGLSLCaps.cpp b/src/gpu/glsl/GrGLSLCaps.cpp
index 5bb22b3974..57e5a0c04e 100644
--- a/src/gpu/glsl/GrGLSLCaps.cpp
+++ b/src/gpu/glsl/GrGLSLCaps.cpp
@@ -47,10 +47,10 @@ GrGLSLCaps::GrGLSLCaps(const GrContextOptions& options) {
fMaxGeometrySamplers = 0;
fMaxFragmentSamplers = 0;
fMaxCombinedSamplers = 0;
- fMaxVertexImages = 0;
- fMaxGeometryImages = 0;
- fMaxFragmentImages = 0;
- fMaxCombinedImages = 0;
+ fMaxVertexImageStorages = 0;
+ fMaxGeometryImageStorages = 0;
+ fMaxFragmentImageStorages = 0;
+ fMaxCombinedImageStorages = 0;
fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
}
@@ -95,10 +95,10 @@ SkString GrGLSLCaps::dump() const {
r.appendf("Max GS Samplers: %d\n", fMaxGeometrySamplers);
r.appendf("Max FS Samplers: %d\n", fMaxFragmentSamplers);
r.appendf("Max Combined Samplers: %d\n", fMaxFragmentSamplers);
- r.appendf("Max VS Images: %d\n", fMaxVertexImages);
- r.appendf("Max GS Images: %d\n", fMaxGeometryImages);
- r.appendf("Max FS Images: %d\n", fMaxFragmentImages);
- r.appendf("Max Combined Images: %d\n", fMaxFragmentImages);
+ r.appendf("Max VS Image Storages: %d\n", fMaxVertexImageStorages);
+ r.appendf("Max GS Image Storages: %d\n", fMaxGeometryImageStorages);
+ r.appendf("Max FS Image Storages: %d\n", fMaxFragmentImageStorages);
+ r.appendf("Max Combined Image Storages: %d\n", fMaxFragmentImageStorages);
r.appendf("Advanced blend equation interaction: %s\n",
kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]);
return r;
diff --git a/src/gpu/glsl/GrGLSLCaps.h b/src/gpu/glsl/GrGLSLCaps.h
index 4c53ad02fd..11ce754527 100644
--- a/src/gpu/glsl/GrGLSLCaps.h
+++ b/src/gpu/glsl/GrGLSLCaps.h
@@ -157,13 +157,13 @@ public:
int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
- int maxVertexImages() const { return fMaxVertexImages; }
+ int maxVertexImageStorages() const { return fMaxVertexImageStorages; }
- int maxGeometryImages() const { return fMaxGeometryImages; }
+ int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; }
- int maxFragmentImages() const { return fMaxFragmentImages; }
+ int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; }
- int maxCombinedImages() const { return fMaxCombinedImages; }
+ int maxCombinedImageStorages() const { return fMaxCombinedImageStorages; }
/**
* Given a texture's config, this determines what swizzle must be appended to accesses to the
@@ -238,10 +238,10 @@ private:
int fMaxFragmentSamplers;
int fMaxCombinedSamplers;
- int fMaxVertexImages;
- int fMaxGeometryImages;
- int fMaxFragmentImages;
- int fMaxCombinedImages;
+ int fMaxVertexImageStorages;
+ int fMaxGeometryImageStorages;
+ int fMaxFragmentImageStorages;
+ int fMaxCombinedImageStorages;
AdvBlendEqInteraction fAdvBlendEqInteraction;
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index 5ae7fee7db..8c32482d8e 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -49,6 +49,7 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
BufferSamplers bufferSamplers = args.fBufferSamplers.childInputs(childIndex);
+ ImageStorages imageStorages = args.fImageStorages.childInputs(childIndex);
EmitArgs childArgs(fragBuilder,
args.fUniformHandler,
args.fGLSLCaps,
@@ -58,6 +59,7 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
coordVars,
textureSamplers,
bufferSamplers,
+ imageStorages,
args.fGpImplementsDistanceVector);
this->childProcessor(childIndex)->emitCode(childArgs);
fragBuilder->codeAppend("}\n");
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h
index aba68b7e05..c8154231b5 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h
@@ -11,13 +11,13 @@
#include "GrFragmentProcessor.h"
#include "GrShaderVar.h"
#include "glsl/GrGLSLProgramDataManager.h"
+#include "glsl/GrGLSLUniformHandler.h"
class GrProcessor;
class GrProcessorKeyBuilder;
class GrGLSLCaps;
class GrGLSLFPBuilder;
class GrGLSLFPFragmentBuilder;
-class GrGLSLUniformHandler;
class GrGLSLFragmentProcessor {
public:
@@ -29,8 +29,9 @@ public:
}
}
- typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
- typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle;
+ using UniformHandle = GrGLSLUniformHandler::UniformHandle;
+ using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
+ using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
private:
/**
@@ -74,6 +75,8 @@ public:
&GrProcessor::numTextureSamplers>;
using BufferSamplers = BuilderInputProvider<SamplerHandle, GrProcessor,
&GrProcessor::numBuffers>;
+ using ImageStorages = BuilderInputProvider<ImageStorageHandle, GrProcessor,
+ &GrProcessor::numImageStorages>;
/** Called when the program stage should insert its code into the shaders. The code in each
shader will be in its own block ({}) and so locally scoped names will not collide across
@@ -99,6 +102,12 @@ public:
@param bufferSamplers Contains one entry for each BufferAccess of the GrProcessor. These
can be passed to the builder to emit buffer reads in the generated
code.
+ @param imageStorages Contains one entry for each ImageStorageAccess of the GrProcessor.
+ These can be passed to the builder to emit image loads and stores
+ in the generated code.
+ @param gpImplementsDistanceVector
+ Does the GrGeometryProcessor implement the feature where it
+ provides a vector to the nearest edge of the shape being rendered.
*/
struct EmitArgs {
EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
@@ -110,6 +119,7 @@ public:
const TransformedCoordVars& transformedCoordVars,
const TextureSamplers& textureSamplers,
const BufferSamplers& bufferSamplers,
+ const ImageStorages& imageStorages,
bool gpImplementsDistanceVector)
: fFragBuilder(fragBuilder)
, fUniformHandler(uniformHandler)
@@ -120,6 +130,7 @@ public:
, fTransformedCoords(transformedCoordVars)
, fTexSamplers(textureSamplers)
, fBufferSamplers(bufferSamplers)
+ , fImageStorages(imageStorages)
, fGpImplementsDistanceVector(gpImplementsDistanceVector) {}
GrGLSLFPFragmentBuilder* fFragBuilder;
GrGLSLUniformHandler* fUniformHandler;
@@ -130,6 +141,7 @@ public:
const TransformedCoordVars& fTransformedCoords;
const TextureSamplers& fTexSamplers;
const BufferSamplers& fBufferSamplers;
+ const ImageStorages& fImageStorages;
bool fGpImplementsDistanceVector;
};
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
index 199163939f..b398cfd5c7 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
@@ -11,6 +11,7 @@
#include "GrFragmentProcessor.h"
#include "GrPrimitiveProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
+#include "glsl/GrGLSLUniformHandler.h"
class GrBatchTracker;
class GrPrimitiveProcessor;
@@ -18,7 +19,6 @@ class GrGLSLCaps;
class GrGLSLPPFragmentBuilder;
class GrGLSLGeometryBuilder;
class GrGLSLGPBuilder;
-class GrGLSLUniformHandler;
class GrGLSLVaryingHandler;
class GrGLSLVertexBuilder;
@@ -28,8 +28,9 @@ public:
virtual ~GrGLSLPrimitiveProcessor() {}
- typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
- typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle;
+ using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
+ using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
+ using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
/**
* This class provides access to the GrCoordTransforms across all GrFragmentProcessors in a
@@ -77,6 +78,7 @@ public:
const char* distanceVectorName,
const SamplerHandle* texSamplers,
const SamplerHandle* bufferSamplers,
+ const ImageStorageHandle* imageStorages,
FPCoordTransformHandler* transformHandler)
: fVertBuilder(vertBuilder)
, fGeomBuilder(geomBuilder)
@@ -90,6 +92,7 @@ public:
, fDistanceVectorName(distanceVectorName)
, fTexSamplers(texSamplers)
, fBufferSamplers(bufferSamplers)
+ , fImageStorages(imageStorages)
, fFPCoordTransformHandler(transformHandler) {}
GrGLSLVertexBuilder* fVertBuilder;
GrGLSLGeometryBuilder* fGeomBuilder;
@@ -103,6 +106,7 @@ public:
const char* fDistanceVectorName;
const SamplerHandle* fTexSamplers;
const SamplerHandle* fBufferSamplers;
+ const ImageStorageHandle* fImageStorages;
FPCoordTransformHandler* fFPCoordTransformHandler;
};
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index e8097c783f..03a9c21d26 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -31,7 +31,10 @@ GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline,
, fXferProcessor(nullptr)
, fNumVertexSamplers(0)
, fNumGeometrySamplers(0)
- , fNumFragmentSamplers(0) {
+ , fNumFragmentSamplers(0)
+ , fNumVertexImageStorages(0)
+ , fNumGeometryImageStorages(0)
+ , fNumFragmentImageStorages(0) {
}
void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
@@ -66,7 +69,7 @@ bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
}
- return this->checkSamplerCounts();
+ return this->checkSamplerCounts() && this->checkImageStorageCounts();
}
void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc,
@@ -97,9 +100,10 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
SkASSERT(!fGeometryProcessor);
fGeometryProcessor = proc.createGLSLInstance(*this->glslCaps());
- SkSTArray<4, SamplerHandle> texSamplers(proc.numTextureSamplers());
- SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers());
- this->emitSamplers(proc, &texSamplers, &bufferSamplers);
+ SkSTArray<4, SamplerHandle> texSamplers(proc.numTextureSamplers());
+ SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers());
+ SkSTArray<2, ImageStorageHandle> imageStorages(proc.numImageStorages());
+ this->emitSamplersAndImageStorages(proc, &texSamplers, &bufferSamplers, &imageStorages);
GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
&fTransformedCoordVars);
@@ -115,6 +119,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
distanceVectorName,
texSamplers.begin(),
bufferSamplers.begin(),
+ imageStorages.begin(),
&transformHandler);
fGeometryProcessor->emitCode(args);
@@ -163,15 +168,18 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers());
SkSTArray<2, SamplerHandle> bufferSamplerArray(fp.numBuffers());
+ SkSTArray<2, ImageStorageHandle> imageStorageArray(fp.numImageStorages());
GrFragmentProcessor::Iter iter(&fp);
while (const GrFragmentProcessor* subFP = iter.next()) {
- this->emitSamplers(*subFP, &textureSamplerArray, &bufferSamplerArray);
+ this->emitSamplersAndImageStorages(*subFP, &textureSamplerArray, &bufferSamplerArray,
+ &imageStorageArray);
}
const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin());
GrGLSLFragmentProcessor::BufferSamplers bufferSamplers(&fp, bufferSamplerArray.begin());
+ GrGLSLFragmentProcessor::ImageStorages imageStorages(&fp, imageStorageArray.begin());
GrGLSLFragmentProcessor::EmitArgs args(&fFS,
this->uniformHandler(),
this->glslCaps(),
@@ -181,6 +189,7 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
coords,
textureSamplers,
bufferSamplers,
+ imageStorages,
this->primitiveProcessor().implementsDistanceVector());
fragProc->emitCode(args);
@@ -217,9 +226,10 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
fFS.codeAppend(openBrace.c_str());
- SkSTArray<4, SamplerHandle> texSamplers(xp.numTextureSamplers());
- SkSTArray<2, SamplerHandle> bufferSamplers(xp.numBuffers());
- this->emitSamplers(xp, &texSamplers, &bufferSamplers);
+ SkSTArray<4, SamplerHandle> texSamplers(xp.numTextureSamplers());
+ SkSTArray<2, SamplerHandle> bufferSamplers(xp.numBuffers());
+ SkSTArray<2, ImageStorageHandle> imageStorageArray(xp.numImageStorages());
+ this->emitSamplersAndImageStorages(xp, &texSamplers, &bufferSamplers, &imageStorageArray);
bool usePLSDstRead = (plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState);
GrGLSLXferProcessor::EmitArgs args(&fFS,
@@ -231,6 +241,7 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
fFS.getSecondaryColorOutputName(),
texSamplers.begin(),
bufferSamplers.begin(),
+ imageStorageArray.begin(),
usePLSDstRead);
fXferProcessor->emitCode(args);
@@ -240,13 +251,16 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
fFS.codeAppend("}");
}
-void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
- SkTArray<SamplerHandle>* outTexSamplers,
- SkTArray<SamplerHandle>* outBufferSamplers) {
+void GrGLSLProgramBuilder::emitSamplersAndImageStorages(
+ const GrProcessor& processor,
+ SkTArray<SamplerHandle>* outTexSamplerHandles,
+ SkTArray<SamplerHandle>* outBufferSamplerHandles,
+ SkTArray<ImageStorageHandle>* outImageStorageHandles) {
SkString name;
int numTextureSamplers = processor.numTextureSamplers();
for (int t = 0; t < numTextureSamplers; ++t) {
const GrProcessor::TextureSampler& sampler = processor.textureSampler(t);
+ name.printf("TextureSampler_%d", outTexSamplerHandles->count());
GrSLType samplerType = sampler.texture()->texturePriv().samplerType();
if (kTextureExternalSampler_GrSLType == samplerType) {
const char* externalFeatureString = this->glslCaps()->externalTextureExtensionString();
@@ -256,9 +270,9 @@ void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
externalFeatureString);
}
- name.printf("TextureSampler_%d", outTexSamplers->count());
- this->emitSampler(samplerType, sampler.texture()->config(),
- name.c_str(), sampler.visibility(), outTexSamplers);
+ this->emitSampler(samplerType, sampler.texture()->config(), name.c_str(),
+ sampler.visibility(), outTexSamplerHandles);
+
}
if (int numBuffers = processor.numBuffers()) {
@@ -267,9 +281,9 @@ void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
for (int b = 0; b < numBuffers; ++b) {
const GrProcessor::BufferAccess& access = processor.bufferAccess(b);
- name.printf("BufferSampler_%d", outBufferSamplers->count());
+ name.printf("BufferSampler_%d", outBufferSamplerHandles->count());
this->emitSampler(kBufferSampler_GrSLType, access.texelConfig(), name.c_str(),
- access.visibility(), outBufferSamplers);
+ access.visibility(), outBufferSamplerHandles);
texelBufferVisibility |= access.visibility();
}
@@ -279,13 +293,19 @@ void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
extension);
}
}
+ int numImageStorages = processor.numImageStorages();
+ for (int i = 0; i < numImageStorages; ++i) {
+ const GrProcessor::ImageStorageAccess& imageStorageAccess = processor.imageStorageAccess(i);
+ name.printf("Image_%d", outImageStorageHandles->count());
+ this->emitImageStorage(imageStorageAccess, name.c_str(), outImageStorageHandles);
+ }
}
void GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
GrPixelConfig config,
const char* name,
GrShaderFlags visibility,
- SkTArray<SamplerHandle>* outSamplers) {
+ SkTArray<SamplerHandle>* outSamplerHandles) {
if (visibility & kVertex_GrShaderFlag) {
++fNumVertexSamplers;
}
@@ -298,12 +318,30 @@ void GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
}
GrSLPrecision precision = this->glslCaps()->samplerPrecision(config, visibility);
GrSwizzle swizzle = this->glslCaps()->configTextureSwizzle(config);
- SamplerHandle handle = this->uniformHandler()->addSampler(visibility,
- swizzle,
- samplerType,
- precision,
- name);
- outSamplers->emplace_back(handle);
+ outSamplerHandles->emplace_back(this->uniformHandler()->addSampler(visibility,
+ swizzle,
+ samplerType,
+ precision,
+ name));
+}
+
+void GrGLSLProgramBuilder::emitImageStorage(const GrProcessor::ImageStorageAccess& access,
+ const char* name,
+ SkTArray<ImageStorageHandle>* outImageStorageHandles) {
+ if (access.visibility() & kVertex_GrShaderFlag) {
+ ++fNumVertexImageStorages;
+ }
+ if (access.visibility() & kGeometry_GrShaderFlag) {
+ SkASSERT(this->primitiveProcessor().willUseGeoShader());
+ ++fNumGeometryImageStorages;
+ }
+ if (access.visibility() & kFragment_GrShaderFlag) {
+ ++fNumFragmentImageStorages;
+ }
+ GrSLType uniformType = access.texture()->texturePriv().imageStorageType();
+ ImageStorageHandle handle = this->uniformHandler()->addImageStorage(access.visibility(),
+ uniformType, access.format(), name);
+ outImageStorageHandles->emplace_back(handle);
}
void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
@@ -345,6 +383,30 @@ bool GrGLSLProgramBuilder::checkSamplerCounts() {
return true;
}
+bool GrGLSLProgramBuilder::checkImageStorageCounts() {
+ const GrGLSLCaps& glslCaps = *this->glslCaps();
+ if (fNumVertexImageStorages > glslCaps.maxVertexImageStorages()) {
+ GrCapsDebugf(this->caps(), "Program would use too many vertex images\n");
+ return false;
+ }
+ if (fNumGeometryImageStorages > glslCaps.maxGeometryImageStorages()) {
+ GrCapsDebugf(this->caps(), "Program would use too many geometry images\n");
+ return false;
+ }
+ if (fNumFragmentImageStorages > glslCaps.maxFragmentImageStorages()) {
+ GrCapsDebugf(this->caps(), "Program would use too many fragment images\n");
+ return false;
+ }
+ // If the same image is used in two different shaders, it counts as two combined images.
+ int numCombinedImages = fNumVertexImageStorages + fNumGeometryImageStorages +
+ fNumFragmentImageStorages;
+ if (numCombinedImages > glslCaps.maxCombinedImageStorages()) {
+ GrCapsDebugf(this->caps(), "Program would use too many combined images\n");
+ return false;
+ }
+ return true;
+}
+
#ifdef SK_DEBUG
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
@@ -393,7 +455,6 @@ void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString
this->uniformHandler()->appendUniformDecls(visibility, out);
}
-
void GrGLSLProgramBuilder::addRTAdjustmentUniform(GrSLPrecision precision,
const char* name,
const char** outName) {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 6c1eb3bf4b..5543537d19 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -28,7 +28,9 @@ typedef SkSTArray<8, GrGLSLFragmentProcessor*, true> GrGLSLFragProcs;
class GrGLSLProgramBuilder {
public:
- typedef GrGLSLUniformHandler::UniformHandle UniformHandle;
+ using UniformHandle = GrGLSLUniformHandler::UniformHandle;
+ using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
+ using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
virtual ~GrGLSLProgramBuilder() {}
@@ -42,8 +44,6 @@ public:
void appendUniformDecls(GrShaderFlags visibility, SkString*) const;
- typedef GrGLSLUniformHandler::SamplerHandle SamplerHandle;
-
const GrShaderVar& samplerVariable(SamplerHandle handle) const {
return this->uniformHandler()->samplerVariable(handle);
}
@@ -52,6 +52,10 @@ public:
return this->uniformHandler()->samplerSwizzle(handle);
}
+ const GrShaderVar& imageStorageVariable(ImageStorageHandle handle) const {
+ return this->uniformHandler()->imageStorageVariable(handle);
+ }
+
// Handles for program uniforms (other than per-effect uniforms)
struct BuiltinUniformHandles {
UniformHandle fRTAdjustmentUni;
@@ -156,17 +160,18 @@ private:
const GrGLSLExpr4& coverageIn,
bool ignoresCoverage,
GrPixelLocalStorageState plsState);
-
- void emitSamplers(const GrProcessor& processor,
- SkTArray<SamplerHandle>* outTexSamplers,
- SkTArray<SamplerHandle>* outBufferSamplers);
- void emitSampler(GrSLType samplerType,
- GrPixelConfig,
- const char* name,
- GrShaderFlags visibility,
- SkTArray<SamplerHandle>* outSamplers);
+ void emitSamplersAndImageStorages(const GrProcessor& processor,
+ SkTArray<SamplerHandle>* outTexSamplerHandles,
+ SkTArray<SamplerHandle>* outBufferSamplerHandles,
+ SkTArray<ImageStorageHandle>* outImageStorageHandles);
+ void emitSampler(GrSLType samplerType, GrPixelConfig, const char* name,
+ GrShaderFlags visibility, SkTArray<SamplerHandle >* outSamplerHandles);
+ void emitImageStorage(const GrProcessor::ImageStorageAccess&,
+ const char* name,
+ SkTArray<ImageStorageHandle>* outImageStorageHandles);
void emitFSOutputSwizzle(bool hasSecondaryOutput);
bool checkSamplerCounts();
+ bool checkImageStorageCounts();
#ifdef SK_DEBUG
void verify(const GrPrimitiveProcessor&);
@@ -177,6 +182,9 @@ private:
int fNumVertexSamplers;
int fNumGeometrySamplers;
int fNumFragmentSamplers;
+ int fNumVertexImageStorages;
+ int fNumGeometryImageStorages;
+ int fNumFragmentImageStorages;
SkSTArray<4, GrShaderVar> fTransformedCoordVars;
};
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index 28578ddf63..1647eefaec 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -169,6 +169,16 @@ void GrGLSLShaderBuilder::appendTexelFetch(SamplerHandle samplerHandle, const ch
this->appendTexelFetch(&this->code(), samplerHandle, coordExpr);
}
+void GrGLSLShaderBuilder::appendImageStorageLoad(SkString* out, ImageStorageHandle handle,
+ const char* coordExpr) {
+ const GrShaderVar& imageStorage = fProgramBuilder->imageStorageVariable(handle);
+ out->appendf("imageLoad(%s, %s)", imageStorage.c_str(), coordExpr);
+}
+
+void GrGLSLShaderBuilder::appendImageStorageLoad(ImageStorageHandle handle, const char* coordExpr) {
+ this->appendImageStorageLoad(&this->code(), handle, coordExpr);
+}
+
bool GrGLSLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) {
if (featureBit & fFeaturesAddedMask) {
return false;
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index b568369cca..983d50b926 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -25,7 +25,8 @@ public:
GrGLSLShaderBuilder(GrGLSLProgramBuilder* program);
virtual ~GrGLSLShaderBuilder() {}
- typedef GrGLSLUniformHandler::SamplerHandle SamplerHandle;
+ using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
+ using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
/** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
@@ -72,6 +73,11 @@ public:
/** Version of above that appends the result to the shader code instead.*/
void appendTexelFetch(SamplerHandle, const char* coordExpr);
+ /** Creates a string of shader code that performs an image load. */
+ void appendImageStorageLoad(SkString* out, ImageStorageHandle, const char* coordExpr);
+ /** Version of above that appends the result to the shader code instead. */
+ void appendImageStorageLoad(ImageStorageHandle, const char* coordExpr);
+
/**
* Adds a constant declaration to the top of the shader.
*/
diff --git a/src/gpu/glsl/GrGLSLUniformHandler.h b/src/gpu/glsl/GrGLSLUniformHandler.h
index d49fbd4820..11ba2f7279 100644
--- a/src/gpu/glsl/GrGLSLUniformHandler.h
+++ b/src/gpu/glsl/GrGLSLUniformHandler.h
@@ -18,8 +18,9 @@ class GrGLSLUniformHandler {
public:
virtual ~GrGLSLUniformHandler() {}
- typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
- typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle;
+ using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
+ GR_DEFINE_RESOURCE_HANDLE_CLASS(SamplerHandle);
+ GR_DEFINE_RESOURCE_HANDLE_CLASS(ImageStorageHandle);
/** Add a uniform variable to the current program, that has visibility in one or more shaders.
visibility is a bitfield of GrShaderFlag values indicating from which shaders the uniform
@@ -67,6 +68,10 @@ private:
virtual SamplerHandle addSampler(uint32_t visibility, GrSwizzle, GrSLType, GrSLPrecision,
const char* name) = 0;
+ virtual const GrShaderVar& imageStorageVariable(ImageStorageHandle) const = 0;
+ virtual ImageStorageHandle addImageStorage(uint32_t visibility, GrSLType type,
+ GrImageStorageFormat, const char* name) = 0;
+
virtual UniformHandle internalAddUniformArray(uint32_t visibility,
GrSLType type,
GrSLPrecision precision,
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.h b/src/gpu/glsl/GrGLSLXferProcessor.h
index bf6ee64299..69e00723a8 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.h
+++ b/src/gpu/glsl/GrGLSLXferProcessor.h
@@ -9,10 +9,10 @@
#define GrGLSLXferProcessor_DEFINED
#include "glsl/GrGLSLProgramDataManager.h"
+#include "glsl/GrGLSLUniformHandler.h"
class GrXferProcessor;
class GrGLSLCaps;
-class GrGLSLUniformHandler;
class GrGLSLXPBuilder;
class GrGLSLXPFragmentBuilder;
@@ -21,7 +21,8 @@ public:
GrGLSLXferProcessor() {}
virtual ~GrGLSLXferProcessor() {}
- typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle;
+ using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
+ using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
struct EmitArgs {
EmitArgs(GrGLSLXPFragmentBuilder* fragBuilder,
@@ -34,6 +35,7 @@ public:
const char* outputSecondary,
const SamplerHandle* texSamplers,
const SamplerHandle* bufferSamplers,
+ const ImageStorageHandle* imageStorages,
const bool usePLSDstRead)
: fXPFragBuilder(fragBuilder)
, fUniformHandler(uniformHandler)
@@ -45,6 +47,7 @@ public:
, fOutputSecondary(outputSecondary)
, fTexSamplers(texSamplers)
, fBufferSamplers(bufferSamplers)
+ , fImageStorages(imageStorages)
, fUsePLSDstRead(usePLSDstRead) {}
GrGLSLXPFragmentBuilder* fXPFragBuilder;
@@ -57,6 +60,7 @@ public:
const char* fOutputSecondary;
const SamplerHandle* fTexSamplers;
const SamplerHandle* fBufferSamplers;
+ const ImageStorageHandle* fImageStorages;
bool fUsePLSDstRead;
};
/**
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 2d53cd8c8d..75b8baaa4f 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -174,6 +174,8 @@ void GrVkPipelineState::abandonGPUResources() {
static void append_texture_bindings(const GrProcessor& processor,
SkTArray<const GrProcessor::TextureSampler*>* textureBindings) {
+ // We don't support image storages in VK.
+ SkASSERT(!processor.numImageStorages());
if (int numTextureSamplers = processor.numTextureSamplers()) {
const GrProcessor::TextureSampler** bindings =
textureBindings->push_back_n(numTextureSamplers);
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp
index 3998c0fd23..8c4f8514b8 100644
--- a/src/gpu/vk/GrVkUniformHandler.cpp
+++ b/src/gpu/vk/GrVkUniformHandler.cpp
@@ -45,6 +45,8 @@ uint32_t grsltype_to_alignment_mask(GrSLType type) {
case kBufferSampler_GrSLType:
case kTexture2D_GrSLType:
case kSampler_GrSLType:
+ case kImageStorage2D_GrSLType:
+ case kIImageStorage2D_GrSLType:
break;
}
SkFAIL("Unexpected type");
@@ -86,6 +88,8 @@ static inline uint32_t grsltype_to_vk_size(GrSLType type) {
case kBufferSampler_GrSLType:
case kTexture2D_GrSLType:
case kSampler_GrSLType:
+ case kImageStorage2D_GrSLType:
+ case kIImageStorage2D_GrSLType:
break;
}
SkFAIL("Unexpected type");
@@ -158,7 +162,7 @@ GrGLSLUniformHandler::UniformHandle GrVkUniformHandler::internalAddUniformArray(
uni.fVariable.setTypeModifier(GrShaderVar::kNone_TypeModifier);
uint32_t* currentOffset = kVertex_GrShaderFlag == visibility ? &fCurrentVertexUBOOffset
- : &fCurrentFragmentUBOOffset;
+ : &fCurrentFragmentUBOOffset;
get_ubo_aligned_offset(&uni.fUBOffset, currentOffset, type, arrayCount);
if (outName) {
diff --git a/src/gpu/vk/GrVkUniformHandler.h b/src/gpu/vk/GrVkUniformHandler.h
index e5d4a4cf10..d8e8c686bf 100644
--- a/src/gpu/vk/GrVkUniformHandler.h
+++ b/src/gpu/vk/GrVkUniformHandler.h
@@ -76,6 +76,18 @@ private:
return fSamplers[handle.toIndex()].fVisibility;
}
+ ImageStorageHandle addImageStorage(uint32_t visibility, GrSLType, GrImageStorageFormat,
+ const char* name) override {
+ SkFAIL("Image storages not implemented for Vulkan.");
+ return 0;
+ }
+
+ const GrShaderVar& imageStorageVariable(ImageStorageHandle handle) const override {
+ SkFAIL("Image storages not implemented for Vulkan.");
+ GrShaderVar* gVar = nullptr;
+ return *gVar;
+ }
+
void appendUniformDecls(GrShaderFlags, SkString*) const override;
bool hasVertexUniforms() const { return fCurrentVertexUBOOffset > 0; }
diff --git a/src/gpu/vk/GrVkVaryingHandler.cpp b/src/gpu/vk/GrVkVaryingHandler.cpp
index 9bab292af8..d7d08c9622 100644
--- a/src/gpu/vk/GrVkVaryingHandler.cpp
+++ b/src/gpu/vk/GrVkVaryingHandler.cpp
@@ -47,6 +47,10 @@ static inline int grsltype_to_location_size(GrSLType type) {
return 0;
case kSampler_GrSLType:
return 0;
+ case kImageStorage2D_GrSLType:
+ return 0;
+ case kIImageStorage2D_GrSLType:
+ return 0;
}
SkFAIL("Unexpected type");
return -1;