Assembler/disassembler via SPIRV-Tools.

This commit is contained in:
Ben Vanik 2015-11-22 17:41:39 -08:00
parent 9072a38f38
commit 1b1ff07bf5
11 changed files with 368 additions and 3 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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")

View File

@ -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",

View File

@ -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 {

View 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

View 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_

View 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

View 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

@ -0,0 +1 @@
Subproject commit df2f5a1b6eebe50d8e5f3becf22f1e70551e3fd1

54
third_party/spirv-tools.lua vendored Normal file
View 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",
})

View File

@ -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