From f9f451213a3951d8a61568998de2ddbd643f6693 Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Tue, 29 Nov 2016 11:59:17 -0500 Subject: Reland image storage with fixes. Revert "Revert "Initial OpenGL Image support."" This reverts commit 59dc41175d99d0a31c046aec0c26c4d82a3a3574. BUG=skia: Change-Id: Ibe3c87ce7f746f065fdbcc5a518388cc291112f5 Reviewed-on: https://skia-review.googlesource.com/5131 Reviewed-by: Ethan Nicholas Commit-Queue: Brian Salomon --- src/gpu/glsl/GrGLSL.h | 4 ++ src/gpu/glsl/GrGLSLCaps.cpp | 16 ++--- src/gpu/glsl/GrGLSLCaps.h | 16 ++--- src/gpu/glsl/GrGLSLFragmentProcessor.cpp | 2 + src/gpu/glsl/GrGLSLFragmentProcessor.h | 18 ++++- src/gpu/glsl/GrGLSLPrimitiveProcessor.h | 10 ++- src/gpu/glsl/GrGLSLProgramBuilder.cpp | 112 ++++++++++++++++++++++++------- src/gpu/glsl/GrGLSLProgramBuilder.h | 32 +++++---- src/gpu/glsl/GrGLSLShaderBuilder.cpp | 10 +++ src/gpu/glsl/GrGLSLShaderBuilder.h | 8 ++- src/gpu/glsl/GrGLSLUniformHandler.h | 10 ++- src/gpu/glsl/GrGLSLXferProcessor.h | 8 ++- 12 files changed, 182 insertions(+), 64 deletions(-) (limited to 'src/gpu/glsl') diff --git a/src/gpu/glsl/GrGLSL.h b/src/gpu/glsl/GrGLSL.h index d27b25f293..417f6d78d2 100644 --- a/src/gpu/glsl/GrGLSL.h +++ b/src/gpu/glsl/GrGLSL.h @@ -121,6 +121,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; + using ImageStorages = BuilderInputProvider; /** 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..0c1661d3b7 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* outTexSamplers, - SkTArray* outBufferSamplers) { +void GrGLSLProgramBuilder::emitSamplersAndImageStorages( + const GrProcessor& processor, + SkTArray* outTexSamplerHandles, + SkTArray* outBufferSamplerHandles, + SkTArray* 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* outSamplers) { + SkTArray* outSamplerHandles) { if (visibility & kVertex_GrShaderFlag) { ++fNumVertexSamplers; } @@ -298,12 +318,31 @@ 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* 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(), access.memoryModel(), access.restrict(), access.ioType(), + name); + outImageStorageHandles->emplace_back(handle); } void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { @@ -345,6 +384,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 +456,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* outTexSamplers, - SkTArray* outBufferSamplers); - void emitSampler(GrSLType samplerType, - GrPixelConfig, - const char* name, - GrShaderFlags visibility, - SkTArray* outSamplers); + void emitSamplersAndImageStorages(const GrProcessor& processor, + SkTArray* outTexSamplerHandles, + SkTArray* outBufferSamplerHandles, + SkTArray* outImageStorageHandles); + void emitSampler(GrSLType samplerType, GrPixelConfig, const char* name, + GrShaderFlags visibility, SkTArray* outSamplerHandles); + void emitImageStorage(const GrProcessor::ImageStorageAccess&, + const char* name, + SkTArray* 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 b6e7ce9ebf..79e977c5be 100644 --- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp @@ -162,6 +162,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..3d21c1cc4b 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,11 @@ 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, GrSLMemoryModel, GrSLRestrict, + GrIOType, 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; }; /** -- cgit v1.2.3