Merge pull request #1335 from KhronosGroup/fix-1325
GLSL/HLSL: Implement unpack/pack2x32Uint
This commit is contained in:
commit
5cb0f0a640
@ -0,0 +1,33 @@
|
||||
static float4 FragColor;
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
uint64_t SPIRV_Cross_packUint2x32(uint2 value)
|
||||
{
|
||||
return (uint64_t(value.y) << 32) | uint64_t(value.x);
|
||||
}
|
||||
|
||||
uint2 SPIRV_Cross_unpackUint2x32(uint64_t value)
|
||||
{
|
||||
uint2 Unpacked;
|
||||
Unpacked.x = uint(value & 0xffffffff);
|
||||
Unpacked.y = uint(value >> 32);
|
||||
return Unpacked;
|
||||
}
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
uint2 unpacked = SPIRV_Cross_unpackUint2x32(SPIRV_Cross_packUint2x32(uint2(18u, 52u)));
|
||||
FragColor = float4(float(unpacked.x), float(unpacked.y), 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main()
|
||||
{
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
#extension GL_ARB_gpu_shader_int64 : require
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
uvec2 unpacked = unpackUint2x32(packUint2x32(uvec2(18u, 52u)));
|
||||
FragColor = vec4(float(unpacked.x), float(unpacked.y), 1.0, 1.0);
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
static float4 FragColor;
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
uint64_t SPIRV_Cross_packUint2x32(uint2 value)
|
||||
{
|
||||
return (uint64_t(value.y) << 32) | uint64_t(value.x);
|
||||
}
|
||||
|
||||
uint2 SPIRV_Cross_unpackUint2x32(uint64_t value)
|
||||
{
|
||||
uint2 Unpacked;
|
||||
Unpacked.x = uint(value & 0xffffffff);
|
||||
Unpacked.y = uint(value >> 32);
|
||||
return Unpacked;
|
||||
}
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
uint64_t _packed = SPIRV_Cross_packUint2x32(uint2(18u, 52u));
|
||||
uint2 unpacked = SPIRV_Cross_unpackUint2x32(_packed);
|
||||
FragColor = float4(float(unpacked.x), float(unpacked.y), 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main()
|
||||
{
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
12
reference/shaders/asm/frag/pack-and-unpack-uint2.asm.frag
Normal file
12
reference/shaders/asm/frag/pack-and-unpack-uint2.asm.frag
Normal file
@ -0,0 +1,12 @@
|
||||
#version 450
|
||||
#extension GL_ARB_gpu_shader_int64 : require
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
uint64_t _packed = packUint2x32(uvec2(18u, 52u));
|
||||
uvec2 unpacked = unpackUint2x32(_packed);
|
||||
FragColor = vec4(float(unpacked.x), float(unpacked.y), 1.0, 1.0);
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 7
|
||||
; Bound: 34
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpCapability Int64
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_ARB_gpu_shader_int64"
|
||||
OpName %main "main"
|
||||
OpName %packed "packed"
|
||||
OpName %unpacked "unpacked"
|
||||
OpName %FragColor "FragColor"
|
||||
OpDecorate %FragColor Location 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%ulong = OpTypeInt 64 0
|
||||
%_ptr_Function_ulong = OpTypePointer Function %ulong
|
||||
%uint = OpTypeInt 32 0
|
||||
%v2uint = OpTypeVector %uint 2
|
||||
%uint_18 = OpConstant %uint 18
|
||||
%uint_52 = OpConstant %uint 52
|
||||
%13 = OpConstantComposite %v2uint %uint_18 %uint_52
|
||||
%_ptr_Function_v2uint = OpTypePointer Function %v2uint
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Function_uint = OpTypePointer Function %uint
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%float_1 = OpConstant %float 1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%packed = OpVariable %_ptr_Function_ulong Function
|
||||
%unpacked = OpVariable %_ptr_Function_v2uint Function
|
||||
%14 = OpBitcast %ulong %13
|
||||
OpStore %packed %14
|
||||
%17 = OpLoad %ulong %packed
|
||||
%18 = OpBitcast %v2uint %17
|
||||
OpStore %unpacked %18
|
||||
%25 = OpAccessChain %_ptr_Function_uint %unpacked %uint_0
|
||||
%26 = OpLoad %uint %25
|
||||
%27 = OpConvertUToF %float %26
|
||||
%29 = OpAccessChain %_ptr_Function_uint %unpacked %uint_1
|
||||
%30 = OpLoad %uint %29
|
||||
%31 = OpConvertUToF %float %30
|
||||
%33 = OpCompositeConstruct %v4float %27 %31 %float_1 %float_1
|
||||
OpStore %FragColor %33
|
||||
OpReturn
|
||||
OpFunctionEnd
|
55
shaders/asm/frag/pack-and-unpack-uint2.asm.frag
Normal file
55
shaders/asm/frag/pack-and-unpack-uint2.asm.frag
Normal file
@ -0,0 +1,55 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 7
|
||||
; Bound: 34
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpCapability Int64
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_ARB_gpu_shader_int64"
|
||||
OpName %main "main"
|
||||
OpName %packed "packed"
|
||||
OpName %unpacked "unpacked"
|
||||
OpName %FragColor "FragColor"
|
||||
OpDecorate %FragColor Location 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%ulong = OpTypeInt 64 0
|
||||
%_ptr_Function_ulong = OpTypePointer Function %ulong
|
||||
%uint = OpTypeInt 32 0
|
||||
%v2uint = OpTypeVector %uint 2
|
||||
%uint_18 = OpConstant %uint 18
|
||||
%uint_52 = OpConstant %uint 52
|
||||
%13 = OpConstantComposite %v2uint %uint_18 %uint_52
|
||||
%_ptr_Function_v2uint = OpTypePointer Function %v2uint
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Function_uint = OpTypePointer Function %uint
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%float_1 = OpConstant %float 1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%packed = OpVariable %_ptr_Function_ulong Function
|
||||
%unpacked = OpVariable %_ptr_Function_v2uint Function
|
||||
%14 = OpBitcast %ulong %13
|
||||
OpStore %packed %14
|
||||
%17 = OpLoad %ulong %packed
|
||||
%18 = OpBitcast %v2uint %17
|
||||
OpStore %unpacked %18
|
||||
%25 = OpAccessChain %_ptr_Function_uint %unpacked %uint_0
|
||||
%26 = OpLoad %uint %25
|
||||
%27 = OpConvertUToF %float %26
|
||||
%29 = OpAccessChain %_ptr_Function_uint %unpacked %uint_1
|
||||
%30 = OpLoad %uint %29
|
||||
%31 = OpConvertUToF %float %30
|
||||
%33 = OpCompositeConstruct %v4float %27 %31 %float_1 %float_1
|
||||
OpStore %FragColor %33
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -6683,6 +6683,8 @@ string CompilerGLSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &i
|
||||
// And finally, some even more special purpose casts.
|
||||
if (out_type.basetype == SPIRType::UInt64 && in_type.basetype == SPIRType::UInt && in_type.vecsize == 2)
|
||||
return "packUint2x32";
|
||||
else if (out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::UInt64 && out_type.vecsize == 2)
|
||||
return "unpackUint2x32";
|
||||
else if (out_type.basetype == SPIRType::Half && in_type.basetype == SPIRType::UInt && in_type.vecsize == 1)
|
||||
return "unpackFloat2x16";
|
||||
else if (out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Half && in_type.vecsize == 2)
|
||||
|
@ -401,8 +401,12 @@ string CompilerHLSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
||||
case SPIRType::Double:
|
||||
return "double";
|
||||
case SPIRType::Int64:
|
||||
if (hlsl_options.shader_model < 60)
|
||||
SPIRV_CROSS_THROW("64-bit integers only supported in SM 6.0.");
|
||||
return "int64_t";
|
||||
case SPIRType::UInt64:
|
||||
if (hlsl_options.shader_model < 60)
|
||||
SPIRV_CROSS_THROW("64-bit integers only supported in SM 6.0.");
|
||||
return "uint64_t";
|
||||
default:
|
||||
return "???";
|
||||
@ -1499,6 +1503,24 @@ void CompilerHLSL::emit_resources()
|
||||
statement("");
|
||||
}
|
||||
|
||||
if (requires_uint2_packing)
|
||||
{
|
||||
statement("uint64_t SPIRV_Cross_packUint2x32(uint2 value)");
|
||||
begin_scope();
|
||||
statement("return (uint64_t(value.y) << 32) | uint64_t(value.x);");
|
||||
end_scope();
|
||||
statement("");
|
||||
|
||||
statement("uint2 SPIRV_Cross_unpackUint2x32(uint64_t value)");
|
||||
begin_scope();
|
||||
statement("uint2 Unpacked;");
|
||||
statement("Unpacked.x = uint(value & 0xffffffff);");
|
||||
statement("Unpacked.y = uint(value >> 32);");
|
||||
statement("return Unpacked;");
|
||||
end_scope();
|
||||
statement("");
|
||||
}
|
||||
|
||||
if (requires_explicit_fp16_packing)
|
||||
{
|
||||
// HLSL does not pack into a single word sadly :(
|
||||
@ -4372,6 +4394,27 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
|
||||
emit_access_chain(instruction);
|
||||
break;
|
||||
}
|
||||
case OpBitcast:
|
||||
{
|
||||
auto bitcast_type = get_bitcast_type(ops[0], ops[2]);
|
||||
if (bitcast_type == CompilerHLSL::TypeNormal)
|
||||
CompilerGLSL::emit_instruction(instruction);
|
||||
else
|
||||
{
|
||||
if (!requires_uint2_packing)
|
||||
{
|
||||
requires_uint2_packing = true;
|
||||
force_recompile();
|
||||
}
|
||||
|
||||
if (bitcast_type == CompilerHLSL::TypePackUint2x32)
|
||||
emit_unary_func_op(ops[0], ops[1], ops[2], "SPIRV_Cross_packUint2x32");
|
||||
else
|
||||
emit_unary_func_op(ops[0], ops[1], ops[2], "SPIRV_Cross_unpackUint2x32");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OpStore:
|
||||
{
|
||||
@ -5350,3 +5393,18 @@ bool CompilerHLSL::is_hlsl_resource_binding_used(ExecutionModel model, uint32_t
|
||||
auto itr = resource_bindings.find(tuple);
|
||||
return itr != end(resource_bindings) && itr->second.second;
|
||||
}
|
||||
|
||||
CompilerHLSL::BitcastType CompilerHLSL::get_bitcast_type(uint32_t result_type, uint32_t op0)
|
||||
{
|
||||
auto &rslt_type = get<SPIRType>(result_type);
|
||||
auto &expr_type = expression_type(op0);
|
||||
|
||||
if (rslt_type.basetype == SPIRType::BaseType::UInt64 && expr_type.basetype == SPIRType::BaseType::UInt &&
|
||||
expr_type.vecsize == 2)
|
||||
return BitcastType::TypePackUint2x32;
|
||||
else if (rslt_type.basetype == SPIRType::BaseType::UInt && rslt_type.vecsize == 2 &&
|
||||
expr_type.basetype == SPIRType::BaseType::UInt64)
|
||||
return BitcastType::TypeUnpackUint64;
|
||||
|
||||
return BitcastType::TypeNormal;
|
||||
}
|
||||
|
@ -249,6 +249,7 @@ private:
|
||||
// TODO: Refactor this to be more similar to MSL, maybe have some common system in place?
|
||||
bool requires_op_fmod = false;
|
||||
bool requires_fp16_packing = false;
|
||||
bool requires_uint2_packing = false;
|
||||
bool requires_explicit_fp16_packing = false;
|
||||
bool requires_unorm8_packing = false;
|
||||
bool requires_snorm8_packing = false;
|
||||
@ -288,6 +289,15 @@ private:
|
||||
QueryTypeCount = 3
|
||||
};
|
||||
|
||||
enum BitcastType
|
||||
{
|
||||
TypeNormal,
|
||||
TypePackUint2x32,
|
||||
TypeUnpackUint64
|
||||
};
|
||||
|
||||
BitcastType get_bitcast_type(uint32_t result_type, uint32_t op0);
|
||||
|
||||
void emit_builtin_variables();
|
||||
bool require_output = false;
|
||||
bool require_input = false;
|
||||
|
Loading…
Reference in New Issue
Block a user