From da6cee924b9a1107b00933625515e0e4a0032891 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sat, 18 Jul 2026 06:21:00 +0200 Subject: [PATCH] Revert "Implement vertex swizzle" This reverts commit f4b52cea2b20a02e1fb8457f8e34d3a54c0be20b. --- src/graphics/host_gpu/renderer/shaders.cpp | 93 +++++++--- .../shader/recompiler/ShaderDecoder.h | 2 - .../shader/recompiler/VectorAluOps.cpp | 16 +- .../shader/recompiler/shaderIR/ShaderIR.cpp | 16 -- .../spirvEmitter/spirvEmitterModule.cpp | 6 +- .../spirvEmitter/spirvEmitterValues.cpp | 22 +-- src/graphics/shader/shader.h | 75 +++------ tests/ShaderRecompilerComputeTests.cpp | 53 ++---- tests/ShaderVertexMetadataTests.cpp | 159 +++++++----------- tests/shaderCfgTests.cpp | 35 ++-- 10 files changed, 195 insertions(+), 282 deletions(-) diff --git a/src/graphics/host_gpu/renderer/shaders.cpp b/src/graphics/host_gpu/renderer/shaders.cpp index a01f63941..4e62361a5 100644 --- a/src/graphics/host_gpu/renderer/shaders.cpp +++ b/src/graphics/host_gpu/renderer/shaders.cpp @@ -22,7 +22,7 @@ namespace Libs::Graphics { -// IDK: maybe we can remove it? +//IDK: maybe we can remove it? constexpr uint32_t kTemporaryPs5BufferFormat121 = 121u; static bool NarrowInputFormat(VkFormat* format, uint32_t* size, uint32_t used_components) { @@ -561,15 +561,13 @@ void CreatePipelineInternal(PipelineCache::GraphicsPipeline* pipeline, VkRenderP input_attr[index].location = index; input_attr[index].offset = b.attr_offsets[ai]; - uint32_t attr_size = 4; - auto registers_num = vs_input_info->resources_dst[index].registers_num; - auto used_components = (vs_input_info->resource_fetch_components[index] > 0 - ? vs_input_info->resource_fetch_components[index] - : registers_num); - const auto raw_components = VertexRawComponentCount( - vs_input_info->resources[index].DstSelXYZW(), static_cast(registers_num)); + uint32_t attr_size = 4; + auto registers_num = vs_input_info->resources_dst[index].registers_num; + auto used_components = (vs_input_info->resource_fetch_components[index] > 0 + ? vs_input_info->resource_fetch_components[index] + : registers_num); GetInputFormat(vs_input_info->resources[index], &input_attr[index].format, &attr_size, - raw_components); + static_cast(used_components)); if (graphics_debug_dump_enabled()) { static std::atomic_uint log_count = 0; @@ -604,18 +602,73 @@ void CreatePipelineInternal(PipelineCache::GraphicsPipeline* pipeline, VkRenderP EXIT_NOT_IMPLEMENTED(vs_input_info->resources[index].AddTid()); EXIT_NOT_IMPLEMENTED(vs_input_info->resources[index].SwizzleEnabled()); - if (registers_num < 1 || registers_num > 4) { - EXIT("invalid vertex destination register count: %u\n", registers_num); - } - for (uint32_t component = 0; component < static_cast(registers_num); - component++) { - const auto selector = - GetDstSel(vs_input_info->resources[index].DstSelXYZW(), component); - if (DecodeVertexDstSelector(selector).kind == VertexDstSelectKind::Reserved) { - EXIT("unsupported reserved vertex dst selector: attr=%u component=%u " - "selector=%u\n", - static_cast(index), component, selector); + auto log_unsupported_vertex_swizzle = [index, attr_size, registers_num]( + uint32_t swizzle, uint32_t expected) { + static bool logged = false; + if (!logged) { + LOGF( + "VertexInput: temporary: accepting unsupported dst swizzle at attr %" PRIu32 + " (attr_size=%" PRIu32 ", regs=%" PRIu32 ", swizzle=0x%03" PRIx32 + ", expected=0x%03" PRIx32 ")\n", + static_cast(index), attr_size, registers_num, swizzle, expected); + logged = true; } + }; + + switch (registers_num) { + case 1: { + auto swizzle = vs_input_info->resources[index].DstSelX(); + if (swizzle != DstSel(4)) { + log_unsupported_vertex_swizzle(swizzle, DstSel(4)); + } + break; + } + case 2: { + auto swizzle = vs_input_info->resources[index].DstSelXY(); + auto expected = (attr_size == 1 ? DstSel(4, 0) : DstSel(4, 5)); + if (swizzle != expected) { + log_unsupported_vertex_swizzle(swizzle, expected); + } + break; + } + case 3: { + auto swizzle = vs_input_info->resources[index].DstSelXYZ(); + auto expected = + (attr_size == 1 ? DstSel(4, 0, 0) + : (attr_size == 2 ? DstSel(4, 5, 0) : DstSel(4, 5, 6))); + if (swizzle != expected) { + log_unsupported_vertex_swizzle(swizzle, expected); + } + break; + } + case 4: { + auto swizzle = vs_input_info->resources[index].DstSelXYZW(); + auto expected = DstSel(4, 5, 6, 7); + bool supported = false; + switch (attr_size) { + case 1: + expected = DstSel(4, 0, 0, 1); + supported = (swizzle == expected); + break; + case 2: + expected = DstSel(4, 5, 0, 1); + supported = (swizzle == expected); + break; + case 3: + expected = DstSel(4, 5, 6, 1); + supported = (swizzle == expected || swizzle == DstSel(4, 5, 6, 0)); + break; + default: + supported = (swizzle == expected || swizzle == DstSel(4, 5, 6, 1) || + swizzle == DstSel(4, 5, 6, 0)); + break; + } + if (!supported) { + log_unsupported_vertex_swizzle(swizzle, expected); + } + break; + } + default: EXIT("invalid registers_num"); } } } diff --git a/src/graphics/shader/recompiler/ShaderDecoder.h b/src/graphics/shader/recompiler/ShaderDecoder.h index ab01cdf7c..a726aeeba 100644 --- a/src/graphics/shader/recompiler/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/ShaderDecoder.h @@ -639,8 +639,6 @@ struct Instruction { bool slc = false; bool idxen = false; bool offen = false; - // V_CMPX writes the comparison result to its normal scalar destination and EXEC. - bool compare_exec = false; int32_t branch_offset = 0; uint32_t branch_target = 0; struct { diff --git a/src/graphics/shader/recompiler/VectorAluOps.cpp b/src/graphics/shader/recompiler/VectorAluOps.cpp index ef45bbe18..f11165661 100644 --- a/src/graphics/shader/recompiler/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/VectorAluOps.cpp @@ -1103,8 +1103,9 @@ bool DecodeVopcSdwa(uint32_t pc, std::span code, uint32_t word_i !DecodeScalarSource(vsrc1 + (fields.s1 == 0u ? 256u : 0u), pc, &inst->src1, error)) { return false; } - inst->compare_exec = IsVopcCompareExec(inst->opcode); - if (fields.sd == 0u) { + if (IsVopcCompareExec(inst->opcode)) { + inst->dst.kind = OperandKind::ExecLo; + } else if (fields.sd == 0u) { inst->dst.kind = OperandKind::VccLo; } else if (!DecodeScalarDestination(fields.sdst, pc, &inst->dst, error)) { return false; @@ -1141,8 +1142,7 @@ bool DecodeVopcDpp(uint32_t pc, std::span code, uint32_t word_in !DecodeVectorGpr(vsrc1, &inst->src1, error)) { return false; } - inst->dst.kind = OperandKind::VccLo; - inst->compare_exec = IsVopcCompareExec(inst->opcode); + inst->dst.kind = IsVopcCompareExec(inst->opcode) ? OperandKind::ExecLo : OperandKind::VccLo; inst->src0.negate = ((modifier >> 20u) & 0x1u) != 0u; inst->src0.absolute = ((modifier >> 21u) & 0x1u) != 0u; inst->src0.dpp = true; @@ -1532,8 +1532,7 @@ bool DecodeVopc(uint32_t pc, std::span code, uint32_t word_index inst->family = Family::VOPC; inst->opcode_id = opcode; inst->opcode = Lookup(VOPC_OPS, static_cast(std::size(VOPC_OPS)), opcode); - inst->dst.kind = OperandKind::VccLo; - inst->compare_exec = IsVopcCompareExec(inst->opcode); + inst->dst.kind = IsVopcCompareExec(inst->opcode) ? OperandKind::ExecLo : OperandKind::VccLo; SetRawWords(inst, code, word_index, 1); switch (src0) { @@ -1619,8 +1618,9 @@ bool DecodeVop3(uint32_t pc, std::span code, uint32_t word_index return true; } bool dst_ok = true; - inst->compare_exec = compare_exec; - if (scalar_dst) { + if (compare_exec) { + inst->dst.kind = OperandKind::ExecLo; + } else if (scalar_dst) { // VOP3A uses VDST for VOPC and the scalar-destination lane-read opcodes. dst_ok = DecodeScalarDestination(vdst, pc, &inst->dst, error); } else { diff --git a/src/graphics/shader/recompiler/shaderIR/ShaderIR.cpp b/src/graphics/shader/recompiler/shaderIR/ShaderIR.cpp index 4977921ea..c062f2972 100644 --- a/src/graphics/shader/recompiler/shaderIR/ShaderIR.cpp +++ b/src/graphics/shader/recompiler/shaderIR/ShaderIR.cpp @@ -1165,22 +1165,6 @@ bool LowerImplemented(const Decoder::Instruction& decoded, BasicBlock* block, st } block->instructions.push_back(inst); - if (decoded.compare_exec) { - // V_CMPX has two architectural destinations. Keep the comparison's normal VCC/SDST - // result, then mirror the complete lane mask to EXEC. A mask is always a 64-bit scalar pair, including wave32 shaders. - for (uint32_t i = 0; i < 2u; i++) { - Instruction move; - move.pc = decoded.pc; - move.op = Opcode::MoveU32; - move.src_count = 1; - move.src[0] = inst.dst; - move.src[0].reg.index += i; - move.dst.kind = OperandKind::Register; - move.dst.reg.file = RegisterFile::Exec; - move.dst.reg.index = i; - block->instructions.push_back(move); - } - } return AppendScalarResultSccNonZero(decoded, block, error); } diff --git a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterModule.cpp b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterModule.cpp index f44d7292a..ce75be3a4 100644 --- a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterModule.cpp +++ b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterModule.cpp @@ -94,12 +94,8 @@ uint32_t VertexParameterComponentCount(const EmitterState& state, const InputBin input.location < ShaderVertexInputInfo::RES_MAX && input.location < static_cast(state.vertex_input_info->resources_num) && state.vertex_input_info->resources_dst[input.location].registers_num > 0) { - const auto& descriptor = state.vertex_input_info->resources[input.location]; - const auto dst_count = static_cast( + count = static_cast( state.vertex_input_info->resources_dst[input.location].registers_num); - // Keep the SPIR-V interface and native VkFormat width identical. A destination - // selector may request a raw component beyond the written VGPR count (W -> X). - count = VertexRawComponentCount(descriptor.DstSelXYZW(), dst_count); } return std::clamp(count, 1u, 4u); } diff --git a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp index d8b7e6c97..44758a094 100644 --- a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp +++ b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp @@ -450,25 +450,7 @@ uint32_t EmitVertexParameterComponentU32(EmitterState* state, const InputBinding uint32_t component) { const auto count = VertexParameterComponentCount(*state, input); const auto kind = VertexParameterScalarKind(*state, input.location); - uint32_t source_component = component; - if (input.location < ShaderVertexInputInfo::RES_MAX && - input.location < static_cast(state->vertex_input_info->resources_num)) { - const auto& descriptor = state->vertex_input_info->resources[input.location]; - const auto selection = - DecodeVertexDstSelector(GetDstSel(descriptor.DstSelXYZW(), component & 3u)); - if (selection.kind == VertexDstSelectKind::Zero) { - return ConstantU32(state, 0u); - } - if (selection.kind == VertexDstSelectKind::One) { - return ConstantU32(state, - kind == VertexInputScalarKind::Float ? 0x3f800000u : 1u); - } - if (selection.kind == VertexDstSelectKind::Reserved) { - EXIT("reserved vertex destination selector\n"); - } - source_component = selection.source_component; - } - if (source_component >= count) { + if (component >= count) { return VertexInputDefaultComponentU32(state, kind, component); } @@ -480,7 +462,7 @@ uint32_t EmitVertexParameterComponentU32(EmitterState* state, const InputBinding const auto pointer_type = VertexParameterScalarPointerType(*state, kind); const auto pointer = state->builder.AllocateId(); state->builder.AddFunction({OpAccessChain, pointer_type, pointer, input.variable_id, - ConstantU32(state, source_component)}); + ConstantU32(state, component)}); state->builder.AddFunction({OpLoad, scalar_type, raw, pointer}); } diff --git a/src/graphics/shader/shader.h b/src/graphics/shader/shader.h index 98683071a..b0f932257 100644 --- a/src/graphics/shader/shader.h +++ b/src/graphics/shader/shader.h @@ -64,41 +64,6 @@ inline uint8_t GetDstSel(uint32_t swizzle, uint32_t channel) { return (swizzle >> (channel * 3u)) & 0x7u; } -enum class VertexDstSelectKind : uint8_t { Zero, One, Component, Reserved }; - -struct VertexDstSelection { - VertexDstSelectKind kind = VertexDstSelectKind::Reserved; - uint8_t source_component = 0; -}; - -constexpr VertexDstSelection DecodeVertexDstSelector(uint8_t selector) { - if (selector == 0u) { - return {VertexDstSelectKind::Zero, 0}; - } - if (selector == 1u) { - return {VertexDstSelectKind::One, 0}; - } - if (selector >= 4u && selector <= 7u) { - return {VertexDstSelectKind::Component, static_cast(selector - 4u)}; - } - return {VertexDstSelectKind::Reserved, 0}; -} - -constexpr uint32_t VertexRawComponentCount(uint32_t swizzle, uint32_t destination_components) { - const auto dst_count = destination_components < 1u - ? 1u - : (destination_components > 4u ? 4u : destination_components); - auto count = dst_count; - for (uint32_t component = 0; component < dst_count; component++) { - const auto selection = DecodeVertexDstSelector(GetDstSel(swizzle, component)); - if (selection.kind == VertexDstSelectKind::Component) { - const auto source_count = static_cast(selection.source_component) + 1u; - count = count > source_count ? count : source_count; - } - } - return count; -} - struct ShaderVertexInputInfo { static constexpr int RES_MAX = 32; @@ -131,26 +96,26 @@ struct ShaderComputeInputInfo { }; struct ShaderPixelInputInfo { - uint32_t interpolator_settings[32] = {0}; - uint32_t input_num = 0; - uint32_t ps_system_input_base = 0; - uint8_t target_output_mode[8] = {}; - std::array target_export_mapping = {}; - uint32_t mrt_output_mask = 0; - uint32_t descriptor_set = 0; - bool ps_pos_x = false; - bool ps_pos_y = false; - bool ps_pos_xy = false; - bool ps_pos_z = false; - bool ps_pos_w = false; - bool ps_front_face = false; - bool ps_no_perspective = false; - bool ps_pixel_kill_enable = false; - bool ps_depth_export_enable = false; - bool ps_sample_mask_export_enable = false; - bool ps_early_z = false; - bool ps_execute_on_noop = false; - ShaderStageRuntime stage; + uint32_t interpolator_settings[32] = {0}; + uint32_t input_num = 0; + uint32_t ps_system_input_base = 0; + uint8_t target_output_mode[8] = {}; + std::array target_export_mapping = {}; + uint32_t mrt_output_mask = 0; + uint32_t descriptor_set = 0; + bool ps_pos_x = false; + bool ps_pos_y = false; + bool ps_pos_xy = false; + bool ps_pos_z = false; + bool ps_pos_w = false; + bool ps_front_face = false; + bool ps_no_perspective = false; + bool ps_pixel_kill_enable = false; + bool ps_depth_export_enable = false; + bool ps_sample_mask_export_enable = false; + bool ps_early_z = false; + bool ps_execute_on_noop = false; + ShaderStageRuntime stage; bool HasPositionInput() const { return ps_pos_x || ps_pos_y || ps_pos_z || ps_pos_w; } }; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index d57135dd0..f5ac01225 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -5871,24 +5871,24 @@ TestCase VectorVop3FloatCompareNegSourceModifier() { {O::VMovB32, O::VCmpLtF32, O::BufferStoreDword, O::SEndpgm}}; } -TestCase VectorVop3CmpxWritesScalarDstAndExecMask() { +TestCase VectorVop3CmpxWritesExecMask() { using O = ShaderOpcode; std::vector code; - AppendVMovU32(&code, 0, 1); - AppendVMovU32(&code, 1, 1); - AppendVMovU32(&code, 2, 7); - AppendVMovU32(&code, 30, 0); - AppendVop3(&code, 0xd2, 5, Vgpr(0), Vgpr(1)); // v_cmpx_eq_u32 s[5:6], true - code.push_back(EncodeSop1(0x0a, 126, 5)); // s_wqm_b64 exec, s[5:6] - AppendBufferStoreDword(&code, 2, 30); - AppendEnd(&code); + AppendVMovU32(&code, 0, 2); + AppendVMovU32(&code, 1, 1); + AppendVMovU32(&code, 2, 0); + AppendVMovU32(&code, 30, 0); + AppendVop3(&code, 0xd1, 5, Vgpr(0), Vgpr(1)); // v_cmpx_lt_u32, false + AppendVMovU32(&code, 2, 7); + AppendBufferStoreDword(&code, 2, 30); + AppendEnd(&code); - return {"VectorVop3CmpxWritesScalarDstAndExecMask", - code, - {0}, - {7}, - {O::VMovB32, O::VCmpxEqU32, O::SWqmB64, O::BufferStoreDword, O::SEndpgm}}; + return {"VectorVop3CmpxWritesExecMask", + code, + {0}, + {0}, + {O::VMovB32, O::VCmpxLtU32, O::BufferStoreDword, O::SEndpgm}}; } TestCase VectorVopcSdwaCmpxWritesExecMask() { @@ -5912,28 +5912,6 @@ TestCase VectorVopcSdwaCmpxWritesExecMask() { {O::VMovB32, O::VCmpxLtU32, O::BufferStoreDword, O::SEndpgm}}; } -TestCase VectorVopcCmpxPreservesVccForWqm() { - using O = ShaderOpcode; - - std::vector code; - AppendVMovU32(&code, 0, 1); - AppendVMovU32(&code, 1, 1); - AppendVMovU32(&code, 2, 7); - AppendVMovU32(&code, 30, 0); - code.push_back(EncodeSop1(0x04, 106, InlineU32(0))); // s_mov_b64 vcc, 0 - code.push_back(EncodeVopc(0xd2, Vgpr(0), 1)); // v_cmpx_eq_u32, true - code.push_back(EncodeSop1(0x0a, 126, 106)); // s_wqm_b64 exec, vcc - AppendBufferStoreDword(&code, 2, 30); - AppendEnd(&code); - - return {"VectorVopcCmpxPreservesVccForWqm", - code, - {0}, - {7}, - {O::VMovB32, O::SMovB64, O::VCmpxEqU32, O::SWqmB64, - O::BufferStoreDword, O::SEndpgm}}; -} - TestCase VectorCompareInvertedMaskSelect() { using O = ShaderOpcode; @@ -8831,9 +8809,8 @@ std::vector MakeCases() { AddCase(Vop3CndmaskAllowsDataSourceModifier); AddCase(VectorCompareExecOps); AddCase(VectorVop3FloatCompareNegSourceModifier); - AddCase(VectorVop3CmpxWritesScalarDstAndExecMask); + AddCase(VectorVop3CmpxWritesExecMask); AddCase(VectorVopcSdwaCmpxWritesExecMask); - AddCase(VectorVopcCmpxPreservesVccForWqm); AddCase(VectorCompareInvertedMaskSelect); AddCase(BranchSelect); AddCase(SimpleLoop); diff --git a/tests/ShaderVertexMetadataTests.cpp b/tests/ShaderVertexMetadataTests.cpp index 8951e6936..d6a710a75 100644 --- a/tests/ShaderVertexMetadataTests.cpp +++ b/tests/ShaderVertexMetadataTests.cpp @@ -9,122 +9,85 @@ namespace { using namespace Libs::Graphics; -void Check(bool value, const char *text) { - if (!value) { - std::fprintf(stderr, "ShaderVertexMetadataTests: failed: %s\n", text); - std::abort(); - } +void Check(bool value, const char* text) { + if (!value) { + std::fprintf(stderr, "ShaderVertexMetadataTests: failed: %s\n", text); + std::abort(); + } } struct Fixture { - std::array(AgcDirectResourceType::Last) + 1> - offsets{}; - ShaderUserData user_data{}; - ShaderSemantic semantic{}; - ShaderMappedData mapped{}; + std::array(AgcDirectResourceType::Last) + 1> offsets {}; + ShaderUserData user_data {}; + ShaderSemantic semantic {}; + ShaderMappedData mapped {}; - Fixture() { - offsets.fill(AGC_ILLEGAL_DIRECT_OFFSET); - offsets[static_cast(AgcDirectResourceType::PtrVertexBufferTable)] = - 2; - offsets[static_cast( - AgcDirectResourceType::PtrVertexAttribDescTable)] = 4; - user_data.direct_resource_offset = offsets.data(); - user_data.direct_resource_count = static_cast(offsets.size()); - mapped.user_data = &user_data; - mapped.input_semantics = &semantic; - mapped.num_input_semantics = 1; - } + Fixture() { + offsets.fill(AGC_ILLEGAL_DIRECT_OFFSET); + offsets[static_cast(AgcDirectResourceType::PtrVertexBufferTable)] = 2; + offsets[static_cast(AgcDirectResourceType::PtrVertexAttribDescTable)] = 4; + user_data.direct_resource_offset = offsets.data(); + user_data.direct_resource_count = static_cast(offsets.size()); + mapped.user_data = &user_data; + mapped.input_semantics = &semantic; + mapped.num_input_semantics = 1; + } }; -void CheckRejected(const ShaderMappedData &data, const char *text) { - ShaderVertexMetadata output; - output.vertex_buffer_reg = 37; - output.vertex_attrib_reg = 41; - output.input_semantics_count = 7; - std::string error; - Check(!ShaderReadVertexMetadata(data, 64, &output, &error), text); - Check(!error.empty(), "metadata rejection omitted its diagnostic"); - Check(output.vertex_buffer_reg == 37 && output.vertex_attrib_reg == 41 && - output.input_semantics_count == 7, - "metadata rejection changed the prior output"); +void CheckRejected(const ShaderMappedData& data, const char* text) { + ShaderVertexMetadata output; + output.vertex_buffer_reg = 37; + output.vertex_attrib_reg = 41; + output.input_semantics_count = 7; + std::string error; + Check(!ShaderReadVertexMetadata(data, 64, &output, &error), text); + Check(!error.empty(), "metadata rejection omitted its diagnostic"); + Check(output.vertex_buffer_reg == 37 && output.vertex_attrib_reg == 41 && + output.input_semantics_count == 7, + "metadata rejection changed the prior output"); } void TestValidAndInvalidMetadata() { - Fixture fixture; - ShaderVertexMetadata output; - std::string error; - Check(ShaderReadVertexMetadata(fixture.mapped, 64, &output, &error), - "valid AGC vertex metadata was rejected"); - Check(output.vertex_buffer_reg == 2 && output.vertex_attrib_reg == 4 && - output.input_semantics_count == 1, - "valid AGC vertex metadata was decoded incorrectly"); + Fixture fixture; + ShaderVertexMetadata output; + std::string error; + Check(ShaderReadVertexMetadata(fixture.mapped, 64, &output, &error), + "valid AGC vertex metadata was rejected"); + Check(output.vertex_buffer_reg == 2 && output.vertex_attrib_reg == 4 && + output.input_semantics_count == 1, + "valid AGC vertex metadata was decoded incorrectly"); - auto missing_header = fixture.mapped; - missing_header.user_data = nullptr; - CheckRejected(missing_header, "missing AGC user-data header was accepted"); + auto missing_header = fixture.mapped; + missing_header.user_data = nullptr; + CheckRejected(missing_header, "missing AGC user-data header was accepted"); - Fixture missing_offsets; - missing_offsets.user_data.direct_resource_offset = nullptr; - CheckRejected(missing_offsets.mapped, - "missing direct-resource offsets were accepted"); + Fixture missing_offsets; + missing_offsets.user_data.direct_resource_offset = nullptr; + CheckRejected(missing_offsets.mapped, "missing direct-resource offsets were accepted"); - Fixture excessive_resources; - excessive_resources.user_data.direct_resource_count = - static_cast(excessive_resources.offsets.size() + 1); - CheckRejected(excessive_resources.mapped, - "excessive direct-resource count was accepted"); + Fixture excessive_resources; + excessive_resources.user_data.direct_resource_count = + static_cast(excessive_resources.offsets.size() + 1); + CheckRejected(excessive_resources.mapped, "excessive direct-resource count was accepted"); - Fixture excessive_semantics; - excessive_semantics.mapped.num_input_semantics = - ShaderVertexInputInfo::RES_MAX + 1; - CheckRejected(excessive_semantics.mapped, - "excessive vertex semantic count was accepted"); + Fixture excessive_semantics; + excessive_semantics.mapped.num_input_semantics = ShaderVertexInputInfo::RES_MAX + 1; + CheckRejected(excessive_semantics.mapped, "excessive vertex semantic count was accepted"); - Fixture excessive_register; - excessive_register.offsets[static_cast( - AgcDirectResourceType::PtrVertexBufferTable)] = 63; - CheckRejected(excessive_register.mapped, - "out-of-domain vertex table SGPR was accepted"); + Fixture excessive_register; + excessive_register.offsets[ + static_cast(AgcDirectResourceType::PtrVertexBufferTable)] = 63; + CheckRejected(excessive_register.mapped, "out-of-domain vertex table SGPR was accepted"); - Fixture missing_semantics; - missing_semantics.mapped.input_semantics = nullptr; - CheckRejected(missing_semantics.mapped, - "missing vertex semantic array was accepted"); -} - -void TestVertexDstSelectors() { - const auto zero = DecodeVertexDstSelector(0); - const auto one = DecodeVertexDstSelector(1); - Check(zero.kind == VertexDstSelectKind::Zero && - one.kind == VertexDstSelectKind::One, - "vertex constant selectors were decoded incorrectly"); - for (uint8_t selector = 4; selector <= 7; selector++) { - const auto component = DecodeVertexDstSelector(selector); - Check(component.kind == VertexDstSelectKind::Component && - component.source_component == selector - 4, - "vertex component selector was decoded incorrectly"); - } - Check(DecodeVertexDstSelector(2).kind == VertexDstSelectKind::Reserved && - DecodeVertexDstSelector(3).kind == VertexDstSelectKind::Reserved, - "reserved vertex selectors were accepted"); - Check(GetDstSel(DstSel(6, 5, 4, 7), 0) == 6 && - GetDstSel(DstSel(6, 5, 4, 7), 1) == 5 && - GetDstSel(DstSel(6, 5, 4, 7), 2) == 4 && - GetDstSel(DstSel(6, 5, 4, 7), 3) == 7, - "BGRA vertex selector packing was decoded incorrectly"); - Check(VertexRawComponentCount(DstSel(7, 0, 0, 0), 1) == 4, - "W-to-X did not widen the raw vertex interface to four components"); - Check(VertexRawComponentCount(DstSel(4, 4, 4, 4), 4) == 4 && - VertexRawComponentCount(DstSel(4, 0, 0, 1), 4) == 4, - "replication or constant selectors changed raw vertex width"); + Fixture missing_semantics; + missing_semantics.mapped.input_semantics = nullptr; + CheckRejected(missing_semantics.mapped, "missing vertex semantic array was accepted"); } } // namespace int main() { - TestValidAndInvalidMetadata(); - TestVertexDstSelectors(); - std::puts("ShaderVertexMetadataTests: all cases passed"); - return 0; + TestValidAndInvalidMetadata(); + std::puts("ShaderVertexMetadataTests: all cases passed"); + return 0; } diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index f00d2a776..3ac27dd84 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -1473,11 +1473,9 @@ void TestNewShaderRecompilerMoreAluFamilies() { "new decoder did not decode old-backed V_CMP_NEQ_F32"); Check(Common::ContainsStr(result.decoded_dump, "v_cmp_neq_f32 s0, 0.500000, v1"), "new decoder did not decode old-backed V_CMP_NEQ_F32 SDWA scalar destination"); - Check(Common::ContainsStr(result.decoded_dump, "v_cmpx_lt_u32 vcc_lo, v5.sdwa(sel=4") && - Common::ContainsStr(result.ir_dump, "CompareMaskLtU32 vcc_lo") && - Common::ContainsStr(result.ir_dump, "MoveU32 exec_lo, vcc_lo") && - Common::ContainsStr(result.ir_dump, "MoveU32 exec_hi, vcc_hi"), - "new decoder did not preserve V_CMPX SDWA destination and mirror its mask to exec"); + Check(Common::ContainsStr(result.decoded_dump, "v_cmpx_lt_u32 exec_lo, v5.sdwa(sel=4") && + Common::ContainsStr(result.ir_dump, "CompareMaskLtU32 exec_lo"), + "new decoder did not route V_CMPX SDWA destination to exec"); Check(Common::ContainsStr(result.decoded_dump, "v_cmp_nlt_f32"), "new decoder did not decode old-backed V_CMP_NLT_F32"); Check(Common::ContainsStr(result.decoded_dump, "v_cmpx_nge_f32"), @@ -1776,12 +1774,10 @@ void TestNewShaderRecompilerMoreAluFamilies() { "VOP3-encoded VOP1 find-first-bit-low did not lower through shared IR"); Check(Common::ContainsStr(result.ir_dump, "CompareGtF32"), "VOPC float compare did not lower to IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskGtF32 vcc_lo") && - Common::ContainsStr(result.ir_dump, "MoveU32 exec_lo, vcc_lo"), - "VOPC float compare-and-mask did not lower to VCC plus EXEC IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskGtU32 vcc_lo") && - Common::ContainsStr(result.ir_dump, "MoveU32 exec_hi, vcc_hi"), - "VOPC uint compare-and-mask did not lower to VCC plus EXEC IR"); + Check(Common::ContainsStr(result.ir_dump, "CompareMaskGtF32 exec_lo"), + "VOPC float compare-and-mask did not lower to exec mask IR"); + Check(Common::ContainsStr(result.ir_dump, "CompareMaskGtU32 exec_lo"), + "VOPC uint compare-and-mask did not lower to exec mask IR"); Check(Common::ContainsStr(result.ir_dump, "CompareFalse vcc_lo, v6, v6"), "VOPC false compare did not lower to shared IR"); Check(Common::ContainsStr(result.ir_dump, "CompareTrue vcc_lo, v6, v6"), @@ -1804,17 +1800,17 @@ void TestNewShaderRecompilerMoreAluFamilies() { "VOPC SDWA unordered-not-equal compare did not lower to scalar-destination IR"); Check(Common::ContainsStr(result.ir_dump, "CompareUnordGeF32 vcc_lo, v6, v6"), "VOPC unordered-greater-equal compare did not lower to shared IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordLtF32 vcc_lo, v6, v6"), + Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordLtF32 exec_lo, v6, v6"), "VOPC unordered-less compare-and-mask did not lower to shared IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordEqF32 vcc_lo, v6, v6"), + Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordEqF32 exec_lo, v6, v6"), "VOPC unordered-equal compare-and-mask did not lower to shared IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordLeF32 vcc_lo, v6, v6"), + Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordLeF32 exec_lo, v6, v6"), "VOPC unordered-less-equal compare-and-mask did not lower to shared IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordGtF32 vcc_lo, v6, v6"), + Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordGtF32 exec_lo, v6, v6"), "VOPC unordered-greater compare-and-mask did not lower to shared IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordNeF32 vcc_lo, v6, v6"), + Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordNeF32 exec_lo, v6, v6"), "VOPC unordered-not-equal compare-and-mask did not lower to shared IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordGeF32 vcc_lo, v6, v6"), + Check(Common::ContainsStr(result.ir_dump, "CompareMaskUnordGeF32 exec_lo, v6, v6"), "VOPC unordered-greater-equal compare-and-mask did not lower to shared IR"); Check(Common::ContainsStr(result.ir_dump, "CompareFalse vcc_lo, v5, v5"), "VOPC integer false compare did not lower to shared IR"); @@ -2691,9 +2687,8 @@ void TestNewShaderRecompilerSignedCompareAlu() { "signed halfword greater-or-equal compare did not lower to IR"); Check(Common::ContainsStr(result.ir_dump, "CompareLtU16"), "unsigned halfword less-than compare did not lower to IR"); - Check(Common::ContainsStr(result.ir_dump, "CompareMaskGtI32 vcc_lo") && - Common::ContainsStr(result.ir_dump, "MoveU32 exec_lo, vcc_lo"), - "signed compare-and-mask did not lower to VCC plus EXEC IR"); + Check(Common::ContainsStr(result.ir_dump, "CompareMaskGtI32 exec_lo"), + "signed compare-and-mask did not lower to exec mask IR"); Check(SpirvContainsOpcode(result.spirv, 173), "SPIR-V binary does not contain OpSGreaterThan"); Check(SpirvContainsOpcode(result.spirv, 177), "SPIR-V binary does not contain OpSLessThan"); Check(SpirvContainsOpcode(result.spirv, 202),