Squashed 'deps/SPIRV-Cross/' changes from e59cc24495..f96c9f9fb4

f96c9f9fb4 Merge pull request #635 from KhronosGroup/fix-631
e044732896 Support OpTypeImage with depth == 2 (unknown) properly.
a6814a405a Merge pull request #630 from KhronosGroup/fix-628
af2d3abd03 Fail more gracefully with some unsupported opcodes.
26107ba200 Fix os.errno issues on Travis.
ee44f6027b Changed OpTypeImage to only flag depth if the op is 1
c863f53cac Merge pull request #627 from KhronosGroup/macro-namespace-fix
9ddbd5aff6 Run format_all.sh.
f1752e58e1 Add basic namespace to internal macros.
d67e586b2e Merge pull request #626 from billhollings/master
9bf226cb05 Fixes for code review of PR 626.
4c5142b9d3 CompilerMSL support larger texel buffers by using 2D Metal textures.
314f39a7c4 Merge pull request #621 from billhollings/master
4beefe756c Fixes from PR 621 code review.
f66507a701 Merge branch 'master' of https://github.com/KhronosGroup/SPIRV-Cross
0ea5e0549e Merge pull request #615 from JustSid/master
5ac55ee735 Fixed emission of some legacy texture ops without requiring the appropriate extensions
ceec708b89 Added better fallbacks for legacy textureProjLod() and textureProjLodOffset() generation
994f789465 Merge pull request #624 from KhronosGroup/fix-619
33c61d2abe Support branch/loop hints in HLSL.
327fb03677 Merge pull request #623 from KhronosGroup/fix-618
2077478651 Merge pull request #622 from KhronosGroup/fix-620
10dfaf79d5 Support globallycoherent in HLSL.
ffa9133d77 Support ternary expressions in OpSpecConstantOp.
e091031613 CompilerMSL pass builtin struct members into functions.
7607eb6923 Merge pull request #617 from KhronosGroup/fix-612
d94d20f4f3 Deal with some builtins being declared with wrong signedness.
0f62b5dc1e Moved check for depth texture and shadowXY emission completely to legacy_tex_op()
447a253ce7 Simplified check for depth texture
76c8e3c1c4 Merge pull request #616 from KhronosGroup/fix-614
b29629fd46 Add support to remove SPIRV_Cross_BaseInstance uniform.
809631ce21 Mention JSON backend in README.
040204d65c Fix warnings and run format_all.sh.
b4c8c3b9b2 Merge branch 'reflection' of git://github.com/jherico/SPIRV-Cross
f6dad78c99 Added support for shadowXY() sample instructions in legacy GLSL
9ad432463c Prefix integer types with underscore
0ad0f948e1 More PR feedback
3b30202bee Add reflection specific test cases, add reflection testing to test_shaders.sh
8d84a541ac Add specialization constant output in reflection
762040084d More feedback
d0a67ba6a7 Code consolidation, const correctness, faster regression testing
3a825349bc More cleanup
6c88b0048b PR feedback
ee86000529 Cleanup code
709d3c60f2 Working on reflection output
0039cb86fc Merge pull request #613 from KhronosGroup/fix-609
9d31154917 Deal with switch case labels which share a block.

git-subtree-dir: deps/SPIRV-Cross
git-subtree-split: f96c9f9fb4fc7d17991cecb2b2294dce06d08d9c
This commit is contained in:
twinaphex 2018-07-04 22:50:02 +02:00
parent 0328298474
commit 2da12dca58
94 changed files with 4898 additions and 494 deletions

View File

@ -93,6 +93,10 @@ spirv_cross_add_library(spirv-cross-cpp spirv_cross_cpp STATIC
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.hpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.cpp)
spirv_cross_add_library(spirv-cross-reflect spirv_cross_reflect STATIC
${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.hpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.cpp)
spirv_cross_add_library(spirv-cross-msl spirv_cross_msl STATIC
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.cpp)
@ -110,7 +114,7 @@ target_compile_options(spirv-cross PRIVATE ${spirv-compiler-options})
target_compile_definitions(spirv-cross PRIVATE ${spirv-compiler-defines})
install(TARGETS spirv-cross RUNTIME DESTINATION bin)
target_link_libraries(spirv-cross spirv-cross-glsl spirv-cross-hlsl spirv-cross-cpp spirv-cross-msl spirv-cross-util spirv-cross-core)
target_link_libraries(spirv-cross spirv-cross-glsl spirv-cross-hlsl spirv-cross-cpp spirv-cross-reflect spirv-cross-msl spirv-cross-util spirv-cross-core)
target_link_libraries(spirv-cross-util spirv-cross-core)
target_link_libraries(spirv-cross-glsl spirv-cross-core)
target_link_libraries(spirv-cross-msl spirv-cross-glsl)

View File

@ -11,6 +11,7 @@ SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader
- Convert SPIR-V to readable, usable and efficient Metal Shading Language (MSL)
- Convert SPIR-V to readable, usable and efficient HLSL
- Convert SPIR-V to debuggable C++ [EXPERIMENTAL]
- Convert SPIR-V to a JSON reflection format [EXPERIMENTAL]
- Reflection API to simplify the creation of Vulkan pipeline layouts
- Reflection API to modify and tweak OpDecorations
- Supports "all" of vertex, fragment, tessellation, geometry and compute shaders.

View File

@ -19,6 +19,7 @@
#include "spirv_glsl.hpp"
#include "spirv_hlsl.hpp"
#include "spirv_msl.hpp"
#include "spirv_reflect.hpp"
#include <algorithm>
#include <cstdio>
#include <cstring>
@ -149,6 +150,22 @@ struct CLIParser
return val;
}
// Return a string only if it's not prefixed with `--`, otherwise return the default value
const char *next_value_string(const char *default_value)
{
if (!argc)
{
return default_value;
}
if (0 == strncmp("--", *argv, 2))
{
return default_value;
}
return next_string();
}
const char *next_string()
{
if (!argc)
@ -461,6 +478,7 @@ struct CLIArguments
bool fixup = false;
bool yflip = false;
bool sso = false;
bool support_nonzero_baseinstance = true;
vector<PLSArg> pls_in;
vector<PLSArg> pls_out;
vector<Remap> remaps;
@ -481,6 +499,7 @@ struct CLIArguments
uint32_t iterations = 1;
bool cpp = false;
string reflect;
bool msl = false;
bool hlsl = false;
bool hlsl_compat = false;
@ -512,6 +531,7 @@ static void print_help()
"\t[--msl]\n"
"\t[--msl-version <MMmmpp>]\n"
"\t[--hlsl]\n"
"\t[--reflect]\n"
"\t[--shader-model]\n"
"\t[--hlsl-enable-compat]\n"
"\t[--separate-shader-objects]\n"
@ -528,7 +548,8 @@ static void print_help()
"\t[--rename-interface-variable <in|out> <location> <new_variable_name>]\n"
"\t[--set-hlsl-vertex-input-semantic <location> <semantic>]\n"
"\t[--rename-entry-point <old> <new> <stage>]\n"
"\t[--combined-samplers-inherit-bindings]"
"\t[--combined-samplers-inherit-bindings]\n"
"\t[--no-support-nonzero-baseinstance]\n"
"\n");
}
@ -663,6 +684,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--flip-vert-y", [&args](CLIParser &) { args.yflip = true; });
cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
cbs.add("--reflect", [&args](CLIParser &parser) { args.reflect = parser.next_value_string("json"); });
cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
@ -737,6 +759,8 @@ static int main_inner(int argc, char *argv[])
cbs.add("--combined-samplers-inherit-bindings",
[&args](CLIParser &) { args.combined_samplers_inherit_bindings = true; });
cbs.add("--no-support-nonzero-baseinstance", [&](CLIParser &) { args.support_nonzero_baseinstance = false; });
cbs.default_handler = [&args](const char *value) { args.input = value; };
cbs.error_handler = [] { print_help(); };
@ -757,8 +781,20 @@ static int main_inner(int argc, char *argv[])
return EXIT_FAILURE;
}
unique_ptr<CompilerGLSL> compiler;
// Special case reflection because it has little to do with the path followed by code-outputting compilers
if (!args.reflect.empty())
{
CompilerReflection compiler(read_spirv_file(args.input));
compiler.set_format(args.reflect);
auto json = compiler.compile();
if (args.output)
write_string_to_file(args.output, json.c_str());
else
printf("%s", json.c_str());
return EXIT_SUCCESS;
}
unique_ptr<CompilerGLSL> compiler;
bool combined_image_samplers = false;
bool build_dummy_sampler = false;
@ -895,6 +931,7 @@ static int main_inner(int argc, char *argv[])
opts.vulkan_semantics = args.vulkan_semantics;
opts.vertex.fixup_clipspace = args.fixup;
opts.vertex.flip_vert_y = args.yflip;
opts.vertex.support_nonzero_base_instance = args.support_nonzero_baseinstance;
compiler->set_common_options(opts);
// Set HLSL specific options.

View File

@ -127,6 +127,7 @@
<ClCompile Include="..\spirv_cpp.cpp" />
<ClCompile Include="..\spirv_cross.cpp" />
<ClCompile Include="..\spirv_glsl.cpp" />
<ClCompile Include="..\spirv_reflect.cpp" />
<ClCompile Include="..\spirv_hlsl.cpp" />
<ClCompile Include="..\spirv_msl.cpp" />
<ClCompile Include="..\spirv_cfg.cpp" />
@ -138,6 +139,7 @@
<ClInclude Include="..\spirv_cpp.hpp" />
<ClInclude Include="..\spirv_cross.hpp" />
<ClInclude Include="..\spirv_glsl.hpp" />
<ClInclude Include="..\spirv_reflect.hpp" />
<ClInclude Include="..\spirv.hpp" />
<ClInclude Include="..\spirv_hlsl.hpp" />
<ClInclude Include="..\spirv_msl.hpp" />

View File

@ -24,6 +24,9 @@
<ClCompile Include="..\spirv_glsl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\spirv_reflect.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\spirv_cpp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -50,6 +53,9 @@
<ClInclude Include="..\spirv_glsl.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\spirv_reflect.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\spirv.hpp">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -0,0 +1,32 @@
RWByteAddressBuffer bar : register(u0);
RWByteAddressBuffer foo : register(u1);
void comp_main()
{
[unroll]
for (int _135 = 0; _135 < 16; )
{
bar.Store4(_135 * 16 + 0, asuint(asfloat(foo.Load4(_135 * 16 + 0))));
_135++;
continue;
}
[loop]
for (int _136 = 0; _136 < 16; )
{
bar.Store4((15 - _136) * 16 + 0, asuint(asfloat(foo.Load4(_136 * 16 + 0))));
_136++;
continue;
}
[branch]
if (asfloat(bar.Load(160)) > 10.0f)
{
foo.Store4(320, asuint(5.0f.xxxx));
}
foo.Store4(320, asuint(20.0f.xxxx));
}
[numthreads(1, 1, 1)]
void main()
{
comp_main();
}

View File

@ -0,0 +1,31 @@
Texture2D<float4> uShadow : register(t0);
SamplerComparisonState _uShadow_sampler : register(s0);
Texture2D<float4> uTexture : register(t1);
SamplerComparisonState uSampler : register(s2);
static float3 vUV;
static float FragColor;
struct SPIRV_Cross_Input
{
float3 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
void frag_main()
{
FragColor = uShadow.SampleCmp(_uShadow_sampler, vUV.xy, vUV.z) + uTexture.SampleCmp(uSampler, vUV.xy, vUV.z);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,28 @@
static float4 gl_Position;
static int gl_VertexIndex;
static int gl_InstanceIndex;
struct SPIRV_Cross_Input
{
uint gl_VertexIndex : SV_VertexID;
uint gl_InstanceIndex : SV_InstanceID;
};
struct SPIRV_Cross_Output
{
float4 gl_Position : SV_Position;
};
void vert_main()
{
gl_Position = float(uint(gl_VertexIndex) + uint(gl_InstanceIndex)).xxxx;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
gl_VertexIndex = int(stage_input.gl_VertexIndex);
gl_InstanceIndex = int(stage_input.gl_InstanceIndex);
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
return stage_output;
}

View File

@ -0,0 +1,16 @@
globallycoherent RWByteAddressBuffer _29 : register(u3);
ByteAddressBuffer _33 : register(t2);
RWTexture2D<float> uImageIn : register(u0);
globallycoherent RWTexture2D<float> uImageOut : register(u1);
void comp_main()
{
uImageOut[int2(9, 7)] = uImageIn[int2(9, 7)].x;
_29.Store(0, asuint(asfloat(_33.Load(0))));
}
[numthreads(1, 1, 1)]
void main()
{
comp_main();
}

View File

@ -0,0 +1,23 @@
static const uint s = 10u;
static const bool _13 = (s > 20u);
static const uint _16 = _13 ? 30u : 50u;
static float FragColor;
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
void frag_main()
{
FragColor = float(_16);
}
SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,22 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float FragColor [[color(0)]];
};
struct main0_in
{
float3 vUV [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], depth2d<float> uShadow [[texture(0)]], depth2d<float> uTexture [[texture(1)]], sampler uShadowSmplr [[sampler(0)]], sampler uSampler [[sampler(2)]])
{
main0_out out = {};
out.FragColor = uShadow.sample_compare(uShadowSmplr, in.vUV.xy, in.vUV.z) + uTexture.sample_compare(uSampler, in.vUV.xy, in.vUV.z);
return out;
}

View File

@ -0,0 +1,17 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position]];
};
vertex main0_out main0(uint gl_VertexIndex [[vertex_id]], uint gl_InstanceIndex [[instance_id]])
{
main0_out out = {};
out.gl_Position = float4(float(gl_VertexIndex + gl_InstanceIndex));
return out;
}

View File

@ -0,0 +1,22 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
constant uint s_tmp [[function_constant(0)]];
constant uint s = is_function_constant_defined(s_tmp) ? s_tmp : 10u;
constant bool _13 = (s > 20u);
constant uint _16 = _13 ? 30u : 50u;
struct main0_out
{
float FragColor [[color(0)]];
};
fragment main0_out main0()
{
main0_out out = {};
out.FragColor = float(_16);
return out;
}

View File

@ -0,0 +1,19 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position]];
float gl_PointSize [[point_size]];
};
vertex main0_out main0()
{
main0_out out = {};
out.gl_PointSize = 1.0;
out.gl_Position = float4(out.gl_PointSize);
return out;
}

View File

@ -1,3 +1,5 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
@ -8,10 +10,16 @@ struct main0_out
float4 gl_Position [[position]];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
vertex main0_out main0(texture2d<float> uSamp [[texture(4)]], texture2d<float> uSampo [[texture(5)]])
{
main0_out out = {};
out.gl_Position = uSamp.read(uint2(10, 0)) + uSampo.read(uint2(100, 0));
out.gl_Position = uSamp.read(spvTexelBufferCoord(10)) + uSampo.read(spvTexelBufferCoord(100));
return out;
}

View File

@ -0,0 +1,33 @@
#version 310 es
precision mediump float;
precision highp int;
layout(location = 0) flat in mediump int vIndex;
layout(location = 0) out float FragColor;
void main()
{
highp float _19;
switch (vIndex)
{
case 0:
case 2:
{
_19 = 1.0;
break;
}
case 1:
default:
{
_19 = 3.0;
break;
}
case 8:
{
_19 = 8.0;
break;
}
}
FragColor = _19;
}

View File

@ -0,0 +1,13 @@
#version 450
layout(binding = 0) uniform sampler2DShadow uShadow;
uniform sampler2DShadow SPIRV_Cross_CombineduTextureuSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
void main()
{
FragColor = texture(uShadow, vec3(vUV.xy, vUV.z)) + texture(SPIRV_Cross_CombineduTextureuSampler, vec3(vUV.xy, vUV.z));
}

View File

@ -0,0 +1,14 @@
#version 450
layout(set = 0, binding = 0) uniform sampler2DShadow uShadow;
layout(set = 0, binding = 1) uniform texture2D uTexture;
layout(set = 0, binding = 2) uniform samplerShadow uSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
void main()
{
FragColor = texture(uShadow, vec3(vUV.xy, vUV.z)) + texture(sampler2DShadow(uTexture, uSampler), vec3(vUV.xy, vUV.z));
}

View File

@ -0,0 +1,41 @@
#version 450
layout(triangles) in;
layout(max_vertices = 3, triangle_strip) out;
struct VertexOutput
{
vec4 pos;
};
struct GeometryOutput
{
vec4 pos;
uint layer;
};
void _main(VertexOutput _input[3], GeometryOutput stream)
{
GeometryOutput _output;
_output.layer = 1u;
for (int v = 0; v < 3; v++)
{
_output.pos = _input[v].pos;
gl_Position = _output.pos;
gl_Layer = int(_output.layer);
EmitVertex();
}
EndPrimitive();
}
void main()
{
VertexOutput _input[3];
_input[0].pos = gl_in[0].gl_Position;
_input[1].pos = gl_in[1].gl_Position;
_input[2].pos = gl_in[2].gl_Position;
VertexOutput param[3] = _input;
GeometryOutput param_1;
_main(param, param_1);
GeometryOutput stream = param_1;
}

View File

@ -0,0 +1,9 @@
#version 450
uniform int SPIRV_Cross_BaseInstance;
void main()
{
gl_Position = vec4(float(uint(gl_VertexID) + uint((gl_InstanceID + SPIRV_Cross_BaseInstance))));
}

View File

@ -0,0 +1,9 @@
#version 450
layout(location = 0) out float FragColor;
void main()
{
FragColor = float((10u > 20u) ? 30u : 50u);
}

View File

@ -0,0 +1,13 @@
#version 450
layout(constant_id = 0) const uint s = 10u;
const bool _13 = (s > 20u);
const uint _16 = _13 ? 30u : 50u;
layout(location = 0) out float FragColor;
void main()
{
FragColor = float(_16);
}

View File

@ -0,0 +1,41 @@
RWByteAddressBuffer bar : register(u0);
RWByteAddressBuffer foo : register(u1);
void _main()
{
[unroll]
for (int i = 0; i < 16; i++)
{
bar.Store4(i * 16 + 0, asuint(asfloat(foo.Load4(i * 16 + 0))));
}
[loop]
for (int i_1 = 0; i_1 < 16; i_1++)
{
bar.Store4((15 - i_1) * 16 + 0, asuint(asfloat(foo.Load4(i_1 * 16 + 0))));
}
float v = asfloat(bar.Load(160));
float w = asfloat(foo.Load(160));
[branch]
if (v > 10.0f)
{
foo.Store4(320, asuint(5.0f.xxxx));
}
float value = 20.0f;
[flatten]
if (w > 40.0f)
{
value = 20.0f;
}
foo.Store4(320, asuint(value.xxxx));
}
void comp_main()
{
_main();
}
[numthreads(1, 1, 1)]
void main()
{
comp_main();
}

