diff --git a/Test/baseResults/spv.sparsetextureoffset_non_const.vert.out b/Test/baseResults/spv.sparsetextureoffset_non_const.vert.out new file mode 100644 index 0000000000..bf37b524b3 --- /dev/null +++ b/Test/baseResults/spv.sparsetextureoffset_non_const.vert.out @@ -0,0 +1,194 @@ +spv.sparsetextureoffset_non_const.vert +Validation failed +// Module Version 10000 +// Generated by (magic number): 8000b +// Id's are bound by 114 + + Capability Shader + Capability ImageGatherExtended + Capability SparseResidency + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 10 14 27 31 45 75 90 98 106 + Source GLSL 450 + SourceExtension "GL_ARB_sparse_texture2" + SourceExtension "GL_EXT_texture_offset_non_const" + Name 4 "main" + Name 8 "gl_PerVertex" + MemberName 8(gl_PerVertex) 0 "gl_Position" + Name 10 "" + Name 14 "a_position" + Name 19 "ret0" + Name 23 "u_sampler" + Name 27 "a_in0" + Name 31 "offsetValue" + Name 34 "aux0" + Name 36 "ResType" + Name 40 "ret1" + Name 45 "a_in1" + Name 49 "aux1" + Name 54 "ret2" + Name 59 "aux2" + Name 63 "ret3" + Name 71 "aux3" + Name 75 "v_color0" + Name 77 "buf0" + MemberName 77(buf0) 0 "u_scale" + Name 79 "" + Name 84 "buf1" + MemberName 84(buf1) 0 "u_bias" + Name 86 "" + Name 90 "v_color1" + Name 98 "v_color2" + Name 106 "v_color3" + Decorate 8(gl_PerVertex) Block + MemberDecorate 8(gl_PerVertex) 0 BuiltIn Position + Decorate 14(a_position) Location 0 + Decorate 23(u_sampler) Binding 0 + Decorate 23(u_sampler) DescriptorSet 0 + Decorate 27(a_in0) Location 4 + Decorate 31(offsetValue) Location 10 + Decorate 45(a_in1) Location 5 + Decorate 75(v_color0) RelaxedPrecision + Decorate 75(v_color0) Location 0 + Decorate 77(buf0) Block + MemberDecorate 77(buf0) 0 Offset 0 + Decorate 79 Binding 1 + Decorate 79 DescriptorSet 0 + Decorate 84(buf1) Block + MemberDecorate 84(buf1) 0 Offset 0 + Decorate 86 Binding 2 + Decorate 86 DescriptorSet 0 + Decorate 90(v_color1) RelaxedPrecision + Decorate 90(v_color1) Location 1 + Decorate 98(v_color2) RelaxedPrecision + Decorate 98(v_color2) Location 2 + Decorate 106(v_color3) RelaxedPrecision + Decorate 106(v_color3) Location 3 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8(gl_PerVertex): TypeStruct 7(fvec4) + 9: TypePointer Output 8(gl_PerVertex) + 10: 9(ptr) Variable Output + 11: TypeInt 32 1 + 12: 11(int) Constant 0 + 13: TypePointer Input 7(fvec4) + 14(a_position): 13(ptr) Variable Input + 16: TypePointer Output 7(fvec4) + 18: TypePointer Function 11(int) + 20: TypeImage 6(float) 2D sampled format:Unknown + 21: TypeSampledImage 20 + 22: TypePointer UniformConstant 21 + 23(u_sampler): 22(ptr) Variable UniformConstant + 25: TypeVector 6(float) 2 + 26: TypePointer Input 25(fvec2) + 27(a_in0): 26(ptr) Variable Input + 29: TypeVector 11(int) 2 + 30: TypePointer Input 29(ivec2) + 31(offsetValue): 30(ptr) Variable Input + 33: TypePointer Function 7(fvec4) + 35: 6(float) Constant 0 + 36(ResType): TypeStruct 11(int) 7(fvec4) + 44: TypePointer Input 6(float) + 45(a_in1): 44(ptr) Variable Input + 75(v_color0): 16(ptr) Variable Output + 77(buf0): TypeStruct 7(fvec4) + 78: TypePointer Uniform 77(buf0) + 79: 78(ptr) Variable Uniform + 80: TypePointer Uniform 7(fvec4) + 84(buf1): TypeStruct 7(fvec4) + 85: TypePointer Uniform 84(buf1) + 86: 85(ptr) Variable Uniform + 90(v_color1): 16(ptr) Variable Output + 98(v_color2): 16(ptr) Variable Output + 106(v_color3): 16(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 19(ret0): 18(ptr) Variable Function + 34(aux0): 33(ptr) Variable Function + 40(ret1): 18(ptr) Variable Function + 49(aux1): 33(ptr) Variable Function + 54(ret2): 18(ptr) Variable Function + 59(aux2): 33(ptr) Variable Function + 63(ret3): 18(ptr) Variable Function + 71(aux3): 33(ptr) Variable Function + 15: 7(fvec4) Load 14(a_position) + 17: 16(ptr) AccessChain 10 12 + Store 17 15 + 24: 21 Load 23(u_sampler) + 28: 25(fvec2) Load 27(a_in0) + 32: 29(ivec2) Load 31(offsetValue) + 37: 36(ResType) ImageSparseSampleExplicitLod 24 28 Lod Offset 35 32 + 38: 7(fvec4) CompositeExtract 37 1 + Store 34(aux0) 38 + 39: 11(int) CompositeExtract 37 0 + Store 19(ret0) 39 + 41: 21 Load 23(u_sampler) + 42: 25(fvec2) Load 27(a_in0) + 43: 29(ivec2) ConvertFToS 42 + 46: 6(float) Load 45(a_in1) + 47: 11(int) ConvertFToS 46 + 48: 29(ivec2) Load 31(offsetValue) + 50: 20 Image 41 + 51: 36(ResType) ImageSparseFetch 50 43 Lod Offset 47 48 + 52: 7(fvec4) CompositeExtract 51 1 + Store 49(aux1) 52 + 53: 11(int) CompositeExtract 51 0 + Store 40(ret1) 53 + 55: 21 Load 23(u_sampler) + 56: 25(fvec2) Load 27(a_in0) + 57: 6(float) Load 45(a_in1) + 58: 29(ivec2) Load 31(offsetValue) + 60: 36(ResType) ImageSparseSampleExplicitLod 55 56 Lod Offset 57 58 + 61: 7(fvec4) CompositeExtract 60 1 + Store 59(aux2) 61 + 62: 11(int) CompositeExtract 60 0 + Store 54(ret2) 62 + 64: 21 Load 23(u_sampler) + 65: 25(fvec2) Load 27(a_in0) + 66: 6(float) Load 45(a_in1) + 67: 25(fvec2) CompositeConstruct 66 66 + 68: 6(float) Load 45(a_in1) + 69: 25(fvec2) CompositeConstruct 68 68 + 70: 29(ivec2) Load 31(offsetValue) + 72: 36(ResType) ImageSparseSampleExplicitLod 64 65 Grad Offset 67 69 70 + 73: 7(fvec4) CompositeExtract 72 1 + Store 71(aux3) 73 + 74: 11(int) CompositeExtract 72 0 + Store 63(ret3) 74 + 76: 7(fvec4) Load 34(aux0) + 81: 80(ptr) AccessChain 79 12 + 82: 7(fvec4) Load 81 + 83: 7(fvec4) FMul 76 82 + 87: 80(ptr) AccessChain 86 12 + 88: 7(fvec4) Load 87 + 89: 7(fvec4) FAdd 83 88 + Store 75(v_color0) 89 + 91: 7(fvec4) Load 49(aux1) + 92: 80(ptr) AccessChain 79 12 + 93: 7(fvec4) Load 92 + 94: 7(fvec4) FMul 91 93 + 95: 80(ptr) AccessChain 86 12 + 96: 7(fvec4) Load 95 + 97: 7(fvec4) FAdd 94 96 + Store 90(v_color1) 97 + 99: 7(fvec4) Load 59(aux2) + 100: 80(ptr) AccessChain 79 12 + 101: 7(fvec4) Load 100 + 102: 7(fvec4) FMul 99 101 + 103: 80(ptr) AccessChain 86 12 + 104: 7(fvec4) Load 103 + 105: 7(fvec4) FAdd 102 104 + Store 98(v_color2) 105 + 107: 7(fvec4) Load 71(aux3) + 108: 80(ptr) AccessChain 79 12 + 109: 7(fvec4) Load 108 + 110: 7(fvec4) FMul 107 109 + 111: 80(ptr) AccessChain 86 12 + 112: 7(fvec4) Load 111 + 113: 7(fvec4) FAdd 110 112 + Store 106(v_color3) 113 + Return + FunctionEnd diff --git a/Test/baseResults/spv.sparsetextureoffset_non_const_fail.vert.out b/Test/baseResults/spv.sparsetextureoffset_non_const_fail.vert.out new file mode 100644 index 0000000000..e56029c30b --- /dev/null +++ b/Test/baseResults/spv.sparsetextureoffset_non_const_fail.vert.out @@ -0,0 +1,9 @@ +spv.sparsetextureoffset_non_const_fail.vert +ERROR: 0:26: 'texel offset' : argument must be compile-time constant +ERROR: 0:27: 'texel offset' : argument must be compile-time constant +ERROR: 0:28: 'texel offset' : argument must be compile-time constant +ERROR: 0:29: 'texel offset' : argument must be compile-time constant +ERROR: 4 compilation errors. No code generated. + + +SPIR-V is not generated for failed compile or link diff --git a/Test/spv.sparsetextureoffset_non_const.vert b/Test/spv.sparsetextureoffset_non_const.vert new file mode 100644 index 0000000000..699d2b8190 --- /dev/null +++ b/Test/spv.sparsetextureoffset_non_const.vert @@ -0,0 +1,36 @@ +#version 450 core +#extension GL_ARB_sparse_texture2 : enable +#extension GL_EXT_texture_offset_non_const : enable +layout(location = 0) in highp vec4 a_position; +layout(location = 4) in highp vec2 a_in0; +layout(location = 5) in highp float a_in1; +layout(location = 10) in highp ivec2 offsetValue; +layout(location = 0) out mediump vec4 v_color0; +layout(location = 1) out mediump vec4 v_color1; +layout(location = 2) out mediump vec4 v_color2; +layout(location = 3) out mediump vec4 v_color3; +layout(set = 0, binding = 0) uniform highp sampler2D u_sampler; +layout(set = 0, binding = 1) uniform buf0 { highp vec4 u_scale; }; +layout(set = 0, binding = 2) uniform buf1 { highp vec4 u_bias; }; +out gl_PerVertex { + vec4 gl_Position; +}; + +void main() +{ + gl_Position = a_position; + vec4 aux0; + vec4 aux1; + vec4 aux2; + vec4 aux3; + + int ret0 = sparseTextureOffsetARB(u_sampler, a_in0, offsetValue, aux0); + int ret1 = sparseTexelFetchOffsetARB(u_sampler, ivec2(a_in0), int(a_in1), offsetValue, aux1); + int ret2 = sparseTextureLodOffsetARB(u_sampler, a_in0, a_in1, offsetValue, aux2); + int ret3 = sparseTextureGradOffsetARB(u_sampler, a_in0, vec2(a_in1, a_in1), vec2(a_in1, a_in1), offsetValue, aux3); + + v_color0 = aux0 * u_scale + u_bias; + v_color1 = aux1 * u_scale + u_bias; + v_color2 = aux2 * u_scale + u_bias; + v_color3 = aux3 * u_scale + u_bias; +} diff --git a/Test/spv.sparsetextureoffset_non_const_fail.vert b/Test/spv.sparsetextureoffset_non_const_fail.vert new file mode 100644 index 0000000000..706f1fffe1 --- /dev/null +++ b/Test/spv.sparsetextureoffset_non_const_fail.vert @@ -0,0 +1,35 @@ +#version 450 core +#extension GL_ARB_sparse_texture2 : enable +layout(location = 0) in highp vec4 a_position; +layout(location = 4) in highp vec2 a_in0; +layout(location = 5) in highp float a_in1; +layout(location = 10) in highp ivec2 offsetValue; +layout(location = 0) out mediump vec4 v_color0; +layout(location = 1) out mediump vec4 v_color1; +layout(location = 2) out mediump vec4 v_color2; +layout(location = 3) out mediump vec4 v_color3; +layout(set = 0, binding = 0) uniform highp sampler2D u_sampler; +layout(set = 0, binding = 1) uniform buf0 { highp vec4 u_scale; }; +layout(set = 0, binding = 2) uniform buf1 { highp vec4 u_bias; }; +out gl_PerVertex { + vec4 gl_Position; +}; + +void main() +{ + gl_Position = a_position; + vec4 aux0; + vec4 aux1; + vec4 aux2; + vec4 aux3; + + int ret0 = sparseTextureOffsetARB(u_sampler, a_in0, offsetValue, aux0); + int ret1 = sparseTexelFetchOffsetARB(u_sampler, ivec2(a_in0), int(a_in1), offsetValue, aux1); + int ret2 = sparseTextureLodOffsetARB(u_sampler, a_in0, a_in1, offsetValue, aux2); + int ret3 = sparseTextureGradOffsetARB(u_sampler, a_in0, vec2(a_in1, a_in1), vec2(a_in1, a_in1), offsetValue, aux3); + + v_color0 = aux0 * u_scale + u_bias; + v_color1 = aux1 * u_scale + u_bias; + v_color2 = aux2 * u_scale + u_bias; + v_color3 = aux3 * u_scale + u_bias; +} diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index e300aa4a18..726bb7f5f0 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2541,18 +2541,26 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan case EOpTextureProjLodOffset: case EOpTextureGradOffset: case EOpTextureProjGradOffset: + case EOpSparseTextureOffset: + case EOpSparseTextureFetchOffset: + case EOpSparseTextureLodOffset: + case EOpSparseTextureGradOffset: { // Handle texture-offset limits checking // Pick which argument has to hold constant offsets int arg = -1; switch (callNode.getOp()) { - case EOpTextureOffset: arg = 2; break; - case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().isRect()) ? 2 : 3; break; - case EOpTextureProjOffset: arg = 2; break; - case EOpTextureLodOffset: arg = 3; break; - case EOpTextureProjLodOffset: arg = 3; break; - case EOpTextureGradOffset: arg = 4; break; - case EOpTextureProjGradOffset: arg = 4; break; + case EOpSparseTextureOffset: // fallthrough + case EOpTextureOffset: arg = 2; break; + case EOpSparseTextureFetchOffset: // fallthrough + case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().isRect()) ? 2 : 3; break; + case EOpTextureProjOffset: arg = 2; break; + case EOpSparseTextureLodOffset: // fallthrough + case EOpTextureLodOffset: arg = 3; break; + case EOpTextureProjLodOffset: arg = 3; break; + case EOpSparseTextureGradOffset: // fallthrough + case EOpTextureGradOffset: arg = 4; break; + case EOpTextureProjGradOffset: arg = 4; break; default: assert(0); break; @@ -2578,6 +2586,8 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } } + // This check does not apply to sparse because + // GL_ARB_sparse_texture2 always includes this function. if (callNode.getOp() == EOpTextureOffset) { TSampler s = arg0->getType().getSampler(); if (s.is2D() && s.isArrayed() && s.isShadow()) { @@ -2598,6 +2608,9 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } } + // This check does not apply to sparse because + // GL_ARB_sparse_texture2 does not define sparseTextureLodOffsetARB + // with a sampler2DArrayShadow. if (callNode.getOp() == EOpTextureLodOffset) { TSampler s = arg0->getType().getSampler(); if (s.is2D() && s.isArrayed() && s.isShadow() && diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 83719502b8..67e404bf78 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -553,6 +553,8 @@ INSTANTIATE_TEST_SUITE_P( "spv.sampledImageBlock.frag", "spv.multiple.var.same.const.frag", "spv.textureoffset_non_const.vert", + "spv.sparsetextureoffset_non_const.vert", + "spv.sparsetextureoffset_non_const_fail.vert", })), FileNameAsCustomTestSuffix );