mirror of
https://github.com/xenia-project/xenia.git
synced 2024-11-23 11:39:45 +00:00
Assembler/disassembler via SPIRV-Tools.
This commit is contained in:
parent
9072a38f38
commit
1b1ff07bf5
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -22,3 +22,6 @@
|
||||
[submodule "third_party/zlib"]
|
||||
path = third_party/zlib
|
||||
url = https://github.com/madler/zlib
|
||||
[submodule "third_party/spirv-tools"]
|
||||
path = third_party/spirv-tools
|
||||
url = https://github.com/xenia-project/SPIRV-Tools.git
|
||||
|
@ -163,6 +163,7 @@ solution("xenia")
|
||||
include("third_party/glew.lua")
|
||||
include("third_party/imgui.lua")
|
||||
include("third_party/libav.lua")
|
||||
include("third_party/spirv-tools.lua")
|
||||
include("third_party/xxhash.lua")
|
||||
include("third_party/zlib.lua")
|
||||
include("build_tools/third_party/gflags.lua")
|
||||
|
@ -7,6 +7,7 @@ project("xenia-gpu-spirv")
|
||||
kind("StaticLib")
|
||||
language("C++")
|
||||
links({
|
||||
"spirv-tools",
|
||||
"xenia-base",
|
||||
"xenia-gpu",
|
||||
})
|
||||
@ -14,6 +15,7 @@ project("xenia-gpu-spirv")
|
||||
})
|
||||
includedirs({
|
||||
project_root.."/build_tools/third_party/gflags/src",
|
||||
project_root.."/third_party/spirv-tools/external/include",
|
||||
})
|
||||
local_platform_files()
|
||||
|
||||
@ -24,6 +26,7 @@ project("xenia-gpu-spirv-compiler")
|
||||
language("C++")
|
||||
links({
|
||||
"gflags",
|
||||
"spirv-tools",
|
||||
"xenia-base",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-spirv",
|
||||
|
@ -13,6 +13,16 @@
|
||||
#include "third_party/spirv/GLSL.std.450.h"
|
||||
#include "third_party/spirv/spirv.h"
|
||||
|
||||
// Forward declarations from SPIRV-Tools so we don't pollute /so/ much.
|
||||
struct spv_binary_t;
|
||||
typedef spv_binary_t* spv_binary;
|
||||
struct spv_context_t;
|
||||
typedef spv_context_t* spv_context;
|
||||
struct spv_diagnostic_t;
|
||||
typedef spv_diagnostic_t* spv_diagnostic;
|
||||
struct spv_text_t;
|
||||
typedef spv_text_t* spv_text;
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace spirv {
|
||||
|
77
src/xenia/gpu/spirv/spv_assembler.cc
Normal file
77
src/xenia/gpu/spirv/spv_assembler.cc
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/gpu/spirv/spv_assembler.h"
|
||||
|
||||
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace spirv {
|
||||
|
||||
SpvAssembler::Result::Result(spv_binary binary, spv_diagnostic diagnostic)
|
||||
: binary_(binary), diagnostic_(diagnostic) {}
|
||||
|
||||
SpvAssembler::Result::~Result() {
|
||||
if (binary_) {
|
||||
spvBinaryDestroy(binary_);
|
||||
}
|
||||
if (diagnostic_) {
|
||||
spvDiagnosticDestroy(diagnostic_);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpvAssembler::Result::has_error() const { return !!diagnostic_; }
|
||||
|
||||
size_t SpvAssembler::Result::error_source_line() const {
|
||||
return diagnostic_ ? diagnostic_->position.line : 0;
|
||||
}
|
||||
|
||||
size_t SpvAssembler::Result::error_source_column() const {
|
||||
return diagnostic_ ? diagnostic_->position.column : 0;
|
||||
}
|
||||
|
||||
const char* SpvAssembler::Result::error_string() const {
|
||||
return diagnostic_ ? diagnostic_->error : "";
|
||||
}
|
||||
|
||||
const uint32_t* SpvAssembler::Result::words() const {
|
||||
return binary_ ? binary_->code : nullptr;
|
||||
}
|
||||
|
||||
size_t SpvAssembler::Result::word_count() const {
|
||||
return binary_ ? binary_->wordCount : 0;
|
||||
}
|
||||
|
||||
SpvAssembler::SpvAssembler() : spv_context_(spvContextCreate()) {}
|
||||
|
||||
SpvAssembler::~SpvAssembler() { spvContextDestroy(spv_context_); }
|
||||
|
||||
std::unique_ptr<SpvAssembler::Result> SpvAssembler::Assemble(
|
||||
const char* source_text, size_t source_text_length) {
|
||||
spv_binary binary = nullptr;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
auto result_code = spvTextToBinary(spv_context_, source_text,
|
||||
source_text_length, &binary, &diagnostic);
|
||||
std::unique_ptr<Result> result(new Result(binary, diagnostic));
|
||||
if (result_code) {
|
||||
XELOGE("Failed to assemble spv: %d", result_code);
|
||||
if (result->has_error()) {
|
||||
return result;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace spirv
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
69
src/xenia/gpu/spirv/spv_assembler.h
Normal file
69
src/xenia/gpu/spirv/spv_assembler.h
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_GPU_SPIRV_SPV_ASSEMBLER_H_
|
||||
#define XENIA_GPU_SPIRV_SPV_ASSEMBLER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "xenia/gpu/spirv/spirv_util.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace spirv {
|
||||
|
||||
class SpvAssembler {
|
||||
public:
|
||||
class Result {
|
||||
public:
|
||||
Result(spv_binary binary, spv_diagnostic diagnostic);
|
||||
~Result();
|
||||
|
||||
// True if the result has an error associated with it.
|
||||
bool has_error() const;
|
||||
// Line of the error in the provided source text.
|
||||
size_t error_source_line() const;
|
||||
// Column of the error in the provided source text.
|
||||
size_t error_source_column() const;
|
||||
// Human-readable description of the error.
|
||||
const char* error_string() const;
|
||||
|
||||
// Assembled SPIRV binary.
|
||||
// Returned pointer lifetime is tied to this Result instance.
|
||||
const uint32_t* words() const;
|
||||
// Size of the SPIRV binary, in words.
|
||||
size_t word_count() const;
|
||||
|
||||
private:
|
||||
spv_binary binary_ = nullptr;
|
||||
spv_diagnostic diagnostic_ = nullptr;
|
||||
};
|
||||
|
||||
SpvAssembler();
|
||||
~SpvAssembler();
|
||||
|
||||
// Assembles the given source text into a SPIRV binary.
|
||||
// The return will be nullptr if assembly fails due to a library error.
|
||||
// The return may have an error set on it if the source text is malformed.
|
||||
std::unique_ptr<Result> Assemble(const char* source_text,
|
||||
size_t source_text_length);
|
||||
std::unique_ptr<Result> Assemble(const std::string& source_text) {
|
||||
return Assemble(source_text.c_str(), source_text.size());
|
||||
}
|
||||
|
||||
private:
|
||||
spv_context spv_context_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace spirv
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_SPIRV_SPV_ASSEMBLER_H_
|
81
src/xenia/gpu/spirv/spv_disassembler.cc
Normal file
81
src/xenia/gpu/spirv/spv_disassembler.cc
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/gpu/spirv/spv_disassembler.h"
|
||||
|
||||
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace spirv {
|
||||
|
||||
SpvDisassembler::Result::Result(spv_text text, spv_diagnostic diagnostic)
|
||||
: text_(text), diagnostic_(diagnostic) {}
|
||||
|
||||
SpvDisassembler::Result::~Result() {
|
||||
if (text_) {
|
||||
spvTextDestroy(text_);
|
||||
}
|
||||
if (diagnostic_) {
|
||||
spvDiagnosticDestroy(diagnostic_);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpvDisassembler::Result::has_error() const { return !!diagnostic_; }
|
||||
|
||||
size_t SpvDisassembler::Result::error_word_index() const {
|
||||
return diagnostic_ ? diagnostic_->position.index : 0;
|
||||
}
|
||||
|
||||
const char* SpvDisassembler::Result::error_string() const {
|
||||
return diagnostic_ ? diagnostic_->error : "";
|
||||
}
|
||||
|
||||
const char* SpvDisassembler::Result::text() const {
|
||||
return text_ ? text_->str : "";
|
||||
}
|
||||
|
||||
std::string SpvDisassembler::Result::to_string() const {
|
||||
return text_ ? std::string(text_->str, text_->length) : "";
|
||||
}
|
||||
|
||||
void SpvDisassembler::Result::AppendText(StringBuffer* target_buffer) const {
|
||||
if (text_) {
|
||||
target_buffer->AppendBytes(reinterpret_cast<const uint8_t*>(text_->str),
|
||||
text_->length);
|
||||
}
|
||||
}
|
||||
|
||||
SpvDisassembler::SpvDisassembler() : spv_context_(spvContextCreate()) {}
|
||||
|
||||
SpvDisassembler::~SpvDisassembler() { spvContextDestroy(spv_context_); }
|
||||
|
||||
std::unique_ptr<SpvDisassembler::Result> SpvDisassembler::Disassemble(
|
||||
const uint32_t* words, size_t word_count) {
|
||||
spv_text text = nullptr;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
auto result_code =
|
||||
spvBinaryToText(spv_context_, words, word_count,
|
||||
SPV_BINARY_TO_TEXT_OPTION_INDENT, &text, &diagnostic);
|
||||
std::unique_ptr<Result> result(new Result(text, diagnostic));
|
||||
if (result_code) {
|
||||
XELOGE("Failed to disassemble spv: %d", result_code);
|
||||
if (result->has_error()) {
|
||||
return result;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace spirv
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
66
src/xenia/gpu/spirv/spv_disassembler.h
Normal file
66
src/xenia/gpu/spirv/spv_disassembler.h
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_GPU_SPIRV_SPV_DISASSEMBLER_H_
|
||||
#define XENIA_GPU_SPIRV_SPV_DISASSEMBLER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/gpu/spirv/spirv_util.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace spirv {
|
||||
|
||||
class SpvDisassembler {
|
||||
public:
|
||||
class Result {
|
||||
public:
|
||||
Result(spv_text text, spv_diagnostic diagnostic);
|
||||
~Result();
|
||||
|
||||
// True if the result has an error associated with it.
|
||||
bool has_error() const;
|
||||
// Index of the error in the provided binary word data.
|
||||
size_t error_word_index() const;
|
||||
// Human-readable description of the error.
|
||||
const char* error_string() const;
|
||||
|
||||
// Disassembled source text.
|
||||
// Returned pointer lifetime is tied to this Result instance.
|
||||
const char* text() const;
|
||||
// Converts the disassembled source text to a string.
|
||||
std::string to_string() const;
|
||||
// Appends the disassembled source text to the given buffer.
|
||||
void AppendText(StringBuffer* target_buffer) const;
|
||||
|
||||
private:
|
||||
spv_text text_ = nullptr;
|
||||
spv_diagnostic diagnostic_ = nullptr;
|
||||
};
|
||||
|
||||
SpvDisassembler();
|
||||
~SpvDisassembler();
|
||||
|
||||
// Disassembles the given SPIRV binary.
|
||||
// The return will be nullptr if disassembly fails due to a library error.
|
||||
// The return may have an error set on it if the SPIRV binary is malformed.
|
||||
std::unique_ptr<Result> Disassemble(const uint32_t* words, size_t word_count);
|
||||
|
||||
private:
|
||||
spv_context spv_context_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace spirv
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_SPIRV_SPV_DISASSEMBLER_H_
|
1
third_party/spirv-tools
vendored
Submodule
1
third_party/spirv-tools
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit df2f5a1b6eebe50d8e5f3becf22f1e70551e3fd1
|
54
third_party/spirv-tools.lua
vendored
Normal file
54
third_party/spirv-tools.lua
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
group("third_party")
|
||||
project("spirv-tools")
|
||||
uuid("621512da-bb50-40f2-85ba-ae615ff13e68")
|
||||
kind("StaticLib")
|
||||
language("C++")
|
||||
links({
|
||||
})
|
||||
defines({
|
||||
"_LIB",
|
||||
})
|
||||
includedirs({
|
||||
"spirv-tools/external/include",
|
||||
"spirv-tools/include",
|
||||
})
|
||||
files({
|
||||
"spirv-tools/external/include/headers/GLSL.std.450.h",
|
||||
"spirv-tools/external/include/headers/OpenCL.std.h",
|
||||
"spirv-tools/external/include/headers/spirv.h",
|
||||
"spirv-tools/include/libspirv/libspirv.h",
|
||||
"spirv-tools/include/util/bitutils.h",
|
||||
"spirv-tools/include/util/hex_float.h",
|
||||
"spirv-tools/source/assembly_grammar.cpp",
|
||||
"spirv-tools/source/assembly_grammar.h",
|
||||
"spirv-tools/source/binary.cpp",
|
||||
"spirv-tools/source/binary.h",
|
||||
"spirv-tools/source/diagnostic.cpp",
|
||||
"spirv-tools/source/diagnostic.h",
|
||||
"spirv-tools/source/disassemble.cpp",
|
||||
"spirv-tools/source/endian.cpp",
|
||||
"spirv-tools/source/endian.h",
|
||||
"spirv-tools/source/ext_inst.cpp",
|
||||
"spirv-tools/source/ext_inst.h",
|
||||
"spirv-tools/source/instruction.h",
|
||||
"spirv-tools/source/opcode.cpp",
|
||||
"spirv-tools/source/opcode.h",
|
||||
"spirv-tools/source/opcode.inc",
|
||||
"spirv-tools/source/opencl_std_ext_inst.inc",
|
||||
"spirv-tools/source/operand.cpp",
|
||||
"spirv-tools/source/operand.h",
|
||||
"spirv-tools/source/print.cpp",
|
||||
"spirv-tools/source/print.h",
|
||||
"spirv-tools/source/spirv_constant.h",
|
||||
"spirv-tools/source/spirv_definition.h",
|
||||
"spirv-tools/source/spirv_operands.h",
|
||||
"spirv-tools/source/table.cpp",
|
||||
"spirv-tools/source/table.h",
|
||||
"spirv-tools/source/text.cpp",
|
||||
"spirv-tools/source/text.h",
|
||||
"spirv-tools/source/text_handler.cpp",
|
||||
"spirv-tools/source/text_handler.h",
|
||||
"spirv-tools/source/validate.cpp",
|
||||
"spirv-tools/source/validate.h",
|
||||
"spirv-tools/source/validate_id.cpp",
|
||||
})
|
6
third_party/spirv/spirv.h
vendored
6
third_party/spirv/spirv.h
vendored
@ -39,8 +39,8 @@
|
||||
// "Mask" in their name, and a parallel enum that has the shift
|
||||
// amount (1 << x) for each corresponding enumerant.
|
||||
|
||||
#ifndef spirv_H
|
||||
#define spirv_H
|
||||
#ifndef spirv_H11
|
||||
#define spirv_H11
|
||||
|
||||
namespace spv {
|
||||
|
||||
@ -874,4 +874,4 @@ inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfil
|
||||
|
||||
} // end namespace spv
|
||||
|
||||
#endif // #ifndef spirv_H
|
||||
#endif // #ifndef spirv_H11
|
||||
|
Loading…
Reference in New Issue
Block a user