Skip to content

Commit

Permalink
MSL: Workaround missing gradient2d() for sampler_compare.
Browse files Browse the repository at this point in the history
  • Loading branch information
HansKristian-Work committed Jan 7, 2019
1 parent 169607c commit 649ce3c
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -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;
}

Original file line number Diff line number Diff line change
@@ -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;
}

22 changes: 22 additions & 0 deletions reference/shaders-msl/frag/sampler-compare-cascade-gradient.frag
Original file line number Diff line number Diff line change
@@ -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;
}

Original file line number Diff line number Diff line change
@@ -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 changes: 11 additions & 0 deletions shaders-msl/frag/sampler-compare-cascade-gradient.frag
Original file line number Diff line number Diff line change
@@ -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 changes: 11 additions & 0 deletions shaders-msl/frag/sampler-compare-cascade-gradient.ios.frag
Original file line number Diff line number Diff line change
@@ -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));
}
15 changes: 15 additions & 0 deletions spirv_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_)
{
Expand Down
15 changes: 12 additions & 3 deletions spirv_glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4231,6 +4231,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,
Expand All @@ -4247,10 +4255,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.");
"textureLod on sampler2DArrayShadow is not constant 0.0. This cannot be expressed in GLSL.");
}
workaround_lod_array_shadow_as_grad = true;
}

Expand Down
2 changes: 2 additions & 0 deletions spirv_glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,8 @@ class CompilerGLSL : public Compiler
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()
{
Expand Down
36 changes: 36 additions & 0 deletions spirv_msl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3321,6 +3321,42 @@ 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
Expand Down

0 comments on commit 649ce3c

Please sign in to comment.