View File

@ -0,0 +1,41 @@
Texture2D<float4> uShadow : register(t0);
SamplerComparisonState _uShadow_sampler : register(s0);
Texture2D<float4> uTexture : register(t1);
SamplerComparisonState uSampler : register(s2);
static float3 vUV;
static float FragColor;
struct SPIRV_Cross_Input
{
float3 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
float sample_combined()
{
return uShadow.SampleCmp(_uShadow_sampler, vUV.xy, vUV.z);
}
float sample_separate()
{
return uTexture.SampleCmp(uSampler, vUV.xy, vUV.z);
}
void frag_main()
{
FragColor = sample_combined() + sample_separate();
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,37 @@
static float4 gl_Position;
static int gl_VertexIndex;
static int gl_InstanceIndex;
struct SPIRV_Cross_Input
{
uint gl_VertexIndex : SV_VertexID;
uint gl_InstanceIndex : SV_InstanceID;
};
struct SPIRV_Cross_Output
{
float4 gl_Position : SV_Position;
};
float4 _main(uint vid, uint iid)
{
return float(vid + iid).xxxx;
}
void vert_main()
{
uint vid = uint(gl_VertexIndex);
uint iid = uint(gl_InstanceIndex);
uint param = vid;
uint param_1 = iid;
gl_Position = _main(param, param_1);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
gl_VertexIndex = int(stage_input.gl_VertexIndex);
gl_InstanceIndex = int(stage_input.gl_InstanceIndex);
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
return stage_output;
}

View File

@ -0,0 +1,18 @@
globallycoherent RWByteAddressBuffer _29 : register(u3);
ByteAddressBuffer _33 : register(t2);
RWTexture2D<float> uImageIn : register(u0);
globallycoherent RWTexture2D<float> uImageOut : register(u1);
void comp_main()
{
int2 coord = int2(9, 7);
float4 indata = uImageIn[coord].xxxx;
uImageOut[coord] = indata.x;
_29.Store(0, asuint(asfloat(_33.Load(0))));
}
[numthreads(1, 1, 1)]
void main()
{
comp_main();
}

View File

@ -0,0 +1,23 @@
static const uint s = 10u;
static const bool _13 = (s > 20u);
static const uint _16 = _13 ? 30u : 50u;
static float FragColor;
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
void frag_main()
{
FragColor = float(_16);
}
SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -36,6 +36,12 @@ struct main0_out
float4 gl_Position [[position]];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
attr_desc fetch_desc(thread const int& location, constant VertexBuffer& v_227)
{
int attribute_flags = v_227.input_attributes[location].w;
@ -76,10 +82,10 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _131 = first_byte;
first_byte = _131 + 1;
tmp.x = input_stream.read(uint2(_131, 0)).x;
tmp.x = input_stream.read(spvTexelBufferCoord(_131)).x;
int _138 = first_byte;
first_byte = _138 + 1;
tmp.y = input_stream.read(uint2(_138, 0)).x;
tmp.y = input_stream.read(spvTexelBufferCoord(_138)).x;
uint4 param = tmp;
int param_1 = desc.swap_bytes;
result[n] = float(get_bits(param, param_1));
@ -89,16 +95,16 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _156 = first_byte;
first_byte = _156 + 1;
tmp.x = input_stream.read(uint2(_156, 0)).x;
tmp.x = input_stream.read(spvTexelBufferCoord(_156)).x;
int _163 = first_byte;
first_byte = _163 + 1;
tmp.y = input_stream.read(uint2(_163, 0)).x;
tmp.y = input_stream.read(spvTexelBufferCoord(_163)).x;
int _170 = first_byte;
first_byte = _170 + 1;
tmp.z = input_stream.read(uint2(_170, 0)).x;
tmp.z = input_stream.read(spvTexelBufferCoord(_170)).x;
int _177 = first_byte;
first_byte = _177 + 1;
tmp.w = input_stream.read(uint2(_177, 0)).x;
tmp.w = input_stream.read(spvTexelBufferCoord(_177)).x;
uint4 param_2 = tmp;
int param_3 = desc.swap_bytes;
result[n] = as_type<float>(get_bits(param_2, param_3));
@ -108,7 +114,7 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _195 = first_byte;
first_byte = _195 + 1;
result[n] = float(input_stream.read(uint2(_195, 0)).x);
result[n] = float(input_stream.read(spvTexelBufferCoord(_195)).x);
reverse_order = desc.swap_bytes != 0;
break;
}

View File

@ -0,0 +1,34 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float FragColor [[color(0)]];
};
struct main0_in
{
float3 vUV [[user(locn0)]];
};
float sample_combined(thread float3& vUV, thread depth2d<float> uShadow, thread const sampler uShadowSmplr)
{
return uShadow.sample_compare(uShadowSmplr, vUV.xy, vUV.z);
}
float sample_separate(thread float3& vUV, thread depth2d<float> uTexture, thread sampler uSampler)
{
return uTexture.sample_compare(uSampler, vUV.xy, vUV.z);
}
fragment main0_out main0(main0_in in [[stage_in]], depth2d<float> uShadow [[texture(0)]], depth2d<float> uTexture [[texture(1)]], sampler uShadowSmplr [[sampler(0)]], sampler uSampler [[sampler(2)]])
{
main0_out out = {};
out.FragColor = sample_combined(in.vUV, uShadow, uShadowSmplr) + sample_separate(in.vUV, uTexture, uSampler);
return out;
}

View File

@ -0,0 +1,28 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position]];
};
float4 _main(thread const uint& vid, thread const uint& iid)
{
return float4(float(vid + iid));
}
vertex main0_out main0(uint gl_VertexIndex [[vertex_id]], uint gl_InstanceIndex [[instance_id]])
{
main0_out out = {};
uint vid = gl_VertexIndex;
uint iid = gl_InstanceIndex;
uint param = vid;
uint param_1 = iid;
out.gl_Position = _main(param, param_1);
return out;
}

View File

@ -0,0 +1,22 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
constant uint s_tmp [[function_constant(0)]];
constant uint s = is_function_constant_defined(s_tmp) ? s_tmp : 10u;
constant bool _13 = (s > 20u);
constant uint _16 = _13 ? 30u : 50u;
struct main0_out
{
float FragColor [[color(0)]];
};
fragment main0_out main0()
{
main0_out out = {};
out.FragColor = float(_16);
return out;
}

View File

@ -0,0 +1,26 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position]];
float gl_PointSize [[point_size]];
};
void write_outblock(thread float4& gl_Position, thread float& gl_PointSize)
{
gl_PointSize = 1.0;
gl_Position = float4(gl_PointSize);
}
vertex main0_out main0()
{
main0_out out = {};
write_outblock(out.gl_Position, out.gl_PointSize);
return out;
}

View File

@ -1,3 +1,5 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
@ -8,10 +10,16 @@ struct main0_out
float4 gl_Position [[position]];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
vertex main0_out main0(texture2d<float> uSamp [[texture(4)]], texture2d<float> uSampo [[texture(5)]])
{
main0_out out = {};
out.gl_Position = uSamp.read(uint2(10, 0)) + uSampo.read(uint2(100, 0));
out.gl_Position = uSamp.read(spvTexelBufferCoord(10)) + uSampo.read(spvTexelBufferCoord(100));
return out;
}

View File

@ -0,0 +1,49 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "vert"
},
{
"name" : "main2",
"mode" : "vert"
},
{
"name" : "main",
"mode" : "frag"
},
{
"name" : "main2",
"mode" : "frag"
}
],
"types" : {
"_8" : {
"name" : "_8",
"members" : [
{
"name" : "_m0",
"type" : "vec4"
},
{
"name" : "_m1",
"type" : "float"
},
{
"name" : "_m2",
"type" : "float",
"array" : [
1
]
},
{
"name" : "_m3",
"type" : "float",
"array" : [
1
]
}
]
}
}
}

View File

@ -0,0 +1,64 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_19" : {
"name" : "Foo",
"members" : [
{
"name" : "m",
"type" : "mat4",
"offset" : 0
}
]
},
"_21" : {
"name" : "SSBO2",
"members" : [
{
"name" : "out_data",
"type" : "_19",
"array" : [
0
],
"offset" : 0
}
]
},
"_28" : {
"name" : "SSBO",
"members" : [
{
"name" : "in_data",
"type" : "_19",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_21",
"name" : "SSBO2",
"writeonly" : true,
"block_size" : 0,
"set" : 0,
"binding" : 1
},
{
"type" : "_28",
"name" : "SSBO",
"readonly" : true,
"block_size" : 0,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,474 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_11" : {
"name" : "S0",
"members" : [
{
"name" : "a",
"type" : "vec2",
"array" : [
1
],
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 8
}
]
},
"_14" : {
"name" : "S1",
"members" : [
{
"name" : "a",
"type" : "vec3",
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 12
}
]
},
"_17" : {
"name" : "S2",
"members" : [
{
"name" : "a",
"type" : "vec3",
"array" : [
1
],
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 16
}
]
},
"_19" : {
"name" : "S3",
"members" : [
{
"name" : "a",
"type" : "vec2",
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 8
}
]
},
"_20" : {
"name" : "S4",
"members" : [
{
"name" : "c",
"type" : "vec2",
"offset" : 0
}
]
},
"_23" : {
"name" : "Content",
"members" : [
{
"name" : "m0s",
"type" : "_11",
"array" : [
1
],
"offset" : 0
},
{
"name" : "m1s",
"type" : "_14",
"array" : [
1
],
"offset" : 16
},
{
"name" : "m2s",
"type" : "_17",
"array" : [
1
],
"offset" : 32
},
{
"name" : "m0",
"type" : "_11",
"offset" : 64
},
{
"name" : "m1",
"type" : "_14",
"offset" : 80
},
{
"name" : "m2",
"type" : "_17",
"offset" : 96
},
{
"name" : "m3",
"type" : "_19",
"offset" : 128
},
{
"name" : "m4",
"type" : "float",
"offset" : 144
},
{
"name" : "m3s",
"type" : "_20",
"array" : [
8
],
"offset" : 152
}
]
},
"_36" : {
"name" : "SSBO1",
"members" : [
{
"name" : "content",
"type" : "_23",
"offset" : 0
},
{
"name" : "content1",
"type" : "_23",
"array" : [
2
],
"offset" : 224
},
{
"name" : "content2",
"type" : "_23",
"offset" : 672
},
{
"name" : "m0",
"type" : "mat2",
"offset" : 896
},
{
"name" : "m1",
"type" : "mat2",
"offset" : 912
},
{
"name" : "m2",
"type" : "mat2x3",
"array" : [
4
],
"offset" : 928
},
{
"name" : "m3",
"type" : "mat3x2",
"offset" : 1056
},
{
"name" : "m4",
"type" : "mat2",
"row_major" : true,
"offset" : 1080
},
{
"name" : "m5",
"type" : "mat2",
"row_major" : true,
"array" : [
9
],
"offset" : 1096
},
{
"name" : "m6",
"type" : "mat2x3",
"row_major" : true,
"array" : [
2,
4
],
"offset" : 1240
},
{
"name" : "m7",
"type" : "mat3x2",
"row_major" : true,
"offset" : 1440
},
{
"name" : "array",
"type" : "float",
"array" : [
0
],
"offset" : 1472
}
]
},
"_42" : {
"name" : "S0",
"members" : [
{
"name" : "a",
"type" : "vec2",
"array" : [
1
],
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 16
}
]
},
"_44" : {
"name" : "S1",
"members" : [
{
"name" : "a",
"type" : "vec3",
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 12
}
]
},
"_47" : {
"name" : "S2",
"members" : [
{
"name" : "a",
"type" : "vec3",
"array" : [
1
],
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 16
}
]
},
"_49" : {
"name" : "S3",
"members" : [
{
"name" : "a",
"type" : "vec2",
"offset" : 0
},
{
"name" : "b",
"type" : "float",
"offset" : 8
}
]
},
"_50" : {
"name" : "S4",
"members" : [
{
"name" : "c",
"type" : "vec2",
"offset" : 0
}
]
},
"_52" : {
"name" : "Content",
"members" : [
{
"name" : "m0s",
"type" : "_42",
"array" : [
1
],
"offset" : 0
},
{
"name" : "m1s",
"type" : "_44",
"array" : [
1
],
"offset" : 32
},
{
"name" : "m2s",
"type" : "_47",
"array" : [
1
],
"offset" : 48
},
{
"name" : "m0",
"type" : "_42",
"offset" : 80
},
{
"name" : "m1",
"type" : "_44",
"offset" : 112
},
{
"name" : "m2",
"type" : "_47",
"offset" : 128
},
{
"name" : "m3",
"type" : "_49",
"offset" : 160
},
{
"name" : "m4",
"type" : "float",
"offset" : 176
},
{
"name" : "m3s",
"type" : "_50",
"array" : [
8
],
"offset" : 192
}
]
},
"_59" : {
"name" : "SSBO0",
"members" : [
{
"name" : "content",
"type" : "_52",
"offset" : 0
},
{
"name" : "content1",
"type" : "_52",
"array" : [
2
],
"offset" : 320
},
{
"name" : "content2",
"type" : "_52",
"offset" : 960
},
{
"name" : "m0",
"type" : "mat2",
"offset" : 1280
},
{
"name" : "m1",
"type" : "mat2",
"offset" : 1312
},
{
"name" : "m2",
"type" : "mat2x3",
"array" : [
4
],
"offset" : 1344
},
{
"name" : "m3",
"type" : "mat3x2",
"offset" : 1472
},
{
"name" : "m4",
"type" : "mat2",
"row_major" : true,
"offset" : 1520
},
{
"name" : "m5",
"type" : "mat2",
"row_major" : true,
"array" : [
9
],
"offset" : 1552
},
{
"name" : "m6",
"type" : "mat2x3",
"row_major" : true,
"array" : [
2,
4
],
"offset" : 1840
},
{
"name" : "m7",
"type" : "mat3x2",
"row_major" : true,
"offset" : 2224
},
{
"name" : "array",
"type" : "float",
"array" : [
0
],
"offset" : 2256
}
]
}
},
"ssbos" : [
{
"type" : "_36",
"name" : "SSBO1",
"restrict" : true,
"block_size" : 1472,
"set" : 0,
"binding" : 1
},
{
"type" : "_59",
"name" : "SSBO0",
"restrict" : true,
"block_size" : 2256,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,37 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"outputs" : [
{
"type" : "float",
"name" : "FragColor",
"location" : 0
}
],
"separate_images" : [
{
"type" : "texture2D",
"name" : "uDepth",
"set" : 0,
"binding" : 2
}
],
"separate_samplers" : [
{
"type" : "sampler",
"name" : "uSampler",
"set" : 0,
"binding" : 0
},
{
"type" : "sampler",
"name" : "uSampler1",
"set" : 0,
"binding" : 1
}
]
}

View File

@ -0,0 +1,50 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"inputs" : [
{
"type" : "vec2",
"name" : "vTex",
"location" : 0
}
],
"outputs" : [
{
"type" : "vec4",
"name" : "FragColor",
"location" : 0
}
],
"separate_images" : [
{
"type" : "texture2D",
"name" : "uTexture0",
"set" : 0,
"binding" : 2
},
{
"type" : "texture2D",
"name" : "uTexture1",
"set" : 0,
"binding" : 3
}
],
"separate_samplers" : [
{
"type" : "sampler",
"name" : "uSampler0",
"set" : 0,
"binding" : 0
},
{
"type" : "sampler",
"name" : "uSampler1",
"set" : 0,
"binding" : 1
}
]
}

View File

@ -0,0 +1,47 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"outputs" : [
{
"type" : "vec4",
"name" : "_entryPointOutput",
"location" : 0
}
],
"textures" : [
{
"type" : "sampler2D",
"name" : "ROIm",
"set" : 0,
"binding" : 1
}
],
"separate_images" : [
{
"type" : "samplerBuffer",
"name" : "ROBuf",
"set" : 0,
"binding" : 0
}
],
"images" : [
{
"type" : "image2D",
"name" : "RWIm",
"set" : 0,
"binding" : 1,
"format" : "rgba32f"
},
{
"type" : "imageBuffer",
"name" : "RWBuf",
"set" : 0,
"binding" : 0,
"format" : "rgba32f"
}
]
}

View File

@ -0,0 +1,31 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"subpass_inputs" : [
{
"type" : "subpassInputMS",
"name" : "uSubpass0",
"set" : 0,
"binding" : 0,
"input_attachment_index" : 0
},
{
"type" : "subpassInputMS",
"name" : "uSubpass1",
"set" : 0,
"binding" : 1,
"input_attachment_index" : 1
}
],
"outputs" : [
{
"type" : "vec4",
"name" : "FragColor",
"location" : 0
}
]
}

View File

@ -0,0 +1,31 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"subpass_inputs" : [
{
"type" : "subpassInput",
"name" : "uSubpass0",
"set" : 0,
"binding" : 0,
"input_attachment_index" : 0
},
{
"type" : "subpassInput",
"name" : "uSubpass1",
"set" : 0,
"binding" : 1,
"input_attachment_index" : 1
}
],
"outputs" : [
{
"type" : "vec4",
"name" : "FragColor",
"location" : 0
}
]
}

View File

@ -0,0 +1,46 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"types" : {
"_13" : {
"name" : "PushConstants",
"members" : [
{
"name" : "value0",
"type" : "vec4",
"offset" : 0
},
{
"name" : "value1",
"type" : "vec4",
"offset" : 16
}
]
}
},
"inputs" : [
{
"type" : "vec4",
"name" : "vColor",
"location" : 0
}
],
"outputs" : [
{
"type" : "vec4",
"name" : "FragColor",
"location" : 0
}
],
"push_constants" : [
{
"type" : "_13",
"name" : "push",
"push_constant" : true
}
]
}

View File

@ -0,0 +1,73 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"inputs" : [
{
"type" : "vec2",
"name" : "vTex",
"location" : 0
},
{
"type" : "vec3",
"name" : "vTex3",
"location" : 1
}
],
"outputs" : [
{
"type" : "vec4",
"name" : "FragColor",
"location" : 0
}
],
"separate_images" : [
{
"type" : "texture2D",
"name" : "uTexture",
"array" : [
4
],
"set" : 0,
"binding" : 1
},
{
"type" : "texture2DArray",
"name" : "uTextureArray",
"array" : [
4
],
"set" : 0,
"binding" : 4
},
{
"type" : "textureCube",
"name" : "uTextureCube",
"array" : [
4
],
"set" : 0,
"binding" : 3
},
{
"type" : "texture3D",
"name" : "uTexture3D",
"array" : [
4
],
"set" : 0,
"binding" : 2
}
],
"separate_samplers" : [
{
"type" : "sampler",
"name" : "uSampler",
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,71 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "frag"
}
],
"types" : {
"_137" : {
"name" : "Foo",
"members" : [
{
"name" : "elems",
"type" : "float",
"array" : [
135
]
}
]
}
},
"outputs" : [
{
"type" : "vec4",
"name" : "FragColor",
"location" : 0
}
],
"specialization_constants" : [
{
"id" : 1,
"type" : "float",
"default_value" : 1.5
},
{
"id" : 2,
"type" : "float",
"default_value" : 2.5
},
{
"id" : 3,
"type" : "int",
"default_value" : 3
},
{
"id" : 4,
"type" : "int",
"default_value" : 4
},
{
"id" : 5,
"type" : "uint",
"default_value" : 5
},
{
"id" : 6,
"type" : "uint",
"default_value" : 6
},
{
"id" : 7,
"type" : "bool",
"default_value" : false
},
{
"id" : 8,
"type" : "bool",
"default_value" : true
}
]
}

