Skeleton SPIRV shader translator.

This commit is contained in:
Ben Vanik 2015-11-25 16:37:28 -08:00
parent 80c6e14cdc
commit 71b9995448
3 changed files with 88 additions and 9 deletions

View File

@ -27,19 +27,25 @@ namespace xe {
namespace gpu { namespace gpu {
int shader_compiler_main(const std::vector<std::wstring>& args) { int shader_compiler_main(const std::vector<std::wstring>& args) {
bool is_vertex_shader = false; ShaderType shader_type;
if (!FLAGS_shader_type.empty()) { if (!FLAGS_shader_type.empty()) {
if (FLAGS_shader_type == "vs") { if (FLAGS_shader_type == "vert") {
is_vertex_shader = false; 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 { } else {
auto last_dot = FLAGS_input_shader.find_last_of('.'); auto last_dot = FLAGS_input_shader.find_last_of('.');
bool valid_type = false; bool valid_type = false;
if (last_dot != std::string::npos) { if (last_dot != std::string::npos) {
if (FLAGS_input_shader.substr(last_dot) == ".vert") { if (FLAGS_input_shader.substr(last_dot) == ".vert") {
is_vertex_shader = true; shader_type = ShaderType::kVertex;
valid_type = true; valid_type = true;
} else if (FLAGS_input_shader.substr(last_dot) == ".frag") { } else if (FLAGS_input_shader.substr(last_dot) == ".frag") {
shader_type = ShaderType::kPixel;
valid_type = true; valid_type = true;
} }
} }
@ -64,11 +70,17 @@ int shader_compiler_main(const std::vector<std::wstring>& args) {
fclose(input_file); fclose(input_file);
XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).", 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); ucode_words.size(), ucode_words.size() * 4);
ShaderTranslator translator; 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; return 0;
} }

View File

@ -19,6 +19,18 @@
namespace xe { namespace xe {
namespace gpu { 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() { ShaderTranslator::ShaderTranslator() {
// HACK(benvanik): in-progress test code just to make sure things compile. // HACK(benvanik): in-progress test code just to make sure things compile.
const std::string spirv_source = R"( const std::string spirv_source = R"(
@ -41,6 +53,31 @@ OpFunctionEnd
auto disasm_result = auto disasm_result =
spirv_disasm.Disassemble(asm_result->words(), asm_result->word_count()); spirv_disasm.Disassemble(asm_result->words(), asm_result->word_count());
return;
}
std::unique_ptr<TranslatedShader> 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<TranslatedShader>(
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; xe::ui::spirv::SpirvEmitter e;
auto glsl_std_450 = e.ImportExtendedInstructions("GLSL.std.450"); auto glsl_std_450 = e.ImportExtendedInstructions("GLSL.std.450");
auto fn = e.MakeMainEntry(); auto fn = e.MakeMainEntry();
@ -50,12 +87,13 @@ OpFunctionEnd
static_cast<int>(spv::GLSLstd450::Acos), {{float_1_0}}); static_cast<int>(spv::GLSLstd450::Acos), {{float_1_0}});
e.MakeReturn(true); e.MakeReturn(true);
std::vector<uint32_t> words; std::vector<uint32_t> spirv_words;
e.Serialize(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 } // namespace gpu

View File

@ -10,15 +10,44 @@
#ifndef XENIA_GPU_SHADER_TRANSLATOR_H_ #ifndef XENIA_GPU_SHADER_TRANSLATOR_H_
#define XENIA_GPU_SHADER_TRANSLATOR_H_ #define XENIA_GPU_SHADER_TRANSLATOR_H_
#include <memory>
#include <vector>
#include "xenia/gpu/xenos.h"
#include "xenia/ui/spirv/spirv_util.h" #include "xenia/ui/spirv/spirv_util.h"
namespace xe { namespace xe {
namespace gpu { 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<uint32_t> ucode_data_;
uint64_t ucode_data_hash_;
bool is_valid_ = false;
};
class ShaderTranslator { class ShaderTranslator {
public: public:
ShaderTranslator(); ShaderTranslator();
std::unique_ptr<TranslatedShader> Translate(ShaderType shader_type,
uint64_t ucode_data_hash,
const uint32_t* ucode_words,
size_t ucode_word_count);
private: private:
}; };