GLSL/HLSL: Support packUint2x32 and unpackUint2x32
This commit is contained in:
parent
3fb86e4385
commit
55dfbead2f
@ -0,0 +1,34 @@
|
||||
static float4 FragColor;
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : COLOR0;
|
||||
};
|
||||
|
||||
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 = float4(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);
|
||||
}
|
||||
|
55
shaders-hlsl/asm/frag/pack-and-unpack-uint2.asm.frag
Normal file
55
shaders-hlsl/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)
|
||||
|
@ -1499,6 +1499,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 +4390,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 +5389,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