View File

@ -0,0 +1,61 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "vert"
}
],
"types" : {
"_89" : {
"name" : "gl_PerVertex",
"members" : [
{
"name" : "gl_Position",
"type" : "vec4"
},
{
"name" : "gl_PointSize",
"type" : "float"
}
]
},
"_102" : {
"name" : "Block",
"members" : [
{
"name" : "var",
"type" : "mat2x3",
"row_major" : true,
"array" : [
4,
3
],
"offset" : 0
}
]
}
},
"inputs" : [
{
"type" : "vec4",
"name" : "a_position",
"location" : 0
}
],
"outputs" : [
{
"type" : "float",
"name" : "v_vtxResult",
"location" : 0
}
],
"ubos" : [
{
"type" : "_102",
"name" : "Block",
"block_size" : 576,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,40 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "vert"
}
],
"types" : {
"_8" : {
"name" : "gl_PerVertex",
"members" : [
{
"name" : "gl_Position",
"type" : "vec4"
},
{
"name" : "gl_PointSize",
"type" : "float"
}
]
}
},
"textures" : [
{
"type" : "samplerBuffer",
"name" : "uSamp",
"set" : 0,
"binding" : 4
}
],
"images" : [
{
"type" : "imageBuffer",
"name" : "uSampo",
"set" : 0,
"binding" : 5,
"format" : "rgba32f"
}
]
}

View File

@ -0,0 +1,33 @@
#version 310 es
precision mediump float;
precision highp int;
layout(location = 0) flat in mediump int vIndex;
layout(location = 0) out float FragColor;
void main()
{
highp float _19;
switch (vIndex)
{
case 0:
case 2:
{
_19 = 1.0;
break;
}
case 1:
default:
{
_19 = 3.0;
break;
}
case 8:
{
_19 = 8.0;
break;
}
}
FragColor = _19;
}

View File

@ -0,0 +1,23 @@
#version 450
layout(binding = 0) uniform sampler2DShadow uShadow;
uniform sampler2DShadow SPIRV_Cross_CombineduTextureuSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
float sample_combined()
{
return texture(uShadow, vec3(vUV.xy, vUV.z));
}
float sample_separate()
{
return texture(SPIRV_Cross_CombineduTextureuSampler, vec3(vUV.xy, vUV.z));
}
void main()
{
FragColor = sample_combined() + sample_separate();
}

View File

@ -0,0 +1,24 @@
#version 450
layout(set = 0, binding = 0) uniform sampler2DShadow uShadow;
layout(set = 0, binding = 1) uniform texture2D uTexture;
layout(set = 0, binding = 2) uniform samplerShadow uSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
float sample_combined()
{
return texture(uShadow, vec3(vUV.xy, vUV.z));
}
float sample_separate()
{
return texture(sampler2DShadow(uTexture, uSampler), vec3(vUV.xy, vUV.z));
}
void main()
{
FragColor = sample_combined() + sample_separate();
}

View File

@ -0,0 +1,41 @@
#version 450
layout(triangles) in;
layout(max_vertices = 3, triangle_strip) out;
struct VertexOutput
{
vec4 pos;
};
struct GeometryOutput
{
vec4 pos;
uint layer;
};
void _main(VertexOutput _input[3], GeometryOutput stream)
{
GeometryOutput _output;
_output.layer = 1u;
for (int v = 0; v < 3; v++)
{
_output.pos = _input[v].pos;
gl_Position = _output.pos;
gl_Layer = int(_output.layer);
EmitVertex();
}
EndPrimitive();
}
void main()
{
VertexOutput _input[3];
_input[0].pos = gl_in[0].gl_Position;
_input[1].pos = gl_in[1].gl_Position;
_input[2].pos = gl_in[2].gl_Position;
VertexOutput param[3] = _input;
GeometryOutput param_1;
_main(param, param_1);
GeometryOutput stream = param_1;
}

View File

@ -0,0 +1,18 @@
#version 450
uniform int SPIRV_Cross_BaseInstance;
vec4 _main(uint vid, uint iid)
{
return vec4(float(vid + iid));
}
void main()
{
uint vid = uint(gl_VertexID);
uint iid = uint((gl_InstanceID + SPIRV_Cross_BaseInstance));
uint param = vid;
uint param_1 = iid;
gl_Position = _main(param, param_1);
}

View File

@ -0,0 +1,9 @@
#version 450
layout(location = 0) out float FragColor;
void main()
{
FragColor = float((10u > 20u) ? 30u : 50u);
}

View File

@ -0,0 +1,13 @@
#version 450
layout(constant_id = 0) const uint s = 10u;
const bool _13 = (s > 20u);
const uint _16 = _13 ? 30u : 50u;
layout(location = 0) out float FragColor;
void main()
{
FragColor = float(_16);
}

View File

@ -0,0 +1,146 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 85
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpSource HLSL 500
OpName %main "main"
OpName %_main_ "@main("
OpName %i "i"
OpName %bar "bar"
OpMemberName %bar 0 "@data"
OpName %bar_0 "bar"
OpName %foo "foo"
OpName %i_0 "i"
OpName %v "v"
OpName %w "w"
OpName %value "value"
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %bar 0 Offset 0
OpDecorate %bar BufferBlock
OpDecorate %bar_0 DescriptorSet 0
OpDecorate %bar_0 Binding 0
OpDecorate %foo DescriptorSet 0
OpDecorate %foo Binding 1
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%int_0 = OpConstant %int 0
%int_16 = OpConstant %int 16
%bool = OpTypeBool
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%bar = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_bar = OpTypePointer Uniform %bar
%bar_0 = OpVariable %_ptr_Uniform_bar Uniform
%foo = OpVariable %_ptr_Uniform_bar Uniform
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%int_1 = OpConstant %int 1
%int_15 = OpConstant %int 15
%_ptr_Function_float = OpTypePointer Function %float
%int_10 = OpConstant %int 10
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%_ptr_Uniform_float = OpTypePointer Uniform %float
%float_10 = OpConstant %float 10
%int_20 = OpConstant %int 20
%float_5 = OpConstant %float 5
%72 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5
%float_20 = OpConstant %float 20
%float_40 = OpConstant %float 40
%main = OpFunction %void None %3
%5 = OpLabel
%84 = OpFunctionCall %void %_main_
OpReturn
OpFunctionEnd
%_main_ = OpFunction %void None %3
%7 = OpLabel
%i = OpVariable %_ptr_Function_int Function
%i_0 = OpVariable %_ptr_Function_int Function
%v = OpVariable %_ptr_Function_float Function
%w = OpVariable %_ptr_Function_float Function
%value = OpVariable %_ptr_Function_float Function
OpStore %i %int_0
OpBranch %12
%12 = OpLabel
OpLoopMerge %14 %15 Unroll
OpBranch %16
%16 = OpLabel
%17 = OpLoad %int %i
%20 = OpSLessThan %bool %17 %int_16
OpBranchConditional %20 %13 %14
%13 = OpLabel
%27 = OpLoad %int %i
%29 = OpLoad %int %i
%31 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %29
%32 = OpLoad %v4float %31
%33 = OpAccessChain %_ptr_Uniform_v4float %bar_0 %int_0 %27
OpStore %33 %32
OpBranch %15
%15 = OpLabel
%34 = OpLoad %int %i
%36 = OpIAdd %int %34 %int_1
OpStore %i %36
OpBranch %12
%14 = OpLabel
OpStore %i_0 %int_0
OpBranch %38
%38 = OpLabel
OpLoopMerge %40 %41 DontUnroll
OpBranch %42
%42 = OpLabel
%43 = OpLoad %int %i_0
%44 = OpSLessThan %bool %43 %int_16
OpBranchConditional %44 %39 %40
%39 = OpLabel
%46 = OpLoad %int %i_0
%47 = OpISub %int %int_15 %46
%48 = OpLoad %int %i_0
%49 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %48
%50 = OpLoad %v4float %49
%51 = OpAccessChain %_ptr_Uniform_v4float %bar_0 %int_0 %47
OpStore %51 %50
OpBranch %41
%41 = OpLabel
%52 = OpLoad %int %i_0
%53 = OpIAdd %int %52 %int_1
OpStore %i_0 %53
OpBranch %38
%40 = OpLabel
%60 = OpAccessChain %_ptr_Uniform_float %bar_0 %int_0 %int_10 %uint_0
%61 = OpLoad %float %60
OpStore %v %61
%63 = OpAccessChain %_ptr_Uniform_float %foo %int_0 %int_10 %uint_0
%64 = OpLoad %float %63
OpStore %w %64
%65 = OpLoad %float %v
%67 = OpFOrdGreaterThan %bool %65 %float_10
OpSelectionMerge %69 DontFlatten
OpBranchConditional %67 %68 %69
%68 = OpLabel
%73 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %int_20
OpStore %73 %72
OpBranch %69
%69 = OpLabel
OpStore %value %float_20
%76 = OpLoad %float %w
%78 = OpFOrdGreaterThan %bool %76 %float_40
OpSelectionMerge %80 Flatten
OpBranchConditional %78 %79 %80
%79 = OpLabel
OpStore %value %float_20
OpBranch %80
%80 = OpLabel
%81 = OpLoad %float %value
%82 = OpCompositeConstruct %v4float %81 %81 %81 %81
%83 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %int_20
OpStore %83 %82
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,71 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 44
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %vUV %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %sample_combined_ "sample_combined("
OpName %sample_separate_ "sample_separate("
OpName %uShadow "uShadow"
OpName %vUV "vUV"
OpName %uTexture "uTexture"
OpName %uSampler "uSampler"
OpName %FragColor "FragColor"
OpDecorate %uShadow DescriptorSet 0
OpDecorate %uShadow Binding 0
OpDecorate %vUV Location 0
OpDecorate %uTexture DescriptorSet 0
OpDecorate %uTexture Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 2
OpDecorate %FragColor Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%12 = OpTypeImage %float 2D 2 0 0 1 Unknown
%13 = OpTypeSampledImage %12
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%vUV = OpVariable %_ptr_Input_v3float Input
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
%uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
%29 = OpTypeSampler
%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
%uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%41 = OpFunctionCall %float %sample_combined_
%42 = OpFunctionCall %float %sample_separate_
%43 = OpFAdd %float %41 %42
OpStore %FragColor %43
OpReturn
OpFunctionEnd
%sample_combined_ = OpFunction %float None %7
%9 = OpLabel
%16 = OpLoad %13 %uShadow
%20 = OpLoad %v3float %vUV
%21 = OpCompositeExtract %float %20 2
%22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
OpReturnValue %22
OpFunctionEnd
%sample_separate_ = OpFunction %float None %7
%11 = OpLabel
%28 = OpLoad %12 %uTexture
%32 = OpLoad %29 %uSampler
%33 = OpSampledImage %13 %28 %32
%34 = OpLoad %v3float %vUV
%35 = OpCompositeExtract %float %34 2
%36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
OpReturnValue %36
OpFunctionEnd

View File

@ -0,0 +1,65 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 36
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %vid_1 %iid_1 %_entryPointOutput
OpSource HLSL 500
OpName %main "main"
OpName %_main_u1_u1_ "@main(u1;u1;"
OpName %vid "vid"
OpName %iid "iid"
OpName %vid_0 "vid"
OpName %vid_1 "vid"
OpName %iid_0 "iid"
OpName %iid_1 "iid"
OpName %_entryPointOutput "@entryPointOutput"
OpName %param "param"
OpName %param_0 "param"
OpDecorate %vid_1 BuiltIn VertexIndex
OpDecorate %iid_1 BuiltIn InstanceIndex
OpDecorate %_entryPointOutput BuiltIn Position
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%_ptr_Function_uint = OpTypePointer Function %uint
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%10 = OpTypeFunction %v4float %_ptr_Function_uint %_ptr_Function_uint
%_ptr_Input_uint = OpTypePointer Input %uint
%vid_1 = OpVariable %_ptr_Input_uint Input
%iid_1 = OpVariable %_ptr_Input_uint Input
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %3
%5 = OpLabel
%vid_0 = OpVariable %_ptr_Function_uint Function
%iid_0 = OpVariable %_ptr_Function_uint Function
%param = OpVariable %_ptr_Function_uint Function
%param_0 = OpVariable %_ptr_Function_uint Function
%25 = OpLoad %uint %vid_1
OpStore %vid_0 %25
%28 = OpLoad %uint %iid_1
OpStore %iid_0 %28
%32 = OpLoad %uint %vid_0
OpStore %param %32
%34 = OpLoad %uint %iid_0
OpStore %param_0 %34
%35 = OpFunctionCall %v4float %_main_u1_u1_ %param %param_0
OpStore %_entryPointOutput %35
OpReturn
OpFunctionEnd
%_main_u1_u1_ = OpFunction %v4float None %10
%vid = OpFunctionParameter %_ptr_Function_uint
%iid = OpFunctionParameter %_ptr_Function_uint
%14 = OpLabel
%15 = OpLoad %uint %vid
%16 = OpLoad %uint %iid
%17 = OpIAdd %uint %15 %16
%18 = OpConvertUToF %float %17
%19 = OpCompositeConstruct %v4float %18 %18 %18 %18
OpReturnValue %19
OpFunctionEnd

View File

@ -0,0 +1,25 @@
#version 450
layout(local_size_x = 1) in;
layout(r32f, binding = 0) uniform readonly image2D uImageIn;
layout(r32f, binding = 1) uniform coherent writeonly image2D uImageOut;
layout(set = 0, binding = 2) readonly buffer Foo
{
float foo;
};
layout(set = 0, binding = 3) coherent writeonly buffer Bar
{
float bar;
};
void main()
{
ivec2 coord = ivec2(9, 7);
vec4 indata = imageLoad(uImageIn, coord);
imageStore(uImageOut, coord, indata);
bar = foo;
}

View File

@ -0,0 +1,9 @@
#version 450
layout(location = 0) out float FragColor;
layout(constant_id = 0) const uint s = 10u;
const uint f = s > 20u ? 30u : 50u;
void main()
{
FragColor = float(f);
}

View File

@ -0,0 +1,71 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 44
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %vUV %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %sample_combined_ "sample_combined("
OpName %sample_separate_ "sample_separate("
OpName %uShadow "uShadow"
OpName %vUV "vUV"
OpName %uTexture "uTexture"
OpName %uSampler "uSampler"
OpName %FragColor "FragColor"
OpDecorate %uShadow DescriptorSet 0
OpDecorate %uShadow Binding 0
OpDecorate %vUV Location 0
OpDecorate %uTexture DescriptorSet 0
OpDecorate %uTexture Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 2
OpDecorate %FragColor Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%12 = OpTypeImage %float 2D 2 0 0 1 Unknown
%13 = OpTypeSampledImage %12
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%vUV = OpVariable %_ptr_Input_v3float Input
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
%uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
%29 = OpTypeSampler
%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
%uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%41 = OpFunctionCall %float %sample_combined_
%42 = OpFunctionCall %float %sample_separate_
%43 = OpFAdd %float %41 %42
OpStore %FragColor %43
OpReturn
OpFunctionEnd
%sample_combined_ = OpFunction %float None %7
%9 = OpLabel
%16 = OpLoad %13 %uShadow
%20 = OpLoad %v3float %vUV
%21 = OpCompositeExtract %float %20 2
%22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
OpReturnValue %22
OpFunctionEnd
%sample_separate_ = OpFunction %float None %7
%11 = OpLabel
%28 = OpLoad %12 %uTexture
%32 = OpLoad %29 %uSampler
%33 = OpSampledImage %13 %28 %32
%34 = OpLoad %v3float %vUV
%35 = OpCompositeExtract %float %34 2
%36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
OpReturnValue %36
OpFunctionEnd

View File

@ -0,0 +1,65 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 36
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %vid_1 %iid_1 %_entryPointOutput
OpSource HLSL 500
OpName %main "main"
OpName %_main_u1_u1_ "@main(u1;u1;"
OpName %vid "vid"
OpName %iid "iid"
OpName %vid_0 "vid"
OpName %vid_1 "vid"
OpName %iid_0 "iid"
OpName %iid_1 "iid"
OpName %_entryPointOutput "@entryPointOutput"
OpName %param "param"
OpName %param_0 "param"
OpDecorate %vid_1 BuiltIn VertexIndex
OpDecorate %iid_1 BuiltIn InstanceIndex
OpDecorate %_entryPointOutput BuiltIn Position
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%_ptr_Function_uint = OpTypePointer Function %uint
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%10 = OpTypeFunction %v4float %_ptr_Function_uint %_ptr_Function_uint
%_ptr_Input_uint = OpTypePointer Input %uint
%vid_1 = OpVariable %_ptr_Input_uint Input
%iid_1 = OpVariable %_ptr_Input_uint Input
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %3
%5 = OpLabel
%vid_0 = OpVariable %_ptr_Function_uint Function
%iid_0 = OpVariable %_ptr_Function_uint Function
%param = OpVariable %_ptr_Function_uint Function
%param_0 = OpVariable %_ptr_Function_uint Function
%25 = OpLoad %uint %vid_1
OpStore %vid_0 %25
%28 = OpLoad %uint %iid_1
OpStore %iid_0 %28
%32 = OpLoad %uint %vid_0
OpStore %param %32
%34 = OpLoad %uint %iid_0
OpStore %param_0 %34
%35 = OpFunctionCall %v4float %_main_u1_u1_ %param %param_0
OpStore %_entryPointOutput %35
OpReturn
OpFunctionEnd
%_main_u1_u1_ = OpFunction %v4float None %10
%vid = OpFunctionParameter %_ptr_Function_uint
%iid = OpFunctionParameter %_ptr_Function_uint
%14 = OpLabel
%15 = OpLoad %uint %vid
%16 = OpLoad %uint %iid
%17 = OpIAdd %uint %15 %16
%18 = OpConvertUToF %float %17
%19 = OpCompositeConstruct %v4float %18 %18 %18 %18
OpReturnValue %19
OpFunctionEnd

View File

