mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-13 05:05:57 +00:00
shader_recompiler: Replace texel buffers with in-shader buffer format interpretation (#2363)
* shader_recompiler: Replace texel buffers with in-shader buffer format interpretation * shader_recompiler: Move 10/11-bit float conversion to functions and address some comments. * vulkan: Remove VK_KHR_maintenance5 as it is no longer needed for buffer views. * shader_recompiler: Add helpers for composites and bitfields in pack/unpack. * shader_recompiler: Use initializer_list for bitfield insert helper.
This commit is contained in:
parent
78b4f10cc6
commit
cfe249debe
35 changed files with 1037 additions and 562 deletions
|
@ -250,7 +250,7 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
|
|||
ctx.AddCapability(spv::Capability::Float64);
|
||||
}
|
||||
ctx.AddCapability(spv::Capability::Int64);
|
||||
if (info.has_storage_images || info.has_image_buffers) {
|
||||
if (info.has_storage_images) {
|
||||
ctx.AddCapability(spv::Capability::StorageImageExtendedFormats);
|
||||
ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat);
|
||||
ctx.AddCapability(spv::Capability::StorageImageWriteWithoutFormat);
|
||||
|
@ -259,12 +259,6 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
|
|||
ctx.AddCapability(spv::Capability::ImageReadWriteLodAMD);
|
||||
}
|
||||
}
|
||||
if (info.has_texel_buffers) {
|
||||
ctx.AddCapability(spv::Capability::SampledBuffer);
|
||||
}
|
||||
if (info.has_image_buffers) {
|
||||
ctx.AddCapability(spv::Capability::ImageBuffer);
|
||||
}
|
||||
if (info.has_image_gather) {
|
||||
ctx.AddCapability(spv::Capability::ImageGatherExtended);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,56 @@
|
|||
|
||||
namespace Shader::Backend::SPIRV {
|
||||
|
||||
struct R {
|
||||
R(u32 a, u32 b) : offset(a), size(b) {}
|
||||
u32 offset;
|
||||
u32 size;
|
||||
};
|
||||
template <bool is_signed, typename... Args>
|
||||
static std::array<Id, sizeof...(Args)> ExtractBitFields(EmitContext& ctx, const Id value,
|
||||
const Args... args) {
|
||||
const auto op_func =
|
||||
is_signed ? &EmitContext::OpBitFieldSExtract : &EmitContext::OpBitFieldUExtract;
|
||||
std::array<Id, sizeof...(Args)> result{};
|
||||
u32 i = 0;
|
||||
(
|
||||
[&] {
|
||||
result[i++] = (ctx.*op_func)(ctx.U32[1], value, ctx.ConstU32(args.offset),
|
||||
ctx.ConstU32(args.size));
|
||||
}(),
|
||||
...);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static Id InsertBitFields(EmitContext& ctx, const std::initializer_list<Id> values,
|
||||
const Args... args) {
|
||||
Id result{};
|
||||
auto it = values.begin();
|
||||
(
|
||||
[&] {
|
||||
if (it == values.begin()) {
|
||||
result = *it;
|
||||
} else {
|
||||
result = ctx.OpBitFieldInsert(ctx.U32[1], result, *it, ctx.ConstU32(args.offset),
|
||||
ctx.ConstU32(args.size));
|
||||
}
|
||||
++it;
|
||||
}(),
|
||||
...);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <u32 num_components>
|
||||
static std::array<Id, num_components> ExtractComposite(EmitContext& ctx, const VectorIds type,
|
||||
const Id value) {
|
||||
std::array<Id, num_components> result{};
|
||||
for (u32 i = 0; i < num_components; i++) {
|
||||
result[i] = ctx.OpCompositeExtract(type[1], value, i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Id EmitBitCastU16F16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpBitcast(ctx.U16, value);
|
||||
}
|
||||
|
@ -42,22 +92,6 @@ Id EmitPackFloat2x32(EmitContext& ctx, Id value) {
|
|||
return ctx.OpBitcast(ctx.F64[1], value);
|
||||
}
|
||||
|
||||
Id EmitPackFloat2x16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpBitcast(ctx.U32[1], value);
|
||||
}
|
||||
|
||||
Id EmitUnpackFloat2x16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpBitcast(ctx.F16[2], value);
|
||||
}
|
||||
|
||||
Id EmitPackHalf2x16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpPackHalf2x16(ctx.U32[1], value);
|
||||
}
|
||||
|
||||
Id EmitUnpackHalf2x16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpUnpackHalf2x16(ctx.F32[2], value);
|
||||
}
|
||||
|
||||
Id EmitPackUnorm2x16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpPackUnorm2x16(ctx.U32[1], value);
|
||||
}
|
||||
|
@ -75,31 +109,157 @@ Id EmitUnpackSnorm2x16(EmitContext& ctx, Id value) {
|
|||
}
|
||||
|
||||
Id EmitPackUint2x16(EmitContext& ctx, Id value) {
|
||||
// No SPIR-V instruction for this, do it manually.
|
||||
const auto x{ctx.OpCompositeExtract(ctx.U32[1], value, 0)};
|
||||
const auto y{ctx.OpCompositeExtract(ctx.U32[1], value, 1)};
|
||||
return ctx.OpBitFieldInsert(ctx.U32[1], x, y, ctx.ConstU32(16U), ctx.ConstU32(16U));
|
||||
const auto unpacked{ctx.OpBitcast(ctx.U32[2], value)};
|
||||
const auto [x, y] = ExtractComposite<2>(ctx, ctx.U32, unpacked);
|
||||
return InsertBitFields(ctx, {x, y}, R(0, 16), R(16, 16));
|
||||
}
|
||||
|
||||
Id EmitUnpackUint2x16(EmitContext& ctx, Id value) {
|
||||
// No SPIR-V instruction for this, do it manually.
|
||||
const auto x{ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.ConstU32(0U), ctx.ConstU32(16U))};
|
||||
const auto y{ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.ConstU32(16U), ctx.ConstU32(16U))};
|
||||
return ctx.OpCompositeConstruct(ctx.U32[2], x, y);
|
||||
const auto [x, y] = ExtractBitFields<false>(ctx, value, R(0, 16), R(16, 16));
|
||||
const auto unpacked{ctx.OpCompositeConstruct(ctx.U32[2], x, y)};
|
||||
return ctx.OpBitcast(ctx.F32[2], unpacked);
|
||||
}
|
||||
|
||||
Id EmitPackSint2x16(EmitContext& ctx, Id value) {
|
||||
// No SPIR-V instruction for this, do it manually.
|
||||
const auto x{ctx.OpCompositeExtract(ctx.U32[1], value, 0)};
|
||||
const auto y{ctx.OpCompositeExtract(ctx.U32[1], value, 1)};
|
||||
return ctx.OpBitFieldInsert(ctx.U32[1], x, y, ctx.ConstU32(16U), ctx.ConstU32(16U));
|
||||
return EmitPackUint2x16(ctx, value);
|
||||
}
|
||||
|
||||
Id EmitUnpackSint2x16(EmitContext& ctx, Id value) {
|
||||
// No SPIR-V instruction for this, do it manually.
|
||||
const auto x{ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.ConstU32(0U), ctx.ConstU32(16U))};
|
||||
const auto y{ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.ConstU32(16U), ctx.ConstU32(16U))};
|
||||
return ctx.OpCompositeConstruct(ctx.U32[2], x, y);
|
||||
const auto [x, y] = ExtractBitFields<true>(ctx, value, R(0, 16), R(16, 16));
|
||||
const auto unpacked{ctx.OpCompositeConstruct(ctx.U32[2], x, y)};
|
||||
return ctx.OpBitcast(ctx.F32[2], unpacked);
|
||||
}
|
||||
|
||||
Id EmitPackHalf2x16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpPackHalf2x16(ctx.U32[1], value);
|
||||
}
|
||||
|
||||
Id EmitUnpackHalf2x16(EmitContext& ctx, Id value) {
|
||||
return ctx.OpUnpackHalf2x16(ctx.F32[2], value);
|
||||
}
|
||||
|
||||
Id EmitPackUnorm4x8(EmitContext& ctx, Id value) {
|
||||
return ctx.OpPackUnorm4x8(ctx.U32[1], value);
|
||||
}
|
||||
|
||||
Id EmitUnpackUnorm4x8(EmitContext& ctx, Id value) {
|
||||
return ctx.OpUnpackUnorm4x8(ctx.F32[4], value);
|
||||
}
|
||||
|
||||
Id EmitPackSnorm4x8(EmitContext& ctx, Id value) {
|
||||
return ctx.OpPackSnorm4x8(ctx.U32[1], value);
|
||||
}
|
||||
|
||||
Id EmitUnpackSnorm4x8(EmitContext& ctx, Id value) {
|
||||
return ctx.OpUnpackSnorm4x8(ctx.F32[4], value);
|
||||
}
|
||||
|
||||
Id EmitPackUint4x8(EmitContext& ctx, Id value) {
|
||||
const auto unpacked{ctx.OpBitcast(ctx.U32[4], value)};
|
||||
const auto [x, y, z, w] = ExtractComposite<4>(ctx, ctx.U32, unpacked);
|
||||
return InsertBitFields(ctx, {x, y, z, w}, R(0, 8), R(8, 8), R(16, 8), R(24, 8));
|
||||
}
|
||||
|
||||
Id EmitUnpackUint4x8(EmitContext& ctx, Id value) {
|
||||
const auto [x, y, z, w] =
|
||||
ExtractBitFields<false>(ctx, value, R(0, 8), R(8, 8), R(16, 8), R(24, 8));
|
||||
const auto unpacked{ctx.OpCompositeConstruct(ctx.U32[4], x, y, z, w)};
|
||||
return ctx.OpBitcast(ctx.F32[4], unpacked);
|
||||
}
|
||||
|
||||
Id EmitPackSint4x8(EmitContext& ctx, Id value) {
|
||||
return EmitPackUint4x8(ctx, value);
|
||||
}
|
||||
|
||||
Id EmitUnpackSint4x8(EmitContext& ctx, Id value) {
|
||||
const auto [x, y, z, w] =
|
||||
ExtractBitFields<true>(ctx, value, R(0, 8), R(8, 8), R(16, 8), R(24, 8));
|
||||
const auto unpacked{ctx.OpCompositeConstruct(ctx.U32[4], x, y, z, w)};
|
||||
return ctx.OpBitcast(ctx.F32[4], unpacked);
|
||||
}
|
||||
|
||||
Id EmitPackUfloat10_11_11(EmitContext& ctx, Id value) {
|
||||
const auto [x, y, z] = ExtractComposite<3>(ctx, ctx.F32, value);
|
||||
const auto cvt_x{ctx.OpFunctionCall(ctx.U32[1], ctx.f32_to_uf11, x)};
|
||||
const auto cvt_y{ctx.OpFunctionCall(ctx.U32[1], ctx.f32_to_uf11, y)};
|
||||
const auto cvt_z{ctx.OpFunctionCall(ctx.U32[1], ctx.f32_to_uf10, z)};
|
||||
return InsertBitFields(ctx, {cvt_x, cvt_y, cvt_z}, R(0, 11), R(11, 11), R(22, 10));
|
||||
}
|
||||
|
||||
Id EmitUnpackUfloat10_11_11(EmitContext& ctx, Id value) {
|
||||
const auto [x, y, z] = ExtractBitFields<false>(ctx, value, R(0, 11), R(11, 11), R(22, 10));
|
||||
const auto cvt_x{ctx.OpFunctionCall(ctx.F32[1], ctx.uf11_to_f32, x)};
|
||||
const auto cvt_y{ctx.OpFunctionCall(ctx.F32[1], ctx.uf11_to_f32, y)};
|
||||
const auto cvt_z{ctx.OpFunctionCall(ctx.F32[1], ctx.uf10_to_f32, z)};
|
||||
return ctx.OpCompositeConstruct(ctx.F32[3], cvt_x, cvt_y, cvt_z);
|
||||
}
|
||||
|
||||
Id EmitPackUnorm2_10_10_10(EmitContext& ctx, Id value) {
|
||||
const auto unorm_min{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(0.f), ctx.ConstF32(0.f),
|
||||
ctx.ConstF32(0.f), ctx.ConstF32(0.f))};
|
||||
const auto unorm_max{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(1.f), ctx.ConstF32(1.f),
|
||||
ctx.ConstF32(1.f), ctx.ConstF32(1.f))};
|
||||
const auto clamped{ctx.OpFClamp(ctx.F32[4], value, unorm_min, unorm_max)};
|
||||
const auto unorm_mul{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(1023.f),
|
||||
ctx.ConstF32(1023.f), ctx.ConstF32(1023.f),
|
||||
ctx.ConstF32(3.f))};
|
||||
const auto as_float{ctx.OpFMul(ctx.F32[4], clamped, unorm_mul)};
|
||||
const auto as_uint{ctx.OpConvertFToU(ctx.U32[4], ctx.OpRoundEven(ctx.F32[4], as_float))};
|
||||
return EmitPackUint2_10_10_10(ctx, ctx.OpBitcast(ctx.F32[4], as_uint));
|
||||
}
|
||||
|
||||
Id EmitUnpackUnorm2_10_10_10(EmitContext& ctx, Id value) {
|
||||
const auto unpacked{ctx.OpBitcast(ctx.U32[4], EmitUnpackUint2_10_10_10(ctx, value))};
|
||||
const auto as_float{ctx.OpConvertUToF(ctx.F32[4], unpacked)};
|
||||
const auto unorm_div{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(1023.f),
|
||||
ctx.ConstF32(1023.f), ctx.ConstF32(1023.f),
|
||||
ctx.ConstF32(3.f))};
|
||||
return ctx.OpFDiv(ctx.F32[4], as_float, unorm_div);
|
||||
}
|
||||
|
||||
Id EmitPackSnorm2_10_10_10(EmitContext& ctx, Id value) {
|
||||
const auto snorm_min{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(-1.f), ctx.ConstF32(-1.f),
|
||||
ctx.ConstF32(-1.f), ctx.ConstF32(-1.f))};
|
||||
const auto snorm_max{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(1.f), ctx.ConstF32(1.f),
|
||||
ctx.ConstF32(1.f), ctx.ConstF32(1.f))};
|
||||
const auto clamped{ctx.OpFClamp(ctx.F32[4], value, snorm_min, snorm_max)};
|
||||
const auto snorm_mul{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(511.f), ctx.ConstF32(511.f),
|
||||
ctx.ConstF32(511.f), ctx.ConstF32(1.f))};
|
||||
const auto as_float{ctx.OpFMul(ctx.F32[4], clamped, snorm_mul)};
|
||||
const auto as_sint{ctx.OpConvertFToS(ctx.U32[4], ctx.OpRoundEven(ctx.F32[4], as_float))};
|
||||
return EmitPackSint2_10_10_10(ctx, ctx.OpBitcast(ctx.F32[4], as_sint));
|
||||
}
|
||||
|
||||
Id EmitUnpackSnorm2_10_10_10(EmitContext& ctx, Id value) {
|
||||
const auto unpacked{ctx.OpBitcast(ctx.U32[4], EmitUnpackSint2_10_10_10(ctx, value))};
|
||||
const auto as_float{ctx.OpConvertSToF(ctx.F32[4], unpacked)};
|
||||
const auto snorm_div{ctx.ConstantComposite(ctx.F32[4], ctx.ConstF32(511.f), ctx.ConstF32(511.f),
|
||||
ctx.ConstF32(511.f), ctx.ConstF32(1.f))};
|
||||
return ctx.OpFDiv(ctx.F32[4], as_float, snorm_div);
|
||||
}
|
||||
|
||||
Id EmitPackUint2_10_10_10(EmitContext& ctx, Id value) {
|
||||
const auto unpacked{ctx.OpBitcast(ctx.U32[4], value)};
|
||||
const auto [x, y, z, w] = ExtractComposite<4>(ctx, ctx.U32, unpacked);
|
||||
return InsertBitFields(ctx, {x, y, z, w}, R(0, 10), R(10, 10), R(20, 10), R(30, 2));
|
||||
}
|
||||
|
||||
Id EmitUnpackUint2_10_10_10(EmitContext& ctx, Id value) {
|
||||
const auto [x, y, z, w] =
|
||||
ExtractBitFields<false>(ctx, value, R(0, 10), R(10, 10), R(20, 10), R(30, 2));
|
||||
const auto unpacked{ctx.OpCompositeConstruct(ctx.U32[4], x, y, z, w)};
|
||||
return ctx.OpBitcast(ctx.F32[4], unpacked);
|
||||
}
|
||||
|
||||
Id EmitPackSint2_10_10_10(EmitContext& ctx, Id value) {
|
||||
return EmitPackUint2_10_10_10(ctx, value);
|
||||
}
|
||||
|
||||
Id EmitUnpackSint2_10_10_10(EmitContext& ctx, Id value) {
|
||||
const auto [x, y, z, w] =
|
||||
ExtractBitFields<true>(ctx, value, R(0, 10), R(10, 10), R(20, 10), R(30, 2));
|
||||
const auto unpacked{ctx.OpCompositeConstruct(ctx.U32[4], x, y, z, w)};
|
||||
return ctx.OpBitcast(ctx.F32[4], unpacked);
|
||||
}
|
||||
|
||||
} // namespace Shader::Backend::SPIRV
|
||||
|
|
|
@ -24,6 +24,10 @@ Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, I
|
|||
return EmitCompositeConstruct(ctx, inst, ctx.U32[4], e1, e2, e3, e4);
|
||||
}
|
||||
|
||||
Id EmitCompositeConstructU32x2x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) {
|
||||
return EmitCompositeConstruct(ctx, inst, ctx.U32[4], e1, e2);
|
||||
}
|
||||
|
||||
Id EmitCompositeExtractU32x2(EmitContext& ctx, Id composite, u32 index) {
|
||||
return ctx.OpCompositeExtract(ctx.U32[1], composite, index);
|
||||
}
|
||||
|
@ -124,6 +128,10 @@ Id EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, I
|
|||
return EmitCompositeConstruct(ctx, inst, ctx.F32[4], e1, e2, e3, e4);
|
||||
}
|
||||
|
||||
Id EmitCompositeConstructF32x2x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) {
|
||||
return EmitCompositeConstruct(ctx, inst, ctx.F32[4], e1, e2);
|
||||
}
|
||||
|
||||
Id EmitCompositeExtractF32x2(EmitContext& ctx, Id composite, u32 index) {
|
||||
return ctx.OpCompositeExtract(ctx.F32[1], composite, index);
|
||||
}
|
||||
|
|
|
@ -416,6 +416,20 @@ static Id EmitLoadBufferU32xN(EmitContext& ctx, u32 handle, Id address) {
|
|||
}
|
||||
}
|
||||
|
||||
Id EmitLoadBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address) {
|
||||
const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(3u))};
|
||||
const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))};
|
||||
const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)};
|
||||
return ctx.OpBitFieldUExtract(ctx.U32[1], dword, bit_offset, ctx.ConstU32(8u));
|
||||
}
|
||||
|
||||
Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address) {
|
||||
const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(2u))};
|
||||
const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))};
|
||||
const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)};
|
||||
return ctx.OpBitFieldUExtract(ctx.U32[1], dword, bit_offset, ctx.ConstU32(16u));
|
||||
}
|
||||
|
||||
Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst*, u32 handle, Id address) {
|
||||
return EmitLoadBufferU32xN<1>(ctx, handle, address);
|
||||
}
|
||||
|
@ -432,18 +446,24 @@ Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) {
|
|||
return EmitLoadBufferU32xN<4>(ctx, handle, address);
|
||||
}
|
||||
|
||||
Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
return ctx.OpBitcast(ctx.F32[1], EmitLoadBufferU32(ctx, inst, handle, address));
|
||||
}
|
||||
|
||||
Id EmitLoadBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
return ctx.OpBitcast(ctx.F32[2], EmitLoadBufferU32x2(ctx, inst, handle, address));
|
||||
}
|
||||
|
||||
Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
return ctx.OpBitcast(ctx.F32[3], EmitLoadBufferU32x3(ctx, inst, handle, address));
|
||||
}
|
||||
|
||||
Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
return ctx.OpBitcast(ctx.F32[4], EmitLoadBufferU32x4(ctx, inst, handle, address));
|
||||
}
|
||||
|
||||
Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
const auto& buffer = ctx.texture_buffers[handle];
|
||||
const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id);
|
||||
const Id coord =
|
||||
ctx.OpIAdd(ctx.U32[1], ctx.OpShiftLeftLogical(ctx.U32[1], address, buffer.coord_shift),
|
||||
buffer.coord_offset);
|
||||
Id texel = buffer.is_storage ? ctx.OpImageRead(buffer.result_type, tex_buffer, coord)
|
||||
: ctx.OpImageFetch(buffer.result_type, tex_buffer, coord);
|
||||
if (buffer.is_integer) {
|
||||
texel = ctx.OpBitcast(ctx.F32[4], texel);
|
||||
}
|
||||
return texel;
|
||||
UNREACHABLE_MSG("SPIR-V instruction");
|
||||
}
|
||||
|
||||
template <u32 N>
|
||||
|
@ -464,32 +484,56 @@ static void EmitStoreBufferU32xN(EmitContext& ctx, u32 handle, Id address, Id va
|
|||
}
|
||||
}
|
||||
|
||||
void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
void EmitStoreBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(3u))};
|
||||
const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))};
|
||||
const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)};
|
||||
const Id new_val{ctx.OpBitFieldInsert(ctx.U32[1], dword, value, bit_offset, ctx.ConstU32(8u))};
|
||||
EmitStoreBufferU32xN<1>(ctx, handle, address, new_val);
|
||||
}
|
||||
|
||||
void EmitStoreBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(2u))};
|
||||
const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))};
|
||||
const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)};
|
||||
const Id new_val{ctx.OpBitFieldInsert(ctx.U32[1], dword, value, bit_offset, ctx.ConstU32(16u))};
|
||||
EmitStoreBufferU32xN<1>(ctx, handle, address, new_val);
|
||||
}
|
||||
|
||||
void EmitStoreBufferU32(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32xN<1>(ctx, handle, address, value);
|
||||
}
|
||||
|
||||
void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32xN<2>(ctx, handle, address, value);
|
||||
}
|
||||
|
||||
void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32xN<3>(ctx, handle, address, value);
|
||||
}
|
||||
|
||||
void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32xN<4>(ctx, handle, address, value);
|
||||
}
|
||||
|
||||
void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[1], value));
|
||||
}
|
||||
|
||||
void EmitStoreBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32x2(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[2], value));
|
||||
}
|
||||
|
||||
void EmitStoreBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32x3(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[3], value));
|
||||
}
|
||||
|
||||
void EmitStoreBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
EmitStoreBufferU32x4(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[4], value));
|
||||
}
|
||||
|
||||
void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||
const auto& buffer = ctx.texture_buffers[handle];
|
||||
const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id);
|
||||
const Id coord =
|
||||
ctx.OpIAdd(ctx.U32[1], ctx.OpShiftLeftLogical(ctx.U32[1], address, buffer.coord_shift),
|
||||
buffer.coord_offset);
|
||||
if (buffer.is_integer) {
|
||||
value = ctx.OpBitcast(buffer.result_type, value);
|
||||
}
|
||||
ctx.OpImageWrite(tex_buffer, coord, value);
|
||||
UNREACHABLE_MSG("SPIR-V instruction");
|
||||
}
|
||||
|
||||
} // namespace Shader::Backend::SPIRV
|
||||
|
|
|
@ -63,15 +63,27 @@ void EmitGetGotoVariable(EmitContext& ctx);
|
|||
void EmitSetScc(EmitContext& ctx);
|
||||
Id EmitReadConst(EmitContext& ctx, IR::Inst* inst);
|
||||
Id EmitReadConstBuffer(EmitContext& ctx, u32 handle, Id index);
|
||||
Id EmitLoadBufferU8(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address);
|
||||
void EmitStoreBufferU8(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferU16(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
Id EmitBufferAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
Id EmitBufferAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
|
||||
|
@ -123,6 +135,7 @@ Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value);
|
|||
Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2);
|
||||
Id EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3);
|
||||
Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4);
|
||||
Id EmitCompositeConstructU32x2x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2);
|
||||
Id EmitCompositeExtractU32x2(EmitContext& ctx, Id composite, u32 index);
|
||||
Id EmitCompositeExtractU32x3(EmitContext& ctx, Id composite, u32 index);
|
||||
Id EmitCompositeExtractU32x4(EmitContext& ctx, Id composite, u32 index);
|
||||
|
@ -151,6 +164,7 @@ Id EmitCompositeShuffleF16x4(EmitContext& ctx, Id composite1, Id composite2, u32
|
|||
Id EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2);
|
||||
Id EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3);
|
||||
Id EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4);
|
||||
Id EmitCompositeConstructF32x2x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2);
|
||||
Id EmitCompositeExtractF32x2(EmitContext& ctx, Id composite, u32 index);
|
||||
Id EmitCompositeExtractF32x3(EmitContext& ctx, Id composite, u32 index);
|
||||
Id EmitCompositeExtractF32x4(EmitContext& ctx, Id composite, u32 index);
|
||||
|
@ -193,10 +207,6 @@ void EmitBitCastF64U64(EmitContext& ctx);
|
|||
Id EmitPackUint2x32(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackUint2x32(EmitContext& ctx, Id value);
|
||||
Id EmitPackFloat2x32(EmitContext& ctx, Id value);
|
||||
Id EmitPackFloat2x16(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackFloat2x16(EmitContext& ctx, Id value);
|
||||
Id EmitPackHalf2x16(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackHalf2x16(EmitContext& ctx, Id value);
|
||||
Id EmitPackUnorm2x16(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackUnorm2x16(EmitContext& ctx, Id value);
|
||||
Id EmitPackSnorm2x16(EmitContext& ctx, Id value);
|
||||
|
@ -205,6 +215,26 @@ Id EmitPackUint2x16(EmitContext& ctx, Id value);
|
|||
Id EmitUnpackUint2x16(EmitContext& ctx, Id value);
|
||||
Id EmitPackSint2x16(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackSint2x16(EmitContext& ctx, Id value);
|
||||
Id EmitPackHalf2x16(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackHalf2x16(EmitContext& ctx, Id value);
|
||||
Id EmitPackUnorm4x8(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackUnorm4x8(EmitContext& ctx, Id value);
|
||||
Id EmitPackSnorm4x8(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackSnorm4x8(EmitContext& ctx, Id value);
|
||||
Id EmitPackUint4x8(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackUint4x8(EmitContext& ctx, Id value);
|
||||
Id EmitPackSint4x8(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackSint4x8(EmitContext& ctx, Id value);
|
||||
Id EmitPackUfloat10_11_11(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackUfloat10_11_11(EmitContext& ctx, Id value);
|
||||
Id EmitPackUnorm2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackUnorm2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitPackSnorm2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackSnorm2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitPackUint2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackUint2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitPackSint2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitUnpackSint2_10_10_10(EmitContext& ctx, Id value);
|
||||
Id EmitFPAbs16(EmitContext& ctx, Id value);
|
||||
Id EmitFPAbs32(EmitContext& ctx, Id value);
|
||||
Id EmitFPAbs64(EmitContext& ctx, Id value);
|
||||
|
|
|
@ -74,8 +74,8 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
|
|||
DefineInterfaces();
|
||||
DefineSharedMemory();
|
||||
DefineBuffers();
|
||||
DefineTextureBuffers();
|
||||
DefineImagesAndSamplers();
|
||||
DefineFunctions();
|
||||
}
|
||||
|
||||
EmitContext::~EmitContext() = default;
|
||||
|
@ -205,19 +205,6 @@ void EmitContext::DefineBufferOffsets() {
|
|||
buffer.offset_dwords = OpShiftRightLogical(U32[1], buffer.offset, ConstU32(2U));
|
||||
Name(buffer.offset_dwords, fmt::format("buf{}_dword_off", binding));
|
||||
}
|
||||
for (TextureBufferDefinition& tex_buffer : texture_buffers) {
|
||||
const u32 binding = tex_buffer.binding;
|
||||
const u32 half = PushData::BufOffsetIndex + (binding >> 4);
|
||||
const u32 comp = (binding & 0xf) >> 2;
|
||||
const u32 offset = (binding & 0x3) << 3;
|
||||
const Id ptr{OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]),
|
||||
push_data_block, ConstU32(half), ConstU32(comp))};
|
||||
const Id value{OpLoad(U32[1], ptr)};
|
||||
tex_buffer.coord_offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(6U));
|
||||
tex_buffer.coord_shift =
|
||||
OpBitFieldUExtract(U32[1], value, ConstU32(offset + 6U), ConstU32(2U));
|
||||
Name(tex_buffer.coord_offset, fmt::format("texbuf{}_off", binding));
|
||||
}
|
||||
}
|
||||
|
||||
void EmitContext::DefineInterpolatedAttribs() {
|
||||
|
@ -676,32 +663,6 @@ void EmitContext::DefineBuffers() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmitContext::DefineTextureBuffers() {
|
||||
for (const auto& desc : info.texture_buffers) {
|
||||
const auto sharp = desc.GetSharp(info);
|
||||
const auto nfmt = sharp.GetNumberFmt();
|
||||
const bool is_integer = AmdGpu::IsInteger(nfmt);
|
||||
const VectorIds& sampled_type{GetAttributeType(*this, nfmt)};
|
||||
const u32 sampled = desc.is_written ? 2 : 1;
|
||||
const Id image_type{TypeImage(sampled_type[1], spv::Dim::Buffer, false, false, false,
|
||||
sampled, spv::ImageFormat::Unknown)};
|
||||
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
|
||||
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
|
||||
Decorate(id, spv::Decoration::Binding, binding.unified++);
|
||||
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
||||
Name(id, fmt::format("{}_{}", desc.is_written ? "imgbuf" : "texbuf", desc.sharp_idx));
|
||||
texture_buffers.push_back({
|
||||
.id = id,
|
||||
.binding = binding.buffer++,
|
||||
.image_type = image_type,
|
||||
.result_type = sampled_type[4],
|
||||
.is_integer = is_integer,
|
||||
.is_storage = desc.is_written,
|
||||
});
|
||||
interfaces.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
spv::ImageFormat GetFormat(const AmdGpu::Image& image) {
|
||||
if (image.GetDataFmt() == AmdGpu::DataFormat::Format32 &&
|
||||
image.GetNumberFmt() == AmdGpu::NumberFormat::Uint) {
|
||||
|
@ -893,4 +854,117 @@ void EmitContext::DefineSharedMemory() {
|
|||
}
|
||||
}
|
||||
|
||||
Id EmitContext::DefineFloat32ToUfloatM5(u32 mantissa_bits, const std::string_view name) {
|
||||
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/util/format_r11g11b10f.h
|
||||
const auto func_type{TypeFunction(U32[1], F32[1])};
|
||||
const auto func{OpFunction(U32[1], spv::FunctionControlMask::MaskNone, func_type)};
|
||||
const auto value{OpFunctionParameter(F32[1])};
|
||||
Name(func, name);
|
||||
AddLabel();
|
||||
|
||||
const auto raw_value{OpBitcast(U32[1], value)};
|
||||
const auto exponent{
|
||||
OpBitcast(S32[1], OpBitFieldSExtract(U32[1], raw_value, ConstU32(23U), ConstU32(8U)))};
|
||||
const auto sign{OpBitFieldUExtract(U32[1], raw_value, ConstU32(31U), ConstU32(1U))};
|
||||
|
||||
const auto is_zero{OpLogicalOr(U1[1], OpIEqual(U1[1], raw_value, ConstU32(0U)),
|
||||
OpIEqual(U1[1], sign, ConstU32(1U)))};
|
||||
const auto is_nan{OpIsNan(U1[1], value)};
|
||||
const auto is_inf{OpIsInf(U1[1], value)};
|
||||
const auto is_denorm{OpSLessThanEqual(U1[1], exponent, ConstS32(-15))};
|
||||
|
||||
const auto denorm_mantissa{OpConvertFToU(
|
||||
U32[1],
|
||||
OpRoundEven(F32[1], OpFMul(F32[1], value,
|
||||
ConstF32(static_cast<float>(1 << (mantissa_bits + 14))))))};
|
||||
const auto denorm_overflow{
|
||||
OpINotEqual(U1[1], OpShiftRightLogical(U32[1], denorm_mantissa, ConstU32(mantissa_bits)),
|
||||
ConstU32(0U))};
|
||||
const auto denorm{
|
||||
OpSelect(U32[1], denorm_overflow, ConstU32(1U << mantissa_bits), denorm_mantissa)};
|
||||
|
||||
const auto norm_mantissa{OpConvertFToU(
|
||||
U32[1],
|
||||
OpRoundEven(F32[1],
|
||||
OpLdexp(F32[1], value,
|
||||
OpISub(S32[1], ConstS32(static_cast<int>(mantissa_bits)), exponent))))};
|
||||
const auto norm_overflow{
|
||||
OpUGreaterThanEqual(U1[1], norm_mantissa, ConstU32(2U << mantissa_bits))};
|
||||
const auto norm_final_mantissa{OpBitwiseAnd(
|
||||
U32[1],
|
||||
OpSelect(U32[1], norm_overflow, OpShiftRightLogical(U32[1], norm_mantissa, ConstU32(1U)),
|
||||
norm_mantissa),
|
||||
ConstU32((1U << mantissa_bits) - 1))};
|
||||
const auto norm_final_exponent{OpBitcast(
|
||||
U32[1],
|
||||
OpIAdd(S32[1],
|
||||
OpSelect(S32[1], norm_overflow, OpIAdd(S32[1], exponent, ConstS32(1)), exponent),
|
||||
ConstS32(15)))};
|
||||
const auto norm{OpBitFieldInsert(U32[1], norm_final_mantissa, norm_final_exponent,
|
||||
ConstU32(mantissa_bits), ConstU32(5U))};
|
||||
|
||||
const auto result{OpSelect(U32[1], is_zero, ConstU32(0U),
|
||||
OpSelect(U32[1], is_nan, ConstU32(31u << mantissa_bits | 1U),
|
||||
OpSelect(U32[1], is_inf, ConstU32(31U << mantissa_bits),
|
||||
OpSelect(U32[1], is_denorm, denorm, norm))))};
|
||||
|
||||
OpReturnValue(result);
|
||||
OpFunctionEnd();
|
||||
return func;
|
||||
}
|
||||
|
||||
Id EmitContext::DefineUfloatM5ToFloat32(u32 mantissa_bits, const std::string_view name) {
|
||||
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/util/format_r11g11b10f.h
|
||||
const auto func_type{TypeFunction(F32[1], U32[1])};
|
||||
const auto func{OpFunction(F32[1], spv::FunctionControlMask::MaskNone, func_type)};
|
||||
const auto value{OpFunctionParameter(U32[1])};
|
||||
Name(func, name);
|
||||
AddLabel();
|
||||
|
||||
const auto raw_mantissa{
|
||||
OpBitFieldUExtract(U32[1], value, ConstU32(0U), ConstU32(mantissa_bits))};
|
||||
const auto mantissa{OpConvertUToF(F32[1], raw_mantissa)};
|
||||
const auto exponent{OpBitcast(
|
||||
S32[1], OpBitFieldSExtract(U32[1], value, ConstU32(mantissa_bits), ConstU32(5U)))};
|
||||
|
||||
const auto is_exp_neg_one{OpIEqual(U1[1], exponent, ConstS32(-1))};
|
||||
const auto is_exp_zero{OpIEqual(U1[1], exponent, ConstS32(0))};
|
||||
|
||||
const auto is_zero{OpIEqual(U1[1], value, ConstU32(0u))};
|
||||
const auto is_nan{
|
||||
OpLogicalAnd(U1[1], is_exp_neg_one, OpINotEqual(U1[1], raw_mantissa, ConstU32(0u)))};
|
||||
const auto is_inf{
|
||||
OpLogicalAnd(U1[1], is_exp_neg_one, OpIEqual(U1[1], raw_mantissa, ConstU32(0u)))};
|
||||
const auto is_denorm{
|
||||
OpLogicalAnd(U1[1], is_exp_zero, OpINotEqual(U1[1], raw_mantissa, ConstU32(0u)))};
|
||||
|
||||
const auto denorm{OpFMul(F32[1], mantissa, ConstF32(1.f / (1 << 20)))};
|
||||
const auto norm{OpLdexp(
|
||||
F32[1],
|
||||
OpFAdd(F32[1],
|
||||
OpFMul(F32[1], mantissa, ConstF32(1.f / static_cast<float>(1 << mantissa_bits))),
|
||||
ConstF32(1.f)),
|
||||
exponent)};
|
||||
|
||||
const auto result{OpSelect(F32[1], is_zero, ConstF32(0.f),
|
||||
OpSelect(F32[1], is_nan, ConstF32(NAN),
|
||||
OpSelect(F32[1], is_inf, ConstF32(INFINITY),
|
||||
OpSelect(F32[1], is_denorm, denorm, norm))))};
|
||||
|
||||
OpReturnValue(result);
|
||||
OpFunctionEnd();
|
||||
return func;
|
||||
}
|
||||
|
||||
void EmitContext::DefineFunctions() {
|
||||
if (info.uses_pack_10_11_11) {
|
||||
f32_to_uf11 = DefineFloat32ToUfloatM5(6, "f32_to_uf11");
|
||||
f32_to_uf10 = DefineFloat32ToUfloatM5(5, "f32_to_uf10");
|
||||
}
|
||||
if (info.uses_unpack_10_11_11) {
|
||||
uf11_to_f32 = DefineUfloatM5ToFloat32(6, "uf11_to_f32");
|
||||
uf10_to_f32 = DefineUfloatM5ToFloat32(5, "uf10_to_f32");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Shader::Backend::SPIRV
|
||||
|
|
|
@ -235,20 +235,9 @@ public:
|
|||
const VectorIds* data_types;
|
||||
Id pointer_type;
|
||||
};
|
||||
struct TextureBufferDefinition {
|
||||
Id id;
|
||||
Id coord_offset;
|
||||
Id coord_shift;
|
||||
u32 binding;
|
||||
Id image_type;
|
||||
Id result_type;
|
||||
bool is_integer = false;
|
||||
bool is_storage = false;
|
||||
};
|
||||
|
||||
Bindings& binding;
|
||||
boost::container::small_vector<BufferDefinition, 16> buffers;
|
||||
boost::container::small_vector<TextureBufferDefinition, 8> texture_buffers;
|
||||
BufferDefinition srt_flatbuf;
|
||||
boost::container::small_vector<TextureDefinition, 8> images;
|
||||
boost::container::small_vector<Id, 4> samplers;
|
||||
|
@ -271,6 +260,11 @@ public:
|
|||
std::array<SpirvAttribute, IR::NumParams> output_params{};
|
||||
std::array<SpirvAttribute, IR::NumRenderTargets> frag_outputs{};
|
||||
|
||||
Id uf11_to_f32{};
|
||||
Id f32_to_uf11{};
|
||||
Id uf10_to_f32{};
|
||||
Id f32_to_uf10{};
|
||||
|
||||
private:
|
||||
void DefineArithmeticTypes();
|
||||
void DefineInterfaces();
|
||||
|
@ -278,12 +272,15 @@ private:
|
|||
void DefineOutputs();
|
||||
void DefinePushDataBlock();
|
||||
void DefineBuffers();
|
||||
void DefineTextureBuffers();
|
||||
void DefineImagesAndSamplers();
|
||||
void DefineSharedMemory();
|
||||
void DefineFunctions();
|
||||
|
||||
SpirvAttribute GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id, u32 num_components,
|
||||
bool output);
|
||||
|
||||
Id DefineFloat32ToUfloatM5(u32 mantissa_bits, std::string_view name);
|
||||
Id DefineUfloatM5ToFloat32(u32 mantissa_bits, std::string_view name);
|
||||
};
|
||||
|
||||
} // namespace Shader::Backend::SPIRV
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue