Skip to content

Incorrect generation of spvDescriptorArray in 1.3.268.1 #2052

@rokuz

Description

@rokuz

I started getting the following error after updated from 1.3.261.1 to 1.3.268.1:

[mvk-error] VK_ERROR_INITIALIZATION_FAILED: Shader library compile failed (Error code 3):
program_source:53:117: error: no template named 'spvDescriptorArray'
float4 textureBindless2D(thread const uint& textureid, thread const uint& samplerid, thread const float2& uv, const spvDescriptorArray<texture2d<float>> kTextures2D, const spvDescriptorArray<sampler> kSamplers)
                                                                                                                    ^
program_source:53:173: error: no template named 'spvDescriptorArray'
float4 textureBindless2D(thread const uint& textureid, thread const uint& samplerid, thread const float2& uv, const spvDescriptorArray<texture2d<float>> kTextures2D, const spvDescriptorArray<sampler> kSamplers)
                                                                                                                                                                            ^
.
[mvk-error] VK_ERROR_INVALID_SHADER_NV: Fragment shader function could not be compiled into pipeline. See previous logged error.
Assertion failed: (false), function Assert, file LVK.cpp, line 140.
Compiler failed to build request

Problem:

New MoltenVK (SPIR-V Cross in it?) generates spvDescriptorArray around arrays of textures and samplers but do not define spvDescriptorArray itself.

// Before update
static inline __attribute__((always_inline))
float4 textureBindless2D(thread const uint& textureid, 
  thread const uint& samplerid, 
  thread const float2& uv, 
  constant array<texture2d<float>, 16>& kTextures2D, 
  constant array<sampler, 16>& kSamplers)
{
    return kTextures2D[textureid].sample(kSamplers[samplerid], uv);
}

// After update: No spvDescriptorArray in MSL output
static inline __attribute__((always_inline))
float4 textureBindless2D(thread const uint& textureid, 
  thread const uint& samplerid, 
  thread const float2& uv, 
  const spvDescriptorArray<texture2d<float>> kTextures2D, 
  const spvDescriptorArray<sampler> kSamplers)
{
    return kTextures2D[textureid].sample(kSamplers[samplerid], uv);
}

Full outputs:

Original GLSL:

#version 460
#extension GL_EXT_buffer_reference_uvec2 : require
#extension GL_EXT_debug_printf : enable
#extension GL_EXT_nonuniform_qualifier : require
#extension GL_EXT_samplerless_texture_functions : require
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require

layout (set = 0, binding = 0) uniform texture2D kTextures2D[];
layout (set = 1, binding = 0) uniform texture3D kTextures3D[];
layout (set = 2, binding = 0) uniform textureCube kTexturesCube[];
layout (set = 0, binding = 1) uniform sampler kSamplers[];
layout (set = 1, binding = 1) uniform samplerShadow kSamplersShadow[];

vec4 textureBindless2D(uint textureid, uint samplerid, vec2 uv) {
  return texture(sampler2D(kTextures2D[textureid], kSamplers[samplerid]), uv);
}
vec4 textureBindless2DLod(uint textureid, uint samplerid, vec2 uv, float lod) {
  return textureLod(sampler2D(kTextures2D[textureid], kSamplers[samplerid]), uv, lod);
}
float textureBindless2DShadow(uint textureid, uint samplerid, vec3 uvw) {
  return texture(sampler2DShadow(kTextures2D[textureid], kSamplersShadow[samplerid]), uvw);
}
ivec2 textureBindlessSize2D(uint textureid) {
  return textureSize(kTextures2D[textureid], 0);
}
vec4 textureBindlessCube(uint textureid, uint samplerid, vec3 uvw) {
  return texture(samplerCube(kTexturesCube[textureid], kSamplers[samplerid]), uvw);
}
vec4 textureBindlessCubeLod(uint textureid, uint samplerid, vec3 uvw, float lod) {
  return textureLod(samplerCube(kTexturesCube[textureid], kSamplers[samplerid]), uvw, lod);
}
int textureBindlessQueryLevels2D(uint textureid) {
  return textureQueryLevels(kTextures2D[textureid]);
}
      