@ -0,0 +1,9 @@
#version 450
layout(location = 0) out float FragColor;
layout(constant_id = 0) const uint s = 10u;
const uint f = s > 20u ? 30u : 50u;
void main()
{
FragColor = float(f);
}

View File

@ -0,0 +1,12 @@
#version 450
void write_outblock()
{
gl_PointSize = 1.0;
gl_Position = vec4(gl_PointSize);
}
void main()
{
write_outblock();
}

View File

@ -0,0 +1,60 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 3
; Bound: 20
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %_
OpEntryPoint Vertex %main2 "main2" %_
OpEntryPoint Fragment %main3 "main" %FragColor
OpEntryPoint Fragment %main4 "main2" %FragColor
OpSource GLSL 450
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
OpDecorate %FragColor Location 0
OpDecorate %gl_PerVertex Block
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%v4floatptr = OpTypePointer Output %v4float
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_float_uint_1 = OpTypeArray %float %uint_1
%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
%FragColor = OpVariable %v4floatptr Output
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%float_1 = OpConstant %float 1
%17 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%float_2 = OpConstant %float 2
%18 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%_ptr_Output_v4float = OpTypePointer Output %v4float
%main = OpFunction %void None %3
%5 = OpLabel
%19 = OpAccessChain %_ptr_Output_v4float %_ %int_0
OpStore %19 %17
OpReturn
OpFunctionEnd
%main2 = OpFunction %void None %3
%6 = OpLabel
%20 = OpAccessChain %_ptr_Output_v4float %_ %int_0
OpStore %20 %18
OpReturn
OpFunctionEnd
%main3 = OpFunction %void None %3
%7 = OpLabel
OpStore %FragColor %17
OpReturn
OpFunctionEnd
%main4 = OpFunction %void None %3
%8 = OpLabel
OpStore %FragColor %18
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,24 @@
#version 310 es
layout(local_size_x = 1) in;
struct Foo
{
mat4 m;
};
layout(std430, binding = 0) readonly buffer SSBO
{
Foo in_data[];
};
layout(std430, binding = 1) writeonly buffer SSBO2
{
Foo out_data[];
};
void main()
{
uint ident = gl_GlobalInvocationID.x;
out_data[ident].m = in_data[ident].m * in_data[ident].m;
}

View File

@ -0,0 +1,87 @@
#version 450
layout(local_size_x = 1) in;
struct S0
{
vec2 a[1];
float b;
};
struct S1
{
vec3 a;
float b;
};
struct S2
{
vec3 a[1];
float b;
};
struct S3
{
vec2 a;
float b;
};
struct S4
{
vec2 c;
};
struct Content
{
S0 m0s[1];
S1 m1s[1];
S2 m2s[1];
S0 m0;
S1 m1;
S2 m2;
S3 m3;
float m4;
S4 m3s[8];
};
layout(binding = 1, std430) restrict buffer SSBO1
{
Content content;
Content content1[2];
Content content2;
layout(column_major) mat2 m0;
layout(column_major) mat2 m1;
layout(column_major) mat2x3 m2[4];
layout(column_major) mat3x2 m3;
layout(row_major) mat2 m4;
layout(row_major) mat2 m5[9];
layout(row_major) mat2x3 m6[4][2];
layout(row_major) mat3x2 m7;
float array[];
} ssbo_430;
layout(binding = 0, std140) restrict buffer SSBO0
{
Content content;
Content content1[2];
Content content2;
layout(column_major) mat2 m0;
layout(column_major) mat2 m1;
layout(column_major) mat2x3 m2[4];
layout(column_major) mat3x2 m3;
layout(row_major) mat2 m4;
layout(row_major) mat2 m5[9];
layout(row_major) mat2x3 m6[4][2];
layout(row_major) mat3x2 m7;
float array[];
} ssbo_140;
void main()
{
ssbo_430.content = ssbo_140.content;
}

View File

@ -0,0 +1,29 @@
#version 310 es
precision mediump float;
layout(set = 0, binding = 0) uniform mediump samplerShadow uSampler;
layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
layout(set = 0, binding = 2) uniform texture2D uDepth;
layout(location = 0) out float FragColor;
float samp2(texture2D t, mediump samplerShadow s)
{
return texture(sampler2DShadow(t, s), vec3(1.0));
}
float samp3(texture2D t, mediump sampler s)
{
return texture(sampler2D(t, s), vec2(1.0)).x;
}
float samp(texture2D t, mediump samplerShadow s, mediump sampler s1)
{
float r0 = samp2(t, s);
float r1 = samp3(t, s1);
return r0 + r1;
}
void main()
{
FragColor = samp(uDepth, uSampler, uSampler1);
}

View File

@ -0,0 +1,47 @@
#version 310 es
precision mediump float;
layout(set = 0, binding = 0) uniform mediump sampler uSampler0;
layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
layout(set = 0, binding = 2) uniform mediump texture2D uTexture0;
layout(set = 0, binding = 3) uniform mediump texture2D uTexture1;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 vTex;
vec4 sample_dual(mediump sampler samp, mediump texture2D tex)
{
return texture(sampler2D(tex, samp), vTex);
}
vec4 sample_global_tex(mediump sampler samp)
{
vec4 a = texture(sampler2D(uTexture0, samp), vTex);
vec4 b = sample_dual(samp, uTexture1);
return a + b;
}
vec4 sample_global_sampler(mediump texture2D tex)
{
vec4 a = texture(sampler2D(tex, uSampler0), vTex);
vec4 b = sample_dual(uSampler1, tex);
return a + b;
}
vec4 sample_duals()
{
vec4 a = sample_dual(uSampler0, uTexture0);
vec4 b = sample_dual(uSampler1, uTexture1);
return a + b;
}
void main()
{
vec4 c0 = sample_duals();
vec4 c1 = sample_global_tex(uSampler0);
vec4 c2 = sample_global_tex(uSampler1);
vec4 c3 = sample_global_sampler(uTexture0);
vec4 c4 = sample_global_sampler(uTexture1);
FragColor = c0 + c1 + c2 + c3 + c4;
}

View File

@ -0,0 +1,103 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 2
; Bound: 63
; Schema: 0
OpCapability Shader
OpCapability SampledBuffer
OpCapability ImageBuffer
%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 %storeTemp "storeTemp"
OpName %RWIm "RWIm"
OpName %v "v"
OpName %RWBuf "RWBuf"
OpName %ROIm "ROIm"
OpName %ROBuf "ROBuf"
OpName %_entryPointOutput "@entryPointOutput"
OpDecorate %RWIm DescriptorSet 0
OpDecorate %RWIm Binding 1
OpDecorate %RWBuf DescriptorSet 0
OpDecorate %RWBuf Binding 0
OpDecorate %ROIm DescriptorSet 0
OpDecorate %ROIm Binding 1
OpDecorate %ROBuf DescriptorSet 0
OpDecorate %ROBuf Binding 0
OpDecorate %_entryPointOutput Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%8 = OpTypeFunction %v4float
%_ptr_Function_v4float = OpTypePointer Function %v4float
%float_10 = OpConstant %float 10
%float_0_5 = OpConstant %float 0.5
%float_8 = OpConstant %float 8
%float_2 = OpConstant %float 2
%17 = OpConstantComposite %v4float %float_10 %float_0_5 %float_8 %float_2
%18 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
%RWIm = OpVariable %_ptr_UniformConstant_18 UniformConstant
%uint = OpTypeInt 32 0
%v2uint = OpTypeVector %uint 2
%uint_10 = OpConstant %uint 10
%25 = OpConstantComposite %v2uint %uint_10 %uint_10
%uint_30 = OpConstant %uint 30
%30 = OpConstantComposite %v2uint %uint_30 %uint_30
%32 = OpTypeImage %float Buffer 0 0 0 2 Rgba32f
%_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32
%RWBuf = OpVariable %_ptr_UniformConstant_32 UniformConstant
%uint_80 = OpConstant %uint 80
%38 = OpTypeImage %float 2D 0 0 0 1 Unknown
%SampledImage = OpTypeSampledImage %38
%_ptr_UniformConstant_38 = OpTypePointer UniformConstant %SampledImage
%ROIm = OpVariable %_ptr_UniformConstant_38 UniformConstant
%uint_50 = OpConstant %uint 50
%uint_60 = OpConstant %uint 60
%44 = OpConstantComposite %v2uint %uint_50 %uint_60
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%50 = OpTypeImage %float Buffer 0 0 0 1 Rgba32f
%_ptr_UniformConstant_50 = OpTypePointer UniformConstant %50
%ROBuf = OpVariable %_ptr_UniformConstant_50 UniformConstant
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %3
%5 = OpLabel
%62 = OpFunctionCall %v4float %_main_
OpStore %_entryPointOutput %62
OpReturn
OpFunctionEnd
%_main_ = OpFunction %v4float None %8
%10 = OpLabel
%storeTemp = OpVariable %_ptr_Function_v4float Function
%v = OpVariable %_ptr_Function_v4float Function
OpStore %storeTemp %17
%21 = OpLoad %18 %RWIm
%26 = OpLoad %v4float %storeTemp
OpImageWrite %21 %25 %26
%28 = OpLoad %18 %RWIm
%31 = OpImageRead %v4float %28 %30
OpStore %v %31
%35 = OpLoad %32 %RWBuf
%37 = OpLoad %v4float %v
OpImageWrite %35 %uint_80 %37
%41 = OpLoad %SampledImage %ROIm
%ROImage = OpImage %38 %41
%47 = OpImageFetch %v4float %ROImage %44 Lod %int_0
%48 = OpLoad %v4float %v
%49 = OpFAdd %v4float %48 %47
OpStore %v %49
%53 = OpLoad %50 %ROBuf
%54 = OpImageFetch %v4float %53 %uint_80
%55 = OpLoad %v4float %v
%56 = OpFAdd %v4float %55 %54
OpStore %v %56
%57 = OpLoad %v4float %v
OpReturnValue %57
OpFunctionEnd

View File

@ -0,0 +1,10 @@
#version 450
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) + subpassLoad(uSubpass0, gl_SampleID);
}

View File

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

View File

@ -0,0 +1,16 @@
#version 310 es
precision mediump float;
layout(push_constant, std430) uniform PushConstants
{
vec4 value0;
vec4 value1;
} push;
layout(location = 0) in vec4 vColor;
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = vColor + push.value0 + push.value1;
}

View File

@ -0,0 +1,42 @@
#version 310 es
precision mediump float;
layout(set = 0, binding = 0) uniform mediump sampler uSampler;
layout(set = 0, binding = 1) uniform mediump texture2D uTexture[4];
layout(set = 0, binding = 2) uniform mediump texture3D uTexture3D[4];
layout(set = 0, binding = 3) uniform mediump textureCube uTextureCube[4];
layout(set = 0, binding = 4) uniform mediump texture2DArray uTextureArray[4];
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 vTex;
layout(location = 1) in vec3 vTex3;
vec4 sample_func(mediump sampler samp, vec2 uv)
{
return texture(sampler2D(uTexture[2], samp), uv);
}
vec4 sample_func_dual(mediump sampler samp, mediump texture2D tex, vec2 uv)
{
return texture(sampler2D(tex, samp), uv);
}
vec4 sample_func_dual_array(mediump sampler samp, mediump texture2D tex[4], vec2 uv)
{
return texture(sampler2D(tex[1], samp), uv);
}
void main()
{
vec2 off = 1.0 / vec2(textureSize(sampler2D(uTexture[1], uSampler), 0));
vec2 off2 = 1.0 / vec2(textureSize(sampler2D(uTexture[2], uSampler), 1));
vec4 c0 = sample_func(uSampler, vTex + off + off2);
vec4 c1 = sample_func_dual(uSampler, uTexture[1], vTex + off + off2);
vec4 c2 = sample_func_dual_array(uSampler, uTexture, vTex + off + off2);
vec4 c3 = texture(sampler2DArray(uTextureArray[3], uSampler), vTex3);
vec4 c4 = texture(samplerCube(uTextureCube[1], uSampler), vTex3);
vec4 c5 = texture(sampler3D(uTexture3D[2], uSampler), vTex3);
FragColor = c0 + c1 + c2 + c3 + c4 + c5;
}

View File

@ -0,0 +1,78 @@
#version 310 es
precision mediump float;
layout(location = 0) out vec4 FragColor;
layout(constant_id = 1) const float a = 1.5;
layout(constant_id = 2) const float b = 2.5;
layout(constant_id = 3) const int c = 3;
layout(constant_id = 4) const int d = 4;
layout(constant_id = 5) const uint e = 5u;
layout(constant_id = 6) const uint f = 6u;
layout(constant_id = 7) const bool g = false;
layout(constant_id = 8) const bool h = true;
// glslang doesn't seem to support partial spec constants or composites yet, so only test the basics.
struct Foo
{
float elems[d + 2];
};
void main()
{
float t0 = a;
float t1 = b;
uint c0 = uint(c); // OpIAdd with different types.
// FConvert, float-to-double.
int c1 = -c; // SNegate
int c2 = ~c; // OpNot
int c3 = c + d; // OpIAdd
int c4 = c - d; // OpISub
int c5 = c * d; // OpIMul
int c6 = c / d; // OpSDiv
uint c7 = e / f; // OpUDiv
int c8 = c % d; // OpSMod
uint c9 = e % f; // OpUMod
// TODO: OpSRem, any way to access this in GLSL?
int c10 = c >> d; // OpShiftRightArithmetic
uint c11 = e >> f; // OpShiftRightLogical
int c12 = c << d; // OpShiftLeftLogical
int c13 = c | d; // OpBitwiseOr
int c14 = c ^ d; // OpBitwiseXor
int c15 = c & d; // OpBitwiseAnd
// VectorShuffle, CompositeExtract, CompositeInsert, not testable atm.
bool c16 = g || h; // OpLogicalOr
bool c17 = g && h; // OpLogicalAnd
bool c18 = !g; // OpLogicalNot
bool c19 = g == h; // OpLogicalEqual
bool c20 = g != h; // OpLogicalNotEqual
// OpSelect not testable atm.
bool c21 = c == d; // OpIEqual
bool c22 = c != d; // OpINotEqual
bool c23 = c < d; // OpSLessThan
bool c24 = e < f; // OpULessThan
bool c25 = c > d; // OpSGreaterThan
bool c26 = e > f; // OpUGreaterThan
bool c27 = c <= d; // OpSLessThanEqual
bool c28 = e <= f; // OpULessThanEqual
bool c29 = c >= d; // OpSGreaterThanEqual
bool c30 = e >= f; // OpUGreaterThanEqual
// OpQuantizeToF16 not testable atm.
int c31 = c8 + c3;
int c32 = int(e); // OpIAdd with different types.
bool c33 = bool(c); // int -> bool
bool c34 = bool(e); // uint -> bool
int c35 = int(g); // bool -> int
uint c36 = uint(g); // bool -> uint
float c37 = float(g); // bool -> float
// Flexible sized arrays with spec constants and spec constant ops.
float vec0[c + 3][8];
float vec1[c + 2];
Foo foo;
FragColor = vec4(t0 + t1) + vec0[0][0] + vec1[0] + foo.elems[c];
}

View File

@ -0,0 +1,20 @@
#version 310 es
layout(location = 0) in highp vec4 a_position;
layout(location = 0) out mediump float v_vtxResult;
layout(set = 0, binding = 0, std140, row_major) uniform Block
{
highp mat2x3 var[3][4];
};
mediump float compare_float (highp float a, highp float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }
mediump float compare_vec3 (highp vec3 a, highp vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }
mediump float compare_mat2x3 (highp mat2x3 a, highp mat2x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }
void main (void)
{
gl_Position = a_position;
mediump float result = 1.0;
result *= compare_mat2x3(var[0][0], mat2x3(2.0, 6.0, -6.0, 0.0, 5.0, 5.0));
v_vtxResult = result;
}

View File

@ -0,0 +1,10 @@
#version 310 es
#extension GL_OES_texture_buffer : require
layout(binding = 4) uniform highp samplerBuffer uSamp;
layout(rgba32f, binding = 5) uniform readonly highp imageBuffer uSampo;
void main()
{
gl_Position = texelFetch(uSamp, 10) + imageLoad(uSampo, 100);
}

View File

@ -0,0 +1,45 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 28
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %vIndex %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource ESSL 310
OpName %main "main"
OpName %vIndex "vIndex"
OpName %FragColor "FragColor"
OpDecorate %vIndex RelaxedPrecision
OpDecorate %vIndex Flat
OpDecorate %vIndex Location 0
OpDecorate %13 RelaxedPrecision
OpDecorate %FragColor RelaxedPrecision
OpDecorate %FragColor Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%float_8 = OpConstant %float 8
%int = OpTypeInt 32 1
%_ptr_Input_int = OpTypePointer Input %int
%vIndex = OpVariable %_ptr_Input_int Input
%float_1 = OpConstant %float 1
%float_3 = OpConstant %float 3
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%13 = OpLoad %int %vIndex
OpSelectionMerge %17 None
OpSwitch %13 %15 0 %14 2 %14 1 %15 8 %17
%15 = OpLabel
OpBranch %17
%14 = OpLabel
OpBranch %17
%17 = OpLabel
%27 = OpPhi %float %float_3 %15 %float_1 %14 %float_8 %5
OpStore %FragColor %27
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,71 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 44
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %vUV %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %sample_combined_ "sample_combined("
OpName %sample_separate_ "sample_separate("
OpName %uShadow "uShadow"
OpName %vUV "vUV"
OpName %uTexture "uTexture"
OpName %uSampler "uSampler"
OpName %FragColor "FragColor"
OpDecorate %uShadow DescriptorSet 0
OpDecorate %uShadow Binding 0
OpDecorate %vUV Location 0
OpDecorate %uTexture DescriptorSet 0
OpDecorate %uTexture Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 2
OpDecorate %FragColor Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%12 = OpTypeImage %float 2D 2 0 0 1 Unknown
%13 = OpTypeSampledImage %12
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%vUV = OpVariable %_ptr_Input_v3float Input
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
%uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
%29 = OpTypeSampler
%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
%uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%41 = OpFunctionCall %float %sample_combined_
%42 = OpFunctionCall %float %sample_separate_
%43 = OpFAdd %float %41 %42
OpStore %FragColor %43
OpReturn
OpFunctionEnd
%sample_combined_ = OpFunction %float None %7
%9 = OpLabel
%16 = OpLoad %13 %uShadow
%20 = OpLoad %v3float %vUV
%21 = OpCompositeExtract %float %20 2
%22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
OpReturnValue %22
OpFunctionEnd
%sample_separate_ = OpFunction %float None %7
%11 = OpLabel
%28 = OpLoad %12 %uTexture
%32 = OpLoad %29 %uSampler
%33 = OpSampledImage %13 %28 %32
%34 = OpLoad %v3float %vUV
%35 = OpCompositeExtract %float %34 2
%36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
OpReturnValue %36
OpFunctionEnd

