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;
}
I started getting the following error after updated from 1.3.261.1 to 1.3.268.1:
Problem:
New MoltenVK (SPIR-V Cross in it?) generates
spvDescriptorArrayaround arrays of textures and samplers but do not definespvDescriptorArrayitself.Full outputs:
Original GLSL:
SPIR-V:
MSL generated in 1.3.268.1 :
MSL generated in 1.3.261.1 :