mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
shader: elide bitcasts between identical physical types
This commit is contained in:
@@ -5,15 +5,17 @@
|
|||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
||||||
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
|
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
|
||||||
|
uint32_t EmitIdentity(ValueEmitContext& ctx, uint32_t value);
|
||||||
|
|
||||||
// Operand signatures distinguish SPIR-V IDs (uint32_t), raw literals/values
|
// Operand signatures distinguish SPIR-V IDs (uint32_t), raw literals/values
|
||||||
// (IR::Value), and instructions whose metadata or operand loads must stay lazy.
|
// (IR::Value), and instructions whose metadata or operand loads must stay lazy.
|
||||||
#define EMIT_NATIVE(name, opcode, type, ...) \
|
#define EMIT_NATIVE(name, opcode, type, ...) \
|
||||||
inline constexpr auto Emit##name = EmitNative<spv::opcode, IR::Type::type, __VA_ARGS__>;
|
inline constexpr auto Emit##name = EmitNative<spv::opcode, IR::Type::type, __VA_ARGS__>;
|
||||||
EMIT_NATIVE(BitCastU16F16, OpBitcast, U32, uint32_t)
|
inline constexpr auto EmitBitCastU16F16 = EmitIdentity;
|
||||||
inline constexpr auto EmitBitCastF16U16 = EmitBitCastU16F16;
|
inline constexpr auto EmitBitCastF16U16 = EmitBitCastU16F16;
|
||||||
inline constexpr auto EmitConvertU32U16 = EmitBitCastU16F16;
|
inline constexpr auto EmitConvertU32U16 = EmitBitCastU16F16;
|
||||||
inline constexpr auto EmitConvertU32U8 = EmitBitCastU16F16;
|
inline constexpr auto EmitConvertU32U8 = EmitBitCastU16F16;
|
||||||
inline constexpr auto EmitBitCastU32F32 = EmitBitCastU16F16;
|
EMIT_NATIVE(BitCastU32F32, OpBitcast, U32, uint32_t)
|
||||||
EMIT_NATIVE(BitCastF32U32, OpBitcast, F32, uint32_t)
|
EMIT_NATIVE(BitCastF32U32, OpBitcast, F32, uint32_t)
|
||||||
EMIT_NATIVE(BitCastU64F64, OpBitcast, U64, uint32_t)
|
EMIT_NATIVE(BitCastU64F64, OpBitcast, U64, uint32_t)
|
||||||
EMIT_NATIVE(BitCastF64U64, OpBitcast, F64, uint32_t)
|
EMIT_NATIVE(BitCastF64U64, OpBitcast, F64, uint32_t)
|
||||||
@@ -207,7 +209,6 @@ uint32_t EmitFPSin(EmitterState& state, uint32_t arg0);
|
|||||||
uint32_t EmitFPCos(EmitterState& state, uint32_t arg0);
|
uint32_t EmitFPCos(EmitterState& state, uint32_t arg0);
|
||||||
#undef EMIT_NATIVE
|
#undef EMIT_NATIVE
|
||||||
|
|
||||||
uint32_t EmitIdentity(ValueEmitContext& ctx, uint32_t value);
|
|
||||||
void EmitVoid(ValueEmitContext&);
|
void EmitVoid(ValueEmitContext&);
|
||||||
inline constexpr auto EmitReference = EmitVoid;
|
inline constexpr auto EmitReference = EmitVoid;
|
||||||
inline constexpr auto EmitReferenceU32 = EmitVoid;
|
inline constexpr auto EmitReferenceU32 = EmitVoid;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#define SPV_ENABLE_UTILITY_CODE
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/emulatorConfig.h"
|
#include "common/emulatorConfig.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
@@ -1610,7 +1612,21 @@ void CheckRectListShaders() {
|
|||||||
ValidateSpirv(name, position_only.evaluation);
|
ValidateSpirv(name, position_only.evaluation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckSpirvText(const TestCase &test, const std::vector<u32> &spirv) {
|
void CheckSpirvEmission(const TestCase &test, const std::vector<u32> &spirv) {
|
||||||
|
std::vector<u32> result_types(spirv[3]);
|
||||||
|
for (size_t offset = 5; offset < spirv.size();) {
|
||||||
|
const auto words = std::span<const u32>(spirv).subspan(offset, spirv[offset] >> 16u);
|
||||||
|
const auto opcode = static_cast<spv::Op>(words[0] & 0xffffu);
|
||||||
|
bool has_result = false, has_type = false;
|
||||||
|
spv::HasResultAndType(opcode, &has_result, &has_type);
|
||||||
|
if (has_result && has_type) result_types[words[2]] = words[1];
|
||||||
|
if (opcode == spv::OpBitcast) {
|
||||||
|
Require(test.name, "bitcast changes representation",
|
||||||
|
words[1] != result_types[words[3]],
|
||||||
|
"emitted a redundant bitcast between identical SPIR-V types");
|
||||||
|
}
|
||||||
|
offset += words.size();
|
||||||
|
}
|
||||||
if (test.required_spirv.empty() && test.forbidden_spirv.empty()) {
|
if (test.required_spirv.empty() && test.forbidden_spirv.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1737,7 +1753,7 @@ CompiledShader CompileCase(const TestCase &test, u32 host_subgroup_size = 64) {
|
|||||||
Require(test.name, "SPIR-V emit", !result.spirv.empty(),
|
Require(test.name, "SPIR-V emit", !result.spirv.empty(),
|
||||||
"recompiler returned empty SPIR-V");
|
"recompiler returned empty SPIR-V");
|
||||||
ValidateSpirv(test.name, result.spirv);
|
ValidateSpirv(test.name, result.spirv);
|
||||||
CheckSpirvText(test, result.spirv);
|
CheckSpirvEmission(test, result.spirv);
|
||||||
if (test.expected_buffer_resources) {
|
if (test.expected_buffer_resources) {
|
||||||
std::vector<u32> resources;
|
std::vector<u32> resources;
|
||||||
for (u32 i = 0; i < result.program.info.buffers.size(); ++i) {
|
for (u32 i = 0; i < result.program.info.buffers.size(); ++i) {
|
||||||
@@ -36184,7 +36200,7 @@ void CheckIndirectBufferStore(VulkanHarness &vulkan) {
|
|||||||
} else {
|
} else {
|
||||||
test.required_spirv = {"OpSwitch"};
|
test.required_spirv = {"OpSwitch"};
|
||||||
}
|
}
|
||||||
CheckSpirvText(test, compiled.spirv);
|
CheckSpirvEmission(test, compiled.spirv);
|
||||||
|
|
||||||
for (const bool swapped : {false, true}) {
|
for (const bool swapped : {false, true}) {
|
||||||
if (layout != Layout::Shared && layout != Layout::IndexedNullChild && swapped) continue;
|
if (layout != Layout::Shared && layout != Layout::IndexedNullChild && swapped) continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user