Assembler/disassembler via SPIRV-Tools.
This commit is contained in:
parent
9072a38f38
commit
1b1ff07bf5
|
@ -22,3 +22,6 @@
|
||||||
[submodule "third_party/zlib"]
|
[submodule "third_party/zlib"]
|
||||||
path = third_party/zlib
|
path = third_party/zlib
|
||||||
url = https://github.com/madler/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/glew.lua")
|
||||||
include("third_party/imgui.lua")
|
include("third_party/imgui.lua")
|
||||||
include("third_party/libav.lua")
|
include("third_party/libav.lua")
|
||||||
|
include("third_party/spirv-tools.lua")
|
||||||
include("third_party/xxhash.lua")
|
include("third_party/xxhash.lua")
|
||||||
include("third_party/zlib.lua")
|
include("third_party/zlib.lua")
|
||||||
include("build_tools/third_party/gflags.lua")
|
include("build_tools/third_party/gflags.lua")
|
||||||
|
|
|
@ -7,6 +7,7 @@ project("xenia-gpu-spirv")
|
||||||
kind("StaticLib")
|
kind("StaticLib")
|
||||||
language("C++")
|
language("C++")
|
||||||
links({
|
links({
|
||||||
|
"spirv-tools",
|
||||||
"xenia-base",
|
"xenia-base",
|
||||||
"xenia-gpu",
|
"xenia-gpu",
|
||||||
})
|
})
|
||||||
|
@ -14,6 +15,7 @@ project("xenia-gpu-spirv")
|
||||||
})
|
})
|
||||||
includedirs({
|
includedirs({
|
||||||
project_root.."/build_tools/third_party/gflags/src",
|
project_root.."/build_tools/third_party/gflags/src",
|
||||||
|
project_root.."/third_party/spirv-tools/external/include",
|
||||||
})
|
})
|
||||||
local_platform_files()
|
local_platform_files()
|
||||||
|
|
||||||
|
@ -24,6 +26,7 @@ project("xenia-gpu-spirv-compiler")
|
||||||
language("C++")
|
language("C++")
|
||||||
links({
|
links({
|
||||||
"gflags",
|
"gflags",
|
||||||
|
"spirv-tools",
|
||||||
"xenia-base",
|
"xenia-base",
|
||||||
"xenia-gpu",
|
"xenia-gpu",
|
||||||
"xenia-gpu-spirv",
|
"xenia-gpu-spirv",
|
||||||
|
|
|
@ -13,6 +13,16 @@
|
||||||
#include "third_party/spirv/GLSL.std.450.h"
|
#include "third_party/spirv/GLSL.std.450.h"
|
||||||
#include "third_party/spirv/spirv.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 xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit df2f5a1b6eebe50d8e5f3becf22f1e70551e3fd1
|
|
@ -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",
|
||||||
|
})
|
|
@ -39,8 +39,8 @@
|
||||||
// "Mask" in their name, and a parallel enum that has the shift
|
// "Mask" in their name, and a parallel enum that has the shift
|
||||||
// amount (1 << x) for each corresponding enumerant.
|
// amount (1 << x) for each corresponding enumerant.
|
||||||
|
|
||||||
#ifndef spirv_H
|
#ifndef spirv_H11
|
||||||
#define spirv_H
|
#define spirv_H11
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
|
@ -874,4 +874,4 @@ inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfil
|
||||||
|
|
||||||
} // end namespace spv
|
} // end namespace spv
|
||||||
|
|
||||||
#endif // #ifndef spirv_H
|
#endif // #ifndef spirv_H11
|
||||||
|
|
Loading…
Reference in New Issue