Merge pull request #1102 from KhronosGroup/fix-1096

MSL: Deal with Modf/Frexp where output is access chain to scalar.
This commit is contained in:
Hans-Kristian Arntzen 2019-07-26 14:28:16 +02:00 committed by GitHub
commit 87513f9ac0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 0 deletions

View File

@ -0,0 +1,17 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
fragment void main0()
{
float3 col;
int2 _18;
float _23;
float _21 = modf(0.1500000059604644775390625, _23);
col.x = _23;
int _24;
float _22 = frexp(0.1500000059604644775390625, _24);
_18.y = _24;
}

View File

@ -0,0 +1,36 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 17
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
OpSource ESSL 310
OpName %main "main"
OpName %col "col"
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%_ptr_Function_float = OpTypePointer Function %float
%float_0_150000006 = OpConstant %float 0.150000006
%v3float = OpTypeVector %float 3
%_ptr_Function_v3float = OpTypePointer Function %v3float
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%v2int = OpTypeVector %int 2
%_ptr_Function_v2int = OpTypePointer Function %v2int
%_ptr_Function_int = OpTypePointer Function %int
%main = OpFunction %void None %3
%5 = OpLabel
%col = OpVariable %_ptr_Function_v3float Function
%icol = OpVariable %_ptr_Function_v2int Function
%ptr_x = OpAccessChain %_ptr_Function_float %col %int_0
%ptr_y = OpAccessChain %_ptr_Function_int %icol %int_1
%16 = OpExtInst %float %1 Modf %float_0_150000006 %ptr_x
%17 = OpExtInst %float %1 Frexp %float_0_150000006 %ptr_y
OpReturn
OpFunctionEnd

View File

@ -5260,6 +5260,32 @@ void CompilerMSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
break;
case GLSLstd450Modf:
case GLSLstd450Frexp:
{
// Special case. If the variable is a scalar access chain, we cannot use it directly. We have to emit a temporary.
auto *ptr = maybe_get<SPIRExpression>(args[1]);
if (ptr && ptr->access_chain && is_scalar(expression_type(args[1])))
{
register_call_out_argument(args[1]);
forced_temporaries.insert(id);
// Need to create temporaries and copy over to access chain after.
// We cannot directly take the reference of a vector swizzle in MSL, even if it's scalar ...
uint32_t &tmp_id = extra_sub_expressions[id];
if (!tmp_id)
tmp_id = ir.increase_bound_by(1);
uint32_t tmp_type_id = get_pointee_type_id(ptr->expression_type);
emit_uninitialized_temporary_expression(tmp_type_id, tmp_id);
emit_binary_func_op(result_type, id, args[0], tmp_id, eop == GLSLstd450Modf ? "modf" : "frexp");
statement(to_expression(args[1]), " = ", to_expression(tmp_id), ";");
}
else
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
break;
}
default:
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
break;