layout (location=0) in vec3 color;
layout (location=1) in vec2 uv;
layout (location=0) out vec4 out_FragColor;

layout(std430, buffer_reference) readonly buffer PerFrame {
  mat4 proj;
  mat4 view;
  uint texture0;
  uint texture1;
  uint sampler0;
};

layout(push_constant) uniform constants {
  PerFrame perFrame;
} pc;

void main() {
  vec4 t0 = textureBindless2D(pc.perFrame.texture0, pc.perFrame.sampler0, 2.0*uv);
  vec4 t1 = textureBindless2D(pc.perFrame.texture1, pc.perFrame.sampler0, uv);
  out_FragColor = vec4(color * (t0.rgb + t1.rgb), 1.0);
};

SPIR-V:

; SPIR-V
; Version: 1.6
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 116
; Schema: 0
               OpCapability Shader
               OpCapability RuntimeDescriptorArray
               OpCapability PhysicalStorageBufferAddresses
          %2 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel PhysicalStorageBuffer64 GLSL450
               OpEntryPoint Fragment %5 "main" %22 %30 %48 %60 %88 %91 %108 %112 %115
               OpExecutionMode %5 OriginUpperLeft
          %1 = OpString ""
               OpSource GLSL 460 %1
               OpSourceExtension "GL_EXT_buffer_reference"
               OpSourceExtension "GL_EXT_buffer_reference_uvec2"
               OpSourceExtension "GL_EXT_debug_printf"
               OpSourceExtension "GL_EXT_nonuniform_qualifier"
               OpSourceExtension "GL_EXT_samplerless_texture_functions"
               OpSourceExtension "GL_EXT_shader_explicit_arithmetic_types_float16"
               OpName %5 "main"
               OpName %17 "textureBindless2D(u1;u1;vf2;"
               OpName %14 "textureid"
               OpName %15 "samplerid"
               OpName %16 "uv"
               OpName %22 "kTextures2D"
               OpName %30 "kSamplers"
               OpName %42 "t0"
               OpName %44 "constants"
               OpMemberName %44 0 "perFrame"
               OpName %46 "PerFrame"
               OpMemberName %46 0 "proj"
               OpMemberName %46 1 "view"
               OpMemberName %46 2 "texture0"
               OpMemberName %46 3 "texture1"
               OpMemberName %46 4 "sampler0"
               OpName %48 "pc"
               OpName %60 "uv"
               OpName %63 "param"
               OpName %67 "param"
               OpName %70 "param"
               OpName %72 "t1"
               OpName %78 "param"
               OpName %81 "param"
               OpName %84 "param"
               OpName %88 "out_FragColor"
               OpName %91 "color"
               OpName %108 "kTextures3D"
               OpName %112 "kTexturesCube"
               OpName %115 "kSamplersShadow"
               OpModuleProcessed "client vulkan100"
               OpModuleProcessed "target-env spirv1.6"
               OpModuleProcessed "target-env vulkan1.3"
               OpModuleProcessed "entry-point main"
               OpModuleProcessed "client vulkan100"
               OpModuleProcessed "target-env spirv1.6"
               OpModuleProcessed "target-env vulkan1.3"
               OpModuleProcessed "entry-point main"
               OpDecorate %22 DescriptorSet 0
               OpDecorate %22 Binding 0
               OpDecorate %30 DescriptorSet 0
               OpDecorate %30 Binding 1
               OpMemberDecorate %44 0 Offset 0
               OpDecorate %44 Block
               OpMemberDecorate %46 0 ColMajor
               OpMemberDecorate %46 0 NonWritable
               OpMemberDecorate %46 0 Offset 0
               OpMemberDecorate %46 0 MatrixStride 16
               OpMemberDecorate %46 1 ColMajor
               OpMemberDecorate %46 1 NonWritable
               OpMemberDecorate %46 1 Offset 64
               OpMemberDecorate %46 1 MatrixStride 16
               OpMemberDecorate %46 2 NonWritable
               OpMemberDecorate %46 2 Offset 128
               OpMemberDecorate %46 3 NonWritable
               OpMemberDecorate %46 3 Offset 132
               OpMemberDecorate %46 4 NonWritable
               OpMemberDecorate %46 4 Offset 136
               OpDecorate %46 Block
               OpDecorate %60 Location 1
               OpDecorate %88 Location 0
               OpDecorate %91 Location 0
               OpDecorate %108 DescriptorSet 1
               OpDecorate %108 Binding 0
               OpDecorate %112 DescriptorSet 2
               OpDecorate %112 Binding 0
               OpDecorate %115 DescriptorSet 1
               OpDecorate %115 Binding 1
          %3 = OpTypeVoid
          %4 = OpTypeFunction %3
          %7 = OpTypeInt 32 0
          %8 = OpTypePointer Function %7
          %9 = OpTypeFloat 32
         %10 = OpTypeVector %9 2
         %11 = OpTypePointer Function %10
         %12 = OpTypeVector %9 4
         %13 = OpTypeFunction %12 %8 %8 %11
         %19 = OpTypeImage %9 2D 0 0 0 1 Unknown
         %20 = OpTypeRuntimeArray %19
         %21 = OpTypePointer UniformConstant %20
         %22 = OpVariable %21 UniformConstant
         %24 = OpTypePointer UniformConstant %19
         %27 = OpTypeSampler
         %28 = OpTypeRuntimeArray %27
         %29 = OpTypePointer UniformConstant %28
         %30 = OpVariable %29 UniformConstant
         %32 = OpTypePointer UniformConstant %27
         %35 = OpTypeSampledImage %19
         %41 = OpTypePointer Function %12
               OpTypeForwardPointer %43 PhysicalStorageBuffer
         %44 = OpTypeStruct %43
         %45 = OpTypeMatrix %12 4
         %46 = OpTypeStruct %45 %45 %7 %7 %7
         %43 = OpTypePointer PhysicalStorageBuffer %46
         %47 = OpTypePointer PushConstant %44
         %48 = OpVariable %47 PushConstant
         %49 = OpTypeInt 32 1
         %50 = OpConstant %49 0
         %51 = OpTypePointer PushConstant %43
         %54 = OpConstant %49 2
         %57 = OpConstant %49 4
         %58 = OpConstant %9 2
         %59 = OpTypePointer Input %10
         %60 = OpVariable %59 Input
         %64 = OpTypePointer PhysicalStorageBuffer %7
         %75 = OpConstant %49 3
         %87 = OpTypePointer Output %12
         %88 = OpVariable %87 Output
         %89 = OpTypeVector %9 3
         %90 = OpTypePointer Input %89
         %91 = OpVariable %90 Input
         %99 = OpConstant %9 1
        %104 = OpTypeImage %9 3D 0 0 0 1 Unknown
        %105 = OpConstant %7 1
        %106 = OpTypeArray %104 %105
        %107 = OpTypePointer UniformConstant %106
        %108 = OpVariable %107 UniformConstant
        %109 = OpTypeImage %9 Cube 0 0 0 1 Unknown
        %110 = OpTypeRuntimeArray %109
        %111 = OpTypePointer UniformConstant %110
        %112 = OpVariable %111 UniformConstant
        %113 = OpTypeRuntimeArray %27
        %114 = OpTypePointer UniformConstant %113
        %115 = OpVariable %114 UniformConstant
               OpLine %1 53 11
          %5 = OpFunction %3 None %4
          %6 = OpLabel
         %42 = OpVariable %41 Function
         %63 = OpVariable %8 Function
         %67 = OpVariable %8 Function
         %70 = OpVariable %11 Function
         %72 = OpVariable %41 Function
         %78 = OpVariable %8 Function
         %81 = OpVariable %8 Function
         %84 = OpVariable %11 Function
               OpLine %1 54 0
         %52 = OpAccessChain %51 %48 %50
         %53 = OpLoad %43 %52
         %55 = OpAccessChain %51 %48 %50
         %56 = OpLoad %43 %55
         %61 = OpLoad %10 %60
         %62 = OpVectorTimesScalar %10 %61 %58
         %65 = OpAccessChain %64 %53 %54
         %66 = OpLoad %7 %65 Aligned 16
               OpStore %63 %66
         %68 = OpAccessChain %64 %56 %57
         %69 = OpLoad %7 %68 Aligned 8
               OpStore %67 %69
               OpStore %70 %62
         %71 = OpFunctionCall %12 %17 %63 %67 %70
               OpStore %42 %71
               OpLine %1 55 0
         %73 = OpAccessChain %51 %48 %50
         %74 = OpLoad %43 %73
         %76 = OpAccessChain %51 %48 %50
         %77 = OpLoad %43 %76
         %79 = OpAccessChain %64 %74 %75
         %80 = OpLoad %7 %79 Aligned 4
               OpStore %78 %80
         %82 = OpAccessChain %64 %77 %57
         %83 = OpLoad %7 %82 Aligned 8
               OpStore %81 %83
         %85 = OpLoad %10 %60
               OpStore %84 %85
         %86 = OpFunctionCall %12 %17 %78 %81 %84
               OpStore %72 %86
               OpLine %1 56 0
         %92 = OpLoad %89 %91
         %93 = OpLoad %12 %42
         %94 = OpVectorShuffle %89 %93 %93 0 1 2
         %95 = OpLoad %12 %72
         %96 = OpVectorShuffle %89 %95 %95 0 1 2
         %97 = OpFAdd %89 %94 %96
         %98 = OpFMul %89 %92 %97
        %100 = OpCompositeExtract %9 %98 0
        %101 = OpCompositeExtract %9 %98 1
        %102 = OpCompositeExtract %9 %98 2
        %103 = OpCompositeConstruct %12 %100 %101 %102 %99
               OpStore %88 %103
               OpReturn
               OpFunctionEnd
               OpLine %1 15 69
         %17 = OpFunction %12 None %13
         %14 = OpFunctionParameter %8
         %15 = OpFunctionParameter %8
         %16 = OpFunctionParameter %11
         %18 = OpLabel
               OpLine %1 16 0
         %23 = OpLoad %7 %14
         %25 = OpAccessChain %24 %22 %23
         %26 = OpLoad %19 %25
         %31 = OpLoad %7 %15
         %33 = OpAccessChain %32 %30 %31
         %34 = OpLoad %27 %33
         %36 = OpSampledImage %35 %26 %34
         %37 = OpLoad %10 %16
         %38 = OpImageSampleImplicitLod %12 %36 %37
               OpReturnValue %38
               OpFunctionEnd

