CompilerMSL support and tests for OpUndef.

This commit is contained in:
Bill Hollings 2017-11-15 22:44:42 -05:00
parent 694cad5332
commit e83e2b2217
15 changed files with 476 additions and 31 deletions

View File

@ -0,0 +1,40 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct _9
{
float _m0;
};
struct _10
{
float _m0;
float _m1;
float _m2;
float _m3;
float _m4;
float _m5;
float _m6;
float _m7;
float _m8;
float _m9;
float _m10;
float _m11;
_9 _m12;
};
struct main0_out
{
float4 m_3 [[color(0)]];
};
fragment main0_out main0()
{
main0_out out = {};
_10 _21;
out.m_3 = float4(_21._m0, _21._m1, _21._m2, _21._m3);
return out;
}

View File

@ -0,0 +1,28 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct D
{
float4 a;
float b;
};
struct main0_out
{
float FragColor [[color(0)]];
};
fragment main0_out main0()
{
main0_out out = {};
float a = 0.0;
float4 b = float4(0.0);
float2x3 c = float2x3(float3(0.0), float3(0.0));
D d = {float4(0.0), 0.0};
float4 e[4] = {float4(0.0), float4(0.0), float4(0.0), float4(0.0)};
out.FragColor = a;
return out;
}

View File

@ -0,0 +1,12 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
fragment void main0()
{
for (int _22 = 35; _22 >= 0; _22--)
{
}
}

View File

@ -0,0 +1,37 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
constant float4 _38 = float4(0);
constant float4 _47 = float4(0);
struct main0_out
{
float4 _entryPointOutput [[color(0)]];
};
fragment main0_out main0()
{
main0_out out = {};
float4 _27;
do
{
float2 _26 = float2(0.0);
if (_26.x != 0.0)
{
_27 = float4(1.0, 0.0, 0.0, 1.0);
break;
}
else
{
_27 = float4(1.0, 1.0, 0.0, 1.0);
break;
}
_27 = _38;
break;
} while (false);
out._entryPointOutput = _27;
return out;
}

View File

@ -0,0 +1,57 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 43
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %2 "main" %3
OpExecutionMode %2 OriginLowerLeft
OpDecorate %3 Location 0
%void = OpTypeVoid
%9 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%12 = OpTypeFunction %v4float
%_struct_5 = OpTypeStruct %float
%_struct_6 = OpTypeStruct %float %float %float %float %float %float %float %float %float %float %float %float %_struct_5
%_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%_ptr_Function_float = OpTypePointer Function %float
%int_1 = OpConstant %int 1
%int_2 = OpConstant %int 2
%int_3 = OpConstant %int 3
%_ptr_Output_v4float = OpTypePointer Output %v4float
%3 = OpVariable %_ptr_Output_v4float Output
%_ptr_Function_v4float = OpTypePointer Function %v4float
%2 = OpFunction %void None %9
%22 = OpLabel
%23 = OpVariable %_ptr_Function__struct_6 Function
%24 = OpAccessChain %_ptr_Function_float %23 %int_0
%25 = OpLoad %float %24
%26 = OpAccessChain %_ptr_Function_float %23 %int_1
%27 = OpLoad %float %26
%28 = OpAccessChain %_ptr_Function_float %23 %int_2
%29 = OpLoad %float %28
%30 = OpAccessChain %_ptr_Function_float %23 %int_3
%31 = OpLoad %float %30
%32 = OpCompositeConstruct %v4float %25 %27 %29 %31
OpStore %3 %32
OpReturn
OpFunctionEnd
%4 = OpFunction %v4float None %12
%33 = OpLabel
%7 = OpVariable %_ptr_Function__struct_6 Function
%34 = OpAccessChain %_ptr_Function_float %7 %int_0
%35 = OpLoad %float %34
%36 = OpAccessChain %_ptr_Function_float %7 %int_1
%37 = OpLoad %float %36
%38 = OpAccessChain %_ptr_Function_float %7 %int_2
%39 = OpLoad %float %38
%40 = OpAccessChain %_ptr_Function_float %7 %int_3
%41 = OpLoad %float %40
%42 = OpCompositeConstruct %v4float %35 %37 %39 %41
OpReturnValue %42
OpFunctionEnd

