diff options
author | 2016-11-29 11:59:17 -0500 | |
---|---|---|
committer | 2016-11-29 17:42:53 +0000 | |
commit | f9f451213a3951d8a61568998de2ddbd643f6693 (patch) | |
tree | ba11ab458cbe8c654337bc704c52f4ca73f6b44a /src/gpu/gl | |
parent | e18c97b73a0392b2eee57a111122dd5b637e36e6 (diff) |
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 <ethannicholas@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 49 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 11 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 26 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 8 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 7 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 7 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDataManager.cpp | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDataManager.h | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGLUniformHandler.cpp | 61 | ||||
-rw-r--r-- | src/gpu/gl/GrGLUniformHandler.h | 12 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.cpp | 1 |
11 files changed, 169 insertions, 24 deletions
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 3e9f82a79c..c4f7560be4 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -324,16 +324,29 @@ 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); + if (glslCaps->fGeometryShaderSupport) { + 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); + // HACK: Currently we only use images in a unit test in the fragment shader. The individual + // stage image limits aren't exposed through GrShaderCaps. Soon GrShaderCaps and GrGLSLCaps + // will merge and the test can look for fragment support. + if (!glslCaps->fMaxFragmentImageStorages) { + glslCaps->fImageLoadStoreSupport = false; + } } /************************************************************************** @@ -2023,6 +2036,24 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa } } + // We currently only support images on rgba textures formats. We could add additional formats + // if desired. The shader builder would have to be updated to add swizzles where appropriate + // (e.g. where we use GL_RED textures to implement alpha configs). + if (this->shaderCaps()->imageLoadStoreSupport()) { + fConfigTable[kRGBA_8888_sint_GrPixelConfig].fFlags |= + ConfigInfo::kCanUseAsImageStorage_Flag; + // In OpenGL ES a texture may only be used with BindImageTexture if it has been made + // immutable via TexStorage. We create non-integer textures as mutable textures using + // TexImage because we may lazily add MIP levels. Thus, on ES we currently disable image + // storage support for non-integer textures. + if (kGL_GrGLStandard == ctxInfo.standard()) { + fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseAsImageStorage_Flag; + fConfigTable[kRGBA_float_GrPixelConfig].fFlags |= + ConfigInfo::kCanUseAsImageStorage_Flag; + fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseAsImageStorage_Flag; + } + } + #ifdef SK_DEBUG // Make sure we initialized everything. ConfigInfo defaultEntry; diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 496635d766..63843a5fc2 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -126,7 +126,9 @@ public: return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag); } } - + bool canConfigBeImageStorage(GrPixelConfig config) const override { + return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseAsImageStorage_Flag); + } bool canConfigBeFBOColorAttachment(GrPixelConfig config) const { return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kFBOColorAttachment_Flag); } @@ -159,6 +161,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 +458,6 @@ private: GrGLenum fExternalFormat[kExternalFormatUsageCnt]; GrGLenum fExternalType; - // Either the base or sized internal format depending on the GL and config. GrGLenum fInternalFormatTexImage; GrGLenum fInternalFormatRenderbuffer; @@ -489,6 +495,7 @@ private: kFBOColorAttachment_Flag = 0x10, kCanUseTexStorage_Flag = 0x20, kCanUseWithTexelBuffer_Flag = 0x40, + kCanUseAsImageStorage_Flag = 0x80, }; uint32_t fFlags; diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 94857789d9..af44af4338 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 820b55c7fe..f09b66869f 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -31,6 +31,7 @@ GrGLProgram::GrGLProgram(GrGLGpu* gpu, GrGLuint programID, const UniformInfoArray& uniforms, const UniformInfoArray& samplers, + const UniformInfoArray& imageStorages, const VaryingInfoArray& pathProcVaryings, GrGLSLPrimitiveProcessor* geometryProcessor, GrGLSLXferProcessor* xferProcessor, @@ -46,6 +47,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() { @@ -161,6 +163,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 d129ddaa3d..9c429782c5 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -102,9 +102,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&, @@ -112,6 +112,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..81755d552a 100644 --- a/src/gpu/gl/GrGLUniformHandler.cpp +++ b/src/gpu/gl/GrGLUniformHandler.cpp @@ -80,11 +80,38 @@ GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(uint32_t visi return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1); } +GrGLSLUniformHandler::ImageStorageHandle GrGLUniformHandler::addImageStorage( + uint32_t visibility, GrSLType type, GrImageStorageFormat format, GrSLMemoryModel model, + GrSLRestrict restrict, GrIOType ioType, 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.fVariable.setMemoryModel(model); + imageStorage.fVariable.setRestrict(restrict); + imageStorage.fVariable.setIOType(ioType); + imageStorage.fVariable.setPrecision(kHigh_GrSLPrecision); + 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 +120,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 +160,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..da7b13c4f5 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,18 @@ private: return fSamplers[handle.toIndex()].fVariable; } + ImageStorageHandle addImageStorage(uint32_t visibility, GrSLType, GrImageStorageFormat, + GrSLMemoryModel, GrSLRestrict, GrIOType, + 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 +75,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, |