Merge Brenwill fork with upstream.
This commit is contained in:
Коммит
a759e2c872
|
@ -22,27 +22,42 @@ if(${CMAKE_GENERATOR} MATCHES "Makefile")
|
|||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(spirv-cross
|
||||
add_library(spirv-cross-core STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.std.450.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_common.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_glsl.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross.cpp)
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross.cpp
|
||||
add_library(spirv-cross-glsl STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_glsl.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.cpp
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_glsl.hpp)
|
||||
|
||||
add_library(spirv-cross-cpp STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.cpp)
|
||||
|
||||
add_library(spirv-cross-msl STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.cpp)
|
||||
|
||||
add_executable(spirv-cross main.cpp)
|
||||
target_link_libraries(spirv-cross spirv-cross-glsl spirv-cross-cpp spirv-cross-msl spirv-cross-core)
|
||||
target_link_libraries(spirv-cross-glsl spirv-cross-core)
|
||||
target_link_libraries(spirv-cross-msl spirv-cross-glsl)
|
||||
target_link_libraries(spirv-cross-cpp spirv-cross-glsl)
|
||||
target_include_directories(spirv-cross-core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# To specify special debug or optimization options, use
|
||||
# -DCMAKE_CXX_COMPILE_FLAGS
|
||||
# However, we require the C++11 dialect.
|
||||
if (NOT "${MSVC}")
|
||||
target_compile_options(spirv-cross PRIVATE -std=c++11 -Wall -Wextra -Werror -Wshadow)
|
||||
set(spirv-compiler-options -std=c++11 -Wall -Wextra -Werror -Wshadow)
|
||||
target_compile_options(spirv-cross-core PRIVATE ${spirv-compiler-options})
|
||||
target_compile_options(spirv-cross-glsl PRIVATE ${spirv-compiler-options})
|
||||
target_compile_options(spirv-cross-msl PRIVATE ${spirv-compiler-options})
|
||||
target_compile_options(spirv-cross-cpp PRIVATE ${spirv-compiler-options})
|
||||
target_compile_options(spirv-cross PRIVATE ${spirv-compiler-options})
|
||||
endif(NOT "${MSVC}")
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ However, most missing features are expected to be "trivial" improvements at this
|
|||
|
||||
SPIRV-Cross has been tested on Linux, OSX and Windows.
|
||||
|
||||
### Linux and OSX
|
||||
### Linux and macOS
|
||||
|
||||
Just run `make` on the command line. A recent GCC (4.8+) or Clang (3.x+) compiler is required as SPIRV-Cross uses C++11 extensively.
|
||||
|
||||
|
|
56
main.cpp
56
main.cpp
|
@ -317,6 +317,8 @@ static void print_resources(const Compiler &compiler, const ShaderResources &res
|
|||
print_resources(compiler, "inputs", res.stage_inputs);
|
||||
print_resources(compiler, "outputs", res.stage_outputs);
|
||||
print_resources(compiler, "textures", res.sampled_images);
|
||||
print_resources(compiler, "separate images", res.separate_images);
|
||||
print_resources(compiler, "separate samplers", res.separate_samplers);
|
||||
print_resources(compiler, "images", res.storage_images);
|
||||
print_resources(compiler, "ssbos", res.storage_buffers);
|
||||
print_resources(compiler, "ubos", res.uniform_buffers);
|
||||
|
@ -345,6 +347,16 @@ static void print_push_constant_resources(const Compiler &compiler, const vector
|
|||
}
|
||||
}
|
||||
|
||||
static void print_spec_constants(const Compiler &compiler)
|
||||
{
|
||||
auto spec_constants = compiler.get_specialization_constants();
|
||||
fprintf(stderr, "Specialization constants\n");
|
||||
fprintf(stderr, "==================\n\n");
|
||||
for (auto &c : spec_constants)
|
||||
fprintf(stderr, "ID: %u, Spec ID: %u\n", c.id, c.constant_id);
|
||||
fprintf(stderr, "==================\n\n");
|
||||
}
|
||||
|
||||
struct PLSArg
|
||||
{
|
||||
PlsFormat format;
|
||||
|
@ -358,6 +370,12 @@ struct Remap
|
|||
unsigned components;
|
||||
};
|
||||
|
||||
struct VariableTypeRemap
|
||||
{
|
||||
string variable_name;
|
||||
string new_variable_type;
|
||||
};
|
||||
|
||||
struct CLIArguments
|
||||
{
|
||||
const char *input = nullptr;
|
||||
|
@ -375,6 +393,7 @@ struct CLIArguments
|
|||
vector<PLSArg> pls_out;
|
||||
vector<Remap> remaps;
|
||||
vector<string> extensions;
|
||||
vector<VariableTypeRemap> variable_type_remaps;
|
||||
string entry;
|
||||
|
||||
uint32_t iterations = 1;
|
||||
|
@ -390,7 +409,8 @@ static void print_help()
|
|||
"version>] [--dump-resources] [--help] [--force-temporary] [--cpp] [--cpp-interface-name <name>] "
|
||||
"[--metal] [--vulkan-semantics] [--flatten-ubo] [--fixup-clipspace] [--iterations iter] [--pls-in "
|
||||
"format input-name] [--pls-out format output-name] [--remap source_name target_name components] "
|
||||
"[--extension ext] [--entry name] [--remove-unused-variables]\n");
|
||||
"[--extension ext] [--entry name] [--remove-unused-variables] "
|
||||
"[--remap-variable-type <variable_name> <new_variable_type>]\n");
|
||||
}
|
||||
|
||||
static bool remap_generic(Compiler &compiler, const vector<Resource> &resources, const Remap &remap)
|
||||
|
@ -517,6 +537,12 @@ int main(int argc, char *argv[])
|
|||
args.remaps.push_back({ move(src), move(dst), components });
|
||||
});
|
||||
|
||||
cbs.add("--remap-variable-type", [&args](CLIParser &parser) {
|
||||
string var_name = parser.next_string();
|
||||
string new_type = parser.next_string();
|
||||
args.variable_type_remaps.push_back({ move(var_name), move(new_type) });
|
||||
});
|
||||
|
||||
cbs.add("--pls-in", [&args](CLIParser &parser) {
|
||||
auto fmt = pls_format(parser.next_string());
|
||||
auto name = parser.next_string();
|
||||
|
@ -552,6 +578,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
unique_ptr<CompilerGLSL> compiler;
|
||||
|
||||
bool combined_image_samplers = false;
|
||||
|
||||
if (args.cpp)
|
||||
{
|
||||
compiler = unique_ptr<CompilerGLSL>(new CompilerCPP(read_spirv_file(args.input)));
|
||||
|
@ -561,7 +589,21 @@ int main(int argc, char *argv[])
|
|||
else if (args.metal)
|
||||
compiler = unique_ptr<CompilerMSL>(new CompilerMSL(read_spirv_file(args.input)));
|
||||
else
|
||||
{
|
||||
combined_image_samplers = !args.vulkan_semantics;
|
||||
compiler = unique_ptr<CompilerGLSL>(new CompilerGLSL(read_spirv_file(args.input)));
|
||||
}
|
||||
|
||||
if (!args.variable_type_remaps.empty())
|
||||
{
|
||||
auto remap_cb = [&](const SPIRType &, const string &name, string &out) -> void {
|
||||
for (const VariableTypeRemap &remap : args.variable_type_remaps)
|
||||
if (name == remap.variable_name)
|
||||
out = remap.new_variable_type;
|
||||
};
|
||||
|
||||
compiler->set_variable_type_remap_callback(move(remap_cb));
|
||||
}
|
||||
|
||||
if (!args.entry.empty())
|
||||
compiler->set_entry_point(args.entry);
|
||||
|
@ -618,6 +660,18 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
print_resources(*compiler, res);
|
||||
print_push_constant_resources(*compiler, res.push_constant_buffers);
|
||||
print_spec_constants(*compiler);
|
||||
}
|
||||
|
||||
if (combined_image_samplers)
|
||||
{
|
||||
compiler->build_combined_image_samplers();
|
||||
// Give the remapped combined samplers new names.
|
||||
for (auto &remap : compiler->get_combined_image_samplers())
|
||||
{
|
||||
compiler->set_name(remap.combined_id, join("SPIRV_Cross_Combined", compiler->get_name(remap.image_id),
|
||||
compiler->get_name(remap.sampler_id)));
|
||||
}
|
||||
}
|
||||
|
||||
string glsl;
|
||||
|
|
|
@ -55,7 +55,11 @@ void main()
|
|||
meow(param_1);
|
||||
foo = param_1;
|
||||
Foo param_2 = foo;
|
||||
Foo param_3 = foobar.foos[gl_GlobalInvocationID.x];
|
||||
Foo param_3;
|
||||
param_3.a = foobar.foos[gl_GlobalInvocationID.x].a;
|
||||
param_3.b = foobar.foos[gl_GlobalInvocationID.x].b;
|
||||
param_3.c = foobar.foos[gl_GlobalInvocationID.x].c;
|
||||
param_3.d = foobar.foos[gl_GlobalInvocationID.x].d;
|
||||
outdata.data[gl_GlobalInvocationID.x] = (bar(param_2) + bar(param_3));
|
||||
}
|
||||
|
|
@ -63,6 +63,20 @@ layout(binding = 0, std140) buffer SSBO0
|
|||
|
||||
void main()
|
||||
{
|
||||
ssbo_430.content = ssbo_140.content;
|
||||
ssbo_430.content.m0s[0].a[0] = ssbo_140.content.m0s[0].a[0];
|
||||
ssbo_430.content.m0s[0].b = ssbo_140.content.m0s[0].b;
|
||||
ssbo_430.content.m1s[0].a = ssbo_140.content.m1s[0].a;
|
||||
ssbo_430.content.m1s[0].b = ssbo_140.content.m1s[0].b;
|
||||
ssbo_430.content.m2s[0].a[0] = ssbo_140.content.m2s[0].a[0];
|
||||
ssbo_430.content.m2s[0].b = ssbo_140.content.m2s[0].b;
|
||||
ssbo_430.content.m0.a[0] = ssbo_140.content.m0.a[0];
|
||||
ssbo_430.content.m0.b = ssbo_140.content.m0.b;
|
||||
ssbo_430.content.m1.a = ssbo_140.content.m1.a;
|
||||
ssbo_430.content.m1.b = ssbo_140.content.m1.b;
|
||||
ssbo_430.content.m2.a[0] = ssbo_140.content.m2.a[0];
|
||||
ssbo_430.content.m2.b = ssbo_140.content.m2.b;
|
||||
ssbo_430.content.m3.a = ssbo_140.content.m3.a;
|
||||
ssbo_430.content.m3.b = ssbo_140.content.m3.b;
|
||||
ssbo_430.content.m4 = ssbo_140.content.m4;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ layout(binding = 0, std430) buffer SSBO0
|
|||
layout(binding = 1, std430) buffer SSBO1
|
||||
{
|
||||
S1 s1s[];
|
||||
} _53;
|
||||
} _55;
|
||||
|
||||
layout(binding = 2, std430) buffer SSBO2
|
||||
{
|
||||
vec4 outputs[];
|
||||
} _62;
|
||||
} _66;
|
||||
|
||||
vec4 overload(S0 s0)
|
||||
{
|
||||
|
@ -38,10 +38,12 @@ vec4 overload(S1 s1)
|
|||
|
||||
void main()
|
||||
{
|
||||
S0 s0 = _36.s0s[gl_GlobalInvocationID.x];
|
||||
S1 s1 = _53.s1s[gl_GlobalInvocationID.x];
|
||||
S0 s0;
|
||||
s0.a = _36.s0s[gl_GlobalInvocationID.x].a;
|
||||
S1 s1;
|
||||
s1.a = _55.s1s[gl_GlobalInvocationID.x].a;
|
||||
S0 param = s0;
|
||||
S1 param_1 = s1;
|
||||
_62.outputs[gl_GlobalInvocationID.x] = (overload(param) + overload(param_1));
|
||||
_66.outputs[gl_GlobalInvocationID.x] = (overload(param) + overload(param_1));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
in VertexData
|
||||
{
|
||||
layout(location = 0) flat float f;
|
||||
layout(location = 1) centroid vec4 g;
|
||||
layout(location = 2) flat int h;
|
||||
layout(location = 3) float i;
|
||||
} vin;
|
||||
|
||||
layout(location = 4) in flat float f;
|
||||
layout(location = 5) in centroid vec4 g;
|
||||
layout(location = 6) in flat int h;
|
||||
layout(location = 7) in sample float i;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = (((((((vec4(vin.f) + vin.g) + vec4(float(vin.h))) + vec4(vin.i)) + vec4(f)) + g) + vec4(float(h))) + vec4(i));
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#version 450
|
||||
|
||||
out VertexData
|
||||
{
|
||||
layout(location = 0) flat float f;
|
||||
layout(location = 1) centroid vec4 g;
|
||||
layout(location = 2) flat int h;
|
||||
layout(location = 3) float i;
|
||||
} vout;
|
||||
|
||||
layout(location = 4) out flat float f;
|
||||
layout(location = 5) out centroid vec4 g;
|
||||
layout(location = 6) out flat int h;
|
||||
layout(location = 7) out float i;
|
||||
|
||||
void main()
|
||||
{
|
||||
vout.f = 10.0;
|
||||
vout.g = vec4(20.0);
|
||||
vout.h = 20;
|
||||
vout.i = 30.0;
|
||||
f = 10.0;
|
||||
g = vec4(20.0);
|
||||
h = 20;
|
||||
i = 30.0;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
layout(lines_adjacency) in;
|
||||
layout(max_vertices = 3, line_strip) out;
|
||||
|
||||
out vec3 vNormal;
|
||||
in VertexData
|
||||
{
|
||||
vec3 normal;
|
||||
} vin[4];
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
vNormal = vin[2].normal;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
layout(lines) in;
|
||||
layout(max_vertices = 2, line_strip) out;
|
||||
|
||||
out vec3 vNormal;
|
||||
in VertexData
|
||||
{
|
||||
vec3 normal;
|
||||
} vin[2];
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
layout(points) in;
|
||||
layout(max_vertices = 3, points) out;
|
||||
|
||||
out vec3 vNormal;
|
||||
in VertexData
|
||||
{
|
||||
vec3 normal;
|
||||
} vin[1];
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
layout(triangles_adjacency) in;
|
||||
layout(max_vertices = 3, triangle_strip) out;
|
||||
|
||||
out vec3 vNormal;
|
||||
in VertexData
|
||||
{
|
||||
vec3 normal;
|
||||
} vin[6];
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
vNormal = vin[2].normal;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
layout(triangles) in;
|
||||
layout(max_vertices = 3, triangle_strip) out;
|
||||
|
||||
out vec3 vNormal;
|
||||
in VertexData
|
||||
{
|
||||
vec3 normal;
|
||||
} vin[3];
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
vNormal = vin[2].normal;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
layout(triangles, ccw, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
layout(triangles, cw, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
layout(triangles, cw, equal_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
layout(triangles, cw, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
layout(triangles, cw, fractional_odd_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
layout(isolines, point_mode, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
layout(triangles, cw, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -44,14 +44,15 @@ layout(binding = 1) uniform mediump sampler2D TexLOD;
|
|||
layout(binding = 0) uniform mediump sampler2D TexHeightmap;
|
||||
|
||||
layout(location = 1) in vec4 LODWeights;
|
||||
uniform int SPIRV_Cross_BaseInstance;
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 1) out vec3 EyeVec;
|
||||
layout(location = 0) out vec2 TexCoord;
|
||||
|
||||
vec2 warp_position()
|
||||
{
|
||||
float vlod = dot(LODWeights, _284.Patches[gl_InstanceID].LODs);
|
||||
vlod = mix(vlod, _284.Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
float vlod = dot(LODWeights, _284.Patches[(gl_InstanceID + SPIRV_Cross_BaseInstance)].LODs);
|
||||
vlod = mix(vlod, _284.Patches[(gl_InstanceID + SPIRV_Cross_BaseInstance)].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
float floor_lod = floor(vlod);
|
||||
float fract_lod = (vlod - floor_lod);
|
||||
uint ufloor_lod = uint(floor_lod);
|
||||
|
@ -93,7 +94,7 @@ vec2 lod_factor(vec2 uv)
|
|||
|
||||
void main()
|
||||
{
|
||||
vec2 PatchPos = (_284.Patches[gl_InstanceID].Position.xz * _381.InvGroundSize_PatchScale.zw);
|
||||
vec2 PatchPos = (_284.Patches[(gl_InstanceID + SPIRV_Cross_BaseInstance)].Position.xz * _381.InvGroundSize_PatchScale.zw);
|
||||
vec2 WarpedPos = warp_position();
|
||||
vec2 VertexPos = (PatchPos + WarpedPos);
|
||||
vec2 NormalizedPos = (VertexPos * _381.InvGroundSize_PatchScale.xy);
|
||||
|
|
|
@ -45,14 +45,15 @@ layout(binding = 1) uniform mediump sampler2D TexLOD;
|
|||
layout(binding = 0) uniform mediump sampler2D TexDisplacement;
|
||||
|
||||
layout(location = 1) in vec4 LODWeights;
|
||||
uniform int SPIRV_Cross_BaseInstance;
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 0) out vec3 EyeVec;
|
||||
layout(location = 1) out vec4 TexCoord;
|
||||
|
||||
vec2 warp_position()
|
||||
{
|
||||
float vlod = dot(LODWeights, _284.Patches[gl_InstanceID].LODs);
|
||||
vlod = mix(vlod, _284.Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
float vlod = dot(LODWeights, _284.Patches[(gl_InstanceID + SPIRV_Cross_BaseInstance)].LODs);
|
||||
vlod = mix(vlod, _284.Patches[(gl_InstanceID + SPIRV_Cross_BaseInstance)].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
float floor_lod = floor(vlod);
|
||||
float fract_lod = (vlod - floor_lod);
|
||||
uint ufloor_lod = uint(floor_lod);
|
||||
|
@ -114,7 +115,7 @@ vec2 lod_factor(vec2 uv)
|
|||
|
||||
void main()
|
||||
{
|
||||
vec2 PatchPos = (_284.Patches[gl_InstanceID].Position.xz * _405.InvOceanSize_PatchScale.zw);
|
||||
vec2 PatchPos = (_284.Patches[(gl_InstanceID + SPIRV_Cross_BaseInstance)].Position.xz * _405.InvOceanSize_PatchScale.zw);
|
||||
vec2 WarpedPos = warp_position();
|
||||
vec2 VertexPos = (PatchPos + WarpedPos);
|
||||
vec2 NormalizedPos = (VertexPos * _405.InvOceanSize_PatchScale.xy);
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
uniform mediump sampler2D SPIRV_Cross_CombineduTexture0uSampler0;
|
||||
uniform mediump sampler2D SPIRV_Cross_CombineduTexture1uSampler1;
|
||||
uniform mediump sampler2D SPIRV_Cross_CombineduTexture1uSampler0;
|
||||
uniform mediump sampler2D SPIRV_Cross_CombineduTexture0uSampler1;
|
||||
|
||||
layout(location = 0) in vec2 vTex;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 sample_dual(mediump sampler2D SPIRV_Cross_Combinedtexsamp)
|
||||
{
|
||||
return texture(SPIRV_Cross_Combinedtexsamp, vTex);
|
||||
}
|
||||
|
||||
vec4 sample_duals()
|
||||
{
|
||||
vec4 a = sample_dual(SPIRV_Cross_CombineduTexture0uSampler0);
|
||||
vec4 b = sample_dual(SPIRV_Cross_CombineduTexture1uSampler1);
|
||||
return (a + b);
|
||||
}
|
||||
|
||||
vec4 sample_global_tex(mediump sampler2D SPIRV_Cross_CombineduTexture0samp, mediump sampler2D SPIRV_Cross_CombineduTexture1samp)
|
||||
{
|
||||
vec4 a = texture(SPIRV_Cross_CombineduTexture0samp, vTex);
|
||||
vec4 b = sample_dual(SPIRV_Cross_CombineduTexture1samp);
|
||||
return (a + b);
|
||||
}
|
||||
|
||||
vec4 sample_global_sampler(mediump sampler2D SPIRV_Cross_CombinedtexuSampler0, mediump sampler2D SPIRV_Cross_CombinedtexuSampler1)
|
||||
{
|
||||
vec4 a = texture(SPIRV_Cross_CombinedtexuSampler0, vTex);
|
||||
vec4 b = sample_dual(SPIRV_Cross_CombinedtexuSampler1);
|
||||
return (a + b);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c0 = sample_duals();
|
||||
vec4 c1 = sample_global_tex(SPIRV_Cross_CombineduTexture0uSampler0, SPIRV_Cross_CombineduTexture1uSampler0);
|
||||
vec4 c2 = sample_global_tex(SPIRV_Cross_CombineduTexture0uSampler1, SPIRV_Cross_CombineduTexture1uSampler1);
|
||||
vec4 c3 = sample_global_sampler(SPIRV_Cross_CombineduTexture0uSampler0, SPIRV_Cross_CombineduTexture0uSampler1);
|
||||
vec4 c4 = sample_global_sampler(SPIRV_Cross_CombineduTexture1uSampler0, SPIRV_Cross_CombineduTexture1uSampler1);
|
||||
FragColor = ((((c0 + c1) + c2) + c3) + c4);
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
layout(set = 0, binding = 2) uniform mediump texture2D uTexture0;
|
||||
layout(set = 0, binding = 3) uniform mediump texture2D uTexture1;
|
||||
layout(set = 0, binding = 0) uniform mediump sampler uSampler0;
|
||||
layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
|
||||
|
||||
layout(location = 0) in vec2 vTex;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 sample_dual(mediump sampler samp, mediump texture2D tex)
|
||||
{
|
||||
return texture(sampler2D(tex, samp), vTex);
|
||||
}
|
||||
|
||||
vec4 sample_duals()
|
||||
{
|
||||
vec4 a = sample_dual(uSampler0, uTexture0);
|
||||
vec4 b = sample_dual(uSampler1, uTexture1);
|
||||
return (a + b);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
layout(binding = 1) uniform mediump texture2D uTexture;
|
||||
layout(binding = 0) uniform mediump sampler uSampler;
|
||||
layout(binding = 4) uniform mediump texture2DArray uTextureArray;
|
||||
layout(binding = 3) uniform mediump textureCube uTextureCube;
|
||||
layout(binding = 2) uniform mediump texture3D uTexture3D;
|
||||
|
||||
layout(location = 0) in vec2 vTex;
|
||||
layout(location = 1) in vec3 vTex3;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 sample_func(mediump sampler samp, vec2 uv)
|
||||
{
|
||||
return texture(sampler2D(uTexture, samp), uv);
|
||||
}
|
||||
|
||||
vec4 sample_func_dual(mediump sampler samp, mediump texture2D tex, vec2 uv)
|
||||
{
|
||||
return texture(sampler2D(tex, samp), uv);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 off = (vec2(1.0) / vec2(textureSize(sampler2D(uTexture, uSampler), 0)));
|
||||
vec2 off2 = (vec2(1.0) / vec2(textureSize(sampler2D(uTexture, uSampler), 1)));
|
||||
highp vec2 param = ((vTex + off) + off2);
|
||||
vec4 c0 = sample_func(uSampler, param);
|
||||
highp vec2 param_1 = ((vTex + off) + off2);
|
||||
vec4 c1 = sample_func_dual(uSampler, uTexture, param_1);
|
||||
vec4 c2 = texture(sampler2DArray(uTextureArray, uSampler), vTex3);
|
||||
vec4 c3 = texture(samplerCube(uTextureCube, uSampler), vTex3);
|
||||
vec4 c4 = texture(sampler3D(uTexture3D, uSampler), vTex3);
|
||||
FragColor = ((((c0 + c1) + c2) + c3) + c4);
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
uniform mediump sampler2D SPIRV_Cross_CombineduTextureuSampler;
|
||||
uniform mediump sampler2DArray SPIRV_Cross_CombineduTextureArrayuSampler;
|
||||
uniform mediump samplerCube SPIRV_Cross_CombineduTextureCubeuSampler;
|
||||
uniform mediump sampler3D SPIRV_Cross_CombineduTexture3DuSampler;
|
||||
|
||||
layout(location = 0) in vec2 vTex;
|
||||
layout(location = 1) in vec3 vTex3;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 sample_func(vec2 uv, mediump sampler2D SPIRV_Cross_CombineduTexturesamp)
|
||||
{
|
||||
return texture(SPIRV_Cross_CombineduTexturesamp, uv);
|
||||
}
|
||||
|
||||
vec4 sample_func_dual(vec2 uv, mediump sampler2D SPIRV_Cross_Combinedtexsamp)
|
||||
{
|
||||
return texture(SPIRV_Cross_Combinedtexsamp, uv);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 off = (vec2(1.0) / vec2(textureSize(SPIRV_Cross_CombineduTextureuSampler, 0)));
|
||||
vec2 off2 = (vec2(1.0) / vec2(textureSize(SPIRV_Cross_CombineduTextureuSampler, 1)));
|
||||
highp vec2 param = ((vTex + off) + off2);
|
||||
vec4 c0 = sample_func(param, SPIRV_Cross_CombineduTextureuSampler);
|
||||
highp vec2 param_1 = ((vTex + off) + off2);
|
||||
vec4 c1 = sample_func_dual(param_1, SPIRV_Cross_CombineduTextureuSampler);
|
||||
vec4 c2 = texture(SPIRV_Cross_CombineduTextureArrayuSampler, vTex3);
|
||||
vec4 c3 = texture(SPIRV_Cross_CombineduTextureCubeuSampler, vTex3);
|
||||
vec4 c4 = texture(SPIRV_Cross_CombineduTexture3DuSampler, vTex3);
|
||||
FragColor = ((((c0 + c1) + c2) + c3) + c4);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
float elems[(4 + 2)];
|
||||
};
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
float t0 = 1.0;
|
||||
float t1 = 2.0;
|
||||
mediump uint c0 = (uint(3) + 0u);
|
||||
mediump int c1 = (-3);
|
||||
mediump int c2 = (~3);
|
||||
mediump int c3 = (3 + 4);
|
||||
mediump int c4 = (3 - 4);
|
||||
mediump int c5 = (3 * 4);
|
||||
mediump int c6 = (3 / 4);
|
||||
mediump uint c7 = (5u / 6u);
|
||||
mediump int c8 = (3 % 4);
|
||||
mediump uint c9 = (5u % 6u);
|
||||
mediump int c10 = (3 >> 4);
|
||||
mediump uint c11 = (5u >> 6u);
|
||||
mediump int c12 = (3 << 4);
|
||||
mediump int c13 = (3 | 4);
|
||||
mediump int c14 = (3 ^ 4);
|
||||
mediump int c15 = (3 & 4);
|
||||
bool c16 = (false || true);
|
||||
bool c17 = (false && true);
|
||||
bool c18 = (!false);
|
||||
bool c19 = (false == true);
|
||||
bool c20 = (false != true);
|
||||
bool c21 = (3 == 4);
|
||||
bool c22 = (3 != 4);
|
||||
bool c23 = (3 < 4);
|
||||
bool c24 = (5u < 6u);
|
||||
bool c25 = (3 > 4);
|
||||
bool c26 = (5u > 6u);
|
||||
bool c27 = (3 <= 4);
|
||||
bool c28 = (5u <= 6u);
|
||||
bool c29 = (3 >= 4);
|
||||
bool c30 = (5u >= 6u);
|
||||
mediump int c31 = (c8 + c3);
|
||||
mediump int c32 = int(5u + 0u);
|
||||
bool c33 = (3 != int(0u));
|
||||
bool c34 = (5u != 0u);
|
||||
mediump int c35 = int(false);
|
||||
mediump uint c36 = uint(false);
|
||||
float c37 = float(false);
|
||||
float vec0[4][(3 + 3)];
|
||||
float vec1[(3 + 2)][(4 + 5)];
|
||||
Foo foo;
|
||||
FragColor = (((vec4((t0 + t1)) + vec4(vec0[0][0])) + vec4(vec1[0][0])) + vec4(foo.elems[3]));
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
layout(constant_id = 1) const float _9 = 1.0;
|
||||
layout(constant_id = 2) const float _11 = 2.0;
|
||||
layout(constant_id = 3) const int _16 = 3;
|
||||
layout(constant_id = 4) const int _25 = 4;
|
||||
layout(constant_id = 5) const uint _34 = 5u;
|
||||
layout(constant_id = 6) const uint _35 = 6u;
|
||||
layout(constant_id = 7) const bool _56 = false;
|
||||
layout(constant_id = 8) const bool _57 = true;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
float elems[(_25 + 2)];
|
||||
};
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
float t0 = _9;
|
||||
float t1 = _11;
|
||||
mediump uint c0 = (uint(_16) + 0u);
|
||||
mediump int c1 = (-_16);
|
||||
mediump int c2 = (~_16);
|
||||
mediump int c3 = (_16 + _25);
|
||||
mediump int c4 = (_16 - _25);
|
||||
mediump int c5 = (_16 * _25);
|
||||
mediump int c6 = (_16 / _25);
|
||||
mediump uint c7 = (_34 / _35);
|
||||
mediump int c8 = (_16 % _25);
|
||||
mediump uint c9 = (_34 % _35);
|
||||
mediump int c10 = (_16 >> _25);
|
||||
mediump uint c11 = (_34 >> _35);
|
||||
mediump int c12 = (_16 << _25);
|
||||
mediump int c13 = (_16 | _25);
|
||||
mediump int c14 = (_16 ^ _25);
|
||||
mediump int c15 = (_16 & _25);
|
||||
bool c16 = (_56 || _57);
|
||||
bool c17 = (_56 && _57);
|
||||
bool c18 = (!_56);
|
||||
bool c19 = (_56 == _57);
|
||||
bool c20 = (_56 != _57);
|
||||
bool c21 = (_16 == _25);
|
||||
bool c22 = (_16 != _25);
|
||||
bool c23 = (_16 < _25);
|
||||
bool c24 = (_34 < _35);
|
||||
bool c25 = (_16 > _25);
|
||||
bool c26 = (_34 > _35);
|
||||
bool c27 = (_16 <= _25);
|
||||
bool c28 = (_34 <= _35);
|
||||
bool c29 = (_16 >= _25);
|
||||
bool c30 = (_34 >= _35);
|
||||
mediump int c31 = (c8 + c3);
|
||||
mediump int c32 = int(_34 + 0u);
|
||||
bool c33 = (_16 != int(0u));
|
||||
bool c34 = (_34 != 0u);
|
||||
mediump int c35 = int(_56);
|
||||
mediump uint c36 = uint(_56);
|
||||
float c37 = float(_56);
|
||||
float vec0[_25][(_16 + 3)];
|
||||
float vec1[(_16 + 2)][(_25 + 5)];
|
||||
Foo foo;
|
||||
FragColor = (((vec4((t0 + t1)) + vec4(vec0[0][0])) + vec4(vec1[0][0])) + vec4(foo.elems[_16]));
|
||||
}
|
||||
|
|
@ -114,9 +114,11 @@
|
|||
%21 = OpVariable %20 Function
|
||||
%34 = OpAccessChain %33 %30 %32
|
||||
%35 = OpLoad %27 %34
|
||||
; This shader has an illegal aliased store for testing purposes. spirv-val is not run for this shader.
|
||||
OpStore %21 %35
|
||||
%45 = OpLoad %19 %21
|
||||
%47 = OpAccessChain %46 %44 %32
|
||||
; This shader has an illegal aliased store for testing purposes. spirv-val is not run for this shader.
|
||||
OpStore %47 %45
|
||||
OpReturn
|
||||
OpFunctionEnd
|
|
@ -0,0 +1,20 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in VertexData {
|
||||
flat float f;
|
||||
centroid vec4 g;
|
||||
flat int h;
|
||||
float i;
|
||||
} vin;
|
||||
|
||||
layout(location = 4) in flat float f;
|
||||
layout(location = 5) in centroid vec4 g;
|
||||
layout(location = 6) in flat int h;
|
||||
layout(location = 7) in sample float i;
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = vin.f + vin.g + float(vin.h) + vin.i + f + g + float(h) + i;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) out VertexData {
|
||||
flat float f;
|
||||
centroid vec4 g;
|
||||
flat int h;
|
||||
float i;
|
||||
} vout;
|
||||
|
||||
layout(location = 4) out flat float f;
|
||||
layout(location = 5) out centroid vec4 g;
|
||||
layout(location = 6) out flat int h;
|
||||
layout(location = 7) out float i;
|
||||
|
||||
void main()
|
||||
{
|
||||
vout.f = 10.0;
|
||||
vout.g = vec4(20.0);
|
||||
vout.h = 20;
|
||||
vout.i = 30.0;
|
||||
|
||||
f = 10.0;
|
||||
g = vec4(20.0);
|
||||
h = 20;
|
||||
i = 30.0;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
layout(line_strip, max_vertices = 3) out;
|
||||
|
||||
in VertexData {
|
||||
vec3 normal;
|
||||
} vin[];
|
||||
|
||||
out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
vNormal = vin[2].normal;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices = 2) out;
|
||||
|
||||
in VertexData {
|
||||
vec3 normal;
|
||||
} vin[];
|
||||
|
||||
out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
|
||||
layout(points) in;
|
||||
layout(points, max_vertices = 3) out;
|
||||
|
||||
in VertexData {
|
||||
vec3 normal;
|
||||
} vin[];
|
||||
|
||||
out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
|
||||
layout(triangles_adjacency) in;
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
|
||||
in VertexData {
|
||||
vec3 normal;
|
||||
} vin[];
|
||||
|
||||
out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
vNormal = vin[2].normal;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_geometry_shader : require
|
||||
|
||||
layout(triangles) in;
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
|
||||
in VertexData {
|
||||
vec3 normal;
|
||||
} vin[];
|
||||
|
||||
out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
vNormal = vin[0].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
vNormal = vin[1].normal;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
vNormal = vin[2].normal;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
|
||||
layout(ccw, triangles, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
|
||||
layout(cw, triangles, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
|
||||
layout(cw, triangles, equal_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
|
||||
layout(cw, triangles, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
|
||||
layout(cw, triangles, fractional_odd_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
|
||||
layout(isolines, point_mode, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
#extension GL_EXT_tessellation_shader : require
|
||||
|
||||
layout(cw, triangles, fractional_even_spacing) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
}
|
||||
|
|
@ -140,10 +140,16 @@ vec2 lod_factor(vec2 uv)
|
|||
return vec2(floor_level, fract_level);
|
||||
}
|
||||
|
||||
#ifdef VULKAN
|
||||
#define INSTANCE_ID gl_InstanceIndex
|
||||
#else
|
||||
#define INSTANCE_ID gl_InstanceID
|
||||
#endif
|
||||
|
||||
vec2 warp_position()
|
||||
{
|
||||
float vlod = dot(LODWeights, Patches[gl_InstanceID].LODs);
|
||||
vlod = mix(vlod, Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
float vlod = dot(LODWeights, Patches[INSTANCE_ID].LODs);
|
||||
vlod = mix(vlod, Patches[INSTANCE_ID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
|
||||
#ifdef DEBUG_LOD_HEIGHT
|
||||
LODFactor = vec4(vlod);
|
||||
|
@ -171,7 +177,7 @@ vec2 warp_position()
|
|||
|
||||
void main()
|
||||
{
|
||||
vec2 PatchPos = Patches[gl_InstanceID].Position.xz * InvGroundSize_PatchScale.zw;
|
||||
vec2 PatchPos = Patches[INSTANCE_ID].Position.xz * InvGroundSize_PatchScale.zw;
|
||||
vec2 WarpedPos = warp_position();
|
||||
vec2 VertexPos = PatchPos + WarpedPos;
|
||||
vec2 NormalizedPos = VertexPos * InvGroundSize_PatchScale.xy;
|
||||
|
|
|
@ -141,10 +141,16 @@ vec2 lod_factor(vec2 uv)
|
|||
return vec2(floor_level, fract_level);
|
||||
}
|
||||
|
||||
#ifdef VULKAN
|
||||
#define INSTANCE_ID gl_InstanceIndex
|
||||
#else
|
||||
#define INSTANCE_ID gl_InstanceID
|
||||
#endif
|
||||
|
||||
vec2 warp_position()
|
||||
{
|
||||
float vlod = dot(LODWeights, Patches[gl_InstanceID].LODs);
|
||||
vlod = mix(vlod, Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
float vlod = dot(LODWeights, Patches[INSTANCE_ID].LODs);
|
||||
vlod = mix(vlod, Patches[INSTANCE_ID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||
|
||||
float floor_lod = floor(vlod);
|
||||
float fract_lod = vlod - floor_lod;
|
||||
|
@ -166,7 +172,7 @@ vec2 warp_position()
|
|||
|
||||
void main()
|
||||
{
|
||||
vec2 PatchPos = Patches[gl_InstanceID].Position.xz * InvOceanSize_PatchScale.zw;
|
||||
vec2 PatchPos = Patches[INSTANCE_ID].Position.xz * InvOceanSize_PatchScale.zw;
|
||||
vec2 WarpedPos = warp_position();
|
||||
vec2 VertexPos = PatchPos + WarpedPos;
|
||||
vec2 NormalizedPos = VertexPos * InvOceanSize_PatchScale.xy;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(constant_id = 1) const float a = 1.0;
|
||||
layout(constant_id = 2) const float b = 2.0;
|
||||
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[d][c + 3];
|
||||
float vec1[c + 2][d + 5];
|
||||
|
||||
Foo foo;
|
||||
FragColor = vec4(t0 + t1) + vec0[0][0] + vec1[0][0] + foo.elems[c];
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#ifndef SPIRV_COMMON_HPP
|
||||
#define SPIRV_COMMON_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -133,6 +134,7 @@ enum Types
|
|||
TypeBlock,
|
||||
TypeExtension,
|
||||
TypeExpression,
|
||||
TypeConstantOp,
|
||||
TypeUndef
|
||||
};
|
||||
|
||||
|
@ -149,6 +151,25 @@ struct SPIRUndef : IVariant
|
|||
uint32_t basetype;
|
||||
};
|
||||
|
||||
struct SPIRConstantOp : IVariant
|
||||
{
|
||||
enum
|
||||
{
|
||||
type = TypeConstantOp
|
||||
};
|
||||
|
||||
SPIRConstantOp(uint32_t result_type, spv::Op op, const uint32_t *args, uint32_t length)
|
||||
: opcode(op)
|
||||
, arguments(args, args + length)
|
||||
, basetype(result_type)
|
||||
{
|
||||
}
|
||||
|
||||
spv::Op opcode;
|
||||
std::vector<uint32_t> arguments;
|
||||
uint32_t basetype;
|
||||
};
|
||||
|
||||
struct SPIRType : IVariant
|
||||
{
|
||||
enum
|
||||
|
@ -181,9 +202,16 @@ struct SPIRType : IVariant
|
|||
uint32_t vecsize = 1;
|
||||
uint32_t columns = 1;
|
||||
|
||||
// Arrays, suport array of arrays by having a vector of array sizes.
|
||||
// Arrays, support array of arrays by having a vector of array sizes.
|
||||
std::vector<uint32_t> array;
|
||||
|
||||
// Array elements can be either specialization constants or specialization ops.
|
||||
// This array determines how to interpret the array size.
|
||||
// If an element is true, the element is a literal,
|
||||
// otherwise, it's an expression, which must be resolved on demand.
|
||||
// The actual size is not really known until runtime.
|
||||
std::vector<bool> array_size_literal;
|
||||
|
||||
// Pointers
|
||||
bool pointer = false;
|
||||
spv::StorageClass storage = spv::StorageClassGeneric;
|
||||
|
@ -255,7 +283,7 @@ struct SPIREntryPoint
|
|||
} workgroup_size;
|
||||
uint32_t invocations = 0;
|
||||
uint32_t output_vertices = 0;
|
||||
spv::ExecutionModel model = {};
|
||||
spv::ExecutionModel model;
|
||||
};
|
||||
|
||||
struct SPIRExpression : IVariant
|
||||
|
@ -439,12 +467,34 @@ struct SPIRFunction : IVariant
|
|||
uint32_t write_count;
|
||||
};
|
||||
|
||||
// When calling a function, and we're remapping separate image samplers,
|
||||
// resolve these arguments into combined image samplers and pass them
|
||||
// as additional arguments in this order.
|
||||
// It gets more complicated as functions can pull in their own globals
|
||||
// and combine them with parameters,
|
||||
// so we need to distinguish if something is local parameter index
|
||||
// or a global ID.
|
||||
struct CombinedImageSamplerParameter
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t image_id;
|
||||
uint32_t sampler_id;
|
||||
bool global_image;
|
||||
bool global_sampler;
|
||||
};
|
||||
|
||||
uint32_t return_type;
|
||||
uint32_t function_type;
|
||||
std::vector<Parameter> arguments;
|
||||
|
||||
// Can be used by backends to add magic arguments.
|
||||
// Currently used by combined image/sampler implementation.
|
||||
|
||||
std::vector<Parameter> shadow_arguments;
|
||||
std::vector<uint32_t> local_variables;
|
||||
uint32_t entry_block = 0;
|
||||
std::vector<uint32_t> blocks;
|
||||
std::vector<CombinedImageSamplerParameter> combined_parameters;
|
||||
|
||||
void add_local_variable(uint32_t id)
|
||||
{
|
||||
|
@ -459,6 +509,7 @@ struct SPIRFunction : IVariant
|
|||
|
||||
bool active = false;
|
||||
bool flush_undeclared = true;
|
||||
bool do_combined_parameters = true;
|
||||
};
|
||||
|
||||
struct SPIRVariable : IVariant
|
||||
|
@ -803,6 +854,7 @@ struct Meta
|
|||
uint32_t offset = 0;
|
||||
uint32_t array_stride = 0;
|
||||
uint32_t input_attachment = 0;
|
||||
uint32_t spec_id = 0;
|
||||
bool builtin = false;
|
||||
bool per_instance = false;
|
||||
};
|
||||
|
@ -811,6 +863,12 @@ struct Meta
|
|||
std::vector<Decoration> members;
|
||||
uint32_t sampler = 0;
|
||||
};
|
||||
|
||||
// A user callback that remaps the type of any variable.
|
||||
// var_name is the declared name of the variable.
|
||||
// name_of_type is the textual name of the type which will be used in the code unless written to by the callback.
|
||||
using VariableTypeRemapCallback =
|
||||
std::function<void(const SPIRType &type, const std::string &var_name, std::string &name_of_type)>;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -87,18 +87,20 @@ void CompilerCPP::emit_uniform(const SPIRVariable &var)
|
|||
uint32_t binding = meta[var.self].decoration.binding;
|
||||
uint32_t location = meta[var.self].decoration.location;
|
||||
|
||||
string type_name = type_to_glsl(type);
|
||||
remap_variable_type_name(type, instance_name, type_name);
|
||||
|
||||
if (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage ||
|
||||
type.basetype == SPIRType::AtomicCounter)
|
||||
{
|
||||
statement("internal::Resource<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
|
||||
statement("internal::Resource<", type_name, type_to_array_glsl(type), "> ", instance_name, "__;");
|
||||
statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
|
||||
resource_registrations.push_back(
|
||||
join("s.register_resource(", instance_name, "__", ", ", descriptor_set, ", ", binding, ");"));
|
||||
}
|
||||
else
|
||||
{
|
||||
statement("internal::UniformConstant<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name,
|
||||
"__;");
|
||||
statement("internal::UniformConstant<", type_name, type_to_array_glsl(type), "> ", instance_name, "__;");
|
||||
statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
|
||||
resource_registrations.push_back(
|
||||
join("s.register_uniform_constant(", instance_name, "__", ", ", location, ");"));
|
||||
|
@ -405,26 +407,32 @@ string CompilerCPP::argument_decl(const SPIRFunction::Parameter &arg)
|
|||
auto &var = get<SPIRVariable>(arg.id);
|
||||
|
||||
string base = type_to_glsl(type);
|
||||
for (auto &array : type.array)
|
||||
base = join("std::array<", base, ", ", array, ">");
|
||||
string variable_name = to_name(var.self);
|
||||
remap_variable_type_name(type, variable_name, base);
|
||||
|
||||
return join(constref ? "const " : "", base, " &", to_name(var.self));
|
||||
for (uint32_t i = 0; i < type.array.size(); i++)
|
||||
base = join("std::array<", base, ", ", to_array_size(type, i), ">");
|
||||
|
||||
return join(constref ? "const " : "", base, " &", variable_name);
|
||||
}
|
||||
|
||||
string CompilerCPP::variable_decl(const SPIRType &type, const string &name)
|
||||
{
|
||||
string base = type_to_glsl(type);
|
||||
remap_variable_type_name(type, name, base);
|
||||
bool runtime = false;
|
||||
for (auto &array : type.array)
|
||||
|
||||
for (uint32_t i = 0; i < type.array.size(); i++)
|
||||
{
|
||||
if (array)
|
||||
base = join("std::array<", base, ", ", array, ">");
|
||||
else
|
||||
auto &array = type.array[i];
|
||||
if (!array && type.array_size_literal[i])
|
||||
{
|
||||
// Avoid using runtime arrays with std::array since this is undefined.
|
||||
// Runtime arrays cannot be passed around as values, so this is fine.
|
||||
runtime = true;
|
||||
}
|
||||
else
|
||||
base = join("std::array<", base, ", ", to_array_size(type, i), ">");
|
||||
}
|
||||
base += ' ';
|
||||
return base + name + (runtime ? "[1]" : "");
|
||||
|
|
432
spirv_cross.cpp
432
spirv_cross.cpp
|
@ -319,6 +319,9 @@ const SPIRType &Compiler::expression_type(uint32_t id) const
|
|||
case TypeConstant:
|
||||
return get<SPIRType>(get<SPIRConstant>(id).constant_type);
|
||||
|
||||
case TypeConstantOp:
|
||||
return get<SPIRType>(get<SPIRConstantOp>(id).basetype);
|
||||
|
||||
case TypeUndef:
|
||||
return get<SPIRType>(get<SPIRUndef>(id).basetype);
|
||||
|
||||
|
@ -354,7 +357,8 @@ bool Compiler::is_immutable(uint32_t id) const
|
|||
}
|
||||
else if (ids[id].get_type() == TypeExpression)
|
||||
return get<SPIRExpression>(id).immutable;
|
||||
else if (ids[id].get_type() == TypeConstant || ids[id].get_type() == TypeUndef)
|
||||
else if (ids[id].get_type() == TypeConstant || ids[id].get_type() == TypeConstantOp ||
|
||||
ids[id].get_type() == TypeUndef)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -382,6 +386,14 @@ bool Compiler::is_hidden_variable(const SPIRVariable &var, bool include_builtins
|
|||
if ((is_builtin_variable(var) && !include_builtins) || var.remapped_variable)
|
||||
return true;
|
||||
|
||||
// Combined image samplers are always considered active as they are "magic" variables.
|
||||
if (find_if(begin(combined_image_samplers), end(combined_image_samplers), [&var](const CombinedImageSampler &samp) {
|
||||
return samp.combined_id == var.self;
|
||||
}) != end(combined_image_samplers))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hidden = false;
|
||||
if (check_active_interface_variables && storage_class_is_interface(var.storage))
|
||||
hidden = active_interface_variables.find(var.self) == end(active_interface_variables);
|
||||
|
@ -583,10 +595,22 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac
|
|||
res.push_constant_buffers.push_back({ var.self, var.basetype, type.self, meta[var.self].decoration.alias });
|
||||
}
|
||||
// Images
|
||||
else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image)
|
||||
else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image &&
|
||||
type.image.sampled == 2)
|
||||
{
|
||||
res.storage_images.push_back({ var.self, var.basetype, type.self, meta[var.self].decoration.alias });
|
||||
}
|
||||
// Separate images
|
||||
else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image &&
|
||||
type.image.sampled == 1)
|
||||
{
|
||||
res.separate_images.push_back({ var.self, var.basetype, type.self, meta[var.self].decoration.alias });
|
||||
}
|
||||
// Separate samplers
|
||||
else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Sampler)
|
||||
{
|
||||
res.separate_samplers.push_back({ var.self, var.basetype, type.self, meta[var.self].decoration.alias });
|
||||
}
|
||||
// Textures
|
||||
else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::SampledImage)
|
||||
{
|
||||
|
@ -794,6 +818,10 @@ void Compiler::set_member_decoration(uint32_t id, uint32_t index, Decoration dec
|
|||
dec.offset = argument;
|
||||
break;
|
||||
|
||||
case DecorationSpecId:
|
||||
dec.spec_id = argument;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -841,6 +869,8 @@ uint32_t Compiler::get_member_decoration(uint32_t id, uint32_t index, Decoration
|
|||
return dec.location;
|
||||
case DecorationOffset:
|
||||
return dec.offset;
|
||||
case DecorationSpecId:
|
||||
return dec.spec_id;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -878,6 +908,10 @@ void Compiler::unset_member_decoration(uint32_t id, uint32_t index, Decoration d
|
|||
dec.offset = 0;
|
||||
break;
|
||||
|
||||
case DecorationSpecId:
|
||||
dec.spec_id = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -919,6 +953,10 @@ void Compiler::set_decoration(uint32_t id, Decoration decoration, uint32_t argum
|
|||
dec.input_attachment = argument;
|
||||
break;
|
||||
|
||||
case DecorationSpecId:
|
||||
dec.spec_id = argument;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -960,6 +998,8 @@ uint32_t Compiler::get_decoration(uint32_t id, Decoration decoration) const
|
|||
return dec.set;
|
||||
case DecorationInputAttachmentIndex:
|
||||
return dec.input_attachment;
|
||||
case DecorationSpecId:
|
||||
return dec.spec_id;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -991,6 +1031,14 @@ void Compiler::unset_decoration(uint32_t id, Decoration decoration)
|
|||
dec.set = 0;
|
||||
break;
|
||||
|
||||
case DecorationInputAttachmentIndex:
|
||||
dec.input_attachment = 0;
|
||||
break;
|
||||
|
||||
case DecorationSpecId:
|
||||
dec.spec_id = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1064,8 +1112,8 @@ void Compiler::parse(const Instruction &instruction)
|
|||
|
||||
case OpEntryPoint:
|
||||
{
|
||||
auto itr = entry_points.emplace(ops[1], SPIREntryPoint(ops[1], static_cast<ExecutionModel>(ops[0]),
|
||||
extract_string(spirv, instruction.offset + 2)));
|
||||
auto itr = entry_points.insert(make_pair(ops[1], SPIREntryPoint(ops[1], static_cast<ExecutionModel>(ops[0]),
|
||||
extract_string(spirv, instruction.offset + 2))));
|
||||
auto &e = itr.first->second;
|
||||
|
||||
// Strings need nul-terminator and consume the whole word.
|
||||
|
@ -1223,7 +1271,12 @@ void Compiler::parse(const Instruction &instruction)
|
|||
auto &arraybase = set<SPIRType>(id);
|
||||
|
||||
arraybase = base;
|
||||
arraybase.array.push_back(get<SPIRConstant>(ops[2]).scalar());
|
||||
|
||||
auto *c = maybe_get<SPIRConstant>(ops[2]);
|
||||
bool literal = c && !c->specialization;
|
||||
|
||||
arraybase.array_size_literal.push_back(literal);
|
||||
arraybase.array.push_back(literal ? c->scalar() : ops[2]);
|
||||
// Do NOT set arraybase.self!
|
||||
break;
|
||||
}
|
||||
|
@ -1237,6 +1290,7 @@ void Compiler::parse(const Instruction &instruction)
|
|||
|
||||
arraybase = base;
|
||||
arraybase.array.push_back(0);
|
||||
arraybase.array_size_literal.push_back(true);
|
||||
// Do NOT set arraybase.self!
|
||||
break;
|
||||
}
|
||||
|
@ -1715,6 +1769,19 @@ void Compiler::parse(const Instruction &instruction)
|
|||
break;
|
||||
}
|
||||
|
||||
case OpSpecConstantOp:
|
||||
{
|
||||
if (length < 3)
|
||||
throw CompilerError("OpSpecConstantOp not enough arguments.");
|
||||
|
||||
uint32_t result_type = ops[0];
|
||||
uint32_t id = ops[1];
|
||||
auto spec_op = static_cast<Op>(ops[2]);
|
||||
|
||||
set<SPIRConstantOp>(id, result_type, spec_op, ops + 3, length - 3);
|
||||
break;
|
||||
}
|
||||
|
||||
// Actual opcodes.
|
||||
default:
|
||||
{
|
||||
|
@ -1907,8 +1974,15 @@ bool Compiler::traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHand
|
|||
if (!handler.handle(op, ops, i.length))
|
||||
return false;
|
||||
|
||||
if (op == OpFunctionCall && !traverse_all_reachable_opcodes(get<SPIRFunction>(ops[2]), handler))
|
||||
return false;
|
||||
if (op == OpFunctionCall)
|
||||
{
|
||||
if (!handler.begin_function_scope(ops, i.length))
|
||||
return false;
|
||||
if (!traverse_all_reachable_opcodes(get<SPIRFunction>(ops[2]), handler))
|
||||
return false;
|
||||
if (!handler.end_function_scope(ops, i.length))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2066,11 +2140,11 @@ std::vector<BufferRange> Compiler::get_active_buffer_ranges(uint32_t id) const
|
|||
// Returns the value of the first ID available for use in the expanded bound.
|
||||
uint32_t Compiler::increase_bound_by(uint32_t incr_amount)
|
||||
{
|
||||
uint32_t curr_bound = (uint32_t)ids.size();
|
||||
uint32_t new_bound = curr_bound + incr_amount;
|
||||
auto curr_bound = ids.size();
|
||||
auto new_bound = curr_bound + incr_amount;
|
||||
ids.resize(new_bound);
|
||||
meta.resize(new_bound);
|
||||
return curr_bound;
|
||||
return uint32_t(curr_bound);
|
||||
}
|
||||
|
||||
bool Compiler::types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const
|
||||
|
@ -2284,3 +2358,341 @@ bool Compiler::interface_variable_exists_in_entry_point(uint32_t id) const
|
|||
return find(begin(execution.interface_variables), end(execution.interface_variables), id) !=
|
||||
end(execution.interface_variables);
|
||||
}
|
||||
|
||||
void Compiler::CombinedImageSamplerHandler::push_remap_parameters(const SPIRFunction &func, const uint32_t *args,
|
||||
uint32_t length)
|
||||
{
|
||||
// If possible, pipe through a remapping table so that parameters know
|
||||
// which variables they actually bind to in this scope.
|
||||
unordered_map<uint32_t, uint32_t> remapping;
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
remapping[func.arguments[i].id] = remap_parameter(args[i]);
|
||||
parameter_remapping.push(move(remapping));
|
||||
}
|
||||
|
||||
void Compiler::CombinedImageSamplerHandler::pop_remap_parameters()
|
||||
{
|
||||
parameter_remapping.pop();
|
||||
}
|
||||
|
||||
uint32_t Compiler::CombinedImageSamplerHandler::remap_parameter(uint32_t id)
|
||||
{
|
||||
auto *var = compiler.maybe_get_backing_variable(id);
|
||||
if (var)
|
||||
id = var->self;
|
||||
|
||||
if (parameter_remapping.empty())
|
||||
return id;
|
||||
|
||||
auto &remapping = parameter_remapping.top();
|
||||
auto itr = remapping.find(id);
|
||||
if (itr != end(remapping))
|
||||
return itr->second;
|
||||
else
|
||||
return id;
|
||||
}
|
||||
|
||||
bool Compiler::CombinedImageSamplerHandler::begin_function_scope(const uint32_t *args, uint32_t length)
|
||||
{
|
||||
if (length < 3)
|
||||
return false;
|
||||
|
||||
auto &callee = compiler.get<SPIRFunction>(args[2]);
|
||||
args += 3;
|
||||
length -= 3;
|
||||
push_remap_parameters(callee, args, length);
|
||||
functions.push(&callee);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Compiler::CombinedImageSamplerHandler::end_function_scope(const uint32_t *args, uint32_t length)
|
||||
{
|
||||
if (length < 3)
|
||||
return false;
|
||||
|
||||
auto &callee = compiler.get<SPIRFunction>(args[2]);
|
||||
args += 3;
|
||||
length -= 3;
|
||||
|
||||
// There are two types of cases we have to handle,
|
||||
// a callee might call sampler2D(texture2D, sampler) directly where
|
||||
// one or more parameters originate from parameters.
|
||||
// Alternatively, we need to provide combined image samplers to our callees,
|
||||
// and in this case we need to add those as well.
|
||||
|
||||
pop_remap_parameters();
|
||||
|
||||
// Our callee has now been processed at least once.
|
||||
// No point in doing it again.
|
||||
callee.do_combined_parameters = false;
|
||||
|
||||
auto ¶ms = functions.top()->combined_parameters;
|
||||
functions.pop();
|
||||
if (functions.empty())
|
||||
return true;
|
||||
|
||||
auto &caller = *functions.top();
|
||||
if (caller.do_combined_parameters)
|
||||
{
|
||||
for (auto ¶m : params)
|
||||
{
|
||||
uint32_t image_id = param.global_image ? param.image_id : args[param.image_id];
|
||||
uint32_t sampler_id = param.global_sampler ? param.sampler_id : args[param.sampler_id];
|
||||
|
||||
auto *i = compiler.maybe_get_backing_variable(image_id);
|
||||
auto *s = compiler.maybe_get_backing_variable(sampler_id);
|
||||
if (i)
|
||||
image_id = i->self;
|
||||
if (s)
|
||||
sampler_id = s->self;
|
||||
|
||||
register_combined_image_sampler(caller, image_id, sampler_id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Compiler::CombinedImageSamplerHandler::register_combined_image_sampler(SPIRFunction &caller, uint32_t image_id,
|
||||
uint32_t sampler_id)
|
||||
{
|
||||
// We now have a texture ID and a sampler ID which will either be found as a global
|
||||
// or a parameter in our own function. If both are global, they will not need a parameter,
|
||||
// otherwise, add it to our list.
|
||||
SPIRFunction::CombinedImageSamplerParameter param = {
|
||||
0u, image_id, sampler_id, true, true,
|
||||
};
|
||||
|
||||
auto texture_itr = find_if(begin(caller.arguments), end(caller.arguments),
|
||||
[image_id](const SPIRFunction::Parameter &p) { return p.id == image_id; });
|
||||
auto sampler_itr = find_if(begin(caller.arguments), end(caller.arguments),
|
||||
[sampler_id](const SPIRFunction::Parameter &p) { return p.id == sampler_id; });
|
||||
|
||||
if (texture_itr != end(caller.arguments))
|
||||
{
|
||||
param.global_image = false;
|
||||
param.image_id = texture_itr - begin(caller.arguments);
|
||||
}
|
||||
|
||||
if (sampler_itr != end(caller.arguments))
|
||||
{
|
||||
param.global_sampler = false;
|
||||
param.sampler_id = sampler_itr - begin(caller.arguments);
|
||||
}
|
||||
|
||||
if (param.global_image && param.global_sampler)
|
||||
return;
|
||||
|
||||
auto itr = find_if(begin(caller.combined_parameters), end(caller.combined_parameters),
|
||||
[¶m](const SPIRFunction::CombinedImageSamplerParameter &p) {
|
||||
return param.image_id == p.image_id && param.sampler_id == p.sampler_id &&
|
||||
param.global_image == p.global_image && param.global_sampler == p.global_sampler;
|
||||
});
|
||||
|
||||
if (itr == end(caller.combined_parameters))
|
||||
{
|
||||
uint32_t id = compiler.increase_bound_by(3);
|
||||
auto type_id = id + 0;
|
||||
auto ptr_type_id = id + 1;
|
||||
auto combined_id = id + 2;
|
||||
auto &base = compiler.expression_type(image_id);
|
||||
auto &type = compiler.set<SPIRType>(type_id);
|
||||
auto &ptr_type = compiler.set<SPIRType>(ptr_type_id);
|
||||
|
||||
type = base;
|
||||
type.self = type_id;
|
||||
type.basetype = SPIRType::SampledImage;
|
||||
type.pointer = false;
|
||||
type.storage = StorageClassGeneric;
|
||||
|
||||
ptr_type = type;
|
||||
ptr_type.pointer = true;
|
||||
ptr_type.storage = StorageClassUniformConstant;
|
||||
|
||||
// Build new variable.
|
||||
compiler.set<SPIRVariable>(combined_id, ptr_type_id, StorageClassFunction, 0);
|
||||
|
||||
// Inherit RelaxedPrecision (and potentially other useful flags if deemed relevant).
|
||||
auto &new_flags = compiler.meta[combined_id].decoration.decoration_flags;
|
||||
auto old_flags = compiler.meta[sampler_id].decoration.decoration_flags;
|
||||
new_flags = old_flags & (1ull << DecorationRelaxedPrecision);
|
||||
|
||||
param.id = combined_id;
|
||||
|
||||
compiler.set_name(combined_id,
|
||||
join("SPIRV_Cross_Combined", compiler.to_name(image_id), compiler.to_name(sampler_id)));
|
||||
|
||||
caller.combined_parameters.push_back(param);
|
||||
caller.shadow_arguments.push_back({ ptr_type_id, combined_id, 0u, 0u });
|
||||
}
|
||||
}
|
||||
|
||||
bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
|
||||
{
|
||||
// We need to figure out where samplers and images are loaded from, so do only the bare bones compilation we need.
|
||||
switch (opcode)
|
||||
{
|
||||
case OpLoad:
|
||||
{
|
||||
if (length < 3)
|
||||
return false;
|
||||
|
||||
uint32_t result_type = args[0];
|
||||
|
||||
auto &type = compiler.get<SPIRType>(result_type);
|
||||
bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
|
||||
bool separate_sampler = type.basetype == SPIRType::Sampler;
|
||||
|
||||
// If not separate image or sampler, don't bother.
|
||||
if (!separate_image && !separate_sampler)
|
||||
return true;
|
||||
|
||||
uint32_t id = args[1];
|
||||
uint32_t ptr = args[2];
|
||||
compiler.set<SPIRExpression>(id, "", result_type, true);
|
||||
compiler.register_read(id, ptr, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
case OpInBoundsAccessChain:
|
||||
case OpAccessChain:
|
||||
{
|
||||
if (length < 3)
|
||||
return false;
|
||||
|
||||
// Technically, it is possible to have arrays of textures and arrays of samplers and combine them, but this becomes essentially
|
||||
// impossible to implement, since we don't know which concrete sampler we are accessing.
|
||||
// One potential way is to create a combinatorial explosion where N textures and M samplers are combined into N * M sampler2Ds,
|
||||
// but this seems ridiculously complicated for a problem which is easy to work around.
|
||||
// Checking access chains like this assumes we don't have samplers or textures inside uniform structs, but this makes no sense.
|
||||
|
||||
auto &type = compiler.get<SPIRType>(args[0]);
|
||||
bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
|
||||
bool separate_sampler = type.basetype == SPIRType::Sampler;
|
||||
if (separate_image)
|
||||
throw CompilerError(
|
||||
"Attempting to use arrays of separate images. This is not possible to statically remap to plain GLSL.");
|
||||
if (separate_sampler)
|
||||
throw CompilerError("Attempting to use arrays of separate samplers. This is not possible to statically "
|
||||
"remap to plain GLSL.");
|
||||
return true;
|
||||
}
|
||||
|
||||
case OpSampledImage:
|
||||
// Do it outside.
|
||||
break;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (length < 4)
|
||||
return false;
|
||||
|
||||
// Registers sampler2D calls used in case they are parameters so
|
||||
// that their callees know which combined image samplers to propagate down the call stack.
|
||||
if (!functions.empty())
|
||||
{
|
||||
auto &callee = *functions.top();
|
||||
if (callee.do_combined_parameters)
|
||||
{
|
||||
uint32_t image_id = args[2];
|
||||
|
||||
auto *image = compiler.maybe_get_backing_variable(image_id);
|
||||
if (image)
|
||||
image_id = image->self;
|
||||
|
||||
uint32_t sampler_id = args[3];
|
||||
auto *sampler = compiler.maybe_get_backing_variable(sampler_id);
|
||||
if (sampler)
|
||||
sampler_id = sampler->self;
|
||||
|
||||
register_combined_image_sampler(callee, image_id, sampler_id);
|
||||
}
|
||||
}
|
||||
|
||||
// For function calls, we need to remap IDs which are function parameters into global variables.
|
||||
// This information is statically known from the current place in the call stack.
|
||||
// Function parameters are not necessarily pointers, so if we don't have a backing variable, remapping will know
|
||||
// which backing variable the image/sample came from.
|
||||
uint32_t image_id = remap_parameter(args[2]);
|
||||
uint32_t sampler_id = remap_parameter(args[3]);
|
||||
|
||||
auto itr = find_if(begin(compiler.combined_image_samplers), end(compiler.combined_image_samplers),
|
||||
[image_id, sampler_id](const CombinedImageSampler &combined) {
|
||||
return combined.image_id == image_id && combined.sampler_id == sampler_id;
|
||||
});
|
||||
|
||||
if (itr == end(compiler.combined_image_samplers))
|
||||
{
|
||||
auto id = compiler.increase_bound_by(2);
|
||||
auto type_id = id + 0;
|
||||
auto combined_id = id + 1;
|
||||
auto sampled_type = args[0];
|
||||
|
||||
// Make a new type, pointer to OpTypeSampledImage, so we can make a variable of this type.
|
||||
// We will probably have this type lying around, but it doesn't hurt to make duplicates for internal purposes.
|
||||
auto &type = compiler.set<SPIRType>(type_id);
|
||||
auto &base = compiler.get<SPIRType>(sampled_type);
|
||||
type = base;
|
||||
type.pointer = true;
|
||||
type.storage = StorageClassUniformConstant;
|
||||
|
||||
// Build new variable.
|
||||
compiler.set<SPIRVariable>(combined_id, type_id, StorageClassUniformConstant, 0);
|
||||
|
||||
// Inherit RelaxedPrecision (and potentially other useful flags if deemed relevant).
|
||||
auto &new_flags = compiler.meta[combined_id].decoration.decoration_flags;
|
||||
auto old_flags = compiler.meta[sampler_id].decoration.decoration_flags;
|
||||
new_flags = old_flags & (1ull << DecorationRelaxedPrecision);
|
||||
|
||||
compiler.combined_image_samplers.push_back({ combined_id, image_id, sampler_id });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Compiler::build_combined_image_samplers()
|
||||
{
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() == TypeFunction)
|
||||
{
|
||||
auto &func = id.get<SPIRFunction>();
|
||||
func.combined_parameters.clear();
|
||||
func.shadow_arguments.clear();
|
||||
func.do_combined_parameters = true;
|
||||
}
|
||||
}
|
||||
|
||||
combined_image_samplers.clear();
|
||||
CombinedImageSamplerHandler handler(*this);
|
||||
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), handler);
|
||||
}
|
||||
|
||||
vector<SpecializationConstant> Compiler::get_specialization_constants() const
|
||||
{
|
||||
vector<SpecializationConstant> spec_consts;
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() == TypeConstant)
|
||||
{
|
||||
auto &c = id.get<SPIRConstant>();
|
||||
if (c.specialization)
|
||||
{
|
||||
spec_consts.push_back({ c.self, get_decoration(c.self, DecorationSpecId) });
|
||||
}
|
||||
}
|
||||
}
|
||||
return spec_consts;
|
||||
}
|
||||
|
||||
SPIRConstant &Compiler::get_constant(uint32_t id)
|
||||
{
|
||||
return get<SPIRConstant>(id);
|
||||
}
|
||||
|
||||
const SPIRConstant &Compiler::get_constant(uint32_t id) const
|
||||
{
|
||||
return get<SPIRConstant>(id);
|
||||
}
|
||||
|
|
114
spirv_cross.hpp
114
spirv_cross.hpp
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "spirv.hpp"
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
@ -73,6 +74,29 @@ struct ShaderResources
|
|||
// There can only be one push constant block,
|
||||
// but keep the vector in case this restriction is lifted in the future.
|
||||
std::vector<Resource> push_constant_buffers;
|
||||
|
||||
// For Vulkan GLSL and HLSL source,
|
||||
// these correspond to separate texture2D and samplers respectively.
|
||||
std::vector<Resource> separate_images;
|
||||
std::vector<Resource> separate_samplers;
|
||||
};
|
||||
|
||||
struct CombinedImageSampler
|
||||
{
|
||||
// The ID of the sampler2D variable.
|
||||
uint32_t combined_id;
|
||||
// The ID of the texture2D variable.
|
||||
uint32_t image_id;
|
||||
// The ID of the sampler variable.
|
||||
uint32_t sampler_id;
|
||||
};
|
||||
|
||||
struct SpecializationConstant
|
||||
{
|
||||
// The ID of the specialization constant.
|
||||
uint32_t id;
|
||||
// The constant ID of the constant, used in Vulkan during pipeline creation.
|
||||
uint32_t constant_id;
|
||||
};
|
||||
|
||||
struct BufferRange
|
||||
|
@ -237,6 +261,54 @@ public:
|
|||
uint32_t get_execution_mode_argument(spv::ExecutionMode mode, uint32_t index = 0) const;
|
||||
spv::ExecutionModel get_execution_model() const;
|
||||
|
||||
// Analyzes all separate image and samplers used from the currently selected entry point,
|
||||
// and re-routes them all to a combined image sampler instead.
|
||||
// This is required to "support" separate image samplers in targets which do not natively support
|
||||
// this feature, like GLSL/ESSL.
|
||||
//
|
||||
// This must be called before compile() if such remapping is desired.
|
||||
// This call will add new sampled images to the SPIR-V,
|
||||
// so it will appear in reflection if get_shader_resources() is called after build_combined_image_samplers.
|
||||
//
|
||||
// If any image/sampler remapping was found, no separate image/samplers will appear in the decompiled output,
|
||||
// but will still appear in reflection.
|
||||
//
|
||||
// The resulting samplers will be void of any decorations like name, descriptor sets and binding points,
|
||||
// so this can be added before compile() if desired.
|
||||
//
|
||||
// Combined image samplers originating from this set are always considered active variables.
|
||||
void build_combined_image_samplers();
|
||||
|
||||
// Gets a remapping for the combined image samplers.
|
||||
const std::vector<CombinedImageSampler> &get_combined_image_samplers() const
|
||||
{
|
||||
return combined_image_samplers;
|
||||
}
|
||||
|
||||
// Set a new variable type remap callback.
|
||||
// The type remapping is designed to allow global interface variable to assume more special types.
|
||||
// A typical example here is to remap sampler2D into samplerExternalOES, which currently isn't supported
|
||||
// directly by SPIR-V.
|
||||
//
|
||||
// In compile() while emitting code,
|
||||
// for every variable that is declared, including function parameters, the callback will be called
|
||||
// and the API user has a chance to change the textual representation of the type used to declare the variable.
|
||||
// The API user can detect special patterns in names to guide the remapping.
|
||||
void set_variable_type_remap_callback(VariableTypeRemapCallback cb)
|
||||
{
|
||||
variable_remap_callback = std::move(cb);
|
||||
}
|
||||
|
||||
// API for querying which specialization constants exist.
|
||||
// To modify a specialization constant before compile(), use get_constant(constant.id),
|
||||
// then update constants directly in the SPIRConstant data structure.
|
||||
// For composite types, the subconstants can be iterated over and modified.
|
||||
// constant_type is the SPIRType for the specialization constant,
|
||||
// which can be queried to determine which fields in the unions should be poked at.
|
||||
std::vector<SpecializationConstant> get_specialization_constants() const;
|
||||
SPIRConstant &get_constant(uint32_t id);
|
||||
const SPIRConstant &get_constant(uint32_t id) const;
|
||||
|
||||
protected:
|
||||
const uint32_t *stream(const Instruction &instr) const
|
||||
{
|
||||
|
@ -393,6 +465,14 @@ protected:
|
|||
// variable is part of that entry points interface.
|
||||
bool interface_variable_exists_in_entry_point(uint32_t id) const;
|
||||
|
||||
std::vector<CombinedImageSampler> combined_image_samplers;
|
||||
|
||||
void remap_variable_type_name(const SPIRType &type, const std::string &var_name, std::string &type_name) const
|
||||
{
|
||||
if (variable_remap_callback)
|
||||
variable_remap_callback(type, var_name, type_name);
|
||||
}
|
||||
|
||||
private:
|
||||
void parse();
|
||||
void parse(const Instruction &i);
|
||||
|
@ -405,6 +485,16 @@ private:
|
|||
// Return true if traversal should continue.
|
||||
// If false, traversal will end immediately.
|
||||
virtual bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) = 0;
|
||||
|
||||
virtual bool begin_function_scope(const uint32_t *, uint32_t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool end_function_scope(const uint32_t *, uint32_t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct BufferAccessHandler : OpcodeHandler
|
||||
|
@ -439,12 +529,36 @@ private:
|
|||
std::unordered_set<uint32_t> &variables;
|
||||
};
|
||||
|
||||
struct CombinedImageSamplerHandler : OpcodeHandler
|
||||
{
|
||||
CombinedImageSamplerHandler(Compiler &compiler_)
|
||||
: compiler(compiler_)
|
||||
{
|
||||
}
|
||||
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
|
||||
bool begin_function_scope(const uint32_t *args, uint32_t length) override;
|
||||
bool end_function_scope(const uint32_t *args, uint32_t length) override;
|
||||
|
||||
Compiler &compiler;
|
||||
|
||||
// Each function in the call stack needs its own remapping for parameters so we can deduce which global variable each texture/sampler the parameter is statically bound to.
|
||||
std::stack<std::unordered_map<uint32_t, uint32_t>> parameter_remapping;
|
||||
std::stack<SPIRFunction *> functions;
|
||||
|
||||
uint32_t remap_parameter(uint32_t id);
|
||||
void push_remap_parameters(const SPIRFunction &func, const uint32_t *args, uint32_t length);
|
||||
void pop_remap_parameters();
|
||||
void register_combined_image_sampler(SPIRFunction &caller, uint32_t texture_id, uint32_t sampler_id);
|
||||
};
|
||||
|
||||
bool traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const;
|
||||
bool traverse_all_reachable_opcodes(const SPIRFunction &block, OpcodeHandler &handler) const;
|
||||
// This must be an ordered data structure so we always pick the same type aliases.
|
||||
std::vector<uint32_t> global_struct_cache;
|
||||
|
||||
ShaderResources get_shader_resources(const std::unordered_set<uint32_t> *active_variables) const;
|
||||
|
||||
VariableTypeRemapCallback variable_remap_callback;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
768
spirv_glsl.cpp
768
spirv_glsl.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -144,6 +144,7 @@ protected:
|
|||
virtual std::string member_decl(const SPIRType &type, const SPIRType &member_type, uint32_t member);
|
||||
virtual std::string image_type_glsl(const SPIRType &type);
|
||||
virtual std::string constant_expression(const SPIRConstant &c);
|
||||
std::string constant_op_expression(const SPIRConstantOp &cop);
|
||||
virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
|
||||
virtual void emit_fixup();
|
||||
virtual std::string variable_decl(const SPIRType &type, const std::string &name);
|
||||
|
@ -204,6 +205,8 @@ protected:
|
|||
Options options;
|
||||
|
||||
std::string type_to_array_glsl(const SPIRType &type);
|
||||
std::string to_array_size(const SPIRType &type, uint32_t index);
|
||||
uint32_t to_array_size_literal(const SPIRType &type, uint32_t index) const;
|
||||
std::string variable_decl(const SPIRVariable &variable);
|
||||
|
||||
void add_local_variable_name(uint32_t id);
|
||||
|
@ -241,6 +244,7 @@ protected:
|
|||
void emit_push_constant_block_glsl(const SPIRVariable &var);
|
||||
void emit_interface_block(const SPIRVariable &type);
|
||||
void emit_block_chain(SPIRBlock &block);
|
||||
void emit_specialization_constant(const SPIRConstant &constant);
|
||||
std::string emit_continue_block(uint32_t continue_block);
|
||||
bool attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method method);
|
||||
void emit_uniform(const SPIRVariable &var);
|
||||
|
@ -255,6 +259,7 @@ protected:
|
|||
|
||||
bool should_forward(uint32_t id);
|
||||
void emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, uint32_t right, uint32_t lerp);
|
||||
bool to_trivial_mix_op(const SPIRType &type, std::string &op, uint32_t left, uint32_t right, uint32_t lerp);
|
||||
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, uint32_t count);
|
||||
void emit_quaternary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2,
|
||||
uint32_t op3, const char *op);
|
||||
|
@ -281,7 +286,7 @@ protected:
|
|||
const char *index_to_swizzle(uint32_t index);
|
||||
std::string remap_swizzle(uint32_t result_type, uint32_t input_components, uint32_t expr);
|
||||
std::string declare_temporary(uint32_t type, uint32_t id);
|
||||
std::string static_func_args(const SPIRFunction &func, uint32_t index);
|
||||
void append_global_func_args(const SPIRFunction &func, uint32_t index, std::vector<std::string> &arglist);
|
||||
std::string to_expression(uint32_t id);
|
||||
std::string to_member_name(const SPIRType &type, uint32_t index);
|
||||
std::string type_to_glsl_constructor(const SPIRType &type);
|
||||
|
@ -291,8 +296,11 @@ protected:
|
|||
const char *flags_to_precision_qualifiers_glsl(const SPIRType &type, uint64_t flags);
|
||||
const char *format_to_glsl(spv::ImageFormat format);
|
||||
std::string layout_for_member(const SPIRType &type, uint32_t index);
|
||||
std::string to_interpolation_qualifiers(uint64_t flags);
|
||||
uint64_t 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);
|
||||
bool skip_argument(uint32_t id) const;
|
||||
|
||||
bool ssbo_is_std430_packing(const SPIRType &type);
|
||||
uint32_t type_to_std430_base_size(const SPIRType &type);
|
||||
|
@ -337,6 +345,16 @@ protected:
|
|||
return (options.es && options.version < 300) || (!options.es && options.version < 130);
|
||||
}
|
||||
|
||||
inline bool is_legacy_es() const
|
||||
{
|
||||
return options.es && options.version < 300;
|
||||
}
|
||||
|
||||
inline bool is_legacy_desktop() const
|
||||
{
|
||||
return !options.es && options.version < 130;
|
||||
}
|
||||
|
||||
bool args_will_forward(uint32_t id, const uint32_t *args, uint32_t num_args, bool pure);
|
||||
void register_call_out_argument(uint32_t id);
|
||||
void register_impure_function_call();
|
||||
|
|
|
@ -31,8 +31,6 @@ CompilerMSL::CompilerMSL(vector<uint32_t> spirv_)
|
|||
string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_vtx_attrs,
|
||||
std::vector<MSLResourceBinding> *p_res_bindings)
|
||||
{
|
||||
next_metal_resource_index = MSLResourceBinding(); // Start bindings at zero
|
||||
|
||||
pad_type_ids_by_pad_len.clear();
|
||||
|
||||
msl_config = msl_cfg;
|
||||
|
@ -48,7 +46,7 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_
|
|||
resource_bindings.clear();
|
||||
if (p_res_bindings)
|
||||
{
|
||||
resource_bindings.reserve(p_vtx_attrs->size());
|
||||
resource_bindings.reserve(p_res_bindings->size());
|
||||
for (auto &rb : *p_res_bindings)
|
||||
{
|
||||
rb.used_by_shader = false;
|
||||
|
@ -79,6 +77,8 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_
|
|||
|
||||
reset();
|
||||
|
||||
next_metal_resource_index = MSLResourceBinding(); // Start bindings at zero
|
||||
|
||||
// Move constructor for this type is broken on GCC 4.9 ...
|
||||
buffer = unique_ptr<ostringstream>(new ostringstream());
|
||||
|
||||
|
@ -502,6 +502,9 @@ uint32_t CompilerMSL::add_interface_struct(StorageClass storage, uint32_t vtx_bi
|
|||
// Emits the file header info
|
||||
void CompilerMSL::emit_header()
|
||||
{
|
||||
for (auto &header : header_lines)
|
||||
statement(header);
|
||||
|
||||
statement("#include <metal_stdlib>");
|
||||
statement("#include <simd/simd.h>");
|
||||
statement("");
|
||||
|
@ -1108,7 +1111,8 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|||
return "";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
uint32_t locn = get_ordered_member_location(type.self, index);
|
||||
return string(" [[color(") + convert_to_string(locn) + ")]]";
|
||||
}
|
||||
|
||||
return "";
|
||||
|
@ -1399,6 +1403,7 @@ SPIRType &CompilerMSL::get_pad_type(uint32_t pad_len)
|
|||
ib_type.basetype = SPIRType::Char;
|
||||
ib_type.width = 8;
|
||||
ib_type.array.push_back(pad_len);
|
||||
ib_type.array_size_literal.push_back(true);
|
||||
set_decoration(ib_type.self, DecorationArrayStride, pad_len);
|
||||
|
||||
pad_type_ids_by_pad_len[pad_len] = pad_type_id;
|
||||
|
@ -1767,7 +1772,7 @@ size_t CompilerMSL::get_declared_type_size(const SPIRType &type, uint64_t dec_ma
|
|||
// ArrayStride is part of the array type not OpMemberDecorate.
|
||||
auto &dec = meta[type.self].decoration;
|
||||
if (dec.decoration_flags & (1ull << DecorationArrayStride))
|
||||
return dec.array_stride * type.array.back();
|
||||
return dec.array_stride * to_array_size_literal(type, type.array.size() - 1);
|
||||
else
|
||||
throw CompilerError("Type does not have ArrayStride set.");
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ def validate_shader(shader, vulkan):
|
|||
else:
|
||||
subprocess.check_call(['glslangValidator', shader])
|
||||
|
||||
def cross_compile(shader, vulkan, spirv, eliminate):
|
||||
def cross_compile(shader, vulkan, spirv, eliminate, invalid_spirv):
|
||||
spirv_f, spirv_path = tempfile.mkstemp()
|
||||
glsl_f, glsl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
|
||||
os.close(spirv_f)
|
||||
|
@ -79,11 +79,10 @@ def cross_compile(shader, vulkan, spirv, eliminate):
|
|||
if spirv:
|
||||
subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
|
||||
else:
|
||||
subprocess.check_call(['glslangValidator', '-V' if vulkan else '-G', '-o', spirv_path, shader])
|
||||
subprocess.check_call(['glslangValidator', '-V', '-o', spirv_path, shader])
|
||||
|
||||
# Workaround Issue #217 in SPIRV-Tools until the issue is resolved.
|
||||
#if spirv:
|
||||
# subprocess.check_call(['spirv-val', spirv_path])
|
||||
if not invalid_spirv:
|
||||
subprocess.check_call(['spirv-val', spirv_path])
|
||||
|
||||
spirv_cross_path = './spirv-cross'
|
||||
if eliminate:
|
||||
|
@ -161,18 +160,22 @@ def shader_is_eliminate_dead_variables(shader):
|
|||
def shader_is_spirv(shader):
|
||||
return '.asm.' in shader
|
||||
|
||||
def shader_is_invalid_spirv(shader):
|
||||
return '.invalid.' in shader
|
||||
|
||||
def test_shader(stats, shader, update, keep):
|
||||
joined_path = os.path.join(shader[0], shader[1])
|
||||
vulkan = shader_is_vulkan(shader[1])
|
||||
desktop = shader_is_desktop(shader[1])
|
||||
eliminate = shader_is_eliminate_dead_variables(shader[1])
|
||||
spirv = shader_is_spirv(shader[1])
|
||||
is_spirv = shader_is_spirv(shader[1])
|
||||
invalid_spirv = shader_is_invalid_spirv(shader[1])
|
||||
|
||||
print('Testing shader:', joined_path)
|
||||
spirv, glsl, vulkan_glsl = cross_compile(joined_path, vulkan, spirv, eliminate)
|
||||
spirv, glsl, vulkan_glsl = cross_compile(joined_path, vulkan, is_spirv, eliminate, invalid_spirv)
|
||||
|
||||
# Only test GLSL stats if we have a shader following GL semantics.
|
||||
if stats and (not vulkan) and (not spirv) and (not desktop):
|
||||
if stats and (not vulkan) and (not is_spirv) and (not desktop):
|
||||
cross_stats = get_shader_stats(glsl)
|
||||
|
||||
regression_check(shader, glsl, update, keep)
|
||||
|
@ -180,7 +183,7 @@ def test_shader(stats, shader, update, keep):
|
|||
regression_check((shader[0], shader[1] + '.vk'), vulkan_glsl, update, keep)
|
||||
os.remove(spirv)
|
||||
|
||||
if stats and (not vulkan):
|
||||
if stats and (not vulkan) and (not is_spirv) and (not desktop):
|
||||
pristine_stats = get_shader_stats(joined_path)
|
||||
|
||||
a = []
|
||||
|
|
Загрузка…
Ссылка в новой задаче