mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
Convert formatted half-float buffer stores from F32
Co-authored-by: TarkusR <90155059+TarkusR@users.noreply.github.com>
This commit is contained in:
@@ -710,10 +710,14 @@ void StoreFormattedInBounds(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
|
|||||||
uint32_t data) {
|
uint32_t data) {
|
||||||
if (component >= plan.info.component_count) return;
|
if (component >= plan.info.component_count) return;
|
||||||
const auto bits = plan.info.component_bits[component];
|
const auto bits = plan.info.component_bits[component];
|
||||||
if (plan.info.type == Format::ComponentType::Snorm && bits == 16u) {
|
if (bits == 16u && (plan.info.type == Format::ComponentType::Snorm ||
|
||||||
|
plan.info.type == Format::ComponentType::Float)) {
|
||||||
const auto value = EmitBitCastF32U32(ctx.state, data);
|
const auto value = EmitBitCastF32U32(ctx.state, data);
|
||||||
data = EmitPackSnorm2x16(
|
const auto pair = EmitCompositeConstructF32x2(ctx.state, value,
|
||||||
ctx.state, EmitCompositeConstructF32x2(ctx.state, value, ConstantF32Value(ctx.state, 0.0f)));
|
ConstantF32Value(ctx.state, 0.0f));
|
||||||
|
data = plan.info.type == Format::ComponentType::Float
|
||||||
|
? EmitPackHalf2x16(ctx.state, pair)
|
||||||
|
: EmitPackSnorm2x16(ctx.state, pair);
|
||||||
}
|
}
|
||||||
if (bits == 8u || bits == 16u) {
|
if (bits == 8u || bits == 16u) {
|
||||||
StoreSubwordInBounds(ctx, mem, plan.resource, plan.addresses[component],
|
StoreSubwordInBounds(ctx, mem, plan.resource, plan.addresses[component],
|
||||||
|
|||||||
@@ -23706,6 +23706,38 @@ TestCase BufferStoreFormatXResource16UintPreservesAdjacentLanes() {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase BufferStoreFormatXyzwFloat16ConvertsComponents() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
// This finite F32 has low bits 0x7e63, which form an F16 NaN if truncated.
|
||||||
|
constexpr std::array<float, 8> values = {
|
||||||
|
std::bit_cast<float>(0x3f807e63u), -2.0f, 0.5f, 0.25f,
|
||||||
|
-4.0f, 3.0f, 0.0f, 2.0f};
|
||||||
|
std::vector<u32> code;
|
||||||
|
for (u32 record = 0; record < 2; record++) {
|
||||||
|
for (u32 component = 0; component < 4; component++) {
|
||||||
|
AppendVMovLiteral(&code, component,
|
||||||
|
std::bit_cast<u32>(values[record * 4 + component]));
|
||||||
|
}
|
||||||
|
AppendVMovU32(&code, 20, record);
|
||||||
|
code.push_back(EncodeMubuf0(0x07u, 0, true, false));
|
||||||
|
code.push_back(EncodeMubuf1(0, 0, 20));
|
||||||
|
}
|
||||||
|
AppendEnd(&code);
|
||||||
|
|
||||||
|
TestCase test;
|
||||||
|
test.name = "BufferStoreFormatXyzwFloat16ConvertsComponents";
|
||||||
|
test.code = std::move(code);
|
||||||
|
test.initial = std::vector<u32>(4, 0xdeadbeefu);
|
||||||
|
test.expected = {0xc0003c04u, 0x34003800u, 0x4200c400u, 0x40000000u};
|
||||||
|
test.user_data = MakeStructuredStorageBufferData(
|
||||||
|
8, 2, false, BufferFormat(Prospero::BufferFormat::k16_16_16_16Float));
|
||||||
|
test.has_user_data = true;
|
||||||
|
test.opcodes = {O::V_MOV_B32, O::BUFFER_STORE_FORMAT_XYZW, O::S_ENDPGM};
|
||||||
|
test.required_spirv = {"PackHalf2x16"};
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase BufferStoreFormatXyzwSnorm16CapturedSkinningVectors() {
|
TestCase BufferStoreFormatXyzwSnorm16CapturedSkinningVectors() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -28430,6 +28462,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(BufferFormatStoreVariants);
|
AddCase(BufferFormatStoreVariants);
|
||||||
AddCase(BufferStoreFormatXResource16UintWritesHalfword);
|
AddCase(BufferStoreFormatXResource16UintWritesHalfword);
|
||||||
AddCase(BufferStoreFormatXResource16UintPreservesAdjacentLanes);
|
AddCase(BufferStoreFormatXResource16UintPreservesAdjacentLanes);
|
||||||
|
AddCase(BufferStoreFormatXyzwFloat16ConvertsComponents);
|
||||||
AddCase(BufferStoreFormatXyzwSnorm16CapturedSkinningVectors);
|
AddCase(BufferStoreFormatXyzwSnorm16CapturedSkinningVectors);
|
||||||
AddCase(BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords);
|
AddCase(BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords);
|
||||||
AddCase(BufferLoadFormatXResource8UintZeroExtendsByte);
|
AddCase(BufferLoadFormatXResource8UintZeroExtendsByte);
|
||||||
@@ -33158,6 +33191,11 @@ int main(int argc, char **argv) {
|
|||||||
RunCase(&vulkan, BufferFormatStoreVariants());
|
RunCase(&vulkan, BufferFormatStoreVariants());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (argc == 2 && std::strcmp(argv[1], "--buffer-float16-store-only") == 0) {
|
||||||
|
VulkanHarness vulkan;
|
||||||
|
RunCase(&vulkan, BufferStoreFormatXyzwFloat16ConvertsComponents());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--s-ashr-i64-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--s-ashr-i64-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, ScalarAshrI64Edges(false));
|
RunCase(&vulkan, ScalarAshrI64Edges(false));
|
||||||
|
|||||||
@@ -6711,9 +6711,9 @@ void TestNewShaderRecompilerFormattedStoreUsesRuntimeArrayLengthOnly() {
|
|||||||
Check(result.resources.buffers.size() == 1 &&
|
Check(result.resources.buffers.size() == 1 &&
|
||||||
result.resources.buffers[0].dwords[2] == 5u,
|
result.resources.buffers[0].dwords[2] == 5u,
|
||||||
"formatted store test did not preserve descriptor NumRecords");
|
"formatted store test did not preserve descriptor NumRecords");
|
||||||
Check((result.decoded_dump.find("buffer_store_format_x") != std::string::npos),
|
Check((result.decoded_dump.find("BUFFER_STORE_FORMAT_X") != std::string::npos),
|
||||||
"formatted store regression did not decode buffer_store_format_x");
|
"formatted store regression did not decode buffer_store_format_x");
|
||||||
Check((result.ir_dump.find("typed=0 formatted=1") != std::string::npos),
|
Check((result.decoded_dump.find("typed=0 formatted=1") != std::string::npos),
|
||||||
"formatted store regression did not preserve formatted metadata");
|
"formatted store regression did not preserve formatted metadata");
|
||||||
CheckSpirvBinaryValidates(result.spirv);
|
CheckSpirvBinaryValidates(result.spirv);
|
||||||
|
|
||||||
@@ -6723,6 +6723,15 @@ void TestNewShaderRecompilerFormattedStoreUsesRuntimeArrayLengthOnly() {
|
|||||||
Check(
|
Check(
|
||||||
!SpirvSourceHasInstructionUsing(source, "OpULessThan", "%uint_5"),
|
!SpirvSourceHasInstructionUsing(source, "OpULessThan", "%uint_5"),
|
||||||
"formatted store SPIR-V baked descriptor NumRecords into a store guard");
|
"formatted store SPIR-V baked descriptor NumRecords into a store guard");
|
||||||
|
|
||||||
|
user_data[1] = 8u << 16u;
|
||||||
|
user_data[3] = static_cast<uint32_t>(Prospero::BufferFormat::k16_16_16_16Float) << 12u;
|
||||||
|
options.user_data = user_data;
|
||||||
|
result = RecompileForTest(shader, options);
|
||||||
|
Check((DisassembleSpirvBinary(result.spirv).find("PackHalf2x16") !=
|
||||||
|
std::string::npos),
|
||||||
|
"formatted half-float store did not convert F32 to F16");
|
||||||
|
CheckSpirvBinaryValidates(result.spirv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestNewShaderRecompilerTypedBufferTranslation() {
|
void TestNewShaderRecompilerTypedBufferTranslation() {
|
||||||
@@ -13515,6 +13524,7 @@ int main() {
|
|||||||
TestNewShaderRecompilerNativeWideBufferIr();
|
TestNewShaderRecompilerNativeWideBufferIr();
|
||||||
TestNewShaderRecompilerScalarB64LaneTranslation();
|
TestNewShaderRecompilerScalarB64LaneTranslation();
|
||||||
TestNewShaderRecompilerMubufFormatTranslation();
|
TestNewShaderRecompilerMubufFormatTranslation();
|
||||||
|
TestNewShaderRecompilerFormattedStoreUsesRuntimeArrayLengthOnly();
|
||||||
TestNewShaderRecompilerTypedBufferTranslation();
|
TestNewShaderRecompilerTypedBufferTranslation();
|
||||||
TestNewShaderRecompilerDsReadWrite2Translation();
|
TestNewShaderRecompilerDsReadWrite2Translation();
|
||||||
TestNewShaderRecompilerDsWideAndAtomicTranslation();
|
TestNewShaderRecompilerDsWideAndAtomicTranslation();
|
||||||
|
|||||||
Reference in New Issue
Block a user