Disallow arrays and structs from becoming loop variables.

Fixes awkward code-gen issue.
This commit is contained in:
Hans-Kristian Arntzen 2018-03-07 14:54:11 +01:00
parent 2e5d06d1ce
commit 922420e346
11 changed files with 211 additions and 2 deletions

View File

@ -0,0 +1,32 @@
static const float _17[5] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
static float4 FragColor;
static float4 v0;
struct SPIRV_Cross_Input
{
float4 v0 : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
float lut[5] = _17;
int _33;
for (int _46 = 0; _46 < 4; _33 = _46 + 1, FragColor += lut[_33].xxxx, _46 = _33)
{
}
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
v0 = stage_input.v0;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,39 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
constant float _17[5] = {1.0, 2.0, 3.0, 4.0, 5.0};
struct main0_out
{
float4 FragColor [[color(0)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
}
// An overload for constant arrays.
template<typename T, uint N>
void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
}
fragment main0_out main0()
{
main0_out out = {};
float lut[5] = {1.0, 2.0, 3.0, 4.0, 5.0};
int _33;
for (int _46 = 0; _46 < 4; _33 = _46 + 1, out.FragColor += float4(lut[_33]), _46 = _33)
{
}
return out;
}

View File

@ -0,0 +1,15 @@
#version 310 es
precision mediump float;
precision highp int;
layout(location = 0) out vec4 FragColor;
void main()
{
float lut[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
mediump int _33;
for (int _46 = 0; _46 < 4; _33 = _46 + 1, FragColor += vec4(lut[_33]), _46 = _33)
{
}
}

View File

@ -0,0 +1,31 @@
static const float _17[5] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
static float4 FragColor;
static float4 v0;
struct SPIRV_Cross_Input
{
float4 v0 : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
float lut[5] = _17;
for (int i = 0; i < 4; i++, FragColor += lut[i].xxxx)
{
}
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
v0 = stage_input.v0;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,38 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
constant float _17[5] = {1.0, 2.0, 3.0, 4.0, 5.0};
struct main0_out
{
float4 FragColor [[color(0)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
}
// An overload for constant arrays.
template<typename T, uint N>
void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
}
fragment main0_out main0()
{
main0_out out = {};
float lut[5] = {1.0, 2.0, 3.0, 4.0, 5.0};
for (int i = 0; i < 4; i++, out.FragColor += float4(lut[i]))
{
}
return out;
}

View File

@ -0,0 +1,14 @@
#version 310 es
precision mediump float;
precision highp int;
layout(location = 0) out vec4 FragColor;
void main()
{
float lut[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
for (mediump int i = 0; i < 4; i++, FragColor += vec4(lut[i]))
{
}
}

View File

@ -0,0 +1,13 @@
#version 310 es
precision mediump float;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec4 v0;
void main()
{
float lut[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
for (int i = 0; i < 4; i++, FragColor += lut[i])
{
}
}

View File

@ -0,0 +1,13 @@
#version 310 es
precision mediump float;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec4 v0;
void main()
{
float lut[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
for (int i = 0; i < 4; i++, FragColor += lut[i])
{
}
}

View File

@ -0,0 +1,13 @@
#version 310 es
precision mediump float;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec4 v0;
void main()
{
float lut[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
for (int i = 0; i < 4; i++, FragColor += lut[i])
{
}
}

View File

@ -3679,7 +3679,8 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// so we will have to lift the dominator up to the relevant loop header instead.
builder.add_block(this->continue_block_to_loop_header[block]);
if (type.vecsize == 1 && type.columns == 1)
// Arrays or structs cannot be loop variables.
if (type.vecsize == 1 && type.columns == 1 && type.basetype != SPIRType::Struct && type.array.empty())
{
// The variable is used in multiple continue blocks, this is not a loop
// candidate, signal that by setting block to -1u.

View File

@ -8573,7 +8573,7 @@ string CompilerGLSL::emit_for_loop_initializers(const SPIRBlock &block)
if (expr.empty())
{
// For loop initializers are of the form <type id = value, id = value, id = value, etc ...
auto &var = get<SPIRVariable>(block.loop_variables.front());
auto &var = get<SPIRVariable>(loop_var);
auto &type = get<SPIRType>(var.basetype);
expr = join(to_qualifiers_glsl(var.self), type_to_glsl(type), " ");
}