Merge pull request #228 from KhronosGroup/various-fixes

Various bug fixes
This commit is contained in:
Hans-Kristian Arntzen 2017-07-24 10:29:09 +02:00 коммит произвёл GitHub
Родитель 2cbeaac76f 6ff9007311
Коммит 2e4422d362
21 изменённых файлов: 329 добавлений и 65 удалений

Просмотреть файл

@ -417,11 +417,11 @@ struct VariableTypeRemap
string new_variable_type;
};
struct InterfaceVariableRename
{
StorageClass storageClass;
uint32_t location;
string variable_name;
struct InterfaceVariableRename
{
StorageClass storageClass;
uint32_t location;
string variable_name;
};
struct CLIArguments
@ -473,7 +473,7 @@ static void print_help()
"[--flatten-multidimensional-arrays] "
"[--remap-variable-type <variable_name> <new_variable_type>] "
"[--rename-interface-variable <in|out> <location> <new_variable_name>] "
"\n");
"\n");
}
static bool remap_generic(Compiler &compiler, const vector<Resource> &resources, const Remap &remap)
@ -560,19 +560,20 @@ static PlsFormat pls_format(const char *str)
return PlsNone;
}
void rename_interface_variable(Compiler &compiler, const vector<Resource> &resources, const InterfaceVariableRename &rename)
{
for (auto &v : resources)
{
if (!compiler.has_decoration(v.id, spv::DecorationLocation))
continue;
auto loc = compiler.get_decoration(v.id, spv::DecorationLocation);
if (loc != rename.location)
continue;
compiler.set_name(v.id, rename.variable_name);
}
void rename_interface_variable(Compiler &compiler, const vector<Resource> &resources,
const InterfaceVariableRename &rename)
{
for (auto &v : resources)
{
if (!compiler.has_decoration(v.id, spv::DecorationLocation))
continue;
auto loc = compiler.get_decoration(v.id, spv::DecorationLocation);
if (loc != rename.location)
continue;
compiler.set_name(v.id, rename.variable_name);
}
}
int main(int argc, char *argv[])
@ -796,7 +797,7 @@ int main(int argc, char *argv[])
continue;
}
for (auto &rename : args.interface_variable_renames)
for (auto &rename : args.interface_variable_renames)
{
if (rename.storageClass == StorageClassInput)
rename_interface_variable(*compiler, res.stage_inputs, rename);

Просмотреть файл

@ -0,0 +1,32 @@
static float4 FragColor;
static float4 vIn;
static int4 vIn1;
struct SPIRV_Cross_Input
{
float4 vIn : TEXCOORD0;
nointerpolation int4 vIn1 : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
FragColor = -(-vIn);
int4 a = ~(~vIn1);
bool b = false;
b = !(!b);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vIn = stage_input.vIn;
vIn1 = stage_input.vIn1;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

Просмотреть файл

@ -0,0 +1,26 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_in
{
int4 vIn1 [[user(locn1)]];
float4 vIn [[user(locn0)]];
};
struct main0_out
{
float4 FragColor [[color(0)]];
};
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.FragColor = -(-in.vIn);
int4 a = ~(~in.vIn1);
bool b = false;
b = !(!b);
return out;
}

Просмотреть файл

@ -0,0 +1,17 @@
#version 450
uniform samplerCubeShadow SPIRV_Cross_CombinedpointLightShadowMapshadowSamplerPCF;
layout(location = 0) out float _entryPointOutput;
float _main()
{
vec4 _33 = vec4(vec3(0.100000001490116119384765625), 0.5);
return textureGrad(SPIRV_Cross_CombinedpointLightShadowMapshadowSamplerPCF, vec4(_33.xyz, _33.w), vec3(0.0), vec3(0.0));
}
void main()
{
_entryPointOutput = _main();
}

Просмотреть файл

@ -0,0 +1,13 @@
#version 310 es
#extension GL_OES_sample_variables : require
precision mediump float;
precision highp int;
layout(location = 0) out vec2 FragColor;
void main()
{
FragColor = (gl_SamplePosition + vec2(float(gl_SampleMaskIn[0]))) + vec2(float(gl_SampleID));
gl_SampleMask[0] = 1;
}

Просмотреть файл

@ -0,0 +1,16 @@
#version 310 es
precision mediump float;
precision highp int;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec4 vIn;
layout(location = 1) flat in mediump ivec4 vIn1;
void main()
{
FragColor = -(-vIn);
mediump ivec4 a = ~(~vIn1);
bool b = false;
b = !(!b);
}

Просмотреть файл

@ -78,7 +78,7 @@ vec2 warp_position()
_117 = 0u;
}
uvec2 rounding = uvec2(_116, _117);
vec4 lower_upper_snapped = vec4((uPosition + rounding).xyxy & ~mask.xxyy);
vec4 lower_upper_snapped = vec4((uPosition + rounding).xyxy & (~mask).xxyy);
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, vec2(fract_lod));
}

Просмотреть файл

@ -100,7 +100,7 @@ vec2 warp_position()
_142 = 0u;
}
rounding.w = _142;
vec4 lower_upper_snapped = vec4((uPosition.xyxy + rounding) & ~mask.xxyy);
vec4 lower_upper_snapped = vec4((uPosition.xyxy + rounding) & (~mask).xxyy);
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, vec2(fract_lod));
}

Просмотреть файл

@ -1,14 +1,12 @@
#version 310 es
precision mediump float;
precision highp int;
#version 450
layout(binding = 0) uniform mediump sampler2DMS uSubpass0;
layout(binding = 1) uniform mediump sampler2DMS uSubpass1;
layout(binding = 0) uniform sampler2DMS uSubpass0;
layout(binding = 1) uniform sampler2DMS uSubpass1;
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = texelFetch(uSubpass0, ivec2(gl_FragCoord.xy), 1) + texelFetch(uSubpass1, ivec2(gl_FragCoord.xy), 2);
FragColor = (texelFetch(uSubpass0, ivec2(gl_FragCoord.xy), 1) + texelFetch(uSubpass1, ivec2(gl_FragCoord.xy), 2)) + texelFetch(uSubpass0, ivec2(gl_FragCoord.xy), gl_SampleID);
}

Просмотреть файл

@ -1,14 +1,12 @@
#version 310 es
precision mediump float;
precision highp int;
#version 450
layout(input_attachment_index = 0, set = 0, binding = 0) uniform mediump subpassInputMS uSubpass0;
layout(input_attachment_index = 1, set = 0, binding = 1) uniform mediump subpassInputMS uSubpass1;
layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInputMS uSubpass0;
layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInputMS uSubpass1;
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = subpassLoad(uSubpass0, 1) + subpassLoad(uSubpass1, 2);
FragColor = (subpassLoad(uSubpass0, 1) + subpassLoad(uSubpass1, 2)) + subpassLoad(uSubpass0, gl_SampleID);
}

Просмотреть файл

@ -0,0 +1,15 @@
#version 310 es
precision mediump float;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec4 vIn;
layout(location = 1) flat in ivec4 vIn1;
void main()
{
FragColor = +(-(-vIn));
ivec4 a = ~(~vIn1);
bool b = false;
b = !!b;
}

Просмотреть файл

@ -0,0 +1,15 @@
#version 310 es
precision mediump float;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec4 vIn;
layout(location = 1) flat in ivec4 vIn1;
void main()
{
FragColor = +(-(-vIn));
ivec4 a = ~(~vIn1);
bool b = false;
b = !!b;
}

Просмотреть файл

@ -0,0 +1,58 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 38
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %_entryPointOutput
OpExecutionMode %main OriginUpperLeft
OpSource HLSL 500
OpName %main "main"
OpName %_main_ "@main("
OpName %pointLightShadowMap "pointLightShadowMap"
OpName %shadowSamplerPCF "shadowSamplerPCF"
OpName %_entryPointOutput "@entryPointOutput"
OpDecorate %pointLightShadowMap DescriptorSet 0
OpDecorate %shadowSamplerPCF DescriptorSet 0
OpDecorate %_entryPointOutput Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%10 = OpTypeImage %float Cube 0 0 0 1 Unknown
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
%pointLightShadowMap = OpVariable %_ptr_UniformConstant_10 UniformConstant
%14 = OpTypeSampler
%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
%shadowSamplerPCF = OpVariable %_ptr_UniformConstant_14 UniformConstant
%18 = OpTypeImage %float Cube 1 0 0 1 Unknown
%19 = OpTypeSampledImage %18
%v3float = OpTypeVector %float 3
%float_0_1 = OpConstant %float 0.1
%23 = OpConstantComposite %v3float %float_0_1 %float_0_1 %float_0_1
%float_0_5 = OpConstant %float 0.5
%v4float = OpTypeVector %float 4
%float_0 = OpConstant %float 0
%_ptr_Output_float = OpTypePointer Output %float
%_entryPointOutput = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%37 = OpFunctionCall %float %_main_
OpStore %_entryPointOutput %37
OpReturn
OpFunctionEnd
%_main_ = OpFunction %float None %7
%9 = OpLabel
%13 = OpLoad %10 %pointLightShadowMap
%17 = OpLoad %14 %shadowSamplerPCF
%20 = OpSampledImage %19 %13 %17
%26 = OpCompositeExtract %float %23 0
%27 = OpCompositeExtract %float %23 1
%28 = OpCompositeExtract %float %23 2
%29 = OpCompositeConstruct %v4float %26 %27 %28 %float_0_5
%31 = OpCompositeExtract %float %29 3
%32 = OpImageSampleDrefExplicitLod %float %20 %29 %31 Lod %float_0
OpReturnValue %32
OpFunctionEnd

Просмотреть файл

@ -0,0 +1,11 @@
#version 310 es
#extension GL_OES_sample_variables : require
precision mediump float;
layout(location = 0) out vec2 FragColor;
void main()
{
FragColor = gl_SamplePosition + vec2(gl_SampleMaskIn[0]) + float(gl_SampleID);
gl_SampleMask[0] = 1;
}

Просмотреть файл

@ -0,0 +1,15 @@
#version 310 es
precision mediump float;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec4 vIn;
layout(location = 1) flat in ivec4 vIn1;
void main()
{
FragColor = +(-(-vIn));
ivec4 a = ~(~vIn1);
bool b = false;
b = !!b;
}

Просмотреть файл

@ -1,11 +1,10 @@
#version 310 es
precision mediump float;
#version 450
layout(input_attachment_index = 0, set = 0, binding = 0) uniform mediump subpassInputMS uSubpass0;
layout(input_attachment_index = 1, set = 0, binding = 1) uniform mediump subpassInputMS uSubpass1;
layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInputMS uSubpass0;
layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInputMS uSubpass1;
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = subpassLoad(uSubpass0, 1) + subpassLoad(uSubpass1, 2);
FragColor = subpassLoad(uSubpass0, 1) + subpassLoad(uSubpass1, 2) + subpassLoad(uSubpass0, gl_SampleID);
}

Просмотреть файл

@ -1812,6 +1812,16 @@ void CompilerGLSL::strip_enclosed_expression(string &expr)
string CompilerGLSL::enclose_expression(const string &expr)
{
bool need_parens = false;
// If the expression starts with a unary we need to enclose to deal with cases where we have back-to-back
// unary expressions.
if (!expr.empty())
{
auto c = expr.front();
if (c == '-' || c == '+' || c == '!' || c == '~')
need_parens = true;
}
uint32_t paren_count = 0;
for (auto c : expr)
{
@ -1917,7 +1927,7 @@ string CompilerGLSL::to_expression(uint32_t id)
{
auto &dec = meta[var.self].decoration;
if (dec.builtin)
return builtin_to_glsl(dec.builtin_type);
return builtin_to_glsl(dec.builtin_type, var.storage);
else
return to_name(id);
}
@ -2966,12 +2976,13 @@ string CompilerGLSL::to_function_name(uint32_t, const SPIRType &imgtype, bool is
{
string fname;
// textureLod on sampler2DArrayShadow does not exist in GLSL for some reason.
// textureLod on sampler2DArrayShadow and samplerCubeShadow does not exist in GLSL for some reason.
// To emulate this, we will have to use textureGrad with a constant gradient of 0.
// The workaround will assert that the LOD is in fact constant 0, or we cannot emit correct code.
// This happens for HLSL SampleCmpLevelZero on Texture2DArray.
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad = false;
if (imgtype.image.arrayed && imgtype.image.dim == Dim2D && imgtype.image.depth && lod)
if (((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
imgtype.image.depth && lod)
{
auto *constant_lod = maybe_get<SPIRConstant>(lod);
if (!constant_lod || constant_lod->scalar_f32() != 0.0f)
@ -3037,12 +3048,13 @@ string CompilerGLSL::to_function_args(uint32_t img, const SPIRType &imgtype, boo
// Only enclose the UV expression if needed.
auto coord_expr = (*swizzle_expr == '\0') ? to_expression(coord) : (to_enclosed_expression(coord) + swizzle_expr);
// textureLod on sampler2DArrayShadow does not exist in GLSL for some reason.
// textureLod on sampler2DArrayShadow and samplerCubeShadow does not exist in GLSL for some reason.
// To emulate this, we will have to use textureGrad with a constant gradient of 0.
// The workaround will assert that the LOD is in fact constant 0, or we cannot emit correct code.
// This happens for HLSL SampleCmpLevelZero on Texture2DArray.
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad =
imgtype.image.arrayed && imgtype.image.dim == Dim2D && imgtype.image.depth && lod;
((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
imgtype.image.depth && lod;
if (dref)
{
@ -3092,7 +3104,10 @@ string CompilerGLSL::to_function_args(uint32_t img, const SPIRType &imgtype, boo
{
// Implement textureGrad() instead. LOD == 0.0 is implemented as gradient of 0.0.
// Implementing this as plain texture() is not safe on some implementations.
farg_str += ", vec2(0.0), vec2(0.0)";
if (imgtype.image.dim == Dim2D)
farg_str += ", vec2(0.0), vec2(0.0)";
else if (imgtype.image.dim == DimCube)
farg_str += ", vec3(0.0), vec3(0.0)";
}
else
{
@ -3443,7 +3458,7 @@ string CompilerGLSL::bitcast_glsl(const SPIRType &result_type, uint32_t argument
return join(op, "(", to_expression(argument), ")");
}
string CompilerGLSL::builtin_to_glsl(BuiltIn builtin)
string CompilerGLSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
{
switch (builtin)
{
@ -3507,6 +3522,32 @@ string CompilerGLSL::builtin_to_glsl(BuiltIn builtin)
return "gl_GlobalInvocationID";
case BuiltInLocalInvocationIndex:
return "gl_LocalInvocationIndex";
case BuiltInSampleId:
if (options.es && options.version < 320)
require_extension("GL_OES_sample_variables");
if (!options.es && options.version < 400)
SPIRV_CROSS_THROW("gl_SampleID not supported before GLSL 400.");
return "gl_SampleID";
case BuiltInSampleMask:
if (options.es && options.version < 320)
require_extension("GL_OES_sample_variables");
if (!options.es && options.version < 400)
SPIRV_CROSS_THROW("gl_SampleMask/gl_SampleMaskIn not supported before GLSL 400.");
if (storage == StorageClassInput)
return "gl_SampleMaskIn";
else
return "gl_SampleMask";
case BuiltInSamplePosition:
if (options.es && options.version < 320)
require_extension("GL_OES_sample_variables");
if (!options.es && options.version < 400)
SPIRV_CROSS_THROW("gl_SamplePosition not supported before GLSL 400.");
return "gl_SamplePosition";
default:
return join("gl_BuiltIn_", convert_to_string(builtin));
}
@ -3624,10 +3665,10 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
if (access_chain_is_arrayed)
{
expr += ".";
expr += builtin_to_glsl(builtin);
expr += builtin_to_glsl(builtin, type->storage);
}
else
expr = builtin_to_glsl(builtin);
expr = builtin_to_glsl(builtin, type->storage);
}
else
{

Просмотреть файл

@ -172,7 +172,7 @@ protected:
virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id);
virtual void emit_texture_op(const Instruction &i);
virtual std::string type_to_glsl(const SPIRType &type, uint32_t id = 0);
virtual std::string builtin_to_glsl(spv::BuiltIn builtin);
virtual std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage);
virtual void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
const std::string &qualifier = "");
virtual std::string image_type_glsl(const SPIRType &type, uint32_t id = 0);

Просмотреть файл

@ -326,7 +326,7 @@ void CompilerHLSL::emit_builtin_outputs_in_struct()
}
if (type && semantic)
statement(type, " ", builtin_to_glsl(builtin), " : ", semantic, ";");
statement(type, " ", builtin_to_glsl(builtin, StorageClassOutput), " : ", semantic, ";");
}
}
@ -375,7 +375,7 @@ void CompilerHLSL::emit_builtin_inputs_in_struct()
}
if (type && semantic)
statement(type, " ", builtin_to_glsl(builtin), " : ", semantic, ";");
statement(type, " ", builtin_to_glsl(builtin, StorageClassInput), " : ", semantic, ";");
}
}
@ -574,8 +574,12 @@ void CompilerHLSL::emit_builtin_variables()
break;
}
StorageClass storage = (active_input_builtins & (1ull << i)) != 0 ? StorageClassInput : StorageClassOutput;
// FIXME: SampleMask can be both in and out with sample builtin,
// need to distinguish that when we add support for that.
if (type)
statement("static ", type, " ", builtin_to_glsl(builtin), ";");
statement("static ", type, " ", builtin_to_glsl(builtin, storage), ";");
}
}
@ -909,7 +913,8 @@ void CompilerHLSL::emit_buffer_block(const SPIRVariable &var)
if (options.shader_model >= 51) // SM 5.1 uses ConstantBuffer<T> instead of cbuffer.
{
statement("ConstantBuffer<", struct_name, "> ", to_name(var.self), type_to_array_glsl(type), to_resource_binding(var), ";");
statement("ConstantBuffer<", struct_name, "> ", to_name(var.self), type_to_array_glsl(type),
to_resource_binding(var), ";");
}
else
{
@ -1065,7 +1070,7 @@ void CompilerHLSL::emit_hlsl_entry_point()
if (!(active_input_builtins & (1ull << i)))
continue;
auto builtin = builtin_to_glsl(static_cast<BuiltIn>(i));
auto builtin = builtin_to_glsl(static_cast<BuiltIn>(i), StorageClassInput);
switch (static_cast<BuiltIn>(i))
{
case BuiltInFragCoord:
@ -1172,7 +1177,7 @@ void CompilerHLSL::emit_hlsl_entry_point()
if (i == BuiltInPointSize)
continue;
auto builtin = builtin_to_glsl(static_cast<BuiltIn>(i));
auto builtin = builtin_to_glsl(static_cast<BuiltIn>(i), StorageClassOutput);
statement("stage_output.", builtin, " = ", builtin, ";");
}

Просмотреть файл

@ -591,7 +591,8 @@ string CompilerMSL::add_input_buffer_block_member(uint32_t mbr_type_id, string m
set_member_decoration(ib_type_id, ib_mbr_idx, DecorationLocation, k_unknown_location);
// Update the original variable reference to include the structure and index reference
string idx_var_name = builtin_to_glsl(p_va->per_instance ? BuiltInInstanceIndex : BuiltInVertexIndex);
string idx_var_name =
builtin_to_glsl(p_va->per_instance ? BuiltInInstanceIndex : BuiltInVertexIndex, StorageClassInput);
return get_name(ib_var_id) + "[" + idx_var_name + "]." + mbr_name;
}
@ -2385,7 +2386,7 @@ string CompilerMSL::to_qualified_member_name(const SPIRType &type, uint32_t inde
// Don't qualify Builtin names because they are unique and are treated as such when building expressions
BuiltIn builtin;
if (is_member_builtin(type, index, &builtin))
return builtin_to_glsl(builtin);
return builtin_to_glsl(builtin, type.storage);
// Strip any underscore prefix from member name
string mbr_name = to_member_name(type, index);
@ -2592,7 +2593,7 @@ string CompilerMSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &in
// Returns an MSL string identifying the name of a SPIR-V builtin.
// Output builtins are qualified with the name of the stage out structure.
string CompilerMSL::builtin_to_glsl(BuiltIn builtin)
string CompilerMSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
{
switch (builtin)
{
@ -2613,12 +2614,12 @@ string CompilerMSL::builtin_to_glsl(BuiltIn builtin)
case BuiltInClipDistance:
case BuiltInLayer:
if (current_function && (current_function->self == entry_point))
return stage_out_var_name + "." + CompilerGLSL::builtin_to_glsl(builtin);
return stage_out_var_name + "." + CompilerGLSL::builtin_to_glsl(builtin, storage);
else
return CompilerGLSL::builtin_to_glsl(builtin);
return CompilerGLSL::builtin_to_glsl(builtin, storage);
default:
return CompilerGLSL::builtin_to_glsl(builtin);
return CompilerGLSL::builtin_to_glsl(builtin, storage);
}
}
@ -2744,7 +2745,10 @@ string CompilerMSL::built_in_func_arg(BuiltIn builtin, bool prefix_comma)
if (prefix_comma)
bi_arg += ", ";
bi_arg += builtin_type_decl(builtin);
bi_arg += " " + builtin_to_glsl(builtin);
assert(builtin == BuiltInVertexIndex || builtin == BuiltInInstanceIndex);
bi_arg += " " + builtin_to_glsl(builtin, StorageClassInput);
bi_arg += " [[" + builtin_qualifier(builtin) + "]]";
return bi_arg;
}

Просмотреть файл

@ -151,7 +151,7 @@ protected:
const std::string &qualifier = "") override;
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string builtin_to_glsl(spv::BuiltIn builtin) override;
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
std::string constant_expression(const SPIRConstant &c) override;
size_t get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const override;
std::string to_func_call_arg(uint32_t id) override;