View File

@ -0,0 +1,130 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 74
; Schema: 0
OpCapability Geometry
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Geometry %main "main" %stream_pos %stream_layer %input_pos
OpExecutionMode %main Triangles
OpExecutionMode %main Invocations 1
OpExecutionMode %main OutputTriangleStrip
OpExecutionMode %main OutputVertices 3
OpSource HLSL 500
OpName %main "main"
OpName %VertexOutput "VertexOutput"
OpMemberName %VertexOutput 0 "pos"
OpName %GeometryOutput "GeometryOutput"
OpMemberName %GeometryOutput 0 "pos"
OpMemberName %GeometryOutput 1 "layer"
OpName %_main_struct_VertexOutput_vf41_3__struct_GeometryOutput_vf4_u11_ "@main(struct-VertexOutput-vf41[3];struct-GeometryOutput-vf4-u11;"
OpName %input "input"
OpName %stream "stream"
OpName %output "output"
OpName %v "v"
OpName %stream_pos "stream.pos"
OpName %stream_layer "stream.layer"
OpName %input_0 "input"
OpName %input_pos "input.pos"
OpName %stream_0 "stream"
OpName %param "param"
OpName %param_0 "param"
OpDecorate %stream_pos BuiltIn Position
OpDecorate %stream_layer BuiltIn Layer
OpDecorate %input_pos BuiltIn Position
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%VertexOutput = OpTypeStruct %v4float
%uint = OpTypeInt 32 0
%uint_3 = OpConstant %uint 3
%_arr_VertexOutput_uint_3 = OpTypeArray %VertexOutput %uint_3
%_ptr_Function__arr_VertexOutput_uint_3 = OpTypePointer Function %_arr_VertexOutput_uint_3
%GeometryOutput = OpTypeStruct %v4float %uint
%_ptr_Function_GeometryOutput = OpTypePointer Function %GeometryOutput
%15 = OpTypeFunction %void %_ptr_Function__arr_VertexOutput_uint_3 %_ptr_Function_GeometryOutput
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%uint_1 = OpConstant %uint 1
%_ptr_Function_uint = OpTypePointer Function %uint
%_ptr_Function_int = OpTypePointer Function %int
%int_0 = OpConstant %int 0
%int_3 = OpConstant %int 3
%bool = OpTypeBool
%_ptr_Function_v4float = OpTypePointer Function %v4float
%_ptr_Output_v4float = OpTypePointer Output %v4float
%stream_pos = OpVariable %_ptr_Output_v4float Output
%_ptr_Output_uint = OpTypePointer Output %uint
%stream_layer = OpVariable %_ptr_Output_uint Output
%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
%_ptr_Input__arr_v4float_uint_3 = OpTypePointer Input %_arr_v4float_uint_3
%input_pos = OpVariable %_ptr_Input__arr_v4float_uint_3 Input
%_ptr_Input_v4float = OpTypePointer Input %v4float
%int_2 = OpConstant %int 2
%main = OpFunction %void None %3
%5 = OpLabel
%input_0 = OpVariable %_ptr_Function__arr_VertexOutput_uint_3 Function
%stream_0 = OpVariable %_ptr_Function_GeometryOutput Function
%param = OpVariable %_ptr_Function__arr_VertexOutput_uint_3 Function
%param_0 = OpVariable %_ptr_Function_GeometryOutput Function
%58 = OpAccessChain %_ptr_Input_v4float %input_pos %int_0
%59 = OpLoad %v4float %58
%60 = OpAccessChain %_ptr_Function_v4float %input_0 %int_0 %int_0
OpStore %60 %59
%61 = OpAccessChain %_ptr_Input_v4float %input_pos %int_1
%62 = OpLoad %v4float %61
%63 = OpAccessChain %_ptr_Function_v4float %input_0 %int_1 %int_0
OpStore %63 %62
%65 = OpAccessChain %_ptr_Input_v4float %input_pos %int_2
%66 = OpLoad %v4float %65
%67 = OpAccessChain %_ptr_Function_v4float %input_0 %int_2 %int_0
OpStore %67 %66
%70 = OpLoad %_arr_VertexOutput_uint_3 %input_0
OpStore %param %70
%72 = OpFunctionCall %void %_main_struct_VertexOutput_vf41_3__struct_GeometryOutput_vf4_u11_ %param %param_0
%73 = OpLoad %GeometryOutput %param_0
OpStore %stream_0 %73
OpReturn
OpFunctionEnd
%_main_struct_VertexOutput_vf41_3__struct_GeometryOutput_vf4_u11_ = OpFunction %void None %15
%input = OpFunctionParameter %_ptr_Function__arr_VertexOutput_uint_3
%stream = OpFunctionParameter %_ptr_Function_GeometryOutput
%19 = OpLabel
%output = OpVariable %_ptr_Function_GeometryOutput Function
%v = OpVariable %_ptr_Function_int Function
%25 = OpAccessChain %_ptr_Function_uint %output %int_1
OpStore %25 %uint_1
OpStore %v %int_0
OpBranch %29
%29 = OpLabel
OpLoopMerge %31 %32 None
OpBranch %33
%33 = OpLabel
%34 = OpLoad %int %v
%37 = OpSLessThan %bool %34 %int_3
OpBranchConditional %37 %30 %31
%30 = OpLabel
%38 = OpLoad %int %v
%40 = OpAccessChain %_ptr_Function_v4float %input %38 %int_0
%41 = OpLoad %v4float %40
%42 = OpAccessChain %_ptr_Function_v4float %output %int_0
OpStore %42 %41
%45 = OpAccessChain %_ptr_Function_v4float %output %int_0
%46 = OpLoad %v4float %45
OpStore %stream_pos %46
%49 = OpAccessChain %_ptr_Function_uint %output %int_1
%50 = OpLoad %uint %49
OpStore %stream_layer %50
OpEmitVertex
OpBranch %32
%32 = OpLabel
%51 = OpLoad %int %v
%52 = OpIAdd %int %51 %int_1
OpStore %v %52
OpBranch %29
%31 = OpLabel
OpEndPrimitive
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,65 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 36
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %vid_1 %iid_1 %_entryPointOutput
OpSource HLSL 500
OpName %main "main"
OpName %_main_u1_u1_ "@main(u1;u1;"
OpName %vid "vid"
OpName %iid "iid"
OpName %vid_0 "vid"
OpName %vid_1 "vid"
OpName %iid_0 "iid"
OpName %iid_1 "iid"
OpName %_entryPointOutput "@entryPointOutput"
OpName %param "param"
OpName %param_0 "param"
OpDecorate %vid_1 BuiltIn VertexIndex
OpDecorate %iid_1 BuiltIn InstanceIndex
OpDecorate %_entryPointOutput BuiltIn Position
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%_ptr_Function_uint = OpTypePointer Function %uint
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%10 = OpTypeFunction %v4float %_ptr_Function_uint %_ptr_Function_uint
%_ptr_Input_uint = OpTypePointer Input %uint
%vid_1 = OpVariable %_ptr_Input_uint Input
%iid_1 = OpVariable %_ptr_Input_uint Input
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %3
%5 = OpLabel
%vid_0 = OpVariable %_ptr_Function_uint Function
%iid_0 = OpVariable %_ptr_Function_uint Function
%param = OpVariable %_ptr_Function_uint Function
%param_0 = OpVariable %_ptr_Function_uint Function
%25 = OpLoad %uint %vid_1
OpStore %vid_0 %25
%28 = OpLoad %uint %iid_1
OpStore %iid_0 %28
%32 = OpLoad %uint %vid_0
OpStore %param %32
%34 = OpLoad %uint %iid_0
OpStore %param_0 %34
%35 = OpFunctionCall %v4float %_main_u1_u1_ %param %param_0
OpStore %_entryPointOutput %35
OpReturn
OpFunctionEnd
%_main_u1_u1_ = OpFunction %v4float None %10
%vid = OpFunctionParameter %_ptr_Function_uint
%iid = OpFunctionParameter %_ptr_Function_uint
%14 = OpLabel
%15 = OpLoad %uint %vid
%16 = OpLoad %uint %iid
%17 = OpIAdd %uint %15 %16
%18 = OpConvertUToF %float %17
%19 = OpCompositeConstruct %v4float %18 %18 %18 %18
OpReturnValue %19
OpFunctionEnd

View File

@ -0,0 +1,9 @@
#version 450
layout(location = 0) out float FragColor;
layout(constant_id = 0) const uint s = 10u;
const uint f = s > 20u ? 30u : 50u;
void main()
{
FragColor = float(f);
}

View File

@ -578,6 +578,15 @@ struct SPIRBlock : IVariant
MergeSelection
};
enum Hints
{
HintNone,
HintUnroll,
HintDontUnroll,
HintFlatten,
HintDontFlatten
};
enum Method
{
MergeToSelectForLoop,
@ -610,6 +619,7 @@ struct SPIRBlock : IVariant
Terminator terminator = Unknown;
Merge merge = MergeNone;
Hints hint = HintNone;
uint32_t next_block = 0;
uint32_t merge_block = 0;
uint32_t continue_block = 0;

View File

@ -1063,6 +1063,34 @@ const SPIRType &Compiler::get_type_from_variable(uint32_t id) const
return get<SPIRType>(get<SPIRVariable>(id).basetype);
}
uint32_t Compiler::get_non_pointer_type_id(uint32_t type_id) const
{
auto *p_type = &get<SPIRType>(type_id);
while (p_type->pointer)
{
assert(p_type->parent_type);
type_id = p_type->parent_type;
p_type = &get<SPIRType>(type_id);
}
return type_id;
}
const SPIRType &Compiler::get_non_pointer_type(const SPIRType &type) const
{
auto *p_type = &type;
while (p_type->pointer)
{
assert(p_type->parent_type);
p_type = &get<SPIRType>(p_type->parent_type);
}
return *p_type;
}
const SPIRType &Compiler::get_non_pointer_type(uint32_t type_id) const
{
return get_non_pointer_type(get<SPIRType>(type_id));
}
void Compiler::set_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration,
const std::string &argument)
{
@ -1814,7 +1842,7 @@ void Compiler::parse(const Instruction &instruction)
type.basetype = SPIRType::Image;
type.image.type = ops[1];
type.image.dim = static_cast<Dim>(ops[2]);
type.image.depth = ops[3] != 0;
type.image.depth = ops[3] == 1;
type.image.arrayed = ops[4] != 0;
type.image.ms = ops[5] != 0;
type.image.sampled = ops[6];
@ -2221,6 +2249,14 @@ void Compiler::parse(const Instruction &instruction)
current_block->next_block = ops[0];
current_block->merge = SPIRBlock::MergeSelection;
selection_merge_targets.insert(current_block->next_block);
if (length >= 2)
{
if (ops[1] & SelectionControlFlattenMask)
current_block->hint = SPIRBlock::HintFlatten;
else if (ops[1] & SelectionControlDontFlattenMask)
current_block->hint = SPIRBlock::HintDontFlatten;
}
break;
}
@ -2243,6 +2279,14 @@ void Compiler::parse(const Instruction &instruction)
// they are treated as continues.
if (current_block->continue_block != current_block->self)
continue_blocks.insert(current_block->continue_block);
if (length >= 3)
{
if (ops[2] & LoopControlUnrollMask)
current_block->hint = SPIRBlock::HintUnroll;
else if (ops[2] & LoopControlDontUnrollMask)
current_block->hint = SPIRBlock::HintDontUnroll;
}
break;
}
@ -4243,14 +4287,8 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args
// Required if we access chain into builtins like gl_GlobalInvocationID.
add_if_builtin(args[2]);
auto *type = &compiler.get<SPIRType>(var->basetype);
// Start traversing type hierarchy at the proper non-pointer types.
while (type->pointer)
{
assert(type->parent_type);
type = &compiler.get<SPIRType>(type->parent_type);
}
auto *type = &compiler.get_non_pointer_type(var->basetype);
auto &flags =
type->storage == StorageClassInput ? compiler.active_input_builtins : compiler.active_output_builtins;
@ -4329,11 +4367,43 @@ bool Compiler::has_active_builtin(BuiltIn builtin, StorageClass storage)
void Compiler::analyze_image_and_sampler_usage()
{
CombinedImageSamplerUsageHandler handler(*this);
CombinedImageSamplerDrefHandler dref_handler(*this);
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), dref_handler);
CombinedImageSamplerUsageHandler handler(*this, dref_handler.dref_combined_samplers);
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), handler);
comparison_samplers = move(handler.comparison_samplers);
comparison_images = move(handler.comparison_images);
comparison_ids = move(handler.comparison_ids);
need_subpass_input = handler.need_subpass_input;
// Forward information from separate images and samplers into combined image samplers.
for (auto &combined : combined_image_samplers)
if (comparison_ids.count(combined.sampler_id))
comparison_ids.insert(combined.combined_id);
}
bool Compiler::CombinedImageSamplerDrefHandler::handle(spv::Op opcode, const uint32_t *args, uint32_t)
{
// Mark all sampled images which are used with Dref.
switch (opcode)
{
case OpImageSampleDrefExplicitLod:
case OpImageSampleDrefImplicitLod:
case OpImageSampleProjDrefExplicitLod:
case OpImageSampleProjDrefImplicitLod:
case OpImageSparseSampleProjDrefImplicitLod:
case OpImageSparseSampleDrefImplicitLod:
case OpImageSparseSampleProjDrefExplicitLod:
case OpImageSparseSampleDrefExplicitLod:
case OpImageDrefGather:
case OpImageSparseDrefGather:
dref_combined_samplers.insert(args[2]);
return true;
default:
break;
}
return true;
}
bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint32_t *args, uint32_t length)
@ -4354,20 +4424,12 @@ bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint
return true;
}
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_images(uint32_t image)
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_ids(uint32_t id)
{
// Traverse the variable dependency hierarchy and tag everything in its path with comparison images.
comparison_images.insert(image);
for (auto &img : dependency_hierarchy[image])
add_hierarchy_to_comparison_images(img);
}
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_samplers(uint32_t sampler)
{
// Traverse the variable dependency hierarchy and tag everything in its path with comparison samplers.
comparison_samplers.insert(sampler);
for (auto &samp : dependency_hierarchy[sampler])
add_hierarchy_to_comparison_samplers(samp);
// Traverse the variable dependency hierarchy and tag everything in its path with comparison ids.
comparison_ids.insert(id);
for (auto &dep_id : dependency_hierarchy[id])
add_hierarchy_to_comparison_ids(dep_id);
}
bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
@ -4387,6 +4449,10 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
auto &type = compiler.get<SPIRType>(args[0]);
if (type.image.dim == DimSubpassData)
need_subpass_input = true;
// If we load a SampledImage and it will be used with Dref, propagate the state up.
if (dref_combined_samplers.count(args[1]) != 0)
add_hierarchy_to_comparison_ids(args[1]);
break;
}
@ -4396,16 +4462,20 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
return false;
uint32_t result_type = args[0];
uint32_t result_id = args[1];
auto &type = compiler.get<SPIRType>(result_type);
if (type.image.depth)
if (type.image.depth || dref_combined_samplers.count(result_id) != 0)
{
// This image must be a depth image.
uint32_t image = args[2];
add_hierarchy_to_comparison_images(image);
add_hierarchy_to_comparison_ids(image);
// This sampler must be a SamplerComparisionState, and not a regular SamplerState.
// This sampler must be a SamplerComparisonState, and not a regular SamplerState.
uint32_t sampler = args[3];
add_hierarchy_to_comparison_samplers(sampler);
add_hierarchy_to_comparison_ids(sampler);
// Mark the OpSampledImage itself as being comparison state.
comparison_ids.insert(result_id);
}
return true;
}
@ -4567,3 +4637,57 @@ bool Compiler::instruction_to_result_type(uint32_t &result_type, uint32_t &resul
return false;
}
}
Bitset Compiler::combined_decoration_for_member(const SPIRType &type, uint32_t index) const
{
Bitset flags;
auto &memb = meta[type.self].members;
if (index >= memb.size())
return flags;
auto &dec = memb[index];
// If our type is a struct, traverse all the members as well recursively.
flags.merge_or(dec.decoration_flags);
for (uint32_t i = 0; i < type.member_types.size(); i++)
flags.merge_or(combined_decoration_for_member(get<SPIRType>(type.member_types[i]), i));
return flags;
}
bool Compiler::is_desktop_only_format(spv::ImageFormat format)
{
switch (format)
{
// Desktop-only formats
case ImageFormatR11fG11fB10f:
case ImageFormatR16f:
case ImageFormatRgb10A2:
case ImageFormatR8:
case ImageFormatRg8:
case ImageFormatR16:
case ImageFormatRg16:
case ImageFormatRgba16:
case ImageFormatR16Snorm:
case ImageFormatRg16Snorm:
case ImageFormatRgba16Snorm:
case ImageFormatR8Snorm:
case ImageFormatRg8Snorm:
case ImageFormatR8ui:
case ImageFormatRg8ui:
case ImageFormatR16ui:
case ImageFormatRgb10a2ui:
case ImageFormatR8i:
case ImageFormatRg8i:
case ImageFormatR16i:
return true;
default:
break;
}
return false;
}
bool Compiler::image_is_comparison(const spirv_cross::SPIRType &type, uint32_t id) const
{
return type.image.depth || (comparison_ids.count(id) != 0);
}

View File

