[GPU] shader-compiler: Accept little-endian ucode

This commit is contained in:
Triang3l 2022-04-26 22:59:02 +03:00
parent 443d61c9e1
commit 69958cba9d
9 changed files with 48 additions and 19 deletions

View File

@ -22,9 +22,12 @@ namespace xe {
namespace gpu {
namespace d3d12 {
D3D12Shader::D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count)
: DxbcShader(shader_type, data_hash, dword_ptr, dword_count) {}
D3D12Shader::D3D12Shader(xenos::ShaderType shader_type,
uint64_t ucode_data_hash, const uint32_t* ucode_dwords,
size_t ucode_dword_count,
std::endian ucode_source_endian)
: DxbcShader(shader_type, ucode_data_hash, ucode_dwords, ucode_dword_count,
ucode_source_endian) {}
void D3D12Shader::D3D12Translation::DisassembleDxbcAndDxil(
const ui::d3d12::D3D12Provider& provider, bool disassemble_dxbc,

View File

@ -33,8 +33,9 @@ class D3D12Shader : public DxbcShader {
IDxcCompiler* dxc_compiler = nullptr);
};
D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count);
D3D12Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count,
std::endian ucode_source_endian = std::endian::big);
// For owning subsystem like the pipeline cache, accessors for unique
// identifiers (used instead of hashes to make sure collisions can't happen)

View File

@ -14,9 +14,11 @@
namespace xe {
namespace gpu {
DxbcShader::DxbcShader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count) {}
DxbcShader::DxbcShader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count,
std::endian ucode_source_endian)
: Shader(shader_type, ucode_data_hash, ucode_dwords, ucode_dword_count,
ucode_source_endian) {}
Shader::Translation* DxbcShader::CreateTranslationInstance(
uint64_t modification) {

View File

@ -28,8 +28,9 @@ class DxbcShader : public Shader {
: Translation(shader, modification) {}
};
DxbcShader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count);
DxbcShader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count,
std::endian ucode_source_endian = std::endian::big);
// Resource bindings are gathered after the successful translation of any
// modification for simplicity of translation (and they don't depend on

View File

@ -25,11 +25,17 @@ namespace gpu {
using namespace ucode;
Shader::Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count)
const uint32_t* ucode_dwords, size_t ucode_dword_count,
std::endian ucode_source_endian)
: shader_type_(shader_type), ucode_data_hash_(ucode_data_hash) {
// We keep ucode data in host native format so it's easier to work with.
ucode_data_.resize(ucode_dword_count);
xe::copy_and_swap(ucode_data_.data(), ucode_dwords, ucode_dword_count);
if (std::endian::native != ucode_source_endian) {
xe::copy_and_swap(ucode_data_.data(), ucode_dwords, ucode_dword_count);
} else {
std::memcpy(ucode_data_.data(), ucode_dwords,
sizeof(uint32_t) * ucode_dword_count);
}
}
Shader::~Shader() {

View File

@ -19,6 +19,7 @@
#include <utility>
#include <vector>
#include "xenia/base/byte_order.h"
#include "xenia/base/math.h"
#include "xenia/base/string_buffer.h"
#include "xenia/gpu/ucode.h"
@ -810,8 +811,11 @@ class Shader {
std::string host_disassembly_;
};
// ucode_source_endian specifies the endianness of the ucode_dwords argument -
// inside the Shader, the ucode will be stored with the native byte order.
Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count);
const uint32_t* ucode_dwords, size_t ucode_dword_count,
std::endian ucode_source_endian = std::endian::big);
virtual ~Shader();
// Whether the shader is identified as a vertex or pixel shader.

View File

@ -33,6 +33,11 @@ DEFINE_path(shader_input, "", "Input shader binary file path.", "GPU");
DEFINE_string(shader_input_type, "",
"'vs', 'ps', or unspecified to infer from the given filename.",
"GPU");
DEFINE_bool(
shader_input_little_endian, false,
"Whether the input shader binary is little-endian (from an Arm device with "
"the Qualcomm Adreno 200, for instance).",
"GPU");
DEFINE_path(shader_output, "", "Output shader file path.", "GPU");
DEFINE_string(shader_output_type, "ucode",
"Translator to use: [ucode, spirv, spirvtext, dxbc, dxbctext].",
@ -104,7 +109,9 @@ int shader_compiler_main(const std::vector<std::string>& args) {
// TODO(benvanik): hash? need to return the data to big-endian format first.
uint64_t ucode_data_hash = 0;
auto shader = std::make_unique<Shader>(
shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size());
shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size(),
cvars::shader_input_little_endian ? std::endian::little
: std::endian::big);
StringBuffer ucode_disasm_buffer;
shader->AnalyzeUcode(ucode_disasm_buffer);

View File

@ -22,9 +22,13 @@ namespace vulkan {
using xe::ui::vulkan::util::CheckResult;
VulkanShader::VulkanShader(const ui::vulkan::VulkanProvider& provider,
xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count),
xenos::ShaderType shader_type,
uint64_t ucode_data_hash,
const uint32_t* ucode_dwords,
size_t ucode_dword_count,
std::endian ucode_source_endian)
: Shader(shader_type, ucode_data_hash, ucode_dwords, ucode_dword_count,
ucode_source_endian),
provider_(provider) {}
VulkanShader::VulkanTranslation::~VulkanTranslation() {

View File

@ -37,8 +37,9 @@ class VulkanShader : public Shader {
};
VulkanShader(const ui::vulkan::VulkanProvider& provider,
xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count);
xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count,
std::endian ucode_source_endian = std::endian::big);
protected:
Translation* CreateTranslationInstance(uint64_t modification) override;