CompilerMSL vertex entry point return void when rasterization disabled.
Add CompilerMSL::Options::disable_rasterization input/output API flag. Disable rasterization via API flag or when writing to textures. Disable rasterization when shader declares no output. Add test shaders for vertex no output and write texture forcing void output.
This commit is contained in:
parent
cc7679ee45
commit
ac238b858b
20
reference/opt/shaders-msl/vert/no_stage_out.vert
Normal file
20
reference/opt/shaders-msl/vert/no_stage_out.vert
Normal file
@ -0,0 +1,20 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct _10
|
||||
{
|
||||
uint4 _m0[1024];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
uint4 m_19 [[attribute(0)]];
|
||||
};
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], device _10& _12 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]])
|
||||
{
|
||||
_12._m0[gl_VertexIndex] = in.m_19;
|
||||
}
|
||||
|
27
reference/opt/shaders-msl/vert/no_stage_out.write_tex.vert
Normal file
27
reference/opt/shaders-msl/vert/no_stage_out.write_tex.vert
Normal file
@ -0,0 +1,27 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 m_17 [[attribute(0)]];
|
||||
};
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], texture1d<uint> _37 [[texture(0)]], texture1d<uint, access::write> _34 [[texture(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.gl_Position = in.m_17;
|
||||
for (int _45 = 0; _45 < 128; )
|
||||
{
|
||||
_34.write(_37.read(uint(_45)), uint(_45));
|
||||
_45++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
20
reference/shaders-msl/vert/no_stage_out.vert
Normal file
20
reference/shaders-msl/vert/no_stage_out.vert
Normal file
@ -0,0 +1,20 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct _10
|
||||
{
|
||||
uint4 _m0[1024];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
uint4 m_19 [[attribute(0)]];
|
||||
};
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], device _10& _12 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]])
|
||||
{
|
||||
_12._m0[gl_VertexIndex] = in.m_19;
|
||||
}
|
||||
|
25
reference/shaders-msl/vert/no_stage_out.write_tex.vert
Normal file
25
reference/shaders-msl/vert/no_stage_out.write_tex.vert
Normal file
@ -0,0 +1,25 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 m_17 [[attribute(0)]];
|
||||
};
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], texture1d<uint> _37 [[texture(0)]], texture1d<uint, access::write> _34 [[texture(1)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.gl_Position = in.m_17;
|
||||
for (int _22 = 0; _22 < 128; _22++)
|
||||
{
|
||||
_34.write(_37.read(uint(_22)), uint(_22));
|
||||
}
|
||||
}
|
||||
|
14
shaders-msl/vert/no_stage_out.vert
Normal file
14
shaders-msl/vert/no_stage_out.vert
Normal file
@ -0,0 +1,14 @@
|
||||
#version 450
|
||||
|
||||
layout(binding = 0, std430) writeonly buffer _10_12
|
||||
{
|
||||
uvec4 _m0[1024];
|
||||
} _12;
|
||||
|
||||
layout(location = 0) in uvec4 _19;
|
||||
|
||||
void main()
|
||||
{
|
||||
_12._m0[gl_VertexIndex] = _19;
|
||||
}
|
||||
|
16
shaders-msl/vert/no_stage_out.write_tex.vert
Normal file
16
shaders-msl/vert/no_stage_out.write_tex.vert
Normal file
@ -0,0 +1,16 @@
|
||||
#version 450
|
||||
|
||||
layout(binding = 1, r32ui) uniform writeonly uimage1D _32;
|
||||
layout(binding = 0, r32ui) uniform readonly uimage1D _35;
|
||||
|
||||
layout(location = 0) in vec4 _14;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = _14;
|
||||
for (int _19 = 0; _19 < 128; _19++)
|
||||
{
|
||||
imageStore(_32, _19, imageLoad(_35, _19));
|
||||
}
|
||||
}
|
||||
|
@ -299,6 +299,11 @@ string CompilerMSL::compile()
|
||||
stage_in_var_id = add_interface_block(StorageClassInput);
|
||||
stage_uniforms_var_id = add_interface_block(StorageClassUniformConstant);
|
||||
|
||||
// Metal vertex functions that define no output must disable rasterization and return void.
|
||||
// Provide feedback to calling API to allow runtime to disable pipeline rasterization.
|
||||
if (!stage_out_var_id && (get_entry_point().model == ExecutionModelVertex))
|
||||
msl_options.disable_rasterization = true;
|
||||
|
||||
// Convert the use of global variables to recursively-passed function parameters
|
||||
localize_global_variables();
|
||||
extract_global_variables_from_functions();
|
||||
@ -376,6 +381,11 @@ void CompilerMSL::preprocess_op_codes()
|
||||
add_header_line("#include <metal_atomic>");
|
||||
add_pragma_line("#pragma clang diagnostic ignored \"-Wunused-variable\"");
|
||||
}
|
||||
|
||||
// Metal vertex functions that write to textures must disable rasterization and return void.
|
||||
// Provide feedback to calling API to allow runtime to disable pipeline rasterization.
|
||||
if (preproc.uses_image_write && get_entry_point().model == ExecutionModelVertex)
|
||||
msl_options.disable_rasterization = true;
|
||||
}
|
||||
|
||||
// Move the Private and Workgroup global variables to the entry function.
|
||||
@ -634,8 +644,7 @@ void CompilerMSL::mark_as_packable(SPIRType &type)
|
||||
void CompilerMSL::mark_location_as_used_by_shader(uint32_t location, StorageClass storage)
|
||||
{
|
||||
MSLVertexAttr *p_va;
|
||||
auto &execution = get_entry_point();
|
||||
if ((execution.model == ExecutionModelVertex) && (storage == StorageClassInput) &&
|
||||
if ((get_entry_point().model == ExecutionModelVertex) && (storage == StorageClassInput) &&
|
||||
(p_va = vtx_attrs_by_location[location]))
|
||||
p_va->used_by_shader = true;
|
||||
}
|
||||
@ -690,16 +699,20 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage)
|
||||
{
|
||||
ib_var_ref = stage_out_var_name;
|
||||
|
||||
// Add the output interface struct as a local variable to the entry function, force
|
||||
// the entry function to return the output interface struct from any blocks that perform
|
||||
// a function return, and indicate the output var requires early initialization
|
||||
// Add the output interface struct as a local variable to the entry function.
|
||||
// If the entry point should return the output struct, set the entry function
|
||||
// to return the output interface struct, otherwise to return nothing.
|
||||
// Indicate the output var requires early initialization.
|
||||
bool ep_should_return_output =
|
||||
!((get_entry_point().model == ExecutionModelVertex) && msl_options.disable_rasterization);
|
||||
uint32_t rtn_id = ep_should_return_output ? ib_var_id : 0;
|
||||
auto &entry_func = get<SPIRFunction>(entry_point);
|
||||
entry_func.add_local_variable(ib_var_id);
|
||||
for (auto &blk_id : entry_func.blocks)
|
||||
{
|
||||
auto &blk = get<SPIRBlock>(blk_id);
|
||||
if (blk.terminator == SPIRBlock::Return)
|
||||
blk.return_value = ib_var_id;
|
||||
blk.return_value = rtn_id;
|
||||
}
|
||||
vars_needing_early_declaration.push_back(ib_var_id);
|
||||
break;
|
||||
@ -1741,7 +1754,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
break;
|
||||
|
||||
case OpAtomicXor:
|
||||
MSL_AFMO (xor);
|
||||
MSL_AFMO(xor);
|
||||
break;
|
||||
|
||||
// Images
|
||||
@ -2844,9 +2857,7 @@ string CompilerMSL::convert_row_major_matrix(string exp_str, const SPIRType &exp
|
||||
// Called automatically at the end of the entry point function
|
||||
void CompilerMSL::emit_fixup()
|
||||
{
|
||||
auto &execution = get_entry_point();
|
||||
|
||||
if ((execution.model == ExecutionModelVertex) && stage_out_var_id && !qual_pos_var_name.empty())
|
||||
if ((get_entry_point().model == ExecutionModelVertex) && stage_out_var_id && !qual_pos_var_name.empty())
|
||||
{
|
||||
if (options.vertex.fixup_clipspace)
|
||||
statement(qual_pos_var_name, ".z = (", qual_pos_var_name, ".z + ", qual_pos_var_name,
|
||||
@ -3081,14 +3092,15 @@ string CompilerMSL::constant_expression(const SPIRConstant &c)
|
||||
// entry type if the current function is the entry point function
|
||||
string CompilerMSL::func_type_decl(SPIRType &type)
|
||||
{
|
||||
auto &execution = get_entry_point();
|
||||
// The regular function return type. If not processing the entry point function, that's all we need
|
||||
string return_type = type_to_glsl(type) + type_to_array_glsl(type);
|
||||
if (!processing_entry_point)
|
||||
return return_type;
|
||||
|
||||
// If an outgoing interface block has been defined, override the entry point return type
|
||||
if (stage_out_var_id)
|
||||
// If an outgoing interface block has been defined, and it should be returned, override the entry point return type
|
||||
bool ep_should_return_output =
|
||||
!((get_entry_point().model == ExecutionModelVertex) && msl_options.disable_rasterization);
|
||||
if (stage_out_var_id && ep_should_return_output)
|
||||
{
|
||||
auto &so_var = get<SPIRVariable>(stage_out_var_id);
|
||||
auto &so_type = get<SPIRType>(so_var.basetype);
|
||||
@ -3097,6 +3109,7 @@ string CompilerMSL::func_type_decl(SPIRType &type)
|
||||
|
||||
// Prepend a entry type, based on the execution model
|
||||
string entry_type;
|
||||
auto &execution = get_entry_point();
|
||||
switch (execution.model)
|
||||
{
|
||||
case ExecutionModelVertex:
|
||||
@ -3609,7 +3622,7 @@ std::string CompilerMSL::sampler_type(const SPIRType &type)
|
||||
return "sampler";
|
||||
}
|
||||
|
||||
// Returns an MSL string describing the SPIR-V image type
|
||||
// Returns an MSL string describing the SPIR-V image type
|
||||
string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
|
||||
{
|
||||
auto *var = maybe_get<SPIRVariable>(id);
|
||||
@ -4027,6 +4040,10 @@ bool CompilerMSL::OpCodePreprocessor::handle(Op opcode, const uint32_t *args, ui
|
||||
suppress_missing_prototypes = true;
|
||||
break;
|
||||
|
||||
case OpImageWrite:
|
||||
uses_image_write = true;
|
||||
break;
|
||||
|
||||
case OpAtomicExchange:
|
||||
case OpAtomicCompareExchange:
|
||||
case OpAtomicCompareExchangeWeak:
|
||||
|
@ -153,6 +153,7 @@ public:
|
||||
uint32_t msl_version = make_msl_version(1, 2);
|
||||
uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers
|
||||
bool enable_point_size_builtin = true;
|
||||
bool disable_rasterization = false; // Used as both input and output
|
||||
bool resolve_specialized_array_lengths = true;
|
||||
|
||||
bool is_ios()
|
||||
@ -399,6 +400,7 @@ protected:
|
||||
std::unordered_map<uint32_t, uint32_t> result_types;
|
||||
bool suppress_missing_prototypes = false;
|
||||
bool uses_atomics = false;
|
||||
bool uses_image_write = false;
|
||||
};
|
||||
|
||||
// Sorts the members of a SPIRType and associated Meta info based on a settable sorting
|
||||
|
Loading…
Reference in New Issue
Block a user