MSL generated in 1.3.268.1 :

#pragma clang diagnostic ignored "-Wmissing-prototypes"

#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct PerFrame;

struct constants
{
    device PerFrame* perFrame;
};

struct PerFrame
{
    float4x4 proj;
    float4x4 view;
    uint texture0;
    uint texture1;
    uint sampler0;
};

struct spvDescriptorSetBuffer0
{
    array<texture2d<float>, 16> kTextures2D [[id(0)]];
    array<sampler, 16> kSamplers [[id(16)]];
};

struct spvDescriptorSetBuffer1
{
    array<texture3d<float>, 1> kTextures3D [[id(0)]];
    array<sampler, 16> kSamplersShadow [[id(16)]];
};

struct spvDescriptorSetBuffer2
{
    array<texturecube<float>, 16> kTexturesCube [[id(0)]];
};

struct main0_out
{
    float4 out_FragColor [[color(0)]];
};

struct main0_in
{
    float3 color [[user(locn0)]];
    float2 uv [[user(locn1)]];
};

static inline __attribute__((always_inline))
float4 textureBindless2D(thread const uint& textureid, thread const uint& samplerid, thread const float2& uv, const spvDescriptorArray<texture2d<float>> kTextures2D, const spvDescriptorArray<sampler> kSamplers)
{
    return kTextures2D[textureid].sample(kSamplers[samplerid], uv);
}

fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant spvDescriptorSetBuffer1& spvDescriptorSet1 [[buffer(1)]], constant spvDescriptorSetBuffer2& spvDescriptorSet2 [[buffer(2)]], constant constants& pc [[buffer(8)]])
{
    main0_out out = {};
    uint param = pc.perFrame->texture0;
    uint param_1 = pc.perFrame->sampler0;
    float2 param_2 = in.uv * 2.0;
    float4 t0 = textureBindless2D(param, param_1, param_2, spvDescriptorSet0.kTextures2D, spvDescriptorSet0.kSamplers);
    uint param_3 = pc.perFrame->texture1;
    uint param_4 = pc.perFrame->sampler0;
    float2 param_5 = in.uv;
    float4 t1 = textureBindless2D(param_3, param_4, param_5, spvDescriptorSet0.kTextures2D, spvDescriptorSet0.kSamplers);
    out.out_FragColor = float4(in.color * (t0.xyz + t1.xyz), 1.0);
    return out;
}

MSL generated in 1.3.261.1 :

#pragma clang diagnostic ignored "-Wmissing-prototypes"

#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct PerFrame;

struct constants
{
    device PerFrame* perFrame;
};

struct PerFrame
{
    float4x4 proj;
    float4x4 view;
    uint texture0;
    uint texture1;
    uint sampler0;
};