View File

@ -0,0 +1,85 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 45
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource ESSL 310
OpName %main "main"
OpName %a "a"
OpName %b "b"
OpName %c "c"
OpName %D "D"
OpMemberName %D 0 "a"
OpMemberName %D 1 "b"
OpName %d "d"
OpName %e "e"
OpName %FragColor "FragColor"
OpDecorate %a RelaxedPrecision
OpDecorate %b RelaxedPrecision
OpDecorate %c RelaxedPrecision
OpMemberDecorate %D 0 RelaxedPrecision
OpMemberDecorate %D 1 RelaxedPrecision
OpDecorate %e RelaxedPrecision
OpDecorate %FragColor RelaxedPrecision
OpDecorate %FragColor Location 0
OpDecorate %44 RelaxedPrecision
OpDecorate %float_1 RelaxedPrecision
OpDecorate %14 RelaxedPrecision
OpDecorate %23 RelaxedPrecision
OpDecorate %41 RelaxedPrecision
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%_ptr_Function_float = OpTypePointer Function %float
%float_1 = OpConstantNull %float
%v4float = OpTypeVector %float 4
%_ptr_Function_v4float = OpTypePointer Function %v4float
%float_2 = OpConstantNull %float
%14 = OpConstantNull %v4float
%v3float = OpTypeVector %float 3
%mat2v3float = OpTypeMatrix %v3float 2
%_ptr_Function_mat2v3float = OpTypePointer Function %mat2v3float
%float_4 = OpConstantNull %float
%20 = OpConstantNull %v3float
%float_5 = OpConstantNull %float
%22 = OpConstantNull %v3float
%23 = OpConstantNull %mat2v3float
%D = OpTypeStruct %v4float %float
%_ptr_Function_D = OpTypePointer Function %D
%27 = OpConstantNull %D
%uint = OpTypeInt 32 0
%uint_4 = OpConstant %uint 4
%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
%_ptr_Function__arr_v4float_uint_4 = OpTypePointer Function %_arr_v4float_uint_4
%float_10 = OpConstantNull %float
%34 = OpConstantNull %v4float
%float_11 = OpConstantNull %float
%36 = OpConstantNull %v4float
%float_12 = OpConstantNull %float
%38 = OpConstantNull %v4float
%float_13 = OpConstantNull %float
%40 = OpConstantNull %v4float
%41 = OpConstantNull %_arr_v4float_uint_4
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%a = OpVariable %_ptr_Function_float Function
%b = OpVariable %_ptr_Function_v4float Function
%c = OpVariable %_ptr_Function_mat2v3float Function
%d = OpVariable %_ptr_Function_D Function
%e = OpVariable %_ptr_Function__arr_v4float_uint_4 Function
OpStore %a %float_1
OpStore %b %14
OpStore %c %23
OpStore %d %27
OpStore %e %41
%44 = OpLoad %float %a
OpStore %FragColor %44
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,71 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 59
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat2v2float = OpTypeMatrix %v2float 2
%_ptr_Function_mat2v2float = OpTypePointer Function %mat2v2float
%v3float = OpTypeVector %float 3
%11 = OpTypeFunction %v3float %_ptr_Function_mat2v2float
%_ptr_Function_v3float = OpTypePointer Function %v3float
%float_1 = OpConstant %float 1
%18 = OpConstantComposite %v3float %float_1 %float_1 %float_1
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%int_35 = OpConstant %int 35
%int_0 = OpConstant %int 0
%bool = OpTypeBool
%int_1 = OpConstant %int 1
%4 = OpFunction %void None %3
%5 = OpLabel
OpBranch %48
%48 = OpLabel
%58 = OpPhi %int %int_35 %5 %56 %50
OpLoopMerge %49 %50 None
OpBranch %51
%51 = OpLabel
%53 = OpSGreaterThanEqual %bool %58 %int_0
OpBranchConditional %53 %54 %49
%54 = OpLabel
OpBranch %50
%50 = OpLabel
%56 = OpISub %int %58 %int_1
OpBranch %48
%49 = OpLabel
OpReturn
OpFunctionEnd
%13 = OpFunction %v3float None %11
%12 = OpFunctionParameter %_ptr_Function_mat2v2float
%14 = OpLabel
%16 = OpVariable %_ptr_Function_v3float Function
%21 = OpVariable %_ptr_Function_int Function
OpStore %16 %18
OpStore %21 %int_35
OpBranch %23
%23 = OpLabel
OpLoopMerge %25 %26 None
OpBranch %27
%27 = OpLabel
%28 = OpLoad %int %21
%31 = OpSGreaterThanEqual %bool %28 %int_0
OpBranchConditional %31 %24 %25
%24 = OpLabel
OpBranch %26
%26 = OpLabel
%32 = OpLoad %int %21
%34 = OpISub %int %32 %int_1
OpStore %21 %34
OpBranch %23
%25 = OpLabel
%35 = OpLoad %v3float %16
OpReturnValue %35
OpFunctionEnd

View File

@ -0,0 +1,85 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 50
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %fragmentProgram "main" %_entryPointOutput
OpExecutionMode %fragmentProgram OriginUpperLeft
OpSource HLSL 500
OpName %fragmentProgram "fragmentProgram"
OpName %_fragmentProgram_ "@fragmentProgram("
OpName %uv "uv"
OpName %_entryPointOutput "@entryPointOutput"
OpDecorate %_entryPointOutput Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%8 = OpTypeFunction %v4float
%v2float = OpTypeVector %float 2
%_ptr_Function_v2float = OpTypePointer Function %v2float
%float_0 = OpConstant %float 0
%15 = OpConstantComposite %v2float %float_0 %float_0
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%_ptr_Function_float = OpTypePointer Function %float
%bool = OpTypeBool
%float_1 = OpConstant %float 1
%26 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
%29 = OpConstantComposite %v4float %float_1 %float_1 %float_0 %float_1
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
%_ptr_Function_v4float = OpTypePointer Function %v4float
%false = OpConstantFalse %bool
%fragmentProgram = OpFunction %void None %3
%5 = OpLabel
%35 = OpVariable %_ptr_Function_v2float Function
%37 = OpVariable %_ptr_Function_v4float Function
OpBranch %38
%38 = OpLabel
OpLoopMerge %39 %40 None
OpBranch %41
%41 = OpLabel
OpStore %35 %15
%42 = OpAccessChain %_ptr_Function_float %35 %uint_0
%43 = OpLoad %float %42
%44 = OpFOrdNotEqual %bool %43 %float_0
OpSelectionMerge %45 None
OpBranchConditional %44 %46 %47
%46 = OpLabel
OpStore %37 %26
OpBranch %39
%47 = OpLabel
OpStore %37 %29
OpBranch %39
%45 = OpLabel
%48 = OpUndef %v4float
OpStore %37 %48
OpBranch %39
%40 = OpLabel
OpBranchConditional %false %38 %39
%39 = OpLabel
%34 = OpLoad %v4float %37
OpStore %_entryPointOutput %34
OpReturn
OpFunctionEnd
%_fragmentProgram_ = OpFunction %v4float None %8
%10 = OpLabel
%uv = OpVariable %_ptr_Function_v2float Function
OpStore %uv %15
%19 = OpAccessChain %_ptr_Function_float %uv %uint_0
%20 = OpLoad %float %19
%22 = OpFOrdNotEqual %bool %20 %float_0
OpSelectionMerge %24 None
OpBranchConditional %22 %23 %28
%23 = OpLabel
OpReturnValue %26
%28 = OpLabel
OpReturnValue %29
%24 = OpLabel
%31 = OpUndef %v4float
OpReturnValue %31
OpFunctionEnd

View File

@ -171,9 +171,8 @@ void CompilerCPP::emit_resources()
auto &type = get<SPIRType>(var.basetype);
if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassUniform &&
!is_hidden_variable(var) &&
(meta[type.self].decoration.decoration_flags &
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
!is_hidden_variable(var) && (meta[type.self].decoration.decoration_flags &
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
{
emit_buffer_block(var);
}

View File

@ -168,7 +168,7 @@ bool Compiler::block_is_pure(const SPIRBlock &block)
case OpMemoryBarrier:
return false;
// OpExtInst is potentially impure depending on extension, but GLSL builtins are at least pure.
// OpExtInst is potentially impure depending on extension, but GLSL builtins are at least pure.
default:
break;
@ -457,7 +457,7 @@ bool Compiler::is_hidden_variable(const SPIRVariable &var, bool include_builtins
// Combined image samplers are always considered active as they are "magic" variables.
if (find_if(begin(combined_image_samplers), end(combined_image_samplers), [&var](const CombinedImageSampler &samp) {
return samp.combined_id == var.self;
}) != end(combined_image_samplers))
}) != end(combined_image_samplers))
{
return false;
}
@ -2548,7 +2548,7 @@ SPIREntryPoint &Compiler::get_entry_point(const std::string &name)
auto itr =
find_if(begin(entry_points), end(entry_points), [&](const std::pair<uint32_t, SPIREntryPoint> &entry) -> bool {
return entry.second.orig_name == name;
});
});
if (itr == end(entry_points))
SPIRV_CROSS_THROW("Entry point does not exist.");
@ -2561,7 +2561,7 @@ const SPIREntryPoint &Compiler::get_entry_point(const std::string &name) const
auto itr =
find_if(begin(entry_points), end(entry_points), [&](const std::pair<uint32_t, SPIREntryPoint> &entry) -> bool {
return entry.second.orig_name == name;
});
});
if (itr == end(entry_points))
SPIRV_CROSS_THROW("Entry point does not exist.");
@ -2730,7 +2730,7 @@ void Compiler::CombinedImageSamplerHandler::register_combined_image_sampler(SPIR
[&param](const SPIRFunction::CombinedImageSamplerParameter &p) {
return param.image_id == p.image_id && param.sampler_id == p.sampler_id &&
param.global_image == p.global_image && param.global_sampler == p.global_sampler;
});
});
if (itr == end(caller.combined_parameters))
{
@ -2867,7 +2867,7 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar
auto itr = find_if(begin(compiler.combined_image_samplers), end(compiler.combined_image_samplers),
[image_id, sampler_id](const CombinedImageSampler &combined) {
return combined.image_id == image_id && combined.sampler_id == sampler_id;
});
});
if (itr == end(compiler.combined_image_samplers))
{
@ -3209,8 +3209,8 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
break;
}
// Atomics shouldn't be able to access function-local variables.
// Some GLSL builtins access a pointer.
// Atomics shouldn't be able to access function-local variables.
// Some GLSL builtins access a pointer.
default:
break;

View File

@ -2689,7 +2689,7 @@ string CompilerGLSL::declare_temporary(uint32_t result_type, uint32_t result_id)
if (find_if(begin(header.declare_temporary), end(header.declare_temporary),
[result_type, result_id](const pair<uint32_t, uint32_t> &tmp) {
return tmp.first == result_type && tmp.second == result_id;
}) == end(header.declare_temporary))
}) == end(header.declare_temporary))
{
header.declare_temporary.emplace_back(result_type, result_id);
force_recompile = true;
@ -2916,9 +2916,8 @@ void CompilerGLSL::emit_quaternary_func_op(uint32_t result_type, uint32_t result
uint32_t op2, uint32_t op3, const char *op)
{
bool forward = should_forward(op0) && should_forward(op1) && should_forward(op2) && should_forward(op3);
emit_op(result_type, result_id,
join(op, "(", to_expression(op0), ", ", to_expression(op1), ", ", to_expression(op2), ", ",
to_expression(op3), ")"),
emit_op(result_type, result_id, join(op, "(", to_expression(op0), ", ", to_expression(op1), ", ",
to_expression(op2), ", ", to_expression(op3), ")"),
forward);
inherit_expression_dependencies(result_id, op0);
@ -5886,8 +5885,8 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
register_read(ops[1], ops[2], should_forward(ops[2]));
break;
// OpAtomicStore unimplemented. Not sure what would use that.
// OpAtomicLoad seems to only be relevant for atomic counters.
// OpAtomicStore unimplemented. Not sure what would use that.
// OpAtomicLoad seems to only be relevant for atomic counters.
case OpAtomicIIncrement:
forced_temporaries.insert(ops[1]);

View File

@ -488,7 +488,7 @@ protected:
bool type_is_empty(const SPIRType &type);
void declare_undefined_values();
virtual void declare_undefined_values();
static std::string sanitize_underscores(const std::string &str);

View File

@ -1064,10 +1064,7 @@ void CompilerHLSL::emit_resources()
if (requires_op_fmod)
{
static const char *types[] = {
"float",
"float2",
"float3",
"float4",
"float", "float2", "float3", "float4",
};
for (auto &type : types)

View File

@ -1041,6 +1041,40 @@ void CompilerMSL::emit_custom_functions()
}
}
// Undefined global memory is not allowed in MSL.
// Declare constant and init to zeros.
void CompilerMSL::declare_undefined_values()
{
bool emitted = false;
for (auto &id : ids)
{
if (id.get_type() == TypeUndef)
{
auto &undef = id.get<SPIRUndef>();
auto &type = get<SPIRType>(undef.basetype);
string arg_str;
switch (type.basetype)
{
case SPIRType::Struct:
arg_str = "";
break;
default:
arg_str = "0";
break;
}
string init_str = type_to_glsl(type) + "(" + arg_str + ")";
statement("constant ", variable_decl(type, to_name(undef.self), undef.self), " = ", init_str, ";");
emitted = true;
}
}
if (emitted)
statement("");
}
void CompilerMSL::emit_resources()
{
// Output non-interface structs. These include local function structs
@ -1077,6 +1111,8 @@ void CompilerMSL::emit_resources()
}
}
declare_undefined_values();
// Output interface structs.
emit_interface_block(stage_in_var_id);
for (auto &nsi_var : non_stage_in_input_var_ids)
@ -1510,7 +1546,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
emit_barrier(ops[0], ops[1], ops[2]);
break;
// OpOuterProduct
// OpOuterProduct
default:
CompilerGLSL::emit_instruction(instruction);
@ -1815,10 +1851,10 @@ void CompilerMSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
break;
}
// TODO:
// GLSLstd450InterpolateAtCentroid (centroid_no_perspective qualifier)
// GLSLstd450InterpolateAtSample (sample_no_perspective qualifier)
// GLSLstd450InterpolateAtOffset
// TODO:
// GLSLstd450InterpolateAtCentroid (centroid_no_perspective qualifier)
// GLSLstd450InterpolateAtSample (sample_no_perspective qualifier)
// GLSLstd450InterpolateAtOffset
default:
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
@ -2703,13 +2739,11 @@ string CompilerMSL::ensure_valid_name(string name, string pfx)
void CompilerMSL::replace_illegal_names()
{
static const unordered_set<string> keywords = {
"kernel",
"bias",
"kernel", "bias",
};
static const unordered_set<string> illegal_func_names = {
"main",
"saturate",
"main", "saturate",
};
for (auto &id : ids)

View File

@ -185,6 +185,7 @@ protected:
bool skip_argument(uint32_t id) const override;
std::string to_qualifiers_glsl(uint32_t id) override;
void replace_illegal_names() override;
void declare_undefined_values() override;
void preprocess_op_codes();
void localize_global_variables();