MSL: Support PrimitiveID in fragment and barycentrics.
This commit is contained in:
Родитель
707312b83a
Коммит
2e1cee5e1e
|
@ -0,0 +1,28 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct Vertices
|
||||
{
|
||||
float2 uvs[1];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 value [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float3 gl_BaryCoordNoPerspNV [[barycentric_coord, center_no_perspective]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], const device Vertices& _19 [[buffer(0)]], uint gl_PrimitiveID [[primitive_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
int _23 = 3 * int(gl_PrimitiveID);
|
||||
out.value = ((_19.uvs[_23] * in.gl_BaryCoordNoPerspNV.x) + (_19.uvs[_23 + 1] * in.gl_BaryCoordNoPerspNV.y)) + (_19.uvs[_23 + 2] * in.gl_BaryCoordNoPerspNV.z);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct Vertices
|
||||
{
|
||||
float2 uvs[1];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 value [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float3 gl_BaryCoordNV [[barycentric_coord, center_perspective]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], const device Vertices& _19 [[buffer(0)]], uint gl_PrimitiveID [[primitive_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
int _23 = 3 * int(gl_PrimitiveID);
|
||||
out.value = ((_19.uvs[_23] * in.gl_BaryCoordNV.x) + (_19.uvs[_23 + 1] * in.gl_BaryCoordNV.y)) + (_19.uvs[_23 + 2] * in.gl_BaryCoordNV.z);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct Vertices
|
||||
{
|
||||
float2 uvs[1];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 value [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float3 gl_BaryCoordNoPerspNV [[barycentric_coord, center_no_perspective]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], const device Vertices& _19 [[buffer(0)]], uint gl_PrimitiveID [[primitive_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
int prim = int(gl_PrimitiveID);
|
||||
float2 uv0 = _19.uvs[(3 * prim) + 0];
|
||||
float2 uv1 = _19.uvs[(3 * prim) + 1];
|
||||
float2 uv2 = _19.uvs[(3 * prim) + 2];
|
||||
out.value = ((uv0 * in.gl_BaryCoordNoPerspNV.x) + (uv1 * in.gl_BaryCoordNoPerspNV.y)) + (uv2 * in.gl_BaryCoordNoPerspNV.z);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct Vertices
|
||||
{
|
||||
float2 uvs[1];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 value [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float3 gl_BaryCoordNV [[barycentric_coord, center_perspective]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], const device Vertices& _19 [[buffer(0)]], uint gl_PrimitiveID [[primitive_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
int prim = int(gl_PrimitiveID);
|
||||
float2 uv0 = _19.uvs[(3 * prim) + 0];
|
||||
float2 uv1 = _19.uvs[(3 * prim) + 1];
|
||||
float2 uv2 = _19.uvs[(3 * prim) + 2];
|
||||
out.value = ((uv0 * in.gl_BaryCoordNV.x) + (uv1 * in.gl_BaryCoordNV.y)) + (uv2 * in.gl_BaryCoordNV.z);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#version 450
|
||||
#extension GL_NV_fragment_shader_barycentric : require
|
||||
|
||||
layout(location = 0) out vec2 value;
|
||||
|
||||
layout(set = 0, binding = 0) readonly buffer Vertices
|
||||
{
|
||||
vec2 uvs[];
|
||||
};
|
||||
|
||||
void main () {
|
||||
int prim = gl_PrimitiveID;
|
||||
vec2 uv0 = uvs[3 * prim + 0];
|
||||
vec2 uv1 = uvs[3 * prim + 1];
|
||||
vec2 uv2 = uvs[3 * prim + 2];
|
||||
value = gl_BaryCoordNoPerspNV.x * uv0 + gl_BaryCoordNoPerspNV.y * uv1 + gl_BaryCoordNoPerspNV.z * uv2;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#version 450
|
||||
#extension GL_NV_fragment_shader_barycentric : require
|
||||
|
||||
layout(location = 0) out vec2 value;
|
||||
|
||||
layout(set = 0, binding = 0) readonly buffer Vertices
|
||||
{
|
||||
vec2 uvs[];
|
||||
};
|
||||
|
||||
void main () {
|
||||
int prim = gl_PrimitiveID;
|
||||
vec2 uv0 = uvs[3 * prim + 0];
|
||||
vec2 uv1 = uvs[3 * prim + 1];
|
||||
vec2 uv2 = uvs[3 * prim + 2];
|
||||
value = gl_BaryCoordNV.x * uv0 + gl_BaryCoordNV.y * uv1 + gl_BaryCoordNV.z * uv2;
|
||||
}
|
|
@ -1942,6 +1942,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
|||
// Accumulate the variables that should appear in the interface struct.
|
||||
SmallVector<SPIRVariable *> vars;
|
||||
bool incl_builtins = storage == StorageClassOutput || is_tessellation_shader();
|
||||
bool has_seen_barycentric = false;
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t var_id, SPIRVariable &var) {
|
||||
if (var.storage != storage)
|
||||
|
@ -1956,6 +1957,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
|||
bool is_interface_block_builtin =
|
||||
(bi_type == BuiltInPosition || bi_type == BuiltInPointSize || bi_type == BuiltInClipDistance ||
|
||||
bi_type == BuiltInCullDistance || bi_type == BuiltInLayer || bi_type == BuiltInViewportIndex ||
|
||||
bi_type == BuiltInBaryCoordNV || bi_type == BuiltInBaryCoordNoPerspNV ||
|
||||
bi_type == BuiltInFragDepth || bi_type == BuiltInFragStencilRefEXT || bi_type == BuiltInSampleMask) ||
|
||||
(get_execution_model() == ExecutionModelTessellationEvaluation &&
|
||||
(bi_type == BuiltInTessLevelOuter || bi_type == BuiltInTessLevelInner));
|
||||
|
@ -1969,7 +1971,17 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
|||
|
||||
bool filter_patch_decoration = (has_decoration(var_id, DecorationPatch) || is_patch_block(type)) == patch;
|
||||
|
||||
if (is_active && !is_hidden_variable(var, incl_builtins) && type.pointer && filter_patch_decoration &&
|
||||
bool hidden = is_hidden_variable(var, incl_builtins);
|
||||
// Barycentric inputs must be emitted in stage-in, because they can have interpolation arguments.
|
||||
if (is_active && (bi_type == BuiltInBaryCoordNV || bi_type == BuiltInBaryCoordNoPerspNV))
|
||||
{
|
||||
if (has_seen_barycentric)
|
||||
SPIRV_CROSS_THROW("Cannot declare both BaryCoordNV and BaryCoordNoPerspNV in same shader in MSL.");
|
||||
has_seen_barycentric = true;
|
||||
hidden = false;
|
||||
}
|
||||
|
||||
if (is_active && !hidden && type.pointer && filter_patch_decoration &&
|
||||
(!is_builtin || is_interface_block_builtin))
|
||||
{
|
||||
vars.push_back(&var);
|
||||
|
@ -5557,7 +5569,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|||
// Fragment function inputs
|
||||
if (execution.model == ExecutionModelFragment && type.storage == StorageClassInput)
|
||||
{
|
||||
string quals = "";
|
||||
string quals;
|
||||
if (is_builtin)
|
||||
{
|
||||
switch (builtin)
|
||||
|
@ -5568,7 +5580,10 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|||
case BuiltInSampleId:
|
||||
case BuiltInSampleMask:
|
||||
case BuiltInLayer:
|
||||
case BuiltInBaryCoordNV:
|
||||
case BuiltInBaryCoordNoPerspNV:
|
||||
quals = builtin_qualifier(builtin);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -5586,6 +5601,19 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|||
quals = string("user(locn") + convert_to_string(locn) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
if (builtin == BuiltInBaryCoordNV || builtin == BuiltInBaryCoordNoPerspNV)
|
||||
{
|
||||
if (has_member_decoration(type.self, index, DecorationFlat) ||
|
||||
has_member_decoration(type.self, index, DecorationCentroid) ||
|
||||
has_member_decoration(type.self, index, DecorationSample) ||
|
||||
has_member_decoration(type.self, index, DecorationNoPerspective))
|
||||
{
|
||||
// NoPerspective is baked into the builtin type.
|
||||
SPIRV_CROSS_THROW("Flat, Centroid, Sample, NoPerspective decorations are not supported for BaryCoord inputs.");
|
||||
}
|
||||
}
|
||||
|
||||
// Don't bother decorating integers with the 'flat' attribute; it's
|
||||
// the default (in fact, the only option). Also don't bother with the
|
||||
// FragCoord builtin; it's always noperspective on Metal.
|
||||
|
@ -5622,6 +5650,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|||
quals += "center_no_perspective";
|
||||
}
|
||||
}
|
||||
|
||||
if (!quals.empty())
|
||||
return " [[" + quals + "]]";
|
||||
}
|
||||
|
@ -5929,13 +5958,14 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args)
|
|||
bi_type != BuiltInPatchVertices && bi_type != BuiltInTessLevelInner &&
|
||||
bi_type != BuiltInTessLevelOuter && bi_type != BuiltInPosition && bi_type != BuiltInPointSize &&
|
||||
bi_type != BuiltInClipDistance && bi_type != BuiltInCullDistance && bi_type != BuiltInSubgroupEqMask &&
|
||||
bi_type != BuiltInBaryCoordNV && bi_type != BuiltInBaryCoordNoPerspNV &&
|
||||
bi_type != BuiltInSubgroupGeMask && bi_type != BuiltInSubgroupGtMask &&
|
||||
bi_type != BuiltInSubgroupLeMask && bi_type != BuiltInSubgroupLtMask)
|
||||
{
|
||||
if (!ep_args.empty())
|
||||
ep_args += ", ";
|
||||
|
||||
ep_args += builtin_type_decl(bi_type) + " " + to_expression(var_id);
|
||||
ep_args += builtin_type_decl(bi_type, var_id) + " " + to_expression(var_id);
|
||||
ep_args += " [[" + builtin_qualifier(bi_type) + "]]";
|
||||
}
|
||||
}
|
||||
|
@ -6504,7 +6534,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
|
|||
if (var.basevariable == stage_in_ptr_var_id || var.basevariable == stage_out_ptr_var_id)
|
||||
decl += type_to_glsl(type, arg.id);
|
||||
else if (builtin)
|
||||
decl += builtin_type_decl(static_cast<BuiltIn>(get_decoration(arg.id, DecorationBuiltIn)));
|
||||
decl += builtin_type_decl(static_cast<BuiltIn>(get_decoration(arg.id, DecorationBuiltIn)), arg.id);
|
||||
else if ((storage == StorageClassUniform || storage == StorageClassStorageBuffer) && is_array(type))
|
||||
decl += join(type_to_glsl(type, arg.id), "*");
|
||||
else
|
||||
|
@ -7541,6 +7571,12 @@ string CompilerMSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
|
|||
|
||||
break;
|
||||
|
||||
case BuiltInBaryCoordNV:
|
||||
case BuiltInBaryCoordNoPerspNV:
|
||||
if (storage == StorageClassInput && current_function && (current_function->self == ir.default_entry_point))
|
||||
return stage_in_var_name + "." + CompilerGLSL::builtin_to_glsl(builtin, storage);
|
||||
break;
|
||||
|
||||
case BuiltInTessLevelOuter:
|
||||
if (get_execution_model() == ExecutionModelTessellationEvaluation)
|
||||
{
|
||||
|
@ -7633,6 +7669,12 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
|
|||
return "threadgroup_position_in_grid";
|
||||
case ExecutionModelTessellationEvaluation:
|
||||
return "patch_id";
|
||||
case ExecutionModelFragment:
|
||||
if (msl_options.is_ios())
|
||||
SPIRV_CROSS_THROW("PrimitiveId is not supported in fragment on iOS.");
|
||||
else if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 2))
|
||||
SPIRV_CROSS_THROW("PrimitiveId on macOS requires MSL 2.2.");
|
||||
return "primitive_id";
|
||||
default:
|
||||
SPIRV_CROSS_THROW("PrimitiveId is not supported in this execution model.");
|
||||
}
|
||||
|
@ -7716,13 +7758,29 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
|
|||
// Shouldn't be reached.
|
||||
SPIRV_CROSS_THROW("Subgroup ballot masks are handled specially in MSL.");
|
||||
|
||||
case BuiltInBaryCoordNV:
|
||||
// TODO: AMD barycentrics as well? Seem to have different swizzle and 2 components rather than 3.
|
||||
if (msl_options.is_ios())
|
||||
SPIRV_CROSS_THROW("Barycentrics not supported on iOS.");
|
||||
else if (!msl_options.supports_msl_version(2, 2))
|
||||
SPIRV_CROSS_THROW("Barycentrics are only supported in MSL 2.2 and above on macOS.");
|
||||
return "barycentric_coord, center_perspective";
|
||||
|
||||
case BuiltInBaryCoordNoPerspNV:
|
||||
// TODO: AMD barycentrics as well? Seem to have different swizzle and 2 components rather than 3.
|
||||
if (msl_options.is_ios())
|
||||
SPIRV_CROSS_THROW("Barycentrics not supported on iOS.");
|
||||
else if (!msl_options.supports_msl_version(2, 2))
|
||||
SPIRV_CROSS_THROW("Barycentrics are only supported in MSL 2.2 and above on macOS.");
|
||||
return "barycentric_coord, center_no_perspective";
|
||||
|
||||
default:
|
||||
return "unsupported-built-in";
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an MSL string type declaration for a SPIR-V builtin
|
||||
string CompilerMSL::builtin_type_decl(BuiltIn builtin)
|
||||
string CompilerMSL::builtin_type_decl(BuiltIn builtin, uint32_t id)
|
||||
{
|
||||
const SPIREntryPoint &execution = get_entry_point();
|
||||
switch (builtin)
|
||||
|
@ -7822,6 +7880,11 @@ string CompilerMSL::builtin_type_decl(BuiltIn builtin)
|
|||
case BuiltInHelperInvocation:
|
||||
return "bool";
|
||||
|
||||
case BuiltInBaryCoordNV:
|
||||
case BuiltInBaryCoordNoPerspNV:
|
||||
// Use the type as declared, can be 1, 2 or 3 components.
|
||||
return type_to_glsl(get_variable_data_type(get<SPIRVariable>(id)));
|
||||
|
||||
default:
|
||||
return "unsupported-built-in-type";
|
||||
}
|
||||
|
@ -8360,6 +8423,7 @@ void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &exp
|
|||
case BuiltInLayer:
|
||||
case BuiltInViewportIndex:
|
||||
case BuiltInFragStencilRefEXT:
|
||||
case BuiltInPrimitiveId:
|
||||
expected_type = SPIRType::UInt;
|
||||
break;
|
||||
|
||||
|
@ -8401,6 +8465,7 @@ void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr
|
|||
case BuiltInLayer:
|
||||
case BuiltInViewportIndex:
|
||||
case BuiltInFragStencilRefEXT:
|
||||
case BuiltInPrimitiveId:
|
||||
expected_type = SPIRType::UInt;
|
||||
break;
|
||||
|
||||
|
|
|
@ -471,7 +471,7 @@ protected:
|
|||
std::string to_swizzle_expression(uint32_t id);
|
||||
std::string to_buffer_size_expression(uint32_t id);
|
||||
std::string builtin_qualifier(spv::BuiltIn builtin);
|
||||
std::string builtin_type_decl(spv::BuiltIn builtin);
|
||||
std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0);
|
||||
std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma);
|
||||
std::string member_attribute_qualifier(const SPIRType &type, uint32_t index);
|
||||
std::string argument_decl(const SPIRFunction::Parameter &arg);
|
||||
|
|
Загрузка…
Ссылка в новой задаче