Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2019-01-17 21:42:05 +0300
committerGitHub <noreply@github.com>2019-01-17 21:42:05 +0300
commit1040cf6cc1e677c179488753dfb78e7326fd759a (patch)
treea1170dbb4c2488bf2a0592326195747c32192135
parentd322087d70fa3e5b40561d22469382eeb33ca1ed (diff)
parentf500d2f70c1334b0239ad99c3c84a81d499869e8 (diff)
Merge pull request #831 from cdavis5e/force-recompile-hooks2019-01-17
MSL: Hoist fixup hooks in entry_point_args() out of the compile loop.
-rw-r--r--reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp138
-rw-r--r--reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp139
-rw-r--r--shaders-msl/comp/force-recompile-hooks.swizzle.comp9
-rw-r--r--spirv_msl.cpp95
-rw-r--r--spirv_msl.hpp1
5 files changed, 350 insertions, 32 deletions
diff --git a/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp b/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp
new file mode 100644
index 00000000..267cc518
--- /dev/null
+++ b/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp
@@ -0,0 +1,138 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct spvAux
+{
+ uint swizzleConst[1];
+};
+
+enum class spvSwizzle : uint
+{
+ none = 0,
+ zero,
+ one,
+ red,
+ green,
+ blue,
+ alpha
+};
+
+template<typename T> struct spvRemoveReference { typedef T type; };
+template<typename T> struct spvRemoveReference<thread T&> { typedef T type; };
+template<typename T> struct spvRemoveReference<thread T&&> { typedef T type; };
+template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type& x)
+{
+ return static_cast<thread T&&>(x);
+}
+template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type&& x)
+{
+ return static_cast<thread T&&>(x);
+}
+
+template<typename T>
+inline T spvGetSwizzle(vec<T, 4> x, T c, spvSwizzle s)
+{
+ switch (s)
+ {
+ case spvSwizzle::none:
+ return c;
+ case spvSwizzle::zero:
+ return 0;
+ case spvSwizzle::one:
+ return 1;
+ case spvSwizzle::red:
+ return x.r;
+ case spvSwizzle::green:
+ return x.g;
+ case spvSwizzle::blue:
+ return x.b;
+ case spvSwizzle::alpha:
+ return x.a;
+ }
+}
+
+// Wrapper function that swizzles texture samples and fetches.
+template<typename T>
+inline vec<T, 4> spvTextureSwizzle(vec<T, 4> x, uint s)
+{
+ if (!s)
+ return x;
+ return vec<T, 4>(spvGetSwizzle(x, x.r, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, x.g, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, x.b, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, x.a, spvSwizzle((s >> 24) & 0xFF)));
+}
+
+template<typename T>
+inline T spvTextureSwizzle(T x, uint s)
+{
+ return spvTextureSwizzle(vec<T, 4>(x, 0, 0, 1), s).x;
+}
+
+// Wrapper function that swizzles texture gathers.
+template<typename T, typename Tex, typename... Ts>
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+{
+ if (sw)
+ {
+ switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF))
+ {
+ case spvSwizzle::none:
+ break;
+ case spvSwizzle::zero:
+ return vec<T, 4>(0, 0, 0, 0);
+ case spvSwizzle::one:
+ return vec<T, 4>(1, 1, 1, 1);
+ case spvSwizzle::red:
+ return t.gather(s, spvForward<Ts>(params)..., component::x);
+ case spvSwizzle::green:
+ return t.gather(s, spvForward<Ts>(params)..., component::y);
+ case spvSwizzle::blue:
+ return t.gather(s, spvForward<Ts>(params)..., component::z);
+ case spvSwizzle::alpha:
+ return t.gather(s, spvForward<Ts>(params)..., component::w);
+ }
+ }
+ switch (c)
+ {
+ case component::x:
+ return t.gather(s, spvForward<Ts>(params)..., component::x);
+ case component::y:
+ return t.gather(s, spvForward<Ts>(params)..., component::y);
+ case component::z:
+ return t.gather(s, spvForward<Ts>(params)..., component::z);
+ case component::w:
+ return t.gather(s, spvForward<Ts>(params)..., component::w);
+ }
+}
+
+// Wrapper function that swizzles depth texture gathers.
+template<typename T, typename Tex, typename... Ts>
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw)
+{
+ if (sw)
+ {
+ switch (spvSwizzle(sw & 0xFF))
+ {
+ case spvSwizzle::none:
+ case spvSwizzle::red:
+ break;
+ case spvSwizzle::zero:
+ case spvSwizzle::green:
+ case spvSwizzle::blue:
+ case spvSwizzle::alpha:
+ return vec<T, 4>(0, 0, 0, 0);
+ case spvSwizzle::one:
+ return vec<T, 4>(1, 1, 1, 1);
+ }
+ }
+ return t.gather_compare(s, spvForward<Ts>(params)...);
+}
+
+kernel void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
+{
+ constant uint32_t& fooSwzl = spvAuxBuffer.swizzleConst[0];
+ bar.write(spvTextureSwizzle(foo.sample(fooSmplr, float2(1.0), level(0.0)), fooSwzl), uint2(int2(0)));
+}
+
diff --git a/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp b/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp
new file mode 100644
index 00000000..667819dc
--- /dev/null
+++ b/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp
@@ -0,0 +1,139 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct spvAux
+{
+ uint swizzleConst[1];
+};
+
+enum class spvSwizzle : uint
+{
+ none = 0,
+ zero,
+ one,
+ red,
+ green,
+ blue,
+ alpha
+};
+
+template<typename T> struct spvRemoveReference { typedef T type; };
+template<typename T> struct spvRemoveReference<thread T&> { typedef T type; };
+template<typename T> struct spvRemoveReference<thread T&&> { typedef T type; };
+template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type& x)
+{
+ return static_cast<thread T&&>(x);
+}
+template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type&& x)
+{
+ return static_cast<thread T&&>(x);
+}
+
+template<typename T>
+inline T spvGetSwizzle(vec<T, 4> x, T c, spvSwizzle s)
+{
+ switch (s)
+ {
+ case spvSwizzle::none:
+ return c;
+ case spvSwizzle::zero:
+ return 0;
+ case spvSwizzle::one:
+ return 1;
+ case spvSwizzle::red:
+ return x.r;
+ case spvSwizzle::green:
+ return x.g;
+ case spvSwizzle::blue:
+ return x.b;
+ case spvSwizzle::alpha:
+ return x.a;
+ }
+}
+
+// Wrapper function that swizzles texture samples and fetches.
+template<typename T>
+inline vec<T, 4> spvTextureSwizzle(vec<T, 4> x, uint s)
+{
+ if (!s)
+ return x;
+ return vec<T, 4>(spvGetSwizzle(x, x.r, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, x.g, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, x.b, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, x.a, spvSwizzle((s >> 24) & 0xFF)));
+}
+
+template<typename T>
+inline T spvTextureSwizzle(T x, uint s)
+{
+ return spvTextureSwizzle(vec<T, 4>(x, 0, 0, 1), s).x;
+}
+
+// Wrapper function that swizzles texture gathers.
+template<typename T, typename Tex, typename... Ts>
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+{
+ if (sw)
+ {
+ switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF))
+ {
+ case spvSwizzle::none:
+ break;
+ case spvSwizzle::zero:
+ return vec<T, 4>(0, 0, 0, 0);
+ case spvSwizzle::one:
+ return vec<T, 4>(1, 1, 1, 1);
+ case spvSwizzle::red:
+ return t.gather(s, spvForward<Ts>(params)..., component::x);
+ case spvSwizzle::green:
+ return t.gather(s, spvForward<Ts>(params)..., component::y);
+ case spvSwizzle::blue:
+ return t.gather(s, spvForward<Ts>(params)..., component::z);
+ case spvSwizzle::alpha:
+ return t.gather(s, spvForward<Ts>(params)..., component::w);
+ }
+ }
+ switch (c)
+ {
+ case component::x:
+ return t.gather(s, spvForward<Ts>(params)..., component::x);
+ case component::y:
+ return t.gather(s, spvForward<Ts>(params)..., component::y);
+ case component::z:
+ return t.gather(s, spvForward<Ts>(params)..., component::z);
+ case component::w:
+ return t.gather(s, spvForward<Ts>(params)..., component::w);
+ }
+}
+
+// Wrapper function that swizzles depth texture gathers.
+template<typename T, typename Tex, typename... Ts>
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw)
+{
+ if (sw)
+ {
+ switch (spvSwizzle(sw & 0xFF))
+ {
+ case spvSwizzle::none:
+ case spvSwizzle::red:
+ break;
+ case spvSwizzle::zero:
+ case spvSwizzle::green:
+ case spvSwizzle::blue:
+ case spvSwizzle::alpha:
+ return vec<T, 4>(0, 0, 0, 0);
+ case spvSwizzle::one:
+ return vec<T, 4>(1, 1, 1, 1);
+ }
+ }
+ return t.gather_compare(s, spvForward<Ts>(params)...);
+}
+
+kernel void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
+{
+ constant uint32_t& fooSwzl = spvAuxBuffer.swizzleConst[0];
+ float4 a = spvTextureSwizzle(foo.sample(fooSmplr, float2(1.0), level(0.0)), fooSwzl);
+ bar.write(a, uint2(int2(0)));
+}
+
diff --git a/shaders-msl/comp/force-recompile-hooks.swizzle.comp b/shaders-msl/comp/force-recompile-hooks.swizzle.comp
new file mode 100644
index 00000000..2752d305
--- /dev/null
+++ b/shaders-msl/comp/force-recompile-hooks.swizzle.comp
@@ -0,0 +1,9 @@
+#version 450
+
+layout(binding = 0) uniform sampler2D foo;
+layout(binding = 1, rgba8) uniform image2D bar;
+
+void main() {
+ vec4 a = texture(foo, vec2(1, 1));
+ imageStore(bar, ivec2(0, 0), a);
+}
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index 87b00ea1..976722a8 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -447,6 +447,10 @@ string CompilerMSL::compile()
// Mark any non-stage-in structs to be tightly packed.
mark_packable_structs();
+ // Add fixup hooks required by shader inputs and outputs. This needs to happen before
+ // the loop, so the hooks aren't added multiple times.
+ fix_up_shader_inputs_outputs();
+
uint32_t pass_count = 0;
do
{
@@ -4463,17 +4467,6 @@ string CompilerMSL::entry_point_args(bool append_comma)
resources.push_back(
{ &id, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype) });
}
-
- if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type))
- {
- auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
- entry_func.fixup_hooks_in.push_back([this, &var, var_id]() {
- auto &aux_type = expression_type(aux_buffer_id);
- statement("constant uint32_t& ", to_swizzle_expression(var_id), " = ", to_name(aux_buffer_id), ".",
- to_member_name(aux_type, k_aux_mbr_idx_swizzle_const), "[",
- convert_to_string(get_metal_resource_index(var, SPIRType::Image)), "];");
- });
- }
}
});
@@ -4554,27 +4547,7 @@ string CompilerMSL::entry_point_args(bool append_comma)
// point, we get that by calling get_sample_position() on the sample ID.
if (var.storage == StorageClassInput && is_builtin_variable(var))
{
- if (bi_type == BuiltInSamplePosition)
- {
- auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
- entry_func.fixup_hooks_in.push_back([=]() {
- statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = get_sample_position(",
- to_expression(builtin_sample_id_id), ");");
- });
- }
- else if (bi_type == BuiltInHelperInvocation)
- {
- if (msl_options.is_ios())
- SPIRV_CROSS_THROW("simd_is_helper_thread() is only supported on macOS.");
- else if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 1))
- SPIRV_CROSS_THROW("simd_is_helper_thread() requires version 2.1 on macOS.");
-
- auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
- entry_func.fixup_hooks_in.push_back([=]() {
- statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = simd_is_helper_thread();");
- });
- }
- else
+ if (bi_type != BuiltInSamplePosition && bi_type != BuiltInHelperInvocation)
{
if (!ep_args.empty())
ep_args += ", ";
@@ -4598,6 +4571,64 @@ string CompilerMSL::entry_point_args(bool append_comma)
return ep_args;
}
+void CompilerMSL::fix_up_shader_inputs_outputs()
+{
+ // Look for sampled images. Add hooks to set up the swizzle constants.
+ ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+ auto &type = get_variable_data_type(var);
+
+ uint32_t var_id = var.self;
+
+ if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
+ var.storage == StorageClassPushConstant || var.storage == StorageClassStorageBuffer) &&
+ !is_hidden_variable(var))
+ {
+ if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type))
+ {
+ auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
+ entry_func.fixup_hooks_in.push_back([this, &var, var_id]() {
+ auto &aux_type = expression_type(aux_buffer_id);
+ statement("constant uint32_t& ", to_swizzle_expression(var_id), " = ", to_name(aux_buffer_id), ".",
+ to_member_name(aux_type, k_aux_mbr_idx_swizzle_const), "[",
+ convert_to_string(get_metal_resource_index(var, SPIRType::Image)), "];");
+ });
+ }
+ }
+ });
+
+ // Builtin variables
+ ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+ uint32_t var_id = var.self;
+ BuiltIn bi_type = ir.meta[var_id].decoration.builtin_type;
+
+ if (var.storage == StorageClassInput && is_builtin_variable(var))
+ {
+ auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
+ switch (bi_type)
+ {
+ case BuiltInSamplePosition:
+ entry_func.fixup_hooks_in.push_back([=]() {
+ statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = get_sample_position(",
+ to_expression(builtin_sample_id_id), ");");
+ });
+ break;
+ case BuiltInHelperInvocation:
+ if (msl_options.is_ios())
+ SPIRV_CROSS_THROW("simd_is_helper_thread() is only supported on macOS.");
+ else if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 1))
+ SPIRV_CROSS_THROW("simd_is_helper_thread() requires version 2.1 on macOS.");
+
+ entry_func.fixup_hooks_in.push_back([=]() {
+ statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = simd_is_helper_thread();");
+ });
+ break;
+ default:
+ break;
+ }
+ }
+ });
+}
+
// Returns the Metal index of the resource of the specified type as used by the specified variable.
uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::BaseType basetype)
{
diff --git a/spirv_msl.hpp b/spirv_msl.hpp
index 8fcb224b..3ea5b4d0 100644
--- a/spirv_msl.hpp
+++ b/spirv_msl.hpp
@@ -392,6 +392,7 @@ protected:
void emit_interface_block(uint32_t ib_var_id);
bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
void add_convert_row_major_matrix_function(uint32_t cols, uint32_t rows);
+ void fix_up_shader_inputs_outputs();
std::string func_type_decl(SPIRType &type);
std::string entry_point_args(bool append_comma);