Skeleton SPIRV shader translator.
This commit is contained in:
parent
80c6e14cdc
commit
71b9995448
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue