Merge pull request #1996 from KhronosGroup/fix-1993

MSL: Fix various bugs with Ptr/U bitcasts.
This commit is contained in:
Hans-Kristian Arntzen 2022-08-09 14:40:55 +02:00 committed by GitHub
commit 61c603f3ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 320 additions and 26 deletions

View File

@ -18,10 +18,10 @@ struct SSBO
kernel void main0(constant UBO& _10 [[buffer(0)]])
{
((device SSBO*)as_type<uint64_t>(_10.b))->a1 = float3(1.0, 2.0, 3.0);
uint2 _35 = as_type<uint2>((uint64_t)((device SSBO*)as_type<uint64_t>(_10.b + uint2(32u))));
(reinterpret_cast<device SSBO*>(as_type<ulong>(_10.b)))->a1 = float3(1.0, 2.0, 3.0);
uint2 _35 = as_type<uint2>(reinterpret_cast<ulong>(reinterpret_cast<device SSBO*>(as_type<ulong>(_10.b + uint2(32u)))));
uint2 v2 = _35;
device SSBO* _39 = ((device SSBO*)as_type<uint64_t>(_35));
device SSBO* _39 = reinterpret_cast<device SSBO*>(as_type<ulong>(_35));
float3 v3 = float3(_39->a1);
_39->a1 = float3(_39->a1) + float3(1.0);
}

View File

@ -0,0 +1,33 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct SomeBuffer;
struct SomeBuffer
{
float4 v;
ulong a;
uint2 b;
};
struct Registers
{
ulong address;
uint2 address2;
};
kernel void main0(constant Registers& registers [[buffer(0)]])
{
device SomeBuffer* _44 = reinterpret_cast<device SomeBuffer*>(registers.address);
device SomeBuffer* _45 = reinterpret_cast<device SomeBuffer*>(registers.address);
device SomeBuffer* _46 = reinterpret_cast<device SomeBuffer*>(as_type<ulong>(registers.address2));
_44->v = float4(1.0, 2.0, 3.0, 4.0);
_45->v = float4(1.0, 2.0, 3.0, 4.0);
_46->v = float4(1.0, 2.0, 3.0, 4.0);
_44->a = reinterpret_cast<ulong>(_44);
_45->a = reinterpret_cast<ulong>(_45);
_46->b = as_type<uint2>(reinterpret_cast<ulong>(_46));
}

View File

@ -18,9 +18,9 @@ struct SSBO
kernel void main0(constant UBO& _10 [[buffer(0)]])
{
((device SSBO*)as_type<uint64_t>(_10.b))->a1 = float3(1.0, 2.0, 3.0);
uint2 v2 = as_type<uint2>((uint64_t)((device SSBO*)as_type<uint64_t>(_10.b + uint2(32u))));
float3 v3 = float3(((device SSBO*)as_type<uint64_t>(v2))->a1);
((device SSBO*)as_type<uint64_t>(v2))->a1 = v3 + float3(1.0);
(reinterpret_cast<device SSBO*>(as_type<ulong>(_10.b)))->a1 = float3(1.0, 2.0, 3.0);
uint2 v2 = as_type<uint2>(reinterpret_cast<ulong>(reinterpret_cast<device SSBO*>(as_type<ulong>(_10.b + uint2(32u)))));
float3 v3 = float3((reinterpret_cast<device SSBO*>(as_type<ulong>(v2)))->a1);
(reinterpret_cast<device SSBO*>(as_type<ulong>(v2)))->a1 = v3 + float3(1.0);
}

View File

@ -0,0 +1,37 @@
#version 450
#if defined(GL_ARB_gpu_shader_int64)
#extension GL_ARB_gpu_shader_int64 : require
#else
#error No extension available for 64-bit integers.
#endif
#extension GL_EXT_buffer_reference : require
#extension GL_EXT_buffer_reference_uvec2 : require
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(buffer_reference) buffer SomeBuffer;
layout(buffer_reference, buffer_reference_align = 16, std430) buffer SomeBuffer
{
vec4 v;
uint64_t a;
uvec2 b;
};
layout(push_constant, std430) uniform Registers
{
uint64_t address;
uvec2 address2;
} registers;
void main()
{
SomeBuffer _44 = SomeBuffer(registers.address);
SomeBuffer _45 = SomeBuffer(registers.address);
SomeBuffer _46 = SomeBuffer(registers.address2);
_44.v = vec4(1.0, 2.0, 3.0, 4.0);
_45.v = vec4(1.0, 2.0, 3.0, 4.0);
_46.v = vec4(1.0, 2.0, 3.0, 4.0);
_44.a = uint64_t(_44);
_45.a = uint64_t(_45);
_46.b = uvec2(_46);
}

View File

@ -0,0 +1,106 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 10
; Bound: 62
; Schema: 0
OpCapability Shader
OpCapability Int64
OpCapability PhysicalStorageBufferAddresses
OpExtension "SPV_KHR_physical_storage_buffer"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel PhysicalStorageBuffer64 GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpSourceExtension "GL_ARB_gpu_shader_int64"
OpSourceExtension "GL_EXT_buffer_reference"
OpSourceExtension "GL_EXT_buffer_reference_uvec2"
OpName %main "main"
OpName %SomeBuffer "SomeBuffer"
OpMemberName %SomeBuffer 0 "v"
OpMemberName %SomeBuffer 1 "a"
OpMemberName %SomeBuffer 2 "b"
OpName %Registers "Registers"
OpMemberName %Registers 0 "address"
OpMemberName %Registers 1 "address2"
OpName %registers "registers"
OpName %a "a"
OpName %b "b"
OpMemberDecorate %SomeBuffer 0 Offset 0
OpMemberDecorate %SomeBuffer 1 Offset 16
OpMemberDecorate %SomeBuffer 2 Offset 24
OpDecorate %SomeBuffer Block
OpMemberDecorate %Registers 0 Offset 0
OpMemberDecorate %Registers 1 Offset 8
OpDecorate %Registers Block
%void = OpTypeVoid
%3 = OpTypeFunction %void
OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_SomeBuffer PhysicalStorageBuffer
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%ulong = OpTypeInt 64 0
%uint = OpTypeInt 32 0
%v2uint = OpTypeVector %uint 2
%SomeBuffer = OpTypeStruct %v4float %ulong %v2uint
%_ptr_PhysicalStorageBuffer_SomeBuffer = OpTypePointer PhysicalStorageBuffer %SomeBuffer
%_ptr_Function__ptr_PhysicalStorageBuffer_SomeBuffer = OpTypePointer Function %_ptr_PhysicalStorageBuffer_SomeBuffer
%Registers = OpTypeStruct %ulong %v2uint
%_ptr_PushConstant_Registers = OpTypePointer PushConstant %Registers
%registers = OpVariable %_ptr_PushConstant_Registers PushConstant
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%_ptr_PushConstant_ulong = OpTypePointer PushConstant %ulong
%int_1 = OpConstant %int 1
%_ptr_PushConstant_v2uint = OpTypePointer PushConstant %v2uint
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%35 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
%_ptr_PhysicalStorageBuffer_v4float = OpTypePointer PhysicalStorageBuffer %v4float
%float_5 = OpConstant %float 5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%float_8 = OpConstant %float 8
%43 = OpConstantComposite %v4float %float_5 %float_6 %float_7 %float_8
%_ptr_Function_ulong = OpTypePointer Function %ulong
%_ptr_Function_v2uint = OpTypePointer Function %v2uint
%_ptr_PhysicalStorageBuffer_ulong = OpTypePointer PhysicalStorageBuffer %ulong
%int_2 = OpConstant %int 2
%_ptr_PhysicalStorageBuffer_v2uint = OpTypePointer PhysicalStorageBuffer %v2uint
%main = OpFunction %void None %3
%5 = OpLabel
%a = OpVariable %_ptr_Function_ulong Function
%b = OpVariable %_ptr_Function_v2uint Function
%21 = OpAccessChain %_ptr_PushConstant_ulong %registers %int_0
%27 = OpAccessChain %_ptr_PushConstant_v2uint %registers %int_1
%uint_ptr0 = OpLoad %ulong %21
%uint_ptr1 = OpLoad %v2uint %27
; ConvertUToPtr and vice versa do not accept vectors.
%ulong_ptr0 = OpConvertUToPtr %_ptr_PhysicalStorageBuffer_SomeBuffer %uint_ptr0
%ulong_ptr1 = OpBitcast %_ptr_PhysicalStorageBuffer_SomeBuffer %uint_ptr0
%uvec2_ptr0 = OpBitcast %_ptr_PhysicalStorageBuffer_SomeBuffer %uint_ptr1
%vec4_write0 = OpAccessChain %_ptr_PhysicalStorageBuffer_v4float %ulong_ptr0 %int_0
%vec4_write1 = OpAccessChain %_ptr_PhysicalStorageBuffer_v4float %ulong_ptr1 %int_0
%vec4_write2 = OpAccessChain %_ptr_PhysicalStorageBuffer_v4float %uvec2_ptr0 %int_0
OpStore %vec4_write0 %35 Aligned 16
OpStore %vec4_write1 %35 Aligned 16
OpStore %vec4_write2 %35 Aligned 16
%ulong_from_ptr0 = OpConvertPtrToU %ulong %ulong_ptr0
%ulong_from_ptr1 = OpBitcast %ulong %ulong_ptr1
%uvec2_from_ptr0 = OpBitcast %v2uint %uvec2_ptr0
%ptr0 = OpAccessChain %_ptr_PhysicalStorageBuffer_ulong %ulong_ptr0 %int_1
%ptr1 = OpAccessChain %_ptr_PhysicalStorageBuffer_ulong %ulong_ptr1 %int_1
%ptr2 = OpAccessChain %_ptr_PhysicalStorageBuffer_v2uint %uvec2_ptr0 %int_2
OpStore %ptr0 %ulong_from_ptr0 Aligned 8
OpStore %ptr1 %ulong_from_ptr1 Aligned 8
OpStore %ptr2 %uvec2_from_ptr0 Aligned 8
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,106 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 10
; Bound: 62
; Schema: 0
OpCapability Shader
OpCapability Int64
OpCapability PhysicalStorageBufferAddresses
OpExtension "SPV_KHR_physical_storage_buffer"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel PhysicalStorageBuffer64 GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpSourceExtension "GL_ARB_gpu_shader_int64"
OpSourceExtension "GL_EXT_buffer_reference"
OpSourceExtension "GL_EXT_buffer_reference_uvec2"
OpName %main "main"
OpName %SomeBuffer "SomeBuffer"
OpMemberName %SomeBuffer 0 "v"
OpMemberName %SomeBuffer 1 "a"
OpMemberName %SomeBuffer 2 "b"
OpName %Registers "Registers"
OpMemberName %Registers 0 "address"
OpMemberName %Registers 1 "address2"
OpName %registers "registers"
OpName %a "a"
OpName %b "b"
OpMemberDecorate %SomeBuffer 0 Offset 0
OpMemberDecorate %SomeBuffer 1 Offset 16
OpMemberDecorate %SomeBuffer 2 Offset 24
OpDecorate %SomeBuffer Block
OpMemberDecorate %Registers 0 Offset 0
OpMemberDecorate %Registers 1 Offset 8
OpDecorate %Registers Block
%void = OpTypeVoid
%3 = OpTypeFunction %void
OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_SomeBuffer PhysicalStorageBuffer
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%ulong = OpTypeInt 64 0
%uint = OpTypeInt 32 0
%v2uint = OpTypeVector %uint 2
%SomeBuffer = OpTypeStruct %v4float %ulong %v2uint
%_ptr_PhysicalStorageBuffer_SomeBuffer = OpTypePointer PhysicalStorageBuffer %SomeBuffer
%_ptr_Function__ptr_PhysicalStorageBuffer_SomeBuffer = OpTypePointer Function %_ptr_PhysicalStorageBuffer_SomeBuffer
%Registers = OpTypeStruct %ulong %v2uint
%_ptr_PushConstant_Registers = OpTypePointer PushConstant %Registers
%registers = OpVariable %_ptr_PushConstant_Registers PushConstant
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%_ptr_PushConstant_ulong = OpTypePointer PushConstant %ulong
%int_1 = OpConstant %int 1
%_ptr_PushConstant_v2uint = OpTypePointer PushConstant %v2uint
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%35 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
%_ptr_PhysicalStorageBuffer_v4float = OpTypePointer PhysicalStorageBuffer %v4float
%float_5 = OpConstant %float 5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%float_8 = OpConstant %float 8
%43 = OpConstantComposite %v4float %float_5 %float_6 %float_7 %float_8
%_ptr_Function_ulong = OpTypePointer Function %ulong
%_ptr_Function_v2uint = OpTypePointer Function %v2uint
%_ptr_PhysicalStorageBuffer_ulong = OpTypePointer PhysicalStorageBuffer %ulong
%int_2 = OpConstant %int 2
%_ptr_PhysicalStorageBuffer_v2uint = OpTypePointer PhysicalStorageBuffer %v2uint
%main = OpFunction %void None %3
%5 = OpLabel
%a = OpVariable %_ptr_Function_ulong Function
%b = OpVariable %_ptr_Function_v2uint Function
%21 = OpAccessChain %_ptr_PushConstant_ulong %registers %int_0
%27 = OpAccessChain %_ptr_PushConstant_v2uint %registers %int_1
%uint_ptr0 = OpLoad %ulong %21
%uint_ptr1 = OpLoad %v2uint %27
; ConvertUToPtr and vice versa do not accept vectors.
%ulong_ptr0 = OpConvertUToPtr %_ptr_PhysicalStorageBuffer_SomeBuffer %uint_ptr0
%ulong_ptr1 = OpBitcast %_ptr_PhysicalStorageBuffer_SomeBuffer %uint_ptr0
%uvec2_ptr0 = OpBitcast %_ptr_PhysicalStorageBuffer_SomeBuffer %uint_ptr1
%vec4_write0 = OpAccessChain %_ptr_PhysicalStorageBuffer_v4float %ulong_ptr0 %int_0
%vec4_write1 = OpAccessChain %_ptr_PhysicalStorageBuffer_v4float %ulong_ptr1 %int_0
%vec4_write2 = OpAccessChain %_ptr_PhysicalStorageBuffer_v4float %uvec2_ptr0 %int_0
OpStore %vec4_write0 %35 Aligned 16
OpStore %vec4_write1 %35 Aligned 16
OpStore %vec4_write2 %35 Aligned 16
%ulong_from_ptr0 = OpConvertPtrToU %ulong %ulong_ptr0
%ulong_from_ptr1 = OpBitcast %ulong %ulong_ptr1
%uvec2_from_ptr0 = OpBitcast %v2uint %uvec2_ptr0
%ptr0 = OpAccessChain %_ptr_PhysicalStorageBuffer_ulong %ulong_ptr0 %int_1
%ptr1 = OpAccessChain %_ptr_PhysicalStorageBuffer_ulong %ulong_ptr1 %int_1
%ptr2 = OpAccessChain %_ptr_PhysicalStorageBuffer_v2uint %uvec2_ptr0 %int_2
OpStore %ptr0 %ulong_from_ptr0 Aligned 8
OpStore %ptr1 %ulong_from_ptr1 Aligned 8
OpStore %ptr2 %uvec2_from_ptr0 Aligned 8
OpReturn
OpFunctionEnd

View File

@ -8851,6 +8851,34 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
#undef MSL_RAY_QUERY_IS_OP2
#undef MSL_RAY_QUERY_GET_OP2
#undef MSL_RAY_QUERY_OP_INNER2
case OpConvertPtrToU:
case OpConvertUToPtr:
case OpBitcast:
{
auto &type = get<SPIRType>(ops[0]);
auto &input_type = expression_type(ops[2]);
if (opcode != OpBitcast || type.pointer || input_type.pointer)
{
string op;
if (type.vecsize == 1 && input_type.vecsize == 1)
op = join("reinterpret_cast<", type_to_glsl(type), ">(", to_unpacked_expression(ops[2]), ")");
else if (input_type.vecsize == 2)
op = join("reinterpret_cast<", type_to_glsl(type), ">(as_type<ulong>(", to_unpacked_expression(ops[2]), "))");
else
op = join("as_type<", type_to_glsl(type), ">(reinterpret_cast<ulong>(", to_unpacked_expression(ops[2]), "))");
emit_op(ops[0], ops[1], op, should_forward(ops[2]));
inherit_expression_dependencies(ops[1], ops[2]);
}
else
CompilerGLSL::emit_instruction(instruction);
break;
}
default:
CompilerGLSL::emit_instruction(instruction);
break;
@ -14590,26 +14618,10 @@ string CompilerMSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &in
return type_to_glsl(out_type);
}
bool CompilerMSL::emit_complex_bitcast(uint32_t result_type, uint32_t id, uint32_t op0)
bool CompilerMSL::emit_complex_bitcast(uint32_t, uint32_t, uint32_t)
{
auto &out_type = get<SPIRType>(result_type);
auto &in_type = expression_type(op0);
bool uvec2_to_ptr = (in_type.basetype == SPIRType::UInt && in_type.vecsize == 2 &&
out_type.pointer && out_type.storage == StorageClassPhysicalStorageBuffer);
bool ptr_to_uvec2 = (in_type.pointer && in_type.storage == StorageClassPhysicalStorageBuffer &&
out_type.basetype == SPIRType::UInt && out_type.vecsize == 2);
string expr;
// Casting between uvec2 and buffer storage pointer per GL_EXT_buffer_reference_uvec2
if (uvec2_to_ptr)
expr = join("((", type_to_glsl(out_type), ")as_type<uint64_t>(", to_unpacked_expression(op0), "))");
else if (ptr_to_uvec2)
expr = join("as_type<", type_to_glsl(out_type), ">((uint64_t)", to_unpacked_expression(op0), ")");
else
return false;
emit_op(result_type, id, expr, should_forward(op0));
return true;
// This is handled from the outside where we deal with PtrToU/UToPtr and friends.
return false;
}
// Returns an MSL string identifying the name of a SPIR-V builtin.