@ -170,6 +170,15 @@ public:
// Gets the SPIR-V type of a variable.
const SPIRType &get_type_from_variable(uint32_t id) const;
// Gets the id of SPIR-V type underlying the given type_id, which might be a pointer.
uint32_t get_non_pointer_type_id(uint32_t type_id) const;
// Gets the SPIR-V type underlying the given type, which might be a pointer.
const SPIRType &get_non_pointer_type(const SPIRType &type) const;
// Gets the SPIR-V type underlying the given type_id, which might be a pointer.
const SPIRType &get_non_pointer_type(uint32_t type_id) const;
// Gets the underlying storage class for an OpVariable.
spv::StorageClass get_storage_class(uint32_t id) const;
@ -817,8 +826,7 @@ protected:
// There might be unrelated IDs found in this set which do not correspond to actual variables.
// This set should only be queried for the existence of samplers which are already known to be variables or parameter IDs.
// Similar is implemented for images, as well as if subpass inputs are needed.
std::unordered_set<uint32_t> comparison_samplers;
std::unordered_set<uint32_t> comparison_images;
std::unordered_set<uint32_t> comparison_ids;
bool need_subpass_input = false;
// In certain backends, we will need to use a dummy sampler to be able to emit code.
@ -827,23 +835,37 @@ protected:
uint32_t dummy_sampler_id = 0;
void analyze_image_and_sampler_usage();
struct CombinedImageSamplerDrefHandler : OpcodeHandler
{
CombinedImageSamplerDrefHandler(Compiler &compiler_)
: compiler(compiler_)
{
}
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
Compiler &compiler;
std::unordered_set<uint32_t> dref_combined_samplers;
};
struct CombinedImageSamplerUsageHandler : OpcodeHandler
{
CombinedImageSamplerUsageHandler(Compiler &compiler_)
CombinedImageSamplerUsageHandler(Compiler &compiler_,
const std::unordered_set<uint32_t> &dref_combined_samplers_)
: compiler(compiler_)
, dref_combined_samplers(dref_combined_samplers_)
{
}
bool begin_function_scope(const uint32_t *args, uint32_t length) override;
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
Compiler &compiler;
const std::unordered_set<uint32_t> &dref_combined_samplers;
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> dependency_hierarchy;
std::unordered_set<uint32_t> comparison_images;
std::unordered_set<uint32_t> comparison_samplers;
std::unordered_set<uint32_t> comparison_ids;
void add_hierarchy_to_comparison_samplers(uint32_t sampler);
void add_hierarchy_to_comparison_images(uint32_t sampler);
void add_hierarchy_to_comparison_ids(uint32_t ids);
bool need_subpass_input = false;
};
@ -856,6 +878,11 @@ protected:
bool instruction_to_result_type(uint32_t &result_type, uint32_t &result_id, spv::Op op, const uint32_t *args,
uint32_t length);
Bitset combined_decoration_for_member(const SPIRType &type, uint32_t index) const;
static bool is_desktop_only_format(spv::ImageFormat format);
bool image_is_comparison(const SPIRType &type, uint32_t id) const;
private:
// Used only to implement the old deprecated get_entry_point() interface.
const SPIREntryPoint &get_first_entry_point(const std::string &name) const;

File diff suppressed because it is too large Load Diff

View File

@ -105,6 +105,11 @@ public:
// Inverts gl_Position.y or equivalent.
bool flip_vert_y = false;
// If true, the backend will assume that InstanceIndex will need to apply
// a base instance offset. Set to false if you know you will never use base instance
// functionality as it might remove some internal uniforms.
bool support_nonzero_base_instance = true;
} vertex;
struct
@ -276,7 +281,6 @@ protected:
{
for (uint32_t i = 0; i < indent; i++)
(*buffer) << " ";
statement_inner(std::forward<Ts>(ts)...);
(*buffer) << '\n';
}
@ -404,6 +408,9 @@ protected:
SPIRType binary_op_bitcast_helper(std::string &cast_op0, std::string &cast_op1, SPIRType::BaseType &input_type,
uint32_t op0, uint32_t op1, bool skip_cast_if_equal_type);
std::string to_ternary_expression(const SPIRType &result_type, uint32_t select, uint32_t true_value,
uint32_t false_value);
void emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op);
bool expression_is_forwarded(uint32_t id);
SPIRExpression &emit_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs,
@ -451,11 +458,11 @@ protected:
const char *format_to_glsl(spv::ImageFormat format);
virtual std::string layout_for_member(const SPIRType &type, uint32_t index);
virtual std::string to_interpolation_qualifiers(const Bitset &flags);
Bitset combined_decoration_for_member(const SPIRType &type, uint32_t index);
std::string layout_for_variable(const SPIRVariable &variable);
std::string to_combined_image_sampler(uint32_t image_id, uint32_t samp_id);
virtual bool skip_argument(uint32_t id) const;
virtual void emit_array_copy(const std::string &lhs, uint32_t rhs_id);
virtual void emit_block_hints(const SPIRBlock &block);
bool buffer_is_packing_standard(const SPIRType &type, BufferPackingStandard packing, uint32_t start_offset = 0,
uint32_t end_offset = std::numeric_limits<uint32_t>::max());
@ -484,7 +491,7 @@ protected:
void replace_fragment_output(SPIRVariable &var);
void replace_fragment_outputs();
bool check_explicit_lod_allowed(uint32_t lod);
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod);
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t id);
uint32_t indent = 0;
@ -562,6 +569,12 @@ protected:
std::string convert_separate_image_to_combined(uint32_t id);
// Builtins in GLSL are always specific signedness, but the SPIR-V can declare them
// as either unsigned or signed.
// Sometimes we will need to automatically perform bitcasts on load and store to make this work.
virtual void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type);
virtual void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type);
private:
void init()
{

View File

@ -224,7 +224,7 @@ static bool hlsl_opcode_is_sign_invariant(Op opcode)
}
}
string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type, uint32_t)
{
auto &imagetype = get<SPIRType>(type.image.type);
const char *dim = nullptr;
@ -275,7 +275,7 @@ string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
">");
}
string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type, uint32_t id)
{
auto &imagetype = get<SPIRType>(type.image.type);
string res;
@ -338,18 +338,18 @@ string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
res += "MS";
if (type.image.arrayed)
res += "Array";
if (type.image.depth)
if (image_is_comparison(type, id))
res += "Shadow";
return res;
}
string CompilerHLSL::image_type_hlsl(const SPIRType &type)
string CompilerHLSL::image_type_hlsl(const SPIRType &type, uint32_t id)
{
if (hlsl_options.shader_model <= 30)
return image_type_hlsl_legacy(type);
return image_type_hlsl_legacy(type, id);
else
return image_type_hlsl_modern(type);
return image_type_hlsl_modern(type, id);
}
// The optional id parameter indicates the object whose type we are trying
@ -370,10 +370,10 @@ string CompilerHLSL::type_to_glsl(const SPIRType &type, uint32_t id)
case SPIRType::Image:
case SPIRType::SampledImage:
return image_type_hlsl(type);
return image_type_hlsl(type, id);
case SPIRType::Sampler:
return comparison_samplers.count(id) ? "SamplerComparisonState" : "SamplerState";
return comparison_ids.count(id) ? "SamplerComparisonState" : "SamplerState";
case SPIRType::Void:
return "void";
@ -1838,9 +1838,10 @@ void CompilerHLSL::emit_buffer_block(const SPIRVariable &var)
{
Bitset flags = get_buffer_block_flags(var);
bool is_readonly = flags.get(DecorationNonWritable);
bool is_coherent = flags.get(DecorationCoherent);
add_resource_name(var.self);
statement(is_readonly ? "ByteAddressBuffer " : "RWByteAddressBuffer ", to_name(var.self),
type_to_array_glsl(type), to_resource_binding(var), ";");
statement(is_coherent ? "globallycoherent " : "", is_readonly ? "ByteAddressBuffer " : "RWByteAddressBuffer ",
to_name(var.self), type_to_array_glsl(type), to_resource_binding(var), ";");
}
else
{
@ -2059,7 +2060,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
{
// Manufacture automatic sampler arg for SampledImage texture
decl += ", ";
decl += join(arg_type.image.depth ? "SamplerComparisonState " : "SamplerState ",
decl += join(image_is_comparison(arg_type, arg.id) ? "SamplerComparisonState " : "SamplerState ",
to_sampler_expression(arg.id), type_to_array_glsl(arg_type));
}
@ -2574,7 +2575,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
{
texop += img_expr;
if (imgtype.image.depth)
if (image_is_comparison(imgtype, img))
{
if (gather)
{
@ -2922,13 +2923,17 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
case SPIRType::SampledImage:
case SPIRType::Image:
{
statement(image_type_hlsl_modern(type), " ", to_name(var.self), type_to_array_glsl(type),
to_resource_binding(var), ";");
bool is_coherent = false;
if (type.basetype == SPIRType::Image && type.image.sampled == 2)
is_coherent = has_decoration(var.self, DecorationCoherent);
statement(is_coherent ? "globallycoherent " : "", image_type_hlsl_modern(type, var.self), " ",
to_name(var.self), type_to_array_glsl(type), to_resource_binding(var), ";");
if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
{
// For combined image samplers, also emit a combined image sampler.
if (type.image.depth)
if (image_is_comparison(type, var.self))
statement("SamplerComparisonState ", to_sampler_expression(var.self), type_to_array_glsl(type),
to_resource_binding_sampler(var), ";");
else
@ -2939,7 +2944,7 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
}
case SPIRType::Sampler:
if (comparison_samplers.count(var.self))
if (comparison_ids.count(var.self))
statement("SamplerComparisonState ", to_name(var.self), type_to_array_glsl(type), to_resource_binding(var),
";");
else
@ -3524,14 +3529,8 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction)
else
base = to_expression(ops[2]);
auto *basetype = &type;
// Start traversing type hierarchy at the proper non-pointer types.
while (basetype->pointer)
{
assert(basetype->parent_type);
basetype = &get<SPIRType>(basetype->parent_type);
}
auto *basetype = &get_non_pointer_type(type);
// Traverse the type hierarchy down to the actual buffer types.
for (uint32_t i = 0; i < to_plain_buffer_length; i++)
@ -3767,7 +3766,7 @@ void CompilerHLSL::emit_subgroup_op(const Instruction &i)
}
// clang-format off
#define GROUP_OP(op, hlsl_op, supports_scan) \
#define HLSL_GROUP_OP(op, hlsl_op, supports_scan) \
case OpGroupNonUniform##op: \
{ \
auto operation = static_cast<GroupOperation>(ops[3]); \
@ -3787,20 +3786,20 @@ case OpGroupNonUniform##op: \
SPIRV_CROSS_THROW("Invalid group operation."); \
break; \
}
GROUP_OP(FAdd, Sum, true)
GROUP_OP(FMul, Product, true)
GROUP_OP(FMin, Min, false)
GROUP_OP(FMax, Max, false)
GROUP_OP(IAdd, Sum, true)
GROUP_OP(IMul, Product, true)
GROUP_OP(SMin, Min, false)
GROUP_OP(SMax, Max, false)
GROUP_OP(UMin, Min, false)
GROUP_OP(UMax, Max, false)
GROUP_OP(BitwiseAnd, BitAnd, false)
GROUP_OP(BitwiseOr, BitOr, false)
GROUP_OP(BitwiseXor, BitXor, false)
#undef GROUP_OP
HLSL_GROUP_OP(FAdd, Sum, true)
HLSL_GROUP_OP(FMul, Product, true)
HLSL_GROUP_OP(FMin, Min, false)
HLSL_GROUP_OP(FMax, Max, false)
HLSL_GROUP_OP(IAdd, Sum, true)
HLSL_GROUP_OP(IMul, Product, true)
HLSL_GROUP_OP(SMin, Min, false)
HLSL_GROUP_OP(SMax, Max, false)
HLSL_GROUP_OP(UMin, Min, false)
HLSL_GROUP_OP(UMax, Max, false)
HLSL_GROUP_OP(BitwiseAnd, BitAnd, false)
HLSL_GROUP_OP(BitwiseOr, BitOr, false)
HLSL_GROUP_OP(BitwiseXor, BitXor, false)
#undef HLSL_GROUP_OP
// clang-format on
case OpGroupNonUniformQuadSwap:
@ -3835,17 +3834,17 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
auto ops = stream(instruction);
auto opcode = static_cast<Op>(instruction.op);
#define BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
#define BOP_CAST(op, type) \
#define HLSL_BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
#define HLSL_BOP_CAST(op, type) \
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, hlsl_opcode_is_sign_invariant(opcode))
#define UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
#define QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define BFOP_CAST(op, type) \
#define HLSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
#define HLSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define HLSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define HLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define HLSL_BFOP_CAST(op, type) \
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, hlsl_opcode_is_sign_invariant(opcode))
#define BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
#define HLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define HLSL_UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
switch (opcode)
{
@ -3914,39 +3913,39 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
}
case OpDPdx:
UFOP(ddx);
HLSL_UFOP(ddx);
register_control_dependent_expression(ops[1]);
break;
case OpDPdy:
UFOP(ddy);
HLSL_UFOP(ddy);
register_control_dependent_expression(ops[1]);
break;
case OpDPdxFine:
UFOP(ddx_fine);
HLSL_UFOP(ddx_fine);
register_control_dependent_expression(ops[1]);
break;
case OpDPdyFine:
UFOP(ddy_fine);
HLSL_UFOP(ddy_fine);
register_control_dependent_expression(ops[1]);
break;
case OpDPdxCoarse:
UFOP(ddx_coarse);
HLSL_UFOP(ddx_coarse);
register_control_dependent_expression(ops[1]);
break;
case OpDPdyCoarse:
UFOP(ddy_coarse);
HLSL_UFOP(ddy_coarse);
register_control_dependent_expression(ops[1]);
break;
case OpFwidth:
case OpFwidthCoarse:
case OpFwidthFine:
UFOP(fwidth);
HLSL_UFOP(fwidth);
register_control_dependent_expression(ops[1]);
break;
@ -3959,7 +3958,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (type.vecsize > 1)
emit_unrolled_unary_op(result_type, id, ops[2], "!");
else
UOP(!);
HLSL_UOP(!);
break;
}
@ -3971,7 +3970,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "==");
else
BOP_CAST(==, SPIRType::Int);
HLSL_BOP_CAST(==, SPIRType::Int);
break;
}
@ -3984,7 +3983,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "==");
else
BOP(==);
HLSL_BOP(==);
break;
}
@ -3996,7 +3995,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "!=");
else
BOP_CAST(!=, SPIRType::Int);
HLSL_BOP_CAST(!=, SPIRType::Int);
break;
}
@ -4009,7 +4008,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "!=");
else
BOP(!=);
HLSL_BOP(!=);
break;
}
@ -4023,7 +4022,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], ">");
else
BOP_CAST(>, type);
HLSL_BOP_CAST(>, type);
break;
}
@ -4035,7 +4034,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], ">");
else
BOP(>);
HLSL_BOP(>);
break;
}
@ -4049,7 +4048,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], ">=");
else
BOP_CAST(>=, type);
HLSL_BOP_CAST(>=, type);
break;
}
@ -4061,7 +4060,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], ">=");
else
BOP(>=);
HLSL_BOP(>=);
break;
}
@ -4075,7 +4074,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "<");
else
BOP_CAST(<, type);
HLSL_BOP_CAST(<, type);
break;
}
@ -4087,7 +4086,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "<");
else
BOP(<);
HLSL_BOP(<);
break;
}
@ -4101,7 +4100,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "<=");
else
BOP_CAST(<=, type);
HLSL_BOP_CAST(<=, type);
break;
}
@ -4113,7 +4112,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
if (expression_type(ops[2]).vecsize > 1)
emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "<=");
else
BOP(<=);
HLSL_BOP(<=);
break;
}
@ -4418,18 +4417,18 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
}
if (opcode == OpBitFieldSExtract)
TFOP(SPIRV_Cross_bitfieldSExtract);
HLSL_TFOP(SPIRV_Cross_bitfieldSExtract);
else
TFOP(SPIRV_Cross_bitfieldUExtract);
HLSL_TFOP(SPIRV_Cross_bitfieldUExtract);
break;
}
case OpBitCount:
UFOP(countbits);
HLSL_UFOP(countbits);
break;
case OpBitReverse:
UFOP(reversebits);
HLSL_UFOP(reversebits);
break;
default:
@ -4605,3 +4604,24 @@ string CompilerHLSL::compile()
return buffer->str();
}
void CompilerHLSL::emit_block_hints(const SPIRBlock &block)
{
switch (block.hint)
{
case SPIRBlock::HintFlatten:
statement("[flatten]");
break;
case SPIRBlock::HintDontFlatten:
statement("[branch]");
break;
case SPIRBlock::HintUnroll:
statement("[unroll]");
break;
case SPIRBlock::HintDontUnroll:
statement("[loop]");
break;
default:
break;
}
}

View File

@ -118,9 +118,9 @@ public:
private:
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string image_type_hlsl(const SPIRType &type);
std::string image_type_hlsl_modern(const SPIRType &type);
std::string image_type_hlsl_legacy(const SPIRType &type);
std::string image_type_hlsl(const SPIRType &type, uint32_t id);
std::string image_type_hlsl_modern(const SPIRType &type, uint32_t id);
std::string image_type_hlsl_legacy(const SPIRType &type, uint32_t id);
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
void emit_hlsl_entry_point();
void emit_header() override;
@ -158,6 +158,7 @@ private:
void emit_store(const Instruction &instruction);
void emit_atomic(const uint32_t *ops, uint32_t length, spv::Op op);
void emit_subgroup_op(const Instruction &i) override;
void emit_block_hints(const SPIRBlock &block) override;
void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, const std::string &qualifier,
uint32_t base_offset = 0) override;

View File

