Merge pull request #546 from DrChat/spv_translator
(WIP) SPIR-V Shader Translator
This commit is contained in:
commit
92a8a03caa
|
@ -14,6 +14,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -353,7 +354,7 @@ bool ShaderTranslator::TranslateBlocks() {
|
||||||
// This is what freedreno does.
|
// This is what freedreno does.
|
||||||
uint32_t max_cf_dword_index = static_cast<uint32_t>(ucode_dword_count_);
|
uint32_t max_cf_dword_index = static_cast<uint32_t>(ucode_dword_count_);
|
||||||
std::set<uint32_t> label_addresses;
|
std::set<uint32_t> label_addresses;
|
||||||
for (uint32_t i = 0; i < max_cf_dword_index; i += 3) {
|
for (uint32_t i = 0, cf_index = 0; i < max_cf_dword_index; i += 3) {
|
||||||
ControlFlowInstruction cf_a;
|
ControlFlowInstruction cf_a;
|
||||||
ControlFlowInstruction cf_b;
|
ControlFlowInstruction cf_b;
|
||||||
UnpackControlFlowInstructions(ucode_dwords_ + i, &cf_a, &cf_b);
|
UnpackControlFlowInstructions(ucode_dwords_ + i, &cf_a, &cf_b);
|
||||||
|
@ -367,6 +368,11 @@ bool ShaderTranslator::TranslateBlocks() {
|
||||||
}
|
}
|
||||||
AddControlFlowTargetLabel(cf_a, &label_addresses);
|
AddControlFlowTargetLabel(cf_a, &label_addresses);
|
||||||
AddControlFlowTargetLabel(cf_b, &label_addresses);
|
AddControlFlowTargetLabel(cf_b, &label_addresses);
|
||||||
|
|
||||||
|
PreProcessControlFlowInstruction(cf_index);
|
||||||
|
++cf_index;
|
||||||
|
PreProcessControlFlowInstruction(cf_index);
|
||||||
|
++cf_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate all instructions.
|
// Translate all instructions.
|
||||||
|
@ -666,11 +672,11 @@ void ShaderTranslator::TranslateExecInstructions(
|
||||||
static_cast<FetchOpcode>(ucode_dwords_[instr_offset * 3] & 0x1F);
|
static_cast<FetchOpcode>(ucode_dwords_[instr_offset * 3] & 0x1F);
|
||||||
if (fetch_opcode == FetchOpcode::kVertexFetch) {
|
if (fetch_opcode == FetchOpcode::kVertexFetch) {
|
||||||
auto& op = *reinterpret_cast<const VertexFetchInstruction*>(
|
auto& op = *reinterpret_cast<const VertexFetchInstruction*>(
|
||||||
ucode_dwords_ + instr_offset * 3);
|
ucode_dwords_ + instr_offset * 3);
|
||||||
TranslateVertexFetchInstruction(op);
|
TranslateVertexFetchInstruction(op);
|
||||||
} else {
|
} else {
|
||||||
auto& op = *reinterpret_cast<const TextureFetchInstruction*>(
|
auto& op = *reinterpret_cast<const TextureFetchInstruction*>(
|
||||||
ucode_dwords_ + instr_offset * 3);
|
ucode_dwords_ + instr_offset * 3);
|
||||||
TranslateTextureFetchInstruction(op);
|
TranslateTextureFetchInstruction(op);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1114,9 +1120,15 @@ void ShaderTranslator::ParseAluVectorInstruction(
|
||||||
i.result.storage_target = InstructionStorageTarget::kPointSize;
|
i.result.storage_target = InstructionStorageTarget::kPointSize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert_true(dest_num < 16);
|
if (dest_num < 16) {
|
||||||
i.result.storage_target = InstructionStorageTarget::kInterpolant;
|
i.result.storage_target = InstructionStorageTarget::kInterpolant;
|
||||||
i.result.storage_index = dest_num;
|
i.result.storage_index = dest_num;
|
||||||
|
} else {
|
||||||
|
// Unimplemented.
|
||||||
|
// assert_always();
|
||||||
|
i.result.storage_target = InstructionStorageTarget::kNone;
|
||||||
|
i.result.storage_index = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (is_pixel_shader()) {
|
} else if (is_pixel_shader()) {
|
||||||
|
@ -1236,9 +1248,19 @@ void ShaderTranslator::ParseAluScalarInstruction(
|
||||||
i.result.storage_target = InstructionStorageTarget::kPointSize;
|
i.result.storage_target = InstructionStorageTarget::kPointSize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert_true(dest_num < 16);
|
if (dest_num < 16) {
|
||||||
i.result.storage_target = InstructionStorageTarget::kInterpolant;
|
i.result.storage_target = InstructionStorageTarget::kInterpolant;
|
||||||
i.result.storage_index = dest_num;
|
i.result.storage_index = dest_num;
|
||||||
|
} else {
|
||||||
|
// Unimplemented.
|
||||||
|
// assert_always();
|
||||||
|
XELOGE(
|
||||||
|
"ShaderTranslator::ParseAluScalarInstruction: Unsupported write "
|
||||||
|
"to export %d",
|
||||||
|
dest_num);
|
||||||
|
i.result.storage_target = InstructionStorageTarget::kNone;
|
||||||
|
i.result.storage_index = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (is_pixel_shader()) {
|
} else if (is_pixel_shader()) {
|
||||||
|
|
|
@ -78,6 +78,9 @@ class ShaderTranslator {
|
||||||
shader->host_disassembly_ = std::move(value);
|
shader->host_disassembly_ = std::move(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pre-process a control-flow instruction before anything else.
|
||||||
|
virtual void PreProcessControlFlowInstruction(uint32_t cf_index) {}
|
||||||
|
|
||||||
// Handles translation for control flow label addresses.
|
// Handles translation for control flow label addresses.
|
||||||
// This is triggered once for each label required (due to control flow
|
// This is triggered once for each label required (due to control flow
|
||||||
// operations) before any of the instructions within the target exec.
|
// operations) before any of the instructions within the target exec.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,7 +32,10 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
std::vector<uint8_t> CompleteTranslation() override;
|
std::vector<uint8_t> CompleteTranslation() override;
|
||||||
void PostTranslation(Shader* shader) override;
|
void PostTranslation(Shader* shader) override;
|
||||||
|
|
||||||
|
void PreProcessControlFlowInstruction(uint32_t cf_index) override;
|
||||||
void ProcessLabel(uint32_t cf_index) override;
|
void ProcessLabel(uint32_t cf_index) override;
|
||||||
|
void ProcessControlFlowInstructionBegin(uint32_t cf_index) override;
|
||||||
|
void ProcessControlFlowInstructionEnd(uint32_t cf_index) override;
|
||||||
void ProcessControlFlowNopInstruction() override;
|
void ProcessControlFlowNopInstruction() override;
|
||||||
void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) override;
|
void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) override;
|
||||||
void ProcessExecInstructionEnd(const ParsedExecInstruction& instr) override;
|
void ProcessExecInstructionEnd(const ParsedExecInstruction& instr) override;
|
||||||
|
@ -75,6 +78,27 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
// TODO(benvanik): replace with something better, make reusable, etc.
|
// TODO(benvanik): replace with something better, make reusable, etc.
|
||||||
std::unique_ptr<spv::Builder> builder_;
|
std::unique_ptr<spv::Builder> builder_;
|
||||||
spv::Id glsl_std_450_instruction_set_ = 0;
|
spv::Id glsl_std_450_instruction_set_ = 0;
|
||||||
|
|
||||||
|
// Types
|
||||||
|
spv::Id float_type_ = 0, bool_type_ = 0;
|
||||||
|
spv::Id vec2_float_type_ = 0, vec3_float_type_ = 0, vec4_float_type_ = 0;
|
||||||
|
spv::Id vec4_uint_type_ = 0;
|
||||||
|
spv::Id vec4_bool_type_ = 0;
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
spv::Id vec4_float_zero_ = 0, vec4_float_one_ = 0;
|
||||||
|
|
||||||
|
// Array of AMD registers
|
||||||
|
// These values are all pointers.
|
||||||
|
spv::Id registers_ptr_ = 0, registers_type_ = 0;
|
||||||
|
spv::Id consts_ = 0, a0_ = 0, aL_ = 0, p0_ = 0;
|
||||||
|
spv::Id ps_ = 0, pv_ = 0; // IDs of previous results
|
||||||
|
spv::Id pos_ = 0;
|
||||||
|
spv::Id interpolators_ = 0;
|
||||||
|
|
||||||
|
// Map of {binding -> {offset -> spv input}}
|
||||||
|
std::map<uint32_t, std::map<uint32_t, spv::Id>> vertex_binding_map_;
|
||||||
|
std::map<uint32_t, spv::Block*> cf_blocks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
|
|
Loading…
Reference in New Issue