From 71b9995448161645a1c3ae89256c1e8c55087273 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Wed, 25 Nov 2015 16:37:28 -0800 Subject: [PATCH] Skeleton SPIRV shader translator. --- src/xenia/gpu/shader_compiler_main.cc | 22 ++++++++++--- src/xenia/gpu/shader_translator.cc | 46 ++++++++++++++++++++++++--- src/xenia/gpu/shader_translator.h | 29 +++++++++++++++++ 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/xenia/gpu/shader_compiler_main.cc b/src/xenia/gpu/shader_compiler_main.cc index 4f9d34d9e..dde7b98a5 100644 --- a/src/xenia/gpu/shader_compiler_main.cc +++ b/src/xenia/gpu/shader_compiler_main.cc @@ -27,19 +27,25 @@ namespace xe { namespace gpu { int shader_compiler_main(const std::vector& args) { - bool is_vertex_shader = false; + ShaderType shader_type; if (!FLAGS_shader_type.empty()) { - if (FLAGS_shader_type == "vs") { - is_vertex_shader = false; + if (FLAGS_shader_type == "vert") { + shader_type = ShaderType::kVertex; + } else if (FLAGS_shader_type == "frag") { + shader_type = ShaderType::kPixel; + } else { + XELOGE("Invalid --shader_type; must be 'vert' or 'frag'."); + return 1; } } else { auto last_dot = FLAGS_input_shader.find_last_of('.'); bool valid_type = false; if (last_dot != std::string::npos) { if (FLAGS_input_shader.substr(last_dot) == ".vert") { - is_vertex_shader = true; + shader_type = ShaderType::kVertex; valid_type = true; } else if (FLAGS_input_shader.substr(last_dot) == ".frag") { + shader_type = ShaderType::kPixel; valid_type = true; } } @@ -64,11 +70,17 @@ int shader_compiler_main(const std::vector& args) { fclose(input_file); XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).", - FLAGS_input_shader.c_str(), is_vertex_shader ? "vertex" : "fragment", + FLAGS_input_shader.c_str(), + shader_type == ShaderType::kVertex ? "vertex" : "fragment", ucode_words.size(), ucode_words.size() * 4); ShaderTranslator translator; + // TODO(benvanik): hash? need to return the data to big-endian format first. + uint64_t ucode_data_hash = 0; + auto translated_shader = translator.Translate( + shader_type, ucode_data_hash, ucode_words.data(), ucode_words.size()); + return 0; } diff --git a/src/xenia/gpu/shader_translator.cc b/src/xenia/gpu/shader_translator.cc index 6f511346d..2c68c009e 100644 --- a/src/xenia/gpu/shader_translator.cc +++ b/src/xenia/gpu/shader_translator.cc @@ -19,6 +19,18 @@ namespace xe { namespace gpu { +TranslatedShader::TranslatedShader(ShaderType shader_type, + uint64_t ucode_data_hash, + const uint32_t* ucode_words, + size_t ucode_word_count) + : shader_type_(shader_type), ucode_data_hash_(ucode_data_hash_) { + ucode_data_.resize(ucode_word_count); + std::memcpy(ucode_data_.data(), ucode_words, + ucode_word_count * sizeof(uint32_t)); +} + +TranslatedShader::~TranslatedShader() = default; + ShaderTranslator::ShaderTranslator() { // HACK(benvanik): in-progress test code just to make sure things compile. const std::string spirv_source = R"( @@ -41,6 +53,31 @@ OpFunctionEnd auto disasm_result = spirv_disasm.Disassemble(asm_result->words(), asm_result->word_count()); + return; +} + +std::unique_ptr ShaderTranslator::Translate( + ShaderType shader_type, uint64_t ucode_data_hash, + const uint32_t* ucode_words, size_t ucode_word_count) { + auto translated_shader = std::make_unique( + shader_type, ucode_data_hash, ucode_words, ucode_word_count); + + // run over once to generate info: + // vertex fetch + // fetch constant + // unnormalized [0-1] or [-1,1] if signed + // signed (integer formats only) + // round index (vs. floor) + // exp adjust [-32, 31] - all data multiplied by 2^(adj) + // stride words + // offset words + // texture fetch + // fetch constant + // unnormalized (0-N) or (0-1) + // alloc/export types/counts + // vs: output (16), position, point size + // ps: color (4), depth + xe::ui::spirv::SpirvEmitter e; auto glsl_std_450 = e.ImportExtendedInstructions("GLSL.std.450"); auto fn = e.MakeMainEntry(); @@ -50,12 +87,13 @@ OpFunctionEnd static_cast(spv::GLSLstd450::Acos), {{float_1_0}}); e.MakeReturn(true); - std::vector words; - e.Serialize(words); + std::vector spirv_words; + e.Serialize(spirv_words); - auto disasm_result2 = spirv_disasm.Disassemble(words.data(), words.size()); + auto disasm_result = xe::ui::spirv::SpirvDisassembler().Disassemble( + spirv_words.data(), spirv_words.size()); - return; + return translated_shader; } } // namespace gpu diff --git a/src/xenia/gpu/shader_translator.h b/src/xenia/gpu/shader_translator.h index 2ac60b223..dd555f442 100644 --- a/src/xenia/gpu/shader_translator.h +++ b/src/xenia/gpu/shader_translator.h @@ -10,15 +10,44 @@ #ifndef XENIA_GPU_SHADER_TRANSLATOR_H_ #define XENIA_GPU_SHADER_TRANSLATOR_H_ +#include +#include + +#include "xenia/gpu/xenos.h" #include "xenia/ui/spirv/spirv_util.h" namespace xe { namespace gpu { +class TranslatedShader { + public: + TranslatedShader(ShaderType shader_type, uint64_t ucode_data_hash, + const uint32_t* ucode_words, size_t ucode_word_count); + ~TranslatedShader(); + + ShaderType type() const { return shader_type_; } + const uint32_t* ucode_words() const { return ucode_data_.data(); } + size_t ucode_word_count() const { return ucode_data_.size(); } + + bool is_valid() const { return is_valid_; } + + private: + ShaderType shader_type_; + std::vector ucode_data_; + uint64_t ucode_data_hash_; + + bool is_valid_ = false; +}; + class ShaderTranslator { public: ShaderTranslator(); + std::unique_ptr Translate(ShaderType shader_type, + uint64_t ucode_data_hash, + const uint32_t* ucode_words, + size_t ucode_word_count); + private: };