@ -534,19 +534,44 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
// Add the global variables as arguments to the function
if (func_id != entry_point)
{
uint32_t next_id = increase_bound_by(uint32_t(added_arg_ids.size()));
for (uint32_t arg_id : added_arg_ids)
{
auto var = get<SPIRVariable>(arg_id);
auto &var = get<SPIRVariable>(arg_id);
uint32_t type_id = var.basetype;
func.add_parameter(type_id, next_id, true);
set<SPIRVariable>(next_id, type_id, StorageClassFunction, 0, arg_id);
auto *p_type = &get<SPIRType>(type_id);
// Ensure the existing variable has a valid name and the new variable has all the same meta info
set_name(arg_id, ensure_valid_name(to_name(arg_id), "v"));
meta[next_id] = meta[arg_id];
if (is_builtin_variable(var) && p_type->basetype == SPIRType::Struct)
{
// Get the non-pointer type
type_id = get_non_pointer_type_id(type_id);
p_type = &get<SPIRType>(type_id);
next_id++;
uint32_t mbr_idx = 0;
for (auto &mbr_type_id : p_type->member_types)
{
BuiltIn builtin;
bool is_builtin = is_member_builtin(*p_type, mbr_idx, &builtin);
if (is_builtin && has_active_builtin(builtin, var.storage))
{
// Add a arg variable with the same type and decorations as the member
uint32_t next_id = increase_bound_by(1);
func.add_parameter(mbr_type_id, next_id, true);
set<SPIRVariable>(next_id, mbr_type_id, StorageClassFunction);
meta[next_id].decoration = meta[type_id].members[mbr_idx];
}
mbr_idx++;
}
}
else
{
uint32_t next_id = increase_bound_by(1);
func.add_parameter(type_id, next_id, true);
set<SPIRVariable>(next_id, type_id, StorageClassFunction, 0, arg_id);
// Ensure the existing variable has a valid name and the new variable has all the same meta info
set_name(arg_id, ensure_valid_name(to_name(arg_id), "v"));
meta[next_id] = meta[arg_id];
}
}
}
}
@ -1148,6 +1173,18 @@ void CompilerMSL::emit_custom_functions()
statement("");
break;
case SPVFuncImplTexelBufferCoords:
{
string tex_width_str = convert_to_string(msl_options.texel_buffer_texture_width);
statement("// Returns 2D texture coords corresponding to 1D texel buffer coords");
statement("uint2 spvTexelBufferCoord(uint tc)");
begin_scope();
statement(join("return uint2(tc % ", tex_width_str, ", tc / ", tex_width_str, ");"));
end_scope();
statement("");
break;
}
case SPVFuncImplInverse4x4:
statement("// Returns the determinant of a 2x2 matrix.");
statement("inline float spvDet2x2(float a1, float a2, float b1, float b2)");
@ -1506,16 +1543,16 @@ void CompilerMSL::emit_specialization_constants()
void CompilerMSL::emit_instruction(const Instruction &instruction)
{
#define BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
#define BOP_CAST(op, type) \
#define MSL_BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
#define MSL_BOP_CAST(op, type) \
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
#define UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
#define QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define BFOP_CAST(op, type) \
#define MSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
#define MSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define MSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define MSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define MSL_BFOP_CAST(op, type) \
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
#define UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
#define MSL_UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
auto ops = stream(instruction);
auto opcode = static_cast<Op>(instruction.op);
@ -1527,81 +1564,81 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
case OpIEqual:
case OpLogicalEqual:
case OpFOrdEqual:
BOP(==);
MSL_BOP(==);
break;
case OpINotEqual:
case OpLogicalNotEqual:
case OpFOrdNotEqual:
BOP(!=);
MSL_BOP(!=);
break;
case OpUGreaterThan:
case OpSGreaterThan:
case OpFOrdGreaterThan:
BOP(>);
MSL_BOP(>);
break;
case OpUGreaterThanEqual:
case OpSGreaterThanEqual:
case OpFOrdGreaterThanEqual:
BOP(>=);
MSL_BOP(>=);
break;
case OpULessThan:
case OpSLessThan:
case OpFOrdLessThan:
BOP(<);
MSL_BOP(<);
break;
case OpULessThanEqual:
case OpSLessThanEqual:
case OpFOrdLessThanEqual:
BOP(<=);
MSL_BOP(<=);
break;
// Derivatives
case OpDPdx:
case OpDPdxFine:
case OpDPdxCoarse:
UFOP(dfdx);
MSL_UFOP(dfdx);
register_control_dependent_expression(ops[1]);
break;
case OpDPdy:
case OpDPdyFine:
case OpDPdyCoarse:
UFOP(dfdy);
MSL_UFOP(dfdy);
register_control_dependent_expression(ops[1]);
break;
case OpFwidth:
case OpFwidthCoarse:
case OpFwidthFine:
UFOP(fwidth);
MSL_UFOP(fwidth);
register_control_dependent_expression(ops[1]);
break;
// Bitfield
case OpBitFieldInsert:
QFOP(insert_bits);
MSL_QFOP(insert_bits);
break;
case OpBitFieldSExtract:
case OpBitFieldUExtract:
TFOP(extract_bits);
MSL_TFOP(extract_bits);
break;
case OpBitReverse:
UFOP(reverse_bits);
MSL_UFOP(reverse_bits);
break;
case OpBitCount:
UFOP(popcount);
MSL_UFOP(popcount);
break;
case OpFRem:
BFOP(fmod);
MSL_BFOP(fmod);
break;
// Atomics
@ -1654,7 +1691,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
break;
}
#define AFMOImpl(op, valsrc) \
#define MSL_AFMO_IMPL(op, valsrc) \
do \
{ \
uint32_t result_type = ops[0]; \
@ -1665,45 +1702,45 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
emit_atomic_func_op(result_type, id, "atomic_fetch_" #op "_explicit", mem_sem, mem_sem, false, ptr, val); \
} while (false)
#define AFMO(op) AFMOImpl(op, ops[5])
#define AFMIO(op) AFMOImpl(op, 1)
#define MSL_AFMO(op) MSL_AFMO_IMPL(op, ops[5])
#define MSL_AFMIO(op) MSL_AFMO_IMPL(op, 1)
case OpAtomicIIncrement:
AFMIO(add);
MSL_AFMIO(add);
break;
case OpAtomicIDecrement:
AFMIO(sub);
MSL_AFMIO(sub);
break;
case OpAtomicIAdd:
AFMO(add);
MSL_AFMO(add);
break;
case OpAtomicISub:
AFMO(sub);
MSL_AFMO(sub);
break;
case OpAtomicSMin:
case OpAtomicUMin:
AFMO(min);
MSL_AFMO(min);
break;
case OpAtomicSMax:
case OpAtomicUMax:
AFMO(max);
MSL_AFMO(max);
break;
case OpAtomicAnd:
AFMO(and);
MSL_AFMO(and);
break;
case OpAtomicOr:
AFMO(or);
MSL_AFMO(or);
break;
case OpAtomicXor:
AFMO (xor);
MSL_AFMO (xor);
break;
// Images
@ -1827,7 +1864,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
break;
}
#define ImgQry(qrytype) \
#define MSL_ImgQry(qrytype) \
do \
{ \
uint32_t rslt_type_id = ops[0]; \
@ -1840,11 +1877,11 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
} while (false)
case OpImageQueryLevels:
ImgQry(mip_levels);
MSL_ImgQry(mip_levels);
break;
case OpImageQuerySamples:
ImgQry(samples);
MSL_ImgQry(samples);
break;
// Casting
@ -1926,7 +1963,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
e->need_transpose = true;
}
else
BOP(*);
MSL_BOP(*);
break;
}
@ -2429,8 +2466,9 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
if (coord_type.vecsize > 1)
tex_coords += ".x";
// Metal texel buffer textures are 2D, so convert 1D coord to 2D.
if (is_fetch)
tex_coords = "uint2(" + round_fp_tex_coords(tex_coords, coord_is_fp) + ", 0)"; // Metal textures are 2D
tex_coords = "spvTexelBufferCoord(" + round_fp_tex_coords(tex_coords, coord_is_fp) + ")";
alt_coord = ".y";
@ -3553,17 +3591,13 @@ std::string CompilerMSL::sampler_type(const SPIRType &type)
SPIRV_CROSS_THROW("MSL 2.0 or greater is required for arrays of samplers.");
// Arrays of samplers in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
auto *parent = &type;
while (parent->pointer)
parent = &get<SPIRType>(parent->parent_type);
parent = &get<SPIRType>(parent->parent_type);
uint32_t array_size =
type.array_size_literal.back() ? type.array.back() : get<SPIRConstant>(type.array.back()).scalar();
if (array_size == 0)
SPIRV_CROSS_THROW("Unsized array of samplers is not supported in MSL.");
return join("array<", sampler_type(*parent), ", ", array_size, ">");
auto &parent = get<SPIRType>(get_non_pointer_type(type).parent_type);
return join("array<", sampler_type(parent), ", ", array_size, ">");
}
else
return "sampler";
@ -3586,25 +3620,20 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
SPIRV_CROSS_THROW("MSL 2.0 or greater is required for arrays of textures.");
// Arrays of images in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
auto *parent = &type;
while (parent->pointer)
parent = &get<SPIRType>(parent->parent_type);
parent = &get<SPIRType>(parent->parent_type);
uint32_t array_size =
type.array_size_literal.back() ? type.array.back() : get<SPIRConstant>(type.array.back()).scalar();
if (array_size == 0)
SPIRV_CROSS_THROW("Unsized array of images is not supported in MSL.");
return join("array<", image_type_glsl(*parent, id), ", ", array_size, ">");
auto &parent = get<SPIRType>(get_non_pointer_type(type).parent_type);
return join("array<", image_type_glsl(parent, id), ", ", array_size, ">");
}
string img_type_name;
// Bypass pointers because we need the real image struct
auto &img_type = get<SPIRType>(type.self).image;
bool shadow_image = comparison_images.count(id) != 0;
if (img_type.depth || shadow_image)
if (image_is_comparison(type, id))
{
switch (img_type.dim)
{
@ -4035,8 +4064,8 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
auto &return_type = compiler.get<SPIRType>(args[0]);
if (!return_type.array.empty())
return SPVFuncImplArrayCopy;
else
return SPVFuncImplNone;
break;
}
case OpStore:
@ -4054,14 +4083,24 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
else
{
// Or ... an expression.
if (result_types[id_rhs] != 0)
type = &compiler.get<SPIRType>(result_types[id_rhs]);
uint32_t tid = result_types[id_rhs];
if (tid)
type = &compiler.get<SPIRType>(tid);
}
if (type && compiler.is_array(*type))
return SPVFuncImplArrayCopy;
else
return SPVFuncImplNone;
break;
}
case OpImageFetch:
{
// Retrieve the image type, and if it's a Buffer, emit a texel coordinate function
uint32_t tid = result_types[args[2]];
if (tid && compiler.get<SPIRType>(tid).image.dim == DimBuffer)
return SPVFuncImplTexelBufferCoords;
break;
}
@ -4179,3 +4218,12 @@ void CompilerMSL::remap_constexpr_sampler(uint32_t id, const spirv_cross::MSLCon
SPIRV_CROSS_THROW("Can not remap array of samplers.");
constexpr_samplers[id] = sampler;
}
// MSL always declares builtins with their SPIR-V type.
void CompilerMSL::bitcast_from_builtin_load(uint32_t, std::string &, const spirv_cross::SPIRType &)
{
}
void CompilerMSL::bitcast_to_builtin_store(uint32_t, std::string &, const spirv_cross::SPIRType &)
{
}

View File

@ -152,6 +152,7 @@ public:
Platform platform = macOS;
uint32_t msl_version = make_msl_version(1, 2);
uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers
bool enable_point_size_builtin = true;
bool resolve_specialized_array_lengths = true;
@ -215,6 +216,7 @@ public:
SPVFuncImplFindSMsb,
SPVFuncImplFindUMsb,
SPVFuncImplArrayCopy,
SPVFuncImplTexelBufferCoords,
SPVFuncImplInverse4x4,
SPVFuncImplInverse3x3,
SPVFuncImplInverse2x2,
@ -356,6 +358,9 @@ protected:
void emit_entry_point_declarations() override;
uint32_t builtin_frag_coord_id = 0;
void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
Options msl_options;
std::set<SPVFuncImpl> spv_function_implementations;
std::unordered_map<uint32_t, MSLVertexAttr *> vtx_attrs_by_location;

573
spirv_reflect.cpp Normal file
View File

