diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index c3ae56eb..81509975 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -90,6 +90,7 @@ public: protected: spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier); spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable); + spv::ImageFormat TranslateImageFormat(const glslang::TType& type); spv::Id createSpvVariable(const glslang::TIntermSymbol*); spv::Id getSampledType(const glslang::TSampler&); spv::Id convertGlslangToSpvType(const glslang::TType& type); @@ -404,10 +405,48 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI } // Translate glslang image layout format to SPIR-V image format. -spv::ImageFormat TranslateImageFormat(const glslang::TType& type) +spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type) { assert(type.getBasicType() == glslang::EbtSampler); + // Check for capabilities + switch (type.getQualifier().layoutFormat) { + case glslang::ElfRg32f: + case glslang::ElfRg16f: + case glslang::ElfR11fG11fB10f: + case glslang::ElfR16f: + case glslang::ElfRgba16: + case glslang::ElfRgb10A2: + case glslang::ElfRg16: + case glslang::ElfRg8: + case glslang::ElfR16: + case glslang::ElfR8: + case glslang::ElfRgba16Snorm: + case glslang::ElfRg16Snorm: + case glslang::ElfRg8Snorm: + case glslang::ElfR16Snorm: + case glslang::ElfR8Snorm: + + case glslang::ElfRg32i: + case glslang::ElfRg16i: + case glslang::ElfRg8i: + case glslang::ElfR16i: + case glslang::ElfR8i: + + case glslang::ElfRgb10a2ui: + case glslang::ElfRg32ui: + case glslang::ElfRg16ui: + case glslang::ElfRg8ui: + case glslang::ElfR16ui: + case glslang::ElfR8ui: + builder.addCapability(spv::CapabilityStorageImageExtendedFormats); + break; + + default: + break; + } + + // do the translation switch (type.getQualifier().layoutFormat) { case glslang::ElfNone: return spv::ImageFormatUnknown; case glslang::ElfRgba32f: return spv::ImageFormatRgba32f; @@ -2137,6 +2176,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO operands.push_back(*opIt); } return builder.createOp(spv::OpImageRead, convertGlslangToSpvType(node->getType()), operands); + if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) + builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); } else if (node->getOp() == glslang::EOpImageStore) { if (sampler.ms) { operands.push_back(*(opIt + 1)); @@ -2145,6 +2186,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO } else operands.push_back(*opIt); builder.createNoResultOp(spv::OpImageWrite, operands); + if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) + builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat); return spv::NoResult; } else if (node->isSparseImage()) { spv::MissingFunctionality("sparse image functions"); @@ -2894,10 +2937,6 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv: return createAtomicOperation(op, precision, typeId, operands, typeProxy); } - case glslang::EOpImageLoad: - unaryOp = spv::OpImageRead; - break; - case glslang::EOpBitFieldReverse: unaryOp = spv::OpBitReverse; break; diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index 92ddac9e..074f8d24 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -124,6 +124,7 @@ public: Id getContainedTypeId(Id typeId) const; Id getContainedTypeId(Id typeId, int) const; StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } diff --git a/Test/baseResults/spv.image.frag.out b/Test/baseResults/spv.image.frag.out index 04e023a7..ca9c588d 100644 --- a/Test/baseResults/spv.image.frag.out +++ b/Test/baseResults/spv.image.frag.out @@ -7,7 +7,7 @@ Linked fragment stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 372 +// Id's are bound by 378 Capability Shader Capability SampledRect @@ -15,10 +15,12 @@ Linked fragment stage: Capability SampledCubeArray Capability SampledBuffer Capability ImageMSArray + Capability StorageImageExtendedFormats Capability ImageQuery + Capability StorageImageWriteWithoutFormat 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Fragment 4 "main" 356 + EntryPoint Fragment 4 "main" 362 ExecutionMode 4 OriginLowerLeft Source GLSL 450 Name 4 "main" @@ -42,8 +44,9 @@ Linked fragment stage: Name 232 "ii1D" Name 245 "ui2D" Name 248 "value" - Name 356 "fragData" - Name 371 "ic4D" + Name 357 "wo2D" + Name 362 "fragData" + Name 377 "ic4D" Decorate 15(i1D) Binding 0 Decorate 27(i2D) Binding 1 Decorate 38(i3D) Binding 2 @@ -57,6 +60,7 @@ Linked fragment stage: Decorate 108(i2DMSArray) Binding 10 Decorate 232(ii1D) Binding 11 Decorate 245(ui2D) Binding 12 + Decorate 357(wo2D) Binding 1 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 1 @@ -90,7 +94,7 @@ Linked fragment stage: 70: TypeImage 12(float) 1D array nonsampled format:Rgba32f 71: TypePointer UniformConstant 70 72(i1DArray): 71(ptr) Variable UniformConstant - 80: TypeImage 12(float) 2D array nonsampled format:Rgba32f + 80: TypeImage 12(float) 2D array nonsampled format:Rg16 81: TypePointer UniformConstant 80 82(i2DArray): 81(ptr) Variable UniformConstant 87: TypeImage 12(float) Buffer nonsampled format:Rgba32f @@ -138,18 +142,21 @@ Linked fragment stage: 340: 6(int) Constant 18 341: 6(int) Constant 17 349: 18(int) Constant 19 - 355: TypePointer Output 125(fvec4) - 356(fragData): 355(ptr) Variable Output - 362: TypeBool - 369: TypeVector 6(int) 4 - 370: TypePointer UniformConstant 369(ivec4) - 371(ic4D): 370(ptr) Variable UniformConstant + 355: TypeImage 12(float) 2D nonsampled format:Unknown + 356: TypePointer UniformConstant 355 + 357(wo2D): 356(ptr) Variable UniformConstant + 361: TypePointer Output 125(fvec4) + 362(fragData): 361(ptr) Variable Output + 368: TypeBool + 375: TypeVector 6(int) 4 + 376: TypePointer UniformConstant 375(ivec4) + 377(ic4D): 376(ptr) Variable UniformConstant 4(main): 2 Function None 3 5: Label 9(iv): 8(ptr) Variable Function 127(v): 126(ptr) Variable Function 229(ui): 228(ptr) Variable Function - 357: 126(ptr) Variable Function + 363: 126(ptr) Variable Function Store 9(iv) 11 16: 13 Load 15(i1D) 17: 6(int) ImageQuerySize 16 @@ -471,22 +478,26 @@ Linked fragment stage: 353: 18(int) Load 229(ui) 354: 18(int) IAdd 353 352 Store 229(ui) 354 - 358: 18(int) Load 229(ui) - 359: 20(ptr) AccessChain 9(iv) 237 - 360: 6(int) Load 359 - 361: 18(int) Bitcast 360 - 363: 362(bool) INotEqual 358 361 - SelectionMerge 365 None - BranchConditional 363 364 367 - 364: Label - 366: 125(fvec4) Load 127(v) - Store 357 366 - Branch 365 - 367: Label - Store 357 129 - Branch 365 - 365: Label - 368: 125(fvec4) Load 357 - Store 356(fragData) 368 + 358: 355 Load 357(wo2D) + 359: 29(ivec2) Load 142(ic2D) + 360: 125(fvec4) Load 127(v) + ImageWrite 358 359 360 + 364: 18(int) Load 229(ui) + 365: 20(ptr) AccessChain 9(iv) 237 + 366: 6(int) Load 365 + 367: 18(int) Bitcast 366 + 369: 368(bool) INotEqual 364 367 + SelectionMerge 371 None + BranchConditional 369 370 373 + 370: Label + 372: 125(fvec4) Load 127(v) + Store 363 372 + Branch 371 + 373: Label + Store 363 129 + Branch 371 + 371: Label + 374: 125(fvec4) Load 363 + Store 362(fragData) 374 Return FunctionEnd diff --git a/Test/spv.image.frag b/Test/spv.image.frag index 2ced0acf..433687dc 100644 --- a/Test/spv.image.frag +++ b/Test/spv.image.frag @@ -7,7 +7,7 @@ layout(rgba32f, binding = 3) uniform imageCube iCube; layout(rgba32f, binding = 4) uniform imageCubeArray iCubeArray; layout(rgba32f, binding = 5) uniform image2DRect i2DRect; layout(rgba32f, binding = 6) uniform image1DArray i1DArray; -layout(rgba32f, binding = 7) uniform image2DArray i2DArray; +layout(rg16, binding = 7) uniform image2DArray i2DArray; layout(rgba32f, binding = 8) uniform imageBuffer iBuffer; layout(rgba32f, binding = 9) uniform image2DMS i2DMS; layout(rgba32f, binding = 10) uniform image2DMSArray i2DMSArray; @@ -15,6 +15,8 @@ layout(rgba32f, binding = 10) uniform image2DMSArray i2DMSArray; layout(r32i, binding = 11) uniform iimage1D ii1D; layout(r32ui, binding = 12) uniform uimage2D ui2D; +writeonly layout(binding = 1) uniform image2D wo2D; + uniform int ic1D; uniform ivec2 ic2D; uniform ivec3 ic3D; @@ -84,6 +86,8 @@ void main() iv.x += imageAtomicCompSwap(ii1D, ic1D, 18, 17); ui += imageAtomicCompSwap(ui2D, ic2D, 19u, value); + imageStore(wo2D, ic2D, v); + fragData = ui != iv.y ? v : vec4(0.0); }