Merge pull request #803 from KhronosGroup/fix-796
MSL: Workaround missing gradient2d() on macOS for typical cascaded shadow mapping
This commit is contained in:
commit
e6cce63679
@ -0,0 +1,22 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vUV [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], depth2d_array<float> uTex [[texture(0)]], sampler uShadow [[sampler(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uTex.sample_compare(uShadow, in.vUV.xy, uint(round(in.vUV.z)), in.vUV.w, level(0));
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vUV [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], depth2d_array<float> uTex [[texture(0)]], sampler uShadow [[sampler(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uTex.sample_compare(uShadow, in.vUV.xy, uint(round(in.vUV.z)), in.vUV.w, gradient2d(float2(0.0), float2(0.0)));
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vUV [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], depth2d_array<float> uTex [[texture(0)]], sampler uShadow [[sampler(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uTex.sample_compare(uShadow, in.vUV.xy, uint(round(in.vUV.z)), in.vUV.w, level(0));
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vUV [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], depth2d_array<float> uTex [[texture(0)]], sampler uShadow [[sampler(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uTex.sample_compare(uShadow, in.vUV.xy, uint(round(in.vUV.z)), in.vUV.w, gradient2d(float2(0.0), float2(0.0)));
|
||||
return out;
|
||||
}
|
||||
|
11
shaders-msl/frag/sampler-compare-cascade-gradient.frag
Normal file
11
shaders-msl/frag/sampler-compare-cascade-gradient.frag
Normal file
@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
layout(binding = 0) uniform texture2DArray uTex;
|
||||
layout(binding = 1) uniform samplerShadow uShadow;
|
||||
layout(location = 0) in vec4 vUV;
|
||||
layout(location = 0) out float FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = textureGrad(sampler2DArrayShadow(uTex, uShadow), vUV, vec2(0.0), vec2(0.0));
|
||||
}
|
11
shaders-msl/frag/sampler-compare-cascade-gradient.ios.frag
Normal file
11
shaders-msl/frag/sampler-compare-cascade-gradient.ios.frag
Normal file
@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
layout(binding = 0) uniform texture2DArray uTex;
|
||||
layout(binding = 1) uniform samplerShadow uShadow;
|
||||
layout(location = 0) in vec4 vUV;
|
||||
layout(location = 0) out float FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = textureGrad(sampler2DArrayShadow(uTex, uShadow), vUV, vec2(0.0), vec2(0.0));
|
||||
}
|
@ -1088,6 +1088,21 @@ struct SPIRConstant : IVariant
|
||||
c.vecsize = constant_type_.vecsize;
|
||||
}
|
||||
|
||||
inline bool constant_is_null() const
|
||||
{
|
||||
if (specialization)
|
||||
return false;
|
||||
if (!subconstants.empty())
|
||||
return false;
|
||||
|
||||
for (uint32_t col = 0; col < columns(); col++)
|
||||
for (uint32_t row = 0; row < vector_size(); row++)
|
||||
if (scalar_u64(col, row) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
explicit SPIRConstant(uint32_t constant_type_)
|
||||
: constant_type(constant_type_)
|
||||
{
|
||||
|
@ -901,8 +901,8 @@ void Compiler::flatten_interface_block(uint32_t id)
|
||||
var.storage = storage;
|
||||
}
|
||||
|
||||
void Compiler::update_name_cache(unordered_set<string> &cache_primary,
|
||||
const unordered_set<string> &cache_secondary, string &name)
|
||||
void Compiler::update_name_cache(unordered_set<string> &cache_primary, const unordered_set<string> &cache_secondary,
|
||||
string &name)
|
||||
{
|
||||
if (name.empty())
|
||||
return;
|
||||
@ -918,9 +918,7 @@ void Compiler::update_name_cache(unordered_set<string> &cache_primary,
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto insert_name = [&](const string &n) {
|
||||
cache_primary.insert(n);
|
||||
};
|
||||
const auto insert_name = [&](const string &n) { cache_primary.insert(n); };
|
||||
|
||||
if (!find_name(name))
|
||||
{
|
||||
|
@ -653,8 +653,7 @@ protected:
|
||||
// but the set is not updated when we have found a new name.
|
||||
// Used primarily when adding block interface names.
|
||||
void update_name_cache(std::unordered_set<std::string> &cache_primary,
|
||||
const std::unordered_set<std::string> &cache_secondary,
|
||||
std::string &name);
|
||||
const std::unordered_set<std::string> &cache_secondary, std::string &name);
|
||||
|
||||
bool function_is_pure(const SPIRFunction &func);
|
||||
bool block_is_pure(const SPIRBlock &block);
|
||||
|
@ -1546,8 +1546,7 @@ void CompilerGLSL::emit_buffer_block_native(const SPIRVariable &var)
|
||||
// Shaders never use the block by interface name, so we don't
|
||||
// have to track this other than updating name caches.
|
||||
// If we have a collision for any reason, just fallback immediately.
|
||||
if (ir.meta[type.self].decoration.alias.empty() ||
|
||||
block_namespace.find(buffer_name) != end(block_namespace) ||
|
||||
if (ir.meta[type.self].decoration.alias.empty() || block_namespace.find(buffer_name) != end(block_namespace) ||
|
||||
resource_names.find(buffer_name) != end(resource_names))
|
||||
{
|
||||
buffer_name = get_block_fallback_name(var.self);
|
||||
@ -4231,6 +4230,14 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
|
||||
}
|
||||
}
|
||||
|
||||
bool CompilerGLSL::expression_is_constant_null(uint32_t id) const
|
||||
{
|
||||
auto *c = maybe_get<SPIRConstant>(id);
|
||||
if (!c)
|
||||
return false;
|
||||
return c->constant_is_null();
|
||||
}
|
||||
|
||||
// Returns the function name for a texture sampling function for the specified image and sampling characteristics.
|
||||
// For some subclasses, the function is a method on the specified image.
|
||||
string CompilerGLSL::to_function_name(uint32_t tex, const SPIRType &imgtype, bool is_fetch, bool is_gather,
|
||||
@ -4247,10 +4254,11 @@ string CompilerGLSL::to_function_name(uint32_t tex, const SPIRType &imgtype, boo
|
||||
if (((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
|
||||
image_is_comparison(imgtype, tex) && lod)
|
||||
{
|
||||
auto *constant_lod = maybe_get<SPIRConstant>(lod);
|
||||
if (!constant_lod || constant_lod->scalar_f32() != 0.0f)
|
||||
if (!expression_is_constant_null(lod))
|
||||
{
|
||||
SPIRV_CROSS_THROW(
|
||||
"textureLod on sampler2DArrayShadow is not constant 0.0. This cannot be expressed in GLSL.");
|
||||
}
|
||||
workaround_lod_array_shadow_as_grad = true;
|
||||
}
|
||||
|
||||
|
@ -577,8 +577,7 @@ protected:
|
||||
// but the set is not updated when we have found a new name.
|
||||
// Used primarily when adding block interface names.
|
||||
void add_variable(std::unordered_set<std::string> &variables_primary,
|
||||
const std::unordered_set<std::string> &variables_secondary,
|
||||
std::string &name);
|
||||
const std::unordered_set<std::string> &variables_secondary, std::string &name);
|
||||
|
||||
void check_function_call_constraints(const uint32_t *args, uint32_t length);
|
||||
void handle_invalid_expression(uint32_t id);
|
||||
@ -615,6 +614,8 @@ protected:
|
||||
void handle_store_to_invariant_variable(uint32_t store_id, uint32_t value_id);
|
||||
void disallow_forwarding_in_expression_chain(const SPIRExpression &expr);
|
||||
|
||||
bool expression_is_constant_null(uint32_t id) const;
|
||||
|
||||
private:
|
||||
void init()
|
||||
{
|
||||
|
@ -3321,6 +3321,43 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
|
||||
forward = forward && should_forward(dref);
|
||||
farg_str += ", ";
|
||||
farg_str += to_expression(dref);
|
||||
|
||||
if (msl_options.is_macos() && (grad_x || grad_y))
|
||||
{
|
||||
// For sample compare, MSL does not support gradient2d for all targets (only iOS apparently according to docs).
|
||||
// However, the most common case here is to have a constant gradient of 0, as that is the only way to express
|
||||
// LOD == 0 in GLSL with sampler2DArrayShadow (cascaded shadow mapping).
|
||||
// We will detect a compile-time constant 0 value for gradient and promote that to level(0) on MSL.
|
||||
bool constant_zero_x = !grad_x || expression_is_constant_null(grad_x);
|
||||
bool constant_zero_y = !grad_y || expression_is_constant_null(grad_y);
|
||||
if (constant_zero_x && constant_zero_y)
|
||||
{
|
||||
lod = 0;
|
||||
grad_x = 0;
|
||||
grad_y = 0;
|
||||
farg_str += ", level(0)";
|
||||
}
|
||||
else
|
||||
{
|
||||
SPIRV_CROSS_THROW("Using non-constant 0.0 gradient() qualifier for sample_compare. This is not "
|
||||
"supported in MSL macOS.");
|
||||
}
|
||||
}
|
||||
|
||||
if (msl_options.is_macos() && bias)
|
||||
{
|
||||
// Bias is not supported either on macOS with sample_compare.
|
||||
// Verify it is compile-time zero, and drop the argument.
|
||||
if (expression_is_constant_null(bias))
|
||||
{
|
||||
bias = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SPIRV_CROSS_THROW(
|
||||
"Using non-constant 0.0 bias() qualifier for sample_compare. This is not supported in MSL macOS.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LOD Options
|
||||
|
Loading…
Reference in New Issue
Block a user