@ -0,0 +1,573 @@
/*
* Copyright 2018 Bradley Austin Davis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "spirv_reflect.hpp"
#include "spirv_glsl.hpp"
#include <iomanip>
using namespace spv;
using namespace spirv_cross;
using namespace std;
namespace simple_json
{
enum class Type
{
Object,
Array,
};
using State = std::pair<Type, bool>;
using Stack = std::stack<State>;
class Stream
{
Stack stack;
std::ostringstream buffer;
uint32_t indent{ 0 };
public:
void begin_json_object();
void end_json_object();
void emit_json_key(const std::string &key);
void emit_json_key_value(const std::string &key, const std::string &value);
void emit_json_key_value(const std::string &key, bool value);
void emit_json_key_value(const std::string &key, uint32_t value);
void emit_json_key_value(const std::string &key, int32_t value);
void emit_json_key_value(const std::string &key, float value);
void emit_json_key_object(const std::string &key);
void emit_json_key_array(const std::string &key);
void begin_json_array();
void end_json_array();
void emit_json_array_value(const std::string &value);
void emit_json_array_value(uint32_t value);
std::string str() const
{
return buffer.str();
}
private:
inline void statement_indent()
{
for (uint32_t i = 0; i < indent; i++)
buffer << " ";
}
template <typename T>
inline void statement_inner(T &&t)
{
buffer << std::forward<T>(t);
}
template <typename T, typename... Ts>
inline void statement_inner(T &&t, Ts &&... ts)
{
buffer << std::forward<T>(t);
statement_inner(std::forward<Ts>(ts)...);
}
template <typename... Ts>
inline void statement(Ts &&... ts)
{
statement_indent();
statement_inner(std::forward<Ts>(ts)...);
buffer << '\n';
}
template <typename... Ts>
void statement_no_return(Ts &&... ts)
{
statement_indent();
statement_inner(std::forward<Ts>(ts)...);
}
};
} // namespace simple_json
using namespace simple_json;
// Hackery to emit JSON without using nlohmann/json C++ library (which requires a
// higher level of compiler compliance than is required by SPIRV-Cross
void Stream::begin_json_array()
{
if (!stack.empty() && stack.top().second)
{
statement_inner(",\n");
}
statement("[");
++indent;
stack.emplace(Type::Array, false);
}
void Stream::end_json_array()
{
if (stack.empty() || stack.top().first != Type::Array)
SPIRV_CROSS_THROW("Invalid JSON state");
if (stack.top().second)
{
statement_inner("\n");
}
--indent;
statement_no_return("]");
stack.pop();
if (!stack.empty())
{
stack.top().second = true;
}
}
void Stream::emit_json_array_value(const std::string &value)
{
if (stack.empty() || stack.top().first != Type::Array)
SPIRV_CROSS_THROW("Invalid JSON state");
if (stack.top().second)
statement_inner(",\n");
statement_no_return("\"", value, "\"");
stack.top().second = true;
}
void Stream::emit_json_array_value(uint32_t value)
{
if (stack.empty() || stack.top().first != Type::Array)
SPIRV_CROSS_THROW("Invalid JSON state");
if (stack.top().second)
statement_inner(",\n");
statement_no_return(std::to_string(value));
stack.top().second = true;
}
void Stream::begin_json_object()
{
if (!stack.empty() && stack.top().second)
{
statement_inner(",\n");
}
statement("{");
++indent;
stack.emplace(Type::Object, false);
}
void Stream::end_json_object()
{
if (stack.empty() || stack.top().first != Type::Object)
SPIRV_CROSS_THROW("Invalid JSON state");
if (stack.top().second)
{
statement_inner("\n");
}
--indent;
statement_no_return("}");
stack.pop();
if (!stack.empty())
{
stack.top().second = true;
}
}
void Stream::emit_json_key(const std::string &key)
{
if (stack.empty() || stack.top().first != Type::Object)
SPIRV_CROSS_THROW("Invalid JSON state");
if (stack.top().second)
statement_inner(",\n");
statement_no_return("\"", key, "\" : ");
stack.top().second = true;
}
void Stream::emit_json_key_value(const std::string &key, const std::string &value)
{
emit_json_key(key);
statement_inner("\"", value, "\"");
}
void Stream::emit_json_key_value(const std::string &key, uint32_t value)
{
emit_json_key(key);
statement_inner(value);
}
void Stream::emit_json_key_value(const std::string &key, int32_t value)
{
emit_json_key(key);
statement_inner(value);
}
void Stream::emit_json_key_value(const std::string &key, float value)
{
emit_json_key(key);
statement_inner(value);
}
void Stream::emit_json_key_value(const std::string &key, bool value)
{
emit_json_key(key);
statement_inner(value ? "true" : "false");
}
void Stream::emit_json_key_object(const std::string &key)
{
emit_json_key(key);
statement_inner("{\n");
++indent;
stack.emplace(Type::Object, false);
}
void Stream::emit_json_key_array(const std::string &key)
{
emit_json_key(key);
statement_inner("[\n");
++indent;
stack.emplace(Type::Array, false);
}
void CompilerReflection::set_format(const std::string &format)
{
if (format != "json")
{
SPIRV_CROSS_THROW("Unsupported format");
}
}
string CompilerReflection::compile()
{
// Force a classic "C" locale, reverts when function returns
ClassicLocale classic_locale;
// Move constructor for this type is broken on GCC 4.9 ...
json_stream = std::make_shared<simple_json::Stream>();
json_stream->begin_json_object();
emit_entry_points();
emit_types();
emit_resources();
emit_specialization_constants();
json_stream->end_json_object();
return json_stream->str();
}
void CompilerReflection::emit_types()
{
bool emitted_open_tag = false;
for (auto &id : ids)
{
auto idType = id.get_type();
if (idType == TypeType)
{
auto &type = id.get<SPIRType>();
if (type.basetype == SPIRType::Struct && !type.pointer && type.array.empty())
{
emit_type(type, emitted_open_tag);
}
}
}
if (emitted_open_tag)
{
json_stream->end_json_object();
}
}
void CompilerReflection::emit_type(const SPIRType &type, bool &emitted_open_tag)
{
auto name = type_to_glsl(type);
if (type.type_alias != 0)
return;
if (!emitted_open_tag)
{
json_stream->emit_json_key_object("types");
emitted_open_tag = true;
}
json_stream->emit_json_key_object("_" + std::to_string(type.self));
json_stream->emit_json_key_value("name", name);
json_stream->emit_json_key_array("members");
// FIXME ideally we'd like to emit the size of a structure as a
// convenience to people parsing the reflected JSON. The problem
// is that there's no implicit size for a type. It's final size
// will be determined by the top level declaration in which it's
// included. So there might be one size for the struct if it's
// included in a std140 uniform block and another if it's included
// in a std430 uniform block.
// The solution is to include *all* potential sizes as a map of
// layout type name to integer, but that will probably require
// some additional logic being written in this class, or in the
// parent CompilerGLSL class.
auto size = type.member_types.size();
for (uint32_t i = 0; i < size; ++i)
{
emit_type_member(type, i);
}
json_stream->end_json_array();
json_stream->end_json_object();
}
void CompilerReflection::emit_type_member(const SPIRType &type, uint32_t index)
{
auto &membertype = get<SPIRType>(type.member_types[index]);
json_stream->begin_json_object();
auto name = to_member_name(type, index);
// FIXME we'd like to emit the offset of each member, but such offsets are
// context dependent. See the comment above regarding structure sizes
json_stream->emit_json_key_value("name", name);
if (membertype.basetype == SPIRType::Struct)
{
json_stream->emit_json_key_value("type", "_" + std::to_string(membertype.self));
}
else
{
json_stream->emit_json_key_value("type", type_to_glsl(membertype));
}
emit_type_member_qualifiers(type, index);
json_stream->end_json_object();
}
void CompilerReflection::emit_type_array(const SPIRType &type)
{
if (!type.array.empty())
{
json_stream->emit_json_key_array("array");
// Note that we emit the zeros here as a means of identifying
// unbounded arrays. This is necessary as otherwise there would
// be no way of differentiating between float[4] and float[4][]
for (const auto &value : type.array)
json_stream->emit_json_array_value(value);
json_stream->end_json_array();
}
}
void CompilerReflection::emit_type_member_qualifiers(const SPIRType &type, uint32_t index)
{
auto flags = combined_decoration_for_member(type, index);
if (flags.get(DecorationRowMajor))
json_stream->emit_json_key_value("row_major", true);
auto &membertype = get<SPIRType>(type.member_types[index]);
emit_type_array(membertype);
auto &memb = meta[type.self].members;
if (index < memb.size())
{
auto &dec = memb[index];
if (dec.decoration_flags.get(DecorationLocation))
json_stream->emit_json_key_value("location", dec.location);
if (dec.decoration_flags.get(DecorationOffset))
json_stream->emit_json_key_value("offset", dec.offset);
}
}
string CompilerReflection::execution_model_to_str(spv::ExecutionModel model)
{
switch (model)
{
case spv::ExecutionModelVertex:
return "vert";
case spv::ExecutionModelTessellationControl:
return "tesc";
case ExecutionModelTessellationEvaluation:
return "tese";
case ExecutionModelGeometry:
return "geom";
case ExecutionModelFragment:
return "frag";
case ExecutionModelGLCompute:
return "comp";
default:
return "???";
}
}
// FIXME include things like the local_size dimensions, geometry output vertex count, etc
void CompilerReflection::emit_entry_points()
{
auto entries = get_entry_points_and_stages();
if (!entries.empty())
{
json_stream->emit_json_key_array("entryPoints");
for (auto &e : entries)
{
json_stream->begin_json_object();
json_stream->emit_json_key_value("name", e.name);
json_stream->emit_json_key_value("mode", execution_model_to_str(e.execution_model));
json_stream->end_json_object();
}
json_stream->end_json_array();
}
}
void CompilerReflection::emit_resources()
{
auto res = get_shader_resources();
emit_resources("subpass_inputs", res.subpass_inputs);
emit_resources("inputs", res.stage_inputs);
emit_resources("outputs", res.stage_outputs);
emit_resources("textures", res.sampled_images);
emit_resources("separate_images", res.separate_images);
emit_resources("separate_samplers", res.separate_samplers);
emit_resources("images", res.storage_images);
emit_resources("ssbos", res.storage_buffers);
emit_resources("ubos", res.uniform_buffers);
emit_resources("push_constants", res.push_constant_buffers);
emit_resources("counters", res.atomic_counters);
}
void CompilerReflection::emit_resources(const char *tag, const vector<Resource> &resources)
{
if (resources.empty())
{
return;
}
json_stream->emit_json_key_array(tag);
for (auto &res : resources)
{
auto &type = get_type(res.type_id);
auto typeflags = meta[type.self].decoration.decoration_flags;
auto &mask = get_decoration_bitset(res.id);
// If we don't have a name, use the fallback for the type instead of the variable
// for SSBOs and UBOs since those are the only meaningful names to use externally.
// Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
bool is_push_constant = get_storage_class(res.id) == StorageClassPushConstant;
bool is_block = get_decoration_bitset(type.self).get(DecorationBlock) ||
get_decoration_bitset(type.self).get(DecorationBufferBlock);
uint32_t fallback_id = !is_push_constant && is_block ? res.base_type_id : res.id;
json_stream->begin_json_object();
if (type.basetype == SPIRType::Struct)
{
json_stream->emit_json_key_value("type", "_" + std::to_string(res.base_type_id));
}
else
{
json_stream->emit_json_key_value("type", type_to_glsl(type));
}
json_stream->emit_json_key_value("name", !res.name.empty() ? res.name : get_fallback_name(fallback_id));
{
bool ssbo_block = type.storage == StorageClassStorageBuffer ||
(type.storage == StorageClassUniform && typeflags.get(DecorationBufferBlock));
if (ssbo_block)
{
auto buffer_flags = get_buffer_block_flags(res.id);
if (buffer_flags.get(DecorationNonReadable))
json_stream->emit_json_key_value("writeonly", true);
if (buffer_flags.get(DecorationNonWritable))
json_stream->emit_json_key_value("readonly", true);
if (buffer_flags.get(DecorationRestrict))
json_stream->emit_json_key_value("restrict", true);
if (buffer_flags.get(DecorationCoherent))
json_stream->emit_json_key_value("coherent", true);
}
}
emit_type_array(type);
{
bool is_sized_block = is_block && (get_storage_class(res.id) == StorageClassUniform ||
get_storage_class(res.id) == StorageClassUniformConstant);
if (is_sized_block)
{
uint32_t block_size = uint32_t(get_declared_struct_size(get_type(res.base_type_id)));
json_stream->emit_json_key_value("block_size", block_size);
}
}
if (type.storage == StorageClassPushConstant)
json_stream->emit_json_key_value("push_constant", true);
if (mask.get(DecorationLocation))
json_stream->emit_json_key_value("location", get_decoration(res.id, DecorationLocation));
if (mask.get(DecorationRowMajor))
json_stream->emit_json_key_value("row_major", true);
if (mask.get(DecorationColMajor))
json_stream->emit_json_key_value("column_major", true);
if (mask.get(DecorationIndex))
json_stream->emit_json_key_value("index", get_decoration(res.id, DecorationIndex));
if (type.storage != StorageClassPushConstant && mask.get(DecorationDescriptorSet))
json_stream->emit_json_key_value("set", get_decoration(res.id, DecorationDescriptorSet));
if (mask.get(DecorationBinding))
json_stream->emit_json_key_value("binding", get_decoration(res.id, DecorationBinding));
if (mask.get(DecorationInputAttachmentIndex))
json_stream->emit_json_key_value("input_attachment_index",
get_decoration(res.id, DecorationInputAttachmentIndex));
if (mask.get(DecorationOffset))
json_stream->emit_json_key_value("offset", get_decoration(res.id, DecorationOffset));
// For images, the type itself adds a layout qualifer.
// Only emit the format for storage images.
if (type.basetype == SPIRType::Image && type.image.sampled == 2)
{
const char *fmt = format_to_glsl(type.image.format);
if (fmt != nullptr)
json_stream->emit_json_key_value("format", std::string(fmt));
}
json_stream->end_json_object();
}
json_stream->end_json_array();
}
void CompilerReflection::emit_specialization_constants()
{
auto specialization_constants = get_specialization_constants();
if (specialization_constants.empty())
return;
json_stream->emit_json_key_array("specialization_constants");
for (const auto spec_const : specialization_constants)
{
auto &c = get<SPIRConstant>(spec_const.id);
auto type = get<SPIRType>(c.constant_type);
json_stream->begin_json_object();
json_stream->emit_json_key_value("id", spec_const.constant_id);
json_stream->emit_json_key_value("type", type_to_glsl(type));
switch (type.basetype)
{
case SPIRType::UInt:
json_stream->emit_json_key_value("default_value", c.scalar());
break;
case SPIRType::Int:
json_stream->emit_json_key_value("default_value", c.scalar_i32());
break;
case SPIRType::Float:
json_stream->emit_json_key_value("default_value", c.scalar_f32());
break;
case SPIRType::Boolean:
json_stream->emit_json_key_value("default_value", c.scalar() != 0);
break;
default:
break;
}
json_stream->end_json_object();
}
json_stream->end_json_array();
}
string CompilerReflection::to_member_name(const SPIRType &type, uint32_t index) const
{
auto &memb = meta[type.self].members;
if (index < memb.size() && !memb[index].alias.empty())
return memb[index].alias;
else
return join("_m", index);
}

72
spirv_reflect.hpp Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright 2018 Bradley Austin Davis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_REFLECT_HPP
#define SPIRV_CROSS_REFLECT_HPP
#include "spirv_glsl.hpp"
#include <utility>
#include <vector>
namespace simple_json
{
class Stream;
}
namespace spirv_cross
{
class CompilerReflection : public CompilerGLSL
{
using Parent = CompilerGLSL;
public:
CompilerReflection(std::vector<uint32_t> spirv_)
: Parent(move(spirv_))
{
options.vulkan_semantics = true;
}
CompilerReflection(const uint32_t *ir, size_t word_count)
: Parent(ir, word_count)
{
options.vulkan_semantics = true;
}
void set_format(const std::string &format);
std::string compile() override;
private:
static std::string execution_model_to_str(spv::ExecutionModel model);
void emit_entry_points();
void emit_types();
void emit_resources();
void emit_specialization_constants();
void emit_type(const SPIRType &type, bool &emitted_open_tag);
void emit_type_member(const SPIRType &type, uint32_t index);
void emit_type_member_qualifiers(const SPIRType &type, uint32_t index);
void emit_type_array(const SPIRType &type);
void emit_resources(const char *tag, const std::vector<Resource> &resources);
std::string to_member_name(const SPIRType &type, uint32_t index) const;
std::shared_ptr<simple_json::Stream> json_stream;
};
} // namespace spirv_cross
#endif

View File

@ -11,8 +11,13 @@ import hashlib
import shutil
import argparse
import codecs
import json
import multiprocessing
import errno
from functools import partial
force_no_external_validation = False
backend = 'glsl'
args = {}
def remove_file(path):
#print('Removing file:', path)
@ -78,7 +83,7 @@ def print_msl_compiler_version():
subprocess.check_call(['xcrun', '--sdk', 'iphoneos', 'metal', '--version'])
print('...are the Metal compiler characteristics.\n') # display after so xcrun FNF is silent
except OSError as e:
if (e.errno != os.errno.ENOENT): # Ignore xcrun not found error
if (e.errno != errno.ENOENT): # Ignore xcrun not found error
raise
def validate_shader_msl(shader, opt):
@ -90,7 +95,7 @@ def validate_shader_msl(shader, opt):
subprocess.check_call(['xcrun', '--sdk', msl_os, 'metal', '-x', 'metal', '-std=osx-metal{}'.format('2.0' if msl2 else '1.2'), '-Werror', '-Wno-unused-variable', msl_path])
print('Compiled Metal shader: ' + msl_path) # display after so xcrun FNF is silent
except OSError as oe:
if (oe.errno != os.errno.ENOENT): # Ignore xcrun not found error
if (oe.errno != errno.ENOENT): # Ignore xcrun not found error
raise
except subprocess.CalledProcessError:
print('Error compiling Metal shader: ' + msl_path)
@ -140,7 +145,7 @@ def shader_to_win_path(shader):
stdout_data, stderr_data = f.communicate()
return stdout_data.decode('utf-8')
except OSError as oe:
if (oe.errno != os.errno.ENOENT): # Ignore not found errors
if (oe.errno != errno.ENOENT): # Ignore not found errors
return shader
except subprocess.CalledProcessError:
raise
@ -152,12 +157,12 @@ def validate_shader_hlsl(shader):
subprocess.check_call(['glslangValidator', '-e', 'main', '-D', '--target-env', 'vulkan1.1', '-V', shader])
is_no_fxc = '.nofxc.' in shader
global ignore_fxc
if (not ignore_fxc) and (not force_no_external_validation) and (not is_no_fxc):
if (not ignore_fxc) and (not args.force_no_external_validation) and (not is_no_fxc):
try:
win_path = shader_to_win_path(shader)
subprocess.check_call(['fxc', '-nologo', shader_model_hlsl(shader), win_path])
except OSError as oe:
if (oe.errno != os.errno.ENOENT): # Ignore not found errors
if (oe.errno != errno.ENOENT): # Ignore not found errors
raise
else:
ignore_fxc = True
@ -199,6 +204,24 @@ def cross_compile_hlsl(shader, spirv, opt):
return (spirv_path, hlsl_path)
def cross_compile_reflect(shader, spirv, opt):
spirv_path = create_temporary()
reflect_path = create_temporary(os.path.basename(shader))
if spirv:
subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
else:
subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', '-o', spirv_path, shader])
if opt:
subprocess.check_call(['spirv-opt', '-O', '-o', spirv_path, spirv_path])
spirv_cross_path = './spirv-cross'
sm = shader_to_sm(shader)
subprocess.check_call([spirv_cross_path, '--entry', 'main', '--output', reflect_path, spirv_path, '--reflect'])
return (spirv_path, reflect_path)
def validate_shader(shader, vulkan):
if vulkan:
subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', shader])
@ -277,6 +300,58 @@ def reference_path(directory, relpath, opt):
reference_dir = os.path.join(reference_dir, split_paths[1])
return os.path.join(reference_dir, relpath)
def json_ordered(obj):
if isinstance(obj, dict):
return sorted((k, json_ordered(v)) for k, v in obj.items())
if isinstance(obj, list):
return sorted(json_ordered(x) for x in obj)
else:
return obj
def json_compare(json_a, json_b):
return json_ordered(json_a) == json_ordered(json_b)
def regression_check_reflect(shader, json_file, update, keep, opt):
reference = reference_path(shader[0], shader[1], opt) + '.json'
joined_path = os.path.join(shader[0], shader[1])
print('Reference shader reflection path:', reference)
if os.path.exists(reference):
actual = ''
expected = ''
with open(json_file) as f:
actual_json = f.read();
actual = json.loads(actual_json)
with open(reference) as f:
expected = json.load(f)
if (json_compare(actual, expected) != True):
if update:
print('Generated reflection json has changed for {}!'.format(reference))
# If we expect changes, update the reference file.
if os.path.exists(reference):
remove_file(reference)
make_reference_dir(reference)
shutil.move(json_file, reference)
else:
print('Generated reflection json in {} does not match reference {}!'.format(json_file, reference))
with open(json_file, 'r') as f:
print('')
print('Generated:')
print('======================')
print(f.read())
print('======================')
print('')
# Otherwise, fail the test. Keep the shader file around so we can inspect.
if not keep:
remove_file(json_file)
sys.exit(1)
else:
remove_file(json_file)
else:
print('Found new shader {}. Placing generated source code in {}'.format(joined_path, reference))
make_reference_dir(reference)
shutil.move(json_file, reference)
def regression_check(shader, glsl, update, keep, opt):
reference = reference_path(shader[0], shader[1], opt)
joined_path = os.path.join(shader[0], shader[1])
@ -396,7 +471,7 @@ def test_shader_msl(stats, shader, update, keep, opt):
# executable from Xcode using args: `--msl --entry main --output msl_path spirv_path`.
# print('SPRIV shader: ' + spirv)
if not force_no_external_validation:
if not args.force_no_external_validation:
validate_shader_msl(shader, opt)
remove_file(spirv)
@ -410,26 +485,50 @@ def test_shader_hlsl(stats, shader, update, keep, opt):
regression_check(shader, hlsl, update, keep, opt)
remove_file(spirv)
def test_shaders_helper(stats, shader_dir, update, malisc, keep, opt, backend):
for root, dirs, files in os.walk(os.path.join(shader_dir)):
def test_shader_reflect(stats, shader, update, keep, opt):
joined_path = os.path.join(shader[0], shader[1])
print('Testing shader reflection:', joined_path)
is_spirv = shader_is_spirv(shader[1])
noopt = shader_is_noopt(shader[1])
spirv, reflect = cross_compile_reflect(joined_path, is_spirv, opt and (not noopt))
regression_check_reflect(shader, reflect, update, keep, opt)
remove_file(spirv)
def test_shader_file(relpath, stats, shader_dir, update, keep, opt, backend):
if backend == 'msl':
test_shader_msl(stats, (shader_dir, relpath), update, keep, opt)
elif backend == 'hlsl':
test_shader_hlsl(stats, (shader_dir, relpath), update, keep, opt)
elif backend == 'reflect':
test_shader_reflect(stats, (shader_dir, relpath), update, keep, opt)
else:
test_shader(stats, (shader_dir, relpath), update, keep, opt)
def test_shaders_helper(stats):
all_files = []
for root, dirs, files in os.walk(os.path.join(args.folder)):
files = [ f for f in files if not f.startswith(".") ] #ignore system files (esp OSX)
for i in files:
path = os.path.join(root, i)
relpath = os.path.relpath(path, shader_dir)
if backend == 'msl':
test_shader_msl(stats, (shader_dir, relpath), update, keep, opt)
elif backend == 'hlsl':
test_shader_hlsl(stats, (shader_dir, relpath), update, keep, opt)
else:
test_shader(stats, (shader_dir, relpath), update, keep, opt)
relpath = os.path.relpath(path, args.folder)
all_files.append(relpath)
def test_shaders(shader_dir, update, malisc, keep, opt, backend):
if malisc:
# The child processes in parallel execution mode don't have the proper state for the global args variable, so
# at this point we need to switch to explicit arguments
if args.parallel:
pool = multiprocessing.Pool(multiprocessing.cpu_count())
pool.map(partial(test_shader_file, stats=stats, shader_dir=args.folder, update=args.update, keep=args.keep, opt=args.opt, backend=backend), all_files)
else:
for i in all_files:
test_shader_file(i, stats, args.folder, args.update, args.keep, args.opt, backend)
def test_shaders():
if args.malisc:
with open('stats.csv', 'w') as stats:
print('Shader,OrigRegs,OrigUniRegs,OrigALUShort,OrigLSShort,OrigTEXShort,OrigALULong,OrigLSLong,OrigTEXLong,CrossRegs,CrossUniRegs,CrossALUShort,CrossLSShort,CrossTEXShort,CrossALULong,CrossLSLong,CrossTEXLong', file = stats)
test_shaders_helper(stats, shader_dir, update, malisc, keep, backend)
test_shaders_helper(stats)
else:
test_shaders_helper(None, shader_dir, update, malisc, keep, opt, backend)
test_shaders_helper(None)
def main():
parser = argparse.ArgumentParser(description = 'Script for regression testing.')
@ -459,19 +558,35 @@ def main():
parser.add_argument('--opt',
action = 'store_true',
help = 'Run SPIRV-Tools optimization passes as well.')
parser.add_argument('--reflect',
action = 'store_true',
help = 'Test reflection backend.')
parser.add_argument('--parallel',
action = 'store_true',
help = 'Execute tests in parallel. Useful for doing regression quickly, but bad for debugging and stat output.')
global args
args = parser.parse_args()
if not args.folder:
sys.stderr.write('Need shader folder.\n')
sys.exit(1)
if (args.parallel and (args.malisc or args.force_no_external_validation or args.update)):
sys.stderr.write('Parallel execution is disabled when using the flags --update, --malisc or --force-no-external-validation\n')
args.parallel = False
if args.msl:
print_msl_compiler_version()
global force_no_external_validation
force_no_external_validation = args.force_no_external_validation
global backend
if (args.msl or args.metal):
backend = 'msl'
elif args.hlsl:
backend = 'hlsl'
elif args.reflect:
backend = 'reflect'
test_shaders(args.folder, args.update, args.malisc, args.keep, args.opt, 'msl' if (args.msl or args.metal) else ('hlsl' if args.hlsl else 'glsl'))
test_shaders()
if args.malisc:
print('Stats in stats.csv!')
print('Tests completed!')

View File

@ -16,4 +16,5 @@ echo "Using spirv-opt in: $(which spirv-opt)."
./test_shaders.py shaders-hlsl --hlsl || exit 1
./test_shaders.py shaders-hlsl --hlsl --opt || exit 1
./test_shaders.py shaders-hlsl-no-opt --hlsl || exit 1
./test_shaders.py shaders-reflection --reflect || exit 1

View File

@ -16,5 +16,6 @@ echo "Using spirv-opt in: $(which spirv-opt)."
./test_shaders.py shaders-hlsl --update --hlsl || exit 1
./test_shaders.py shaders-hlsl --update --hlsl --opt || exit 1
./test_shaders.py shaders-hlsl-no-opt --update --hlsl || exit 1
./test_shaders.py shaders-reflection --reflect --update || exit 1