Do not declare constant composites inline in HLSL.

Move arrays and structs out to their own global static constants.

Also, replace illegal names in HLSL as well.
This commit is contained in:
Hans-Kristian Arntzen 2018-02-02 10:10:17 +01:00
Родитель a1857a4d58
Коммит 5d9df6a31c
14 изменённых файлов: 302 добавлений и 4 удалений

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

@ -0,0 +1,43 @@
struct Foo
{
float a;
float b;
};
static const float _16[4] = { 1.0f, 4.0f, 3.0f, 2.0f };
static const Foo _24 = { 10.0f, 20.0f };
static const Foo _27 = { 30.0f, 40.0f };
static const Foo _28[2] = { { 10.0f, 20.0f }, { 30.0f, 40.0f } };
static float4 FragColor;
static int _line;
struct SPIRV_Cross_Input
{
nointerpolation int _line : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
static float lut[4];
static Foo foos[2];
void frag_main()
{
lut = _16;
foos = _28;
FragColor = lut[_line].xxxx;
FragColor += (foos[_line].a * (foos[1 - _line].a)).xxxx;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
_line = stage_input._line;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

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

@ -0,0 +1,31 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct Foo
{
float a;
float b;
};
struct main0_in
{
int line [[user(locn0)]];
};
struct main0_out
{
float4 FragColor [[color(0)]];
};
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
float lut[4] = {1.0, 4.0, 3.0, 2.0};
Foo foos[2] = {{10.0, 20.0}, {30.0, 40.0}};
out.FragColor = float4(lut[in.line]);
out.FragColor += float4(foos[in.line].a * (foos[1 - in.line].a));
return out;
}

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

@ -0,0 +1,23 @@
#version 310 es
precision mediump float;
precision highp int;
struct Foo
{
float a;
float b;
};
layout(location = 0) out vec4 FragColor;
layout(location = 0) flat in mediump int _line;
float lut[4];
Foo foos[2];
void main()
{
lut = float[](1.0, 4.0, 3.0, 2.0);
foos = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
FragColor = vec4(lut[_line]);
FragColor += vec4(foos[_line].a * (foos[1 - _line].a));
}

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

@ -0,0 +1,43 @@
struct Foo
{
float a;
float b;
};
static const float _16[4] = { 1.0f, 4.0f, 3.0f, 2.0f };
static const Foo _24 = { 10.0f, 20.0f };
static const Foo _27 = { 30.0f, 40.0f };
static const Foo _28[2] = { { 10.0f, 20.0f }, { 30.0f, 40.0f } };
static float4 FragColor;
static int _line;
struct SPIRV_Cross_Input
{
nointerpolation int _line : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
static float lut[4];
static Foo foos[2];
void frag_main()
{
lut = _16;
foos = _28;
FragColor = lut[_line].xxxx;
FragColor += (foos[_line].a * (foos[1 - _line].a)).xxxx;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
_line = stage_input._line;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

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

@ -4,6 +4,8 @@ struct B
float b;
};
static const B _80 = { 10.0f, 20.0f };
cbuffer _42 : register(b0)
{
int _42_some_value : packoffset(c0);
@ -61,7 +63,7 @@ void frag_main()
float4 param_3;
branchy_inout_2(param_3);
a = param_3;
B b = { 10.0f, 20.0f };
B b = _80;
B param_4 = b;
partial_inout(param_4);
b = param_4;

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

@ -0,0 +1,31 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct Foo
{
float a;
float b;
};
struct main0_in
{
int line [[user(locn0)]];
};
struct main0_out
{
float4 FragColor [[color(0)]];
};
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
float lut[4] = {1.0, 4.0, 3.0, 2.0};
Foo foos[2] = {{10.0, 20.0}, {30.0, 40.0}};
out.FragColor = float4(lut[in.line]);
out.FragColor += float4(foos[in.line].a * (foos[1 - in.line].a));
return out;
}

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

@ -0,0 +1,23 @@
#version 310 es
precision mediump float;
precision highp int;
struct Foo
{
float a;
float b;
};
layout(location = 0) out vec4 FragColor;
layout(location = 0) flat in mediump int _line;
float lut[4];
Foo foos[2];
void main()
{
lut = float[](1.0, 4.0, 3.0, 2.0);
foos = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
FragColor = vec4(lut[_line]);
FragColor += vec4(foos[_line].a * (foos[1 - _line].a));
}

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

@ -0,0 +1,20 @@
#version 310 es
precision mediump float;
float lut[4] = float[](1.0, 4.0, 3.0, 2.0);
struct Foo
{
float a;
float b;
};
Foo foos[2] = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
layout(location = 0) out vec4 FragColor;
layout(location = 0) flat in int line;
void main()
{
FragColor = vec4(lut[line]);
FragColor += foos[line].a * foos[1 - line].a;
}

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

@ -0,0 +1,20 @@
#version 310 es
precision mediump float;
float lut[4] = float[](1.0, 4.0, 3.0, 2.0);
struct Foo
{
float a;
float b;
};
Foo foos[2] = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
layout(location = 0) out vec4 FragColor;
layout(location = 0) flat in int line;
void main()
{
FragColor = vec4(lut[line]);
FragColor += foos[line].a * foos[1 - line].a;
}

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

@ -0,0 +1,20 @@
#version 310 es
precision mediump float;
float lut[4] = float[](1.0, 4.0, 3.0, 2.0);
struct Foo
{
float a;
float b;
};
Foo foos[2] = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
layout(location = 0) out vec4 FragColor;
layout(location = 0) flat in int line;
void main()
{
FragColor = vec4(lut[line]);
FragColor += foos[line].a * foos[1 - line].a;
}

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

@ -1634,10 +1634,10 @@ void CompilerGLSL::replace_illegal_names()
"iimageCubeArray", "image1D", "image1DArray", "image2D", "image2DArray", "image2DMS", "image2DMSArray", "image2DRect",
"image3D", "imageBuffer", "imageCube", "imageCubeArray", "in", "inline", "inout", "input", "int", "interface", "invariant",
"isampler1D", "isampler1DArray", "isampler2D", "isampler2DArray", "isampler2DMS", "isampler2DMSArray", "isampler2DRect",
"isampler3D", "isamplerBuffer", "isamplerCube", "isamplerCubeArray", "ivec2", "ivec3", "ivec4", "layout", "long", "lowp",
"isampler3D", "isamplerBuffer", "isamplerCube", "isamplerCubeArray", "ivec2", "ivec3", "ivec4", "layout", "line", "linear", "long", "lowp",
"mat2", "mat2x2", "mat2x3", "mat2x4", "mat3", "mat3x2", "mat3x3", "mat3x4", "mat4", "mat4x2", "mat4x3", "mat4x4", "mediump",
"namespace", "noinline", "noperspective", "out", "output", "packed", "partition", "patch", "precision", "public", "readonly",
"resource", "restrict", "return", "row_major", "sample", "sampler1D", "sampler1DArray", "sampler1DArrayShadow",
"namespace", "noinline", "noperspective", "out", "output", "packed", "partition", "patch", "point", "precision", "public", "readonly",
"resource", "restrict", "return", "row_major", "sample", "sampler", "sampler1D", "sampler1DArray", "sampler1DArrayShadow",
"sampler1DShadow", "sampler2D", "sampler2DArray", "sampler2DArrayShadow", "sampler2DMS", "sampler2DMSArray",
"sampler2DRect", "sampler2DRectShadow", "sampler2DShadow", "sampler3D", "sampler3DRect", "samplerBuffer",
"samplerCube", "samplerCubeArray", "samplerCubeArrayShadow", "samplerCubeShadow", "short", "sizeof", "smooth", "static",
@ -2256,6 +2256,7 @@ string CompilerGLSL::to_expression(uint32_t id)
case TypeConstant:
{
auto &c = get<SPIRConstant>(id);
auto &type = get<SPIRType>(c.constant_type);
// WorkGroupSize may be a constant.
auto &dec = meta[c.self].decoration;
@ -2263,6 +2264,10 @@ string CompilerGLSL::to_expression(uint32_t id)
return builtin_to_glsl(dec.builtin_type, StorageClassGeneric);
else if (c.specialization && options.vulkan_semantics)
return to_name(id);
else if (type.basetype == SPIRType::Struct && !backend.can_declare_struct_inline)
return to_name(id);
else if (!type.array.empty() && !backend.can_declare_arrays_inline)
return to_name(id);
else
return constant_expression(c);
}
@ -5497,6 +5502,8 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (out_type.basetype == SPIRType::Struct && !backend.can_declare_struct_inline)
forward = false;
if (!out_type.array.empty() && !backend.can_declare_arrays_inline)
forward = false;
string constructor_op;
if (backend.use_initializer_list && composite)

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

@ -323,6 +323,7 @@ protected:
bool use_initializer_list = false;
bool use_typed_initializer_list = false;
bool can_declare_struct_inline = true;
bool can_declare_arrays_inline = true;
bool native_row_major_matrix = true;
bool use_constructor_splatting = true;
bool boolean_mix_support = true;

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

@ -841,6 +841,34 @@ void CompilerHLSL::emit_builtin_variables()
}
}
void CompilerHLSL::emit_composite_constants()
{
// HLSL cannot declare structs or arrays inline, so we must move them out to
// global constants directly.
bool emitted = false;
for (auto &id : ids)
{
if (id.get_type() == TypeConstant)
{
auto &c = id.get<SPIRConstant>();
if (c.specialization)
continue;
auto &type = get<SPIRType>(c.constant_type);
if (type.basetype == SPIRType::Struct || !type.array.empty())
{
auto name = to_name(c.self);
statement("static const ", variable_decl(type, name), " = ", constant_expression(c), ";");
emitted = true;
}
}
}
if (emitted)
statement("");
}
void CompilerHLSL::emit_specialization_constants()
{
bool emitted = false;
@ -880,6 +908,8 @@ void CompilerHLSL::emit_resources()
{
auto &execution = get_entry_point();
replace_illegal_names();
emit_specialization_constants();
// Output all basic struct types which are not Block or BufferBlock as these are declared inplace
@ -898,6 +928,8 @@ void CompilerHLSL::emit_resources()
}
}
emit_composite_constants();
bool emitted = false;
// Output UBOs and SSBOs
@ -3648,6 +3680,7 @@ string CompilerHLSL::compile()
backend.boolean_mix_support = false;
backend.can_swizzle_scalar = true;
backend.can_declare_struct_inline = false;
backend.can_declare_arrays_inline = false;
update_active_builtins();
analyze_sampler_comparison_states();

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

@ -91,6 +91,7 @@ private:
void emit_modern_uniform(const SPIRVariable &var);
void emit_legacy_uniform(const SPIRVariable &var);
void emit_specialization_constants();
void emit_composite_constants();
void emit_fixup() override;
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
std::string layout_for_member(const SPIRType &type, uint32_t index) override;