struct spvDescriptorSetBuffer0
{
    array<texture2d<float>, 16> kTextures2D [[id(0)]];
    array<sampler, 16> kSamplers [[id(16)]];
};

struct spvDescriptorSetBuffer1
{
    array<texture3d<float>, 1> kTextures3D [[id(0)]];
    array<sampler, 16> kSamplersShadow [[id(16)]];
};

struct spvDescriptorSetBuffer2
{
    array<texturecube<float>, 16> kTexturesCube [[id(0)]];
};

struct main0_out
{
    float4 out_FragColor [[color(0)]];
};

struct main0_in
{
    float3 color [[user(locn0)]];
    float2 uv [[user(locn1)]];
};

static inline __attribute__((always_inline))
float4 textureBindless2D(thread const uint& textureid, thread const uint& samplerid, thread const float2& uv, constant array<texture2d<float>, 16>& kTextures2D, constant array<sampler, 16>& kSamplers)
{
    return kTextures2D[textureid].sample(kSamplers[samplerid], uv);
}

fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant spvDescriptorSetBuffer1& spvDescriptorSet1 [[buffer(1)]], constant spvDescriptorSetBuffer2& spvDescriptorSet2 [[buffer(2)]], constant constants& pc [[buffer(8)]])
{
    main0_out out = {};
    uint param = pc.perFrame->texture0;
    uint param_1 = pc.perFrame->sampler0;
    float2 param_2 = in.uv * 2.0;
    float4 t0 = textureBindless2D(param, param_1, param_2, spvDescriptorSet0.kTextures2D, spvDescriptorSet0.kSamplers);
    uint param_3 = pc.perFrame->texture1;
    uint param_4 = pc.perFrame->sampler0;
    float2 param_5 = in.uv;
    float4 t1 = textureBindless2D(param_3, param_4, param_5, spvDescriptorSet0.kTextures2D, spvDescriptorSet0.kSamplers);
    out.out_FragColor = float4(in.color * (t0.xyz + t1.xyz), 1.0);
    return out;
}

Metadata

Metadata

Assignees

Labels

BugCompletedIssue has been fixed, or enhancement implemented.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions