diff --git a/reference/shaders/asm/frag/op-constant-null.asm.frag b/reference/shaders/asm/frag/op-constant-null.asm.frag new file mode 100644 index 00000000..c4ae981f --- /dev/null +++ b/reference/shaders/asm/frag/op-constant-null.asm.frag @@ -0,0 +1,22 @@ +#version 310 es +precision mediump float; +precision highp int; + +struct D +{ + vec4 a; + float b; +}; + +layout(location = 0) out float FragColor; + +void main() +{ + float a = 0.0; + vec4 b = vec4(0.0); + mat2x3 c = mat2x3(vec3(0.0), vec3(0.0)); + D d = D(vec4(0.0), 0.0); + vec4 e[4] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); + FragColor = a; +} + diff --git a/shaders/asm/frag/op-constant-null.asm.frag b/shaders/asm/frag/op-constant-null.asm.frag new file mode 100644 index 00000000..61d2e579 --- /dev/null +++ b/shaders/asm/frag/op-constant-null.asm.frag @@ -0,0 +1,85 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 1 +; Bound: 45 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColor + OpExecutionMode %main OriginUpperLeft + OpSource ESSL 310 + OpName %main "main" + OpName %a "a" + OpName %b "b" + OpName %c "c" + OpName %D "D" + OpMemberName %D 0 "a" + OpMemberName %D 1 "b" + OpName %d "d" + OpName %e "e" + OpName %FragColor "FragColor" + OpDecorate %a RelaxedPrecision + OpDecorate %b RelaxedPrecision + OpDecorate %c RelaxedPrecision + OpMemberDecorate %D 0 RelaxedPrecision + OpMemberDecorate %D 1 RelaxedPrecision + OpDecorate %e RelaxedPrecision + OpDecorate %FragColor RelaxedPrecision + OpDecorate %FragColor Location 0 + OpDecorate %44 RelaxedPrecision + OpDecorate %float_1 RelaxedPrecision + OpDecorate %14 RelaxedPrecision + OpDecorate %23 RelaxedPrecision + OpDecorate %41 RelaxedPrecision + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 +%_ptr_Function_float = OpTypePointer Function %float + %float_1 = OpConstantNull %float + %v4float = OpTypeVector %float 4 +%_ptr_Function_v4float = OpTypePointer Function %v4float + %float_2 = OpConstantNull %float + %14 = OpConstantNull %v4float + %v3float = OpTypeVector %float 3 +%mat2v3float = OpTypeMatrix %v3float 2 +%_ptr_Function_mat2v3float = OpTypePointer Function %mat2v3float + %float_4 = OpConstantNull %float + %20 = OpConstantNull %v3float + %float_5 = OpConstantNull %float + %22 = OpConstantNull %v3float + %23 = OpConstantNull %mat2v3float + %D = OpTypeStruct %v4float %float +%_ptr_Function_D = OpTypePointer Function %D + %27 = OpConstantNull %D + %uint = OpTypeInt 32 0 + %uint_4 = OpConstant %uint 4 +%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4 +%_ptr_Function__arr_v4float_uint_4 = OpTypePointer Function %_arr_v4float_uint_4 + %float_10 = OpConstantNull %float + %34 = OpConstantNull %v4float + %float_11 = OpConstantNull %float + %36 = OpConstantNull %v4float + %float_12 = OpConstantNull %float + %38 = OpConstantNull %v4float + %float_13 = OpConstantNull %float + %40 = OpConstantNull %v4float + %41 = OpConstantNull %_arr_v4float_uint_4 +%_ptr_Output_float = OpTypePointer Output %float + %FragColor = OpVariable %_ptr_Output_float Output + %main = OpFunction %void None %3 + %5 = OpLabel + %a = OpVariable %_ptr_Function_float Function + %b = OpVariable %_ptr_Function_v4float Function + %c = OpVariable %_ptr_Function_mat2v3float Function + %d = OpVariable %_ptr_Function_D Function + %e = OpVariable %_ptr_Function__arr_v4float_uint_4 Function + OpStore %a %float_1 + OpStore %b %14 + OpStore %c %23 + OpStore %d %27 + OpStore %e %41 + %44 = OpLoad %float %a + OpStore %FragColor %44 + OpReturn + OpFunctionEnd diff --git a/spirv_common.hpp b/spirv_common.hpp index 95111507..f32ad322 100644 --- a/spirv_common.hpp +++ b/spirv_common.hpp @@ -729,10 +729,17 @@ struct SPIRConstant : IVariant return m.columns; } + inline void make_null(const SPIRType &constant_type_) + { + std::memset(&m, 0, sizeof(m)); + m.columns = constant_type_.columns; + for (auto &c : m.c) + c.vecsize = constant_type_.vecsize; + } + SPIRConstant(uint32_t constant_type_) : constant_type(constant_type_) { - std::memset(&m, 0, sizeof(m)); } SPIRConstant(uint32_t constant_type_, const uint32_t *elements, uint32_t num_elements) diff --git a/spirv_cross.cpp b/spirv_cross.cpp index bc255ef1..4fcdebcf 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -1654,7 +1654,7 @@ void Compiler::parse(const Instruction &instruction) { uint32_t id = ops[1]; uint32_t type = ops[0]; - set(id, type); + make_constant_null(id, type); break; } @@ -3556,3 +3556,39 @@ bool Compiler::buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) } return false; } + +void Compiler::make_constant_null(uint32_t id, uint32_t type) +{ + auto &constant_type = get(type); + + if (!constant_type.array.empty()) + { + assert(constant_type.parent_type); + uint32_t parent_id = increase_bound_by(1); + make_constant_null(parent_id, constant_type.parent_type); + + if (!constant_type.array_size_literal.back()) + SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal."); + + vector elements(constant_type.array.back()); + for (uint32_t i = 0; i < constant_type.array.back(); i++) + elements[i] = parent_id; + set(id, type, elements.data(), elements.size()); + } + else if (!constant_type.member_types.empty()) + { + uint32_t member_ids = increase_bound_by(constant_type.member_types.size()); + vector elements(constant_type.member_types.size()); + for (uint32_t i = 0; i < constant_type.member_types.size(); i++) + { + make_constant_null(member_ids + i, constant_type.member_types[i]); + elements[i] = member_ids + i; + } + set(id, type, elements.data(), elements.size()); + } + else + { + auto &constant = set(id, type); + constant.make_null(constant_type); + } +} diff --git a/spirv_cross.hpp b/spirv_cross.hpp index c2123077..071075e6 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -668,6 +668,8 @@ protected: void add_hierarchy_to_comparison_samplers(uint32_t sampler); }; + + void make_constant_null(uint32_t id, uint32_t type); }; } diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 3c1b8283..1a7d2a31 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -2140,7 +2140,7 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c) if (subc.specialization && options.vulkan_semantics) res += to_name(elem); else - res += constant_expression(get(elem)); + res += constant_expression(subc); if (&elem != &c.subconstants.back()) res += ", ";