[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 gpu {
namespace d3d12 { namespace d3d12 {
D3D12Shader::D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash, D3D12Shader::D3D12Shader(xenos::ShaderType shader_type,
const uint32_t* dword_ptr, uint32_t dword_count) uint64_t ucode_data_hash, const uint32_t* ucode_dwords,
: DxbcShader(shader_type, data_hash, dword_ptr, dword_count) {} 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( void D3D12Shader::D3D12Translation::DisassembleDxbcAndDxil(
const ui::d3d12::D3D12Provider& provider, bool disassemble_dxbc, const ui::d3d12::D3D12Provider& provider, bool disassemble_dxbc,

View File

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

View File

@ -14,9 +14,11 @@
namespace xe { namespace xe {
namespace gpu { namespace gpu {
DxbcShader::DxbcShader(xenos::ShaderType shader_type, uint64_t data_hash, DxbcShader::DxbcShader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* dword_ptr, uint32_t dword_count) const uint32_t* ucode_dwords, size_t ucode_dword_count,
: Shader(shader_type, data_hash, dword_ptr, 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( Shader::Translation* DxbcShader::CreateTranslationInstance(
uint64_t modification) { uint64_t modification) {

View File

@ -28,8 +28,9 @@ class DxbcShader : public Shader {
: Translation(shader, modification) {} : Translation(shader, modification) {}
}; };
DxbcShader(xenos::ShaderType shader_type, uint64_t data_hash, DxbcShader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* dword_ptr, uint32_t dword_count); 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 // Resource bindings are gathered after the successful translation of any
// modification for simplicity of translation (and they don't depend on // modification for simplicity of translation (and they don't depend on

View File

@ -25,11 +25,17 @@ namespace gpu {
using namespace ucode; using namespace ucode;
Shader::Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash, 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) { : 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. // We keep ucode data in host native format so it's easier to work with.
ucode_data_.resize(ucode_dword_count); 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() { Shader::~Shader() {

View File

@ -19,6 +19,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "xenia/base/byte_order.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/string_buffer.h" #include "xenia/base/string_buffer.h"
#include "xenia/gpu/ucode.h" #include "xenia/gpu/ucode.h"
@ -810,8 +811,11 @@ class Shader {
std::string host_disassembly_; 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, 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(); virtual ~Shader();
// Whether the shader is identified as a vertex or pixel 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, "", DEFINE_string(shader_input_type, "",
"'vs', 'ps', or unspecified to infer from the given filename.", "'vs', 'ps', or unspecified to infer from the given filename.",
"GPU"); "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_path(shader_output, "", "Output shader file path.", "GPU");
DEFINE_string(shader_output_type, "ucode", DEFINE_string(shader_output_type, "ucode",
"Translator to use: [ucode, spirv, spirvtext, dxbc, dxbctext].", "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. // TODO(benvanik): hash? need to return the data to big-endian format first.
uint64_t ucode_data_hash = 0; uint64_t ucode_data_hash = 0;
auto shader = std::make_unique<Shader>( 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; StringBuffer ucode_disasm_buffer;
shader->AnalyzeUcode(ucode_disasm_buffer); shader->AnalyzeUcode(ucode_disasm_buffer);

View File

@ -22,9 +22,13 @@ namespace vulkan {
using xe::ui::vulkan::util::CheckResult; using xe::ui::vulkan::util::CheckResult;
VulkanShader::VulkanShader(const ui::vulkan::VulkanProvider& provider, VulkanShader::VulkanShader(const ui::vulkan::VulkanProvider& provider,
xenos::ShaderType shader_type, uint64_t data_hash, xenos::ShaderType shader_type,
const uint32_t* dword_ptr, uint32_t dword_count) uint64_t ucode_data_hash,
: Shader(shader_type, data_hash, dword_ptr, dword_count), 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) {} provider_(provider) {}
VulkanShader::VulkanTranslation::~VulkanTranslation() { VulkanShader::VulkanTranslation::~VulkanTranslation() {

View File

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