Shuffling spirv code so it's not tied to xe::gpu.
Will make it easier to use in standalone apps.
This commit is contained in:
parent
cf68d02142
commit
6a546ebe4d
|
@ -179,12 +179,12 @@ solution("xenia")
|
||||||
include("src/xenia/debug/ui")
|
include("src/xenia/debug/ui")
|
||||||
include("src/xenia/gpu")
|
include("src/xenia/gpu")
|
||||||
include("src/xenia/gpu/gl4")
|
include("src/xenia/gpu/gl4")
|
||||||
include("src/xenia/gpu/spirv")
|
|
||||||
include("src/xenia/hid")
|
include("src/xenia/hid")
|
||||||
include("src/xenia/hid/nop")
|
include("src/xenia/hid/nop")
|
||||||
include("src/xenia/kernel")
|
include("src/xenia/kernel")
|
||||||
include("src/xenia/ui")
|
include("src/xenia/ui")
|
||||||
include("src/xenia/ui/gl")
|
include("src/xenia/ui/gl")
|
||||||
|
include("src/xenia/ui/spirv")
|
||||||
include("src/xenia/vfs")
|
include("src/xenia/vfs")
|
||||||
|
|
||||||
if os.is("windows") then
|
if os.is("windows") then
|
||||||
|
|
|
@ -8,8 +8,10 @@ project("xenia-gpu")
|
||||||
language("C++")
|
language("C++")
|
||||||
links({
|
links({
|
||||||
"elemental-forms",
|
"elemental-forms",
|
||||||
|
"spirv-tools",
|
||||||
"xenia-base",
|
"xenia-base",
|
||||||
"xenia-ui",
|
"xenia-ui",
|
||||||
|
"xenia-ui-spirv",
|
||||||
"xxhash",
|
"xxhash",
|
||||||
"zlib",
|
"zlib",
|
||||||
})
|
})
|
||||||
|
@ -17,6 +19,41 @@ project("xenia-gpu")
|
||||||
})
|
})
|
||||||
includedirs({
|
includedirs({
|
||||||
project_root.."/third_party/elemental-forms/src",
|
project_root.."/third_party/elemental-forms/src",
|
||||||
|
project_root.."/third_party/spirv-tools/external/include",
|
||||||
project_root.."/build_tools/third_party/gflags/src",
|
project_root.."/build_tools/third_party/gflags/src",
|
||||||
})
|
})
|
||||||
local_platform_files()
|
local_platform_files()
|
||||||
|
|
||||||
|
group("src")
|
||||||
|
project("xenia-gpu-shader-compiler")
|
||||||
|
uuid("ad76d3e4-4c62-439b-a0f6-f83fcf0e83c5")
|
||||||
|
kind("ConsoleApp")
|
||||||
|
language("C++")
|
||||||
|
links({
|
||||||
|
"gflags",
|
||||||
|
"spirv-tools",
|
||||||
|
"xenia-base",
|
||||||
|
"xenia-gpu",
|
||||||
|
"xenia-ui-spirv",
|
||||||
|
})
|
||||||
|
defines({
|
||||||
|
})
|
||||||
|
includedirs({
|
||||||
|
project_root.."/build_tools/third_party/gflags/src",
|
||||||
|
})
|
||||||
|
files({
|
||||||
|
"shader_compiler_main.cc",
|
||||||
|
"../base/main_"..platform_suffix..".cc",
|
||||||
|
})
|
||||||
|
|
||||||
|
filter("platforms:Windows")
|
||||||
|
-- Only create the .user file if it doesn't already exist.
|
||||||
|
local user_file = project_root.."/build/xenia-gpu-shader-compiler.vcxproj.user"
|
||||||
|
if not os.isfile(user_file) then
|
||||||
|
debugdir(project_root)
|
||||||
|
debugargs({
|
||||||
|
"--flagfile=scratch/flags.txt",
|
||||||
|
"2>&1",
|
||||||
|
"1>scratch/stdout-shader-compiler.txt",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
|
@ -15,22 +15,19 @@
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/main.h"
|
#include "xenia/base/main.h"
|
||||||
#include "xenia/base/string.h"
|
#include "xenia/base/string.h"
|
||||||
#include "xenia/gpu/spirv/spirv_compiler.h"
|
#include "xenia/gpu/shader_translator.h"
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace spirv {
|
|
||||||
|
|
||||||
int compiler_main(const std::vector<std::wstring>& args) {
|
int shader_compiler_main(const std::vector<std::wstring>& args) {
|
||||||
SpirvCompiler c;
|
ShaderTranslator c;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
DEFINE_ENTRY_POINT(L"xenia-gpu-spirv-compiler",
|
DEFINE_ENTRY_POINT(L"xenia-gpu-shader-compiler",
|
||||||
L"xenia-gpu-spirv-compiler shader.bin",
|
L"xenia-gpu-shader-compiler shader.bin",
|
||||||
xe::gpu::spirv::compiler_main);
|
xe::gpu::shader_compiler_main);
|
|
@ -7,20 +7,21 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spirv_compiler.h"
|
#include "xenia/gpu/shader_translator.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
||||||
#include "xenia/gpu/spirv/spv_assembler.h"
|
#include "xenia/ui/spirv/spirv_assembler.h"
|
||||||
#include "xenia/gpu/spirv/spv_disassembler.h"
|
#include "xenia/ui/spirv/spirv_disassembler.h"
|
||||||
#include "xenia/gpu/spirv/spv_emitter.h"
|
#include "xenia/ui/spirv/spirv_emitter.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace spirv {
|
|
||||||
|
|
||||||
SpirvCompiler::SpirvCompiler() {
|
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 = R"(
|
const std::string spirv_source = R"(
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
%1 = OpExtInstImport "GLSL.std.450"
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
OpMemoryModel Logical Simple
|
OpMemoryModel Logical Simple
|
||||||
|
@ -33,14 +34,14 @@ OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
)";
|
)";
|
||||||
|
|
||||||
SpvAssembler spv_asm;
|
xe::ui::spirv::SpirvAssembler spirv_asm;
|
||||||
auto asm_result = spv_asm.Assemble(spirv);
|
auto asm_result = spirv_asm.Assemble(spirv_source);
|
||||||
|
|
||||||
SpvDisassembler spv_disasm;
|
xe::ui::spirv::SpirvDisassembler spirv_disasm;
|
||||||
auto disasm_result =
|
auto disasm_result =
|
||||||
spv_disasm.Disassemble(asm_result->words(), asm_result->word_count());
|
spirv_disasm.Disassemble(asm_result->words(), asm_result->word_count());
|
||||||
|
|
||||||
SpvEmitter 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();
|
||||||
auto float_1_0 = e.MakeFloatConstant(1.0f);
|
auto float_1_0 = e.MakeFloatConstant(1.0f);
|
||||||
|
@ -52,11 +53,10 @@ OpFunctionEnd
|
||||||
std::vector<uint32_t> words;
|
std::vector<uint32_t> words;
|
||||||
e.Serialize(words);
|
e.Serialize(words);
|
||||||
|
|
||||||
auto disasm_result2 = spv_disasm.Disassemble(words.data(), words.size());
|
auto disasm_result2 = spirv_disasm.Disassemble(words.data(), words.size());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
} // namespace xe
|
} // namespace xe
|
|
@ -7,24 +7,22 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_GPU_SPIRV_SPIRV_COMPILER_H_
|
#ifndef XENIA_GPU_SHADER_TRANSLATOR_H_
|
||||||
#define XENIA_GPU_SPIRV_SPIRV_COMPILER_H_
|
#define XENIA_GPU_SHADER_TRANSLATOR_H_
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
#include "xenia/ui/spirv/spirv_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace spirv {
|
|
||||||
|
|
||||||
class SpirvCompiler {
|
class ShaderTranslator {
|
||||||
public:
|
public:
|
||||||
SpirvCompiler();
|
ShaderTranslator();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spirv
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_GPU_SPIRV_SPIRV_COMPILER_H_
|
#endif // XENIA_GPU_SHADER_TRANSLATOR_H_
|
|
@ -1,54 +0,0 @@
|
||||||
project_root = "../../../.."
|
|
||||||
include(project_root.."/build_tools")
|
|
||||||
|
|
||||||
group("src")
|
|
||||||
project("xenia-gpu-spirv")
|
|
||||||
uuid("e8a9f997-39ff-4ae2-803f-937525ad4bfb")
|
|
||||||
kind("StaticLib")
|
|
||||||
language("C++")
|
|
||||||
links({
|
|
||||||
"spirv-tools",
|
|
||||||
"xenia-base",
|
|
||||||
"xenia-gpu",
|
|
||||||
})
|
|
||||||
defines({
|
|
||||||
})
|
|
||||||
includedirs({
|
|
||||||
project_root.."/build_tools/third_party/gflags/src",
|
|
||||||
project_root.."/third_party/spirv-tools/external/include",
|
|
||||||
})
|
|
||||||
local_platform_files()
|
|
||||||
|
|
||||||
group("src")
|
|
||||||
project("xenia-gpu-spirv-compiler")
|
|
||||||
uuid("ad76d3e4-4c62-439b-a0f6-f83fcf0e83c5")
|
|
||||||
kind("ConsoleApp")
|
|
||||||
language("C++")
|
|
||||||
links({
|
|
||||||
"gflags",
|
|
||||||
"spirv-tools",
|
|
||||||
"xenia-base",
|
|
||||||
"xenia-gpu",
|
|
||||||
"xenia-gpu-spirv",
|
|
||||||
})
|
|
||||||
defines({
|
|
||||||
})
|
|
||||||
includedirs({
|
|
||||||
project_root.."/build_tools/third_party/gflags/src",
|
|
||||||
})
|
|
||||||
files({
|
|
||||||
"spirv_compiler_main.cc",
|
|
||||||
"../../base/main_"..platform_suffix..".cc",
|
|
||||||
})
|
|
||||||
|
|
||||||
filter("platforms:Windows")
|
|
||||||
-- Only create the .user file if it doesn't already exist.
|
|
||||||
local user_file = project_root.."/build/xenia-gpu-spirv-compiler.vcxproj.user"
|
|
||||||
if not os.isfile(user_file) then
|
|
||||||
debugdir(project_root)
|
|
||||||
debugargs({
|
|
||||||
"--flagfile=scratch/flags.txt",
|
|
||||||
"2>&1",
|
|
||||||
"1>scratch/stdout-spirv-compiler.txt",
|
|
||||||
})
|
|
||||||
end
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
project_root = "../../../.."
|
||||||
|
include(project_root.."/build_tools")
|
||||||
|
|
||||||
|
group("src")
|
||||||
|
project("xenia-ui-spirv")
|
||||||
|
uuid("2323a069-5b29-44a3-b524-f35451a81978")
|
||||||
|
kind("StaticLib")
|
||||||
|
language("C++")
|
||||||
|
links({
|
||||||
|
"spirv-tools",
|
||||||
|
"xenia-base",
|
||||||
|
})
|
||||||
|
defines({
|
||||||
|
})
|
||||||
|
includedirs({
|
||||||
|
project_root.."/build_tools/third_party/gflags/src",
|
||||||
|
project_root.."/third_party/spirv-tools/external/include",
|
||||||
|
})
|
||||||
|
local_platform_files()
|
|
@ -7,19 +7,19 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spv_assembler.h"
|
#include "xenia/ui/spirv/spirv_assembler.h"
|
||||||
|
|
||||||
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
SpvAssembler::Result::Result(spv_binary binary, spv_diagnostic diagnostic)
|
SpirvAssembler::Result::Result(spv_binary binary, spv_diagnostic diagnostic)
|
||||||
: binary_(binary), diagnostic_(diagnostic) {}
|
: binary_(binary), diagnostic_(diagnostic) {}
|
||||||
|
|
||||||
SpvAssembler::Result::~Result() {
|
SpirvAssembler::Result::~Result() {
|
||||||
if (binary_) {
|
if (binary_) {
|
||||||
spvBinaryDestroy(binary_);
|
spvBinaryDestroy(binary_);
|
||||||
}
|
}
|
||||||
|
@ -28,33 +28,33 @@ SpvAssembler::Result::~Result() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpvAssembler::Result::has_error() const { return !!diagnostic_; }
|
bool SpirvAssembler::Result::has_error() const { return !!diagnostic_; }
|
||||||
|
|
||||||
size_t SpvAssembler::Result::error_source_line() const {
|
size_t SpirvAssembler::Result::error_source_line() const {
|
||||||
return diagnostic_ ? diagnostic_->position.line : 0;
|
return diagnostic_ ? diagnostic_->position.line : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SpvAssembler::Result::error_source_column() const {
|
size_t SpirvAssembler::Result::error_source_column() const {
|
||||||
return diagnostic_ ? diagnostic_->position.column : 0;
|
return diagnostic_ ? diagnostic_->position.column : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SpvAssembler::Result::error_string() const {
|
const char* SpirvAssembler::Result::error_string() const {
|
||||||
return diagnostic_ ? diagnostic_->error : "";
|
return diagnostic_ ? diagnostic_->error : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t* SpvAssembler::Result::words() const {
|
const uint32_t* SpirvAssembler::Result::words() const {
|
||||||
return binary_ ? binary_->code : nullptr;
|
return binary_ ? binary_->code : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SpvAssembler::Result::word_count() const {
|
size_t SpirvAssembler::Result::word_count() const {
|
||||||
return binary_ ? binary_->wordCount : 0;
|
return binary_ ? binary_->wordCount : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvAssembler::SpvAssembler() : spv_context_(spvContextCreate()) {}
|
SpirvAssembler::SpirvAssembler() : spv_context_(spvContextCreate()) {}
|
||||||
|
|
||||||
SpvAssembler::~SpvAssembler() { spvContextDestroy(spv_context_); }
|
SpirvAssembler::~SpirvAssembler() { spvContextDestroy(spv_context_); }
|
||||||
|
|
||||||
std::unique_ptr<SpvAssembler::Result> SpvAssembler::Assemble(
|
std::unique_ptr<SpirvAssembler::Result> SpirvAssembler::Assemble(
|
||||||
const char* source_text, size_t source_text_length) {
|
const char* source_text, size_t source_text_length) {
|
||||||
spv_binary binary = nullptr;
|
spv_binary binary = nullptr;
|
||||||
spv_diagnostic diagnostic = nullptr;
|
spv_diagnostic diagnostic = nullptr;
|
||||||
|
@ -73,5 +73,5 @@ std::unique_ptr<SpvAssembler::Result> SpvAssembler::Assemble(
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
|
@ -7,19 +7,19 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_GPU_SPIRV_SPV_ASSEMBLER_H_
|
#ifndef XENIA_UI_SPIRV_SPIRV_ASSEMBLER_H_
|
||||||
#define XENIA_GPU_SPIRV_SPV_ASSEMBLER_H_
|
#define XENIA_UI_SPIRV_SPIRV_ASSEMBLER_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
#include "xenia/ui/spirv/spirv_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
class SpvAssembler {
|
class SpirvAssembler {
|
||||||
public:
|
public:
|
||||||
class Result {
|
class Result {
|
||||||
public:
|
public:
|
||||||
|
@ -46,8 +46,8 @@ class SpvAssembler {
|
||||||
spv_diagnostic diagnostic_ = nullptr;
|
spv_diagnostic diagnostic_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
SpvAssembler();
|
SpirvAssembler();
|
||||||
~SpvAssembler();
|
~SpirvAssembler();
|
||||||
|
|
||||||
// Assembles the given source text into a SPIRV binary.
|
// Assembles the given source text into a SPIRV binary.
|
||||||
// The return will be nullptr if assembly fails due to a library error.
|
// The return will be nullptr if assembly fails due to a library error.
|
||||||
|
@ -63,7 +63,7 @@ class SpvAssembler {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_GPU_SPIRV_SPV_ASSEMBLER_H_
|
#endif // XENIA_UI_SPIRV_SPIRV_ASSEMBLER_H_
|
|
@ -7,19 +7,19 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spv_disassembler.h"
|
#include "xenia/ui/spirv/spirv_disassembler.h"
|
||||||
|
|
||||||
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
#include "third_party/spirv-tools/include/libspirv/libspirv.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
SpvDisassembler::Result::Result(spv_text text, spv_diagnostic diagnostic)
|
SpirvDisassembler::Result::Result(spv_text text, spv_diagnostic diagnostic)
|
||||||
: text_(text), diagnostic_(diagnostic) {}
|
: text_(text), diagnostic_(diagnostic) {}
|
||||||
|
|
||||||
SpvDisassembler::Result::~Result() {
|
SpirvDisassembler::Result::~Result() {
|
||||||
if (text_) {
|
if (text_) {
|
||||||
spvTextDestroy(text_);
|
spvTextDestroy(text_);
|
||||||
}
|
}
|
||||||
|
@ -28,36 +28,36 @@ SpvDisassembler::Result::~Result() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpvDisassembler::Result::has_error() const { return !!diagnostic_; }
|
bool SpirvDisassembler::Result::has_error() const { return !!diagnostic_; }
|
||||||
|
|
||||||
size_t SpvDisassembler::Result::error_word_index() const {
|
size_t SpirvDisassembler::Result::error_word_index() const {
|
||||||
return diagnostic_ ? diagnostic_->position.index : 0;
|
return diagnostic_ ? diagnostic_->position.index : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SpvDisassembler::Result::error_string() const {
|
const char* SpirvDisassembler::Result::error_string() const {
|
||||||
return diagnostic_ ? diagnostic_->error : "";
|
return diagnostic_ ? diagnostic_->error : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SpvDisassembler::Result::text() const {
|
const char* SpirvDisassembler::Result::text() const {
|
||||||
return text_ ? text_->str : "";
|
return text_ ? text_->str : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SpvDisassembler::Result::to_string() const {
|
std::string SpirvDisassembler::Result::to_string() const {
|
||||||
return text_ ? std::string(text_->str, text_->length) : "";
|
return text_ ? std::string(text_->str, text_->length) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvDisassembler::Result::AppendText(StringBuffer* target_buffer) const {
|
void SpirvDisassembler::Result::AppendText(StringBuffer* target_buffer) const {
|
||||||
if (text_) {
|
if (text_) {
|
||||||
target_buffer->AppendBytes(reinterpret_cast<const uint8_t*>(text_->str),
|
target_buffer->AppendBytes(reinterpret_cast<const uint8_t*>(text_->str),
|
||||||
text_->length);
|
text_->length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvDisassembler::SpvDisassembler() : spv_context_(spvContextCreate()) {}
|
SpirvDisassembler::SpirvDisassembler() : spv_context_(spvContextCreate()) {}
|
||||||
|
|
||||||
SpvDisassembler::~SpvDisassembler() { spvContextDestroy(spv_context_); }
|
SpirvDisassembler::~SpirvDisassembler() { spvContextDestroy(spv_context_); }
|
||||||
|
|
||||||
std::unique_ptr<SpvDisassembler::Result> SpvDisassembler::Disassemble(
|
std::unique_ptr<SpirvDisassembler::Result> SpirvDisassembler::Disassemble(
|
||||||
const uint32_t* words, size_t word_count) {
|
const uint32_t* words, size_t word_count) {
|
||||||
spv_text text = nullptr;
|
spv_text text = nullptr;
|
||||||
spv_diagnostic diagnostic = nullptr;
|
spv_diagnostic diagnostic = nullptr;
|
||||||
|
@ -77,5 +77,5 @@ std::unique_ptr<SpvDisassembler::Result> SpvDisassembler::Disassemble(
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
|
@ -7,20 +7,20 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_GPU_SPIRV_SPV_DISASSEMBLER_H_
|
#ifndef XENIA_UI_SPIRV_SPIRV_DISASSEMBLER_H_
|
||||||
#define XENIA_GPU_SPIRV_SPV_DISASSEMBLER_H_
|
#define XENIA_UI_SPIRV_SPIRV_DISASSEMBLER_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xenia/base/string_buffer.h"
|
#include "xenia/base/string_buffer.h"
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
#include "xenia/ui/spirv/spirv_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
class SpvDisassembler {
|
class SpirvDisassembler {
|
||||||
public:
|
public:
|
||||||
class Result {
|
class Result {
|
||||||
public:
|
public:
|
||||||
|
@ -47,8 +47,8 @@ class SpvDisassembler {
|
||||||
spv_diagnostic diagnostic_ = nullptr;
|
spv_diagnostic diagnostic_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
SpvDisassembler();
|
SpirvDisassembler();
|
||||||
~SpvDisassembler();
|
~SpirvDisassembler();
|
||||||
|
|
||||||
// Disassembles the given SPIRV binary.
|
// Disassembles the given SPIRV binary.
|
||||||
// The return will be nullptr if disassembly fails due to a library error.
|
// The return will be nullptr if disassembly fails due to a library error.
|
||||||
|
@ -60,7 +60,7 @@ class SpvDisassembler {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_GPU_SPIRV_SPV_DISASSEMBLER_H_
|
#endif // XENIA_UI_SPIRV_SPIRV_DISASSEMBLER_H_
|
|
@ -43,7 +43,7 @@
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spv_emitter.h"
|
#include "xenia/ui/spirv/spirv_emitter.h"
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
@ -51,14 +51,14 @@
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
SpvEmitter::SpvEmitter() { ClearAccessChain(); }
|
SpirvEmitter::SpirvEmitter() { ClearAccessChain(); }
|
||||||
|
|
||||||
SpvEmitter::~SpvEmitter() = default;
|
SpirvEmitter::~SpirvEmitter() = default;
|
||||||
|
|
||||||
Id SpvEmitter::ImportExtendedInstructions(const char* name) {
|
Id SpirvEmitter::ImportExtendedInstructions(const char* name) {
|
||||||
auto import =
|
auto import =
|
||||||
new Instruction(AllocateUniqueId(), NoType, Op::OpExtInstImport);
|
new Instruction(AllocateUniqueId(), NoType, Op::OpExtInstImport);
|
||||||
import->AddStringOperand(name);
|
import->AddStringOperand(name);
|
||||||
|
@ -69,7 +69,7 @@ Id SpvEmitter::ImportExtendedInstructions(const char* name) {
|
||||||
|
|
||||||
// For creating new grouped_types_ (will return old type if the requested one
|
// For creating new grouped_types_ (will return old type if the requested one
|
||||||
// was already made).
|
// was already made).
|
||||||
Id SpvEmitter::MakeVoidType() {
|
Id SpirvEmitter::MakeVoidType() {
|
||||||
Instruction* type;
|
Instruction* type;
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeVoid)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeVoid)];
|
||||||
if (grouped_type.empty()) {
|
if (grouped_type.empty()) {
|
||||||
|
@ -84,7 +84,7 @@ Id SpvEmitter::MakeVoidType() {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeBoolType() {
|
Id SpirvEmitter::MakeBoolType() {
|
||||||
Instruction* type;
|
Instruction* type;
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeBool)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeBool)];
|
||||||
if (grouped_type.empty()) {
|
if (grouped_type.empty()) {
|
||||||
|
@ -99,7 +99,7 @@ Id SpvEmitter::MakeBoolType() {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeSamplerType() {
|
Id SpirvEmitter::MakeSamplerType() {
|
||||||
Instruction* type;
|
Instruction* type;
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeSampler)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeSampler)];
|
||||||
if (grouped_type.empty()) {
|
if (grouped_type.empty()) {
|
||||||
|
@ -113,7 +113,7 @@ Id SpvEmitter::MakeSamplerType() {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakePointer(spv::StorageClass storage_class, Id pointee) {
|
Id SpirvEmitter::MakePointer(spv::StorageClass storage_class, Id pointee) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypePointer)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypePointer)];
|
||||||
for (auto& type : grouped_type) {
|
for (auto& type : grouped_type) {
|
||||||
|
@ -134,7 +134,7 @@ Id SpvEmitter::MakePointer(spv::StorageClass storage_class, Id pointee) {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeIntegerType(int bit_width, bool is_signed) {
|
Id SpirvEmitter::MakeIntegerType(int bit_width, bool is_signed) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeInt)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeInt)];
|
||||||
for (auto& type : grouped_type) {
|
for (auto& type : grouped_type) {
|
||||||
|
@ -155,7 +155,7 @@ Id SpvEmitter::MakeIntegerType(int bit_width, bool is_signed) {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeFloatType(int bit_width) {
|
Id SpirvEmitter::MakeFloatType(int bit_width) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeFloat)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeFloat)];
|
||||||
for (auto& type : grouped_type) {
|
for (auto& type : grouped_type) {
|
||||||
|
@ -178,7 +178,7 @@ Id SpvEmitter::MakeFloatType(int bit_width) {
|
||||||
// See makeStructResultType() for non-decorated structs
|
// See makeStructResultType() for non-decorated structs
|
||||||
// needed as the result of some instructions, which does
|
// needed as the result of some instructions, which does
|
||||||
// check for duplicates.
|
// check for duplicates.
|
||||||
Id SpvEmitter::MakeStructType(std::initializer_list<Id> members,
|
Id SpirvEmitter::MakeStructType(std::initializer_list<Id> members,
|
||||||
const char* name) {
|
const char* name) {
|
||||||
// Don't look for previous one, because in the general case,
|
// Don't look for previous one, because in the general case,
|
||||||
// structs can be duplicated except for decorations.
|
// structs can be duplicated except for decorations.
|
||||||
|
@ -198,7 +198,7 @@ Id SpvEmitter::MakeStructType(std::initializer_list<Id> members,
|
||||||
|
|
||||||
// Make a struct for the simple results of several instructions,
|
// Make a struct for the simple results of several instructions,
|
||||||
// checking for duplication.
|
// checking for duplication.
|
||||||
Id SpvEmitter::MakePairStructType(Id type0, Id type1) {
|
Id SpirvEmitter::MakePairStructType(Id type0, Id type1) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeStruct)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeStruct)];
|
||||||
for (auto& type : grouped_type) {
|
for (auto& type : grouped_type) {
|
||||||
|
@ -215,7 +215,7 @@ Id SpvEmitter::MakePairStructType(Id type0, Id type1) {
|
||||||
return MakeStructType({type0, type1}, "ResType");
|
return MakeStructType({type0, type1}, "ResType");
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeVectorType(Id component_type, int component_count) {
|
Id SpirvEmitter::MakeVectorType(Id component_type, int component_count) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeVector)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeVector)];
|
||||||
for (auto& type : grouped_type) {
|
for (auto& type : grouped_type) {
|
||||||
|
@ -236,7 +236,7 @@ Id SpvEmitter::MakeVectorType(Id component_type, int component_count) {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeMatrix2DType(Id component_type, int cols, int rows) {
|
Id SpirvEmitter::MakeMatrix2DType(Id component_type, int cols, int rows) {
|
||||||
assert(cols <= kMaxMatrixSize && rows <= kMaxMatrixSize);
|
assert(cols <= kMaxMatrixSize && rows <= kMaxMatrixSize);
|
||||||
|
|
||||||
Id column = MakeVectorType(component_type, rows);
|
Id column = MakeVectorType(component_type, rows);
|
||||||
|
@ -261,7 +261,7 @@ Id SpvEmitter::MakeMatrix2DType(Id component_type, int cols, int rows) {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeArrayType(Id element_type, int length) {
|
Id SpirvEmitter::MakeArrayType(Id element_type, int length) {
|
||||||
// First, we need a constant instruction for the size
|
// First, we need a constant instruction for the size
|
||||||
Id length_id = MakeUintConstant(length);
|
Id length_id = MakeUintConstant(length);
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ Id SpvEmitter::MakeArrayType(Id element_type, int length) {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeRuntimeArray(Id element_type) {
|
Id SpirvEmitter::MakeRuntimeArray(Id element_type) {
|
||||||
auto type =
|
auto type =
|
||||||
new Instruction(AllocateUniqueId(), NoType, Op::OpTypeRuntimeArray);
|
new Instruction(AllocateUniqueId(), NoType, Op::OpTypeRuntimeArray);
|
||||||
type->AddIdOperand(element_type);
|
type->AddIdOperand(element_type);
|
||||||
|
@ -295,7 +295,7 @@ Id SpvEmitter::MakeRuntimeArray(Id element_type) {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeFunctionType(Id return_type,
|
Id SpirvEmitter::MakeFunctionType(Id return_type,
|
||||||
std::initializer_list<Id> param_types) {
|
std::initializer_list<Id> param_types) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeFunction)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeFunction)];
|
||||||
|
@ -326,9 +326,9 @@ Id SpvEmitter::MakeFunctionType(Id return_type,
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeImageType(Id sampled_type, spv::Dim dim, bool has_depth,
|
Id SpirvEmitter::MakeImageType(Id sampled_type, spv::Dim dim, bool has_depth,
|
||||||
bool is_arrayed, bool is_multisampled, int sampled,
|
bool is_arrayed, bool is_multisampled,
|
||||||
spv::ImageFormat format) {
|
int sampled, spv::ImageFormat format) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeImage)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeImage)];
|
||||||
for (auto& type : grouped_type) {
|
for (auto& type : grouped_type) {
|
||||||
|
@ -360,7 +360,7 @@ Id SpvEmitter::MakeImageType(Id sampled_type, spv::Dim dim, bool has_depth,
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeSampledImageType(Id image_type) {
|
Id SpirvEmitter::MakeSampledImageType(Id image_type) {
|
||||||
// try to find it
|
// try to find it
|
||||||
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeSampledImage)];
|
auto& grouped_type = grouped_types_[static_cast<int>(Op::OpTypeSampledImage)];
|
||||||
for (auto& type : grouped_type) {
|
for (auto& type : grouped_type) {
|
||||||
|
@ -381,13 +381,13 @@ Id SpvEmitter::MakeSampledImageType(Id image_type) {
|
||||||
return type->result_id();
|
return type->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::GetDerefTypeId(Id result_id) const {
|
Id SpirvEmitter::GetDerefTypeId(Id result_id) const {
|
||||||
Id type_id = GetTypeId(result_id);
|
Id type_id = GetTypeId(result_id);
|
||||||
assert(IsPointerType(type_id));
|
assert(IsPointerType(type_id));
|
||||||
return module_.instruction(type_id)->immediate_operand(1);
|
return module_.instruction(type_id)->immediate_operand(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Op SpvEmitter::GetMostBasicTypeClass(Id type_id) const {
|
Op SpirvEmitter::GetMostBasicTypeClass(Id type_id) const {
|
||||||
auto instr = module_.instruction(type_id);
|
auto instr = module_.instruction(type_id);
|
||||||
|
|
||||||
Op type_class = instr->opcode();
|
Op type_class = instr->opcode();
|
||||||
|
@ -411,7 +411,7 @@ Op SpvEmitter::GetMostBasicTypeClass(Id type_id) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SpvEmitter::GetTypeComponentCount(Id type_id) const {
|
int SpirvEmitter::GetTypeComponentCount(Id type_id) const {
|
||||||
auto instr = module_.instruction(type_id);
|
auto instr = module_.instruction(type_id);
|
||||||
|
|
||||||
switch (instr->opcode()) {
|
switch (instr->opcode()) {
|
||||||
|
@ -434,7 +434,7 @@ int SpvEmitter::GetTypeComponentCount(Id type_id) const {
|
||||||
// floats.
|
// floats.
|
||||||
// However, it includes returning a structure, if say, it is an array of
|
// However, it includes returning a structure, if say, it is an array of
|
||||||
// structure.
|
// structure.
|
||||||
Id SpvEmitter::GetScalarTypeId(Id type_id) const {
|
Id SpirvEmitter::GetScalarTypeId(Id type_id) const {
|
||||||
auto instr = module_.instruction(type_id);
|
auto instr = module_.instruction(type_id);
|
||||||
|
|
||||||
Op type_class = instr->opcode();
|
Op type_class = instr->opcode();
|
||||||
|
@ -458,7 +458,7 @@ Id SpvEmitter::GetScalarTypeId(Id type_id) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the type of 'member' of a composite.
|
// Return the type of 'member' of a composite.
|
||||||
Id SpvEmitter::GetContainedTypeId(Id type_id, int member) const {
|
Id SpirvEmitter::GetContainedTypeId(Id type_id, int member) const {
|
||||||
auto instr = module_.instruction(type_id);
|
auto instr = module_.instruction(type_id);
|
||||||
|
|
||||||
Op type_class = instr->opcode();
|
Op type_class = instr->opcode();
|
||||||
|
@ -479,13 +479,13 @@ Id SpvEmitter::GetContainedTypeId(Id type_id, int member) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the immediately contained type of a given composite type.
|
// Return the immediately contained type of a given composite type.
|
||||||
Id SpvEmitter::GetContainedTypeId(Id type_id) const {
|
Id SpirvEmitter::GetContainedTypeId(Id type_id) const {
|
||||||
return GetContainedTypeId(type_id, 0);
|
return GetContainedTypeId(type_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if a scalar constant of this type has already been created, so it
|
// See if a scalar constant of this type has already been created, so it
|
||||||
// can be reused rather than duplicated. (Required by the specification).
|
// can be reused rather than duplicated. (Required by the specification).
|
||||||
Id SpvEmitter::FindScalarConstant(Op type_class, Op opcode, Id type_id,
|
Id SpirvEmitter::FindScalarConstant(Op type_class, Op opcode, Id type_id,
|
||||||
uint32_t value) const {
|
uint32_t value) const {
|
||||||
auto& grouped_constant = grouped_constants_[static_cast<int>(type_class)];
|
auto& grouped_constant = grouped_constants_[static_cast<int>(type_class)];
|
||||||
for (auto constant : grouped_constant) {
|
for (auto constant : grouped_constant) {
|
||||||
|
@ -499,7 +499,7 @@ Id SpvEmitter::FindScalarConstant(Op type_class, Op opcode, Id type_id,
|
||||||
|
|
||||||
// Version of findScalarConstant (see above) for scalars that take two operands
|
// Version of findScalarConstant (see above) for scalars that take two operands
|
||||||
// (e.g. a 'double').
|
// (e.g. a 'double').
|
||||||
Id SpvEmitter::FindScalarConstant(Op type_class, Op opcode, Id type_id,
|
Id SpirvEmitter::FindScalarConstant(Op type_class, Op opcode, Id type_id,
|
||||||
uint32_t v1, uint32_t v2) const {
|
uint32_t v1, uint32_t v2) const {
|
||||||
auto& grouped_constant = grouped_constants_[static_cast<int>(type_class)];
|
auto& grouped_constant = grouped_constants_[static_cast<int>(type_class)];
|
||||||
for (auto constant : grouped_constant) {
|
for (auto constant : grouped_constant) {
|
||||||
|
@ -515,7 +515,7 @@ Id SpvEmitter::FindScalarConstant(Op type_class, Op opcode, Id type_id,
|
||||||
// Return true if consuming 'opcode' means consuming a constant.
|
// Return true if consuming 'opcode' means consuming a constant.
|
||||||
// "constant" here means after final transform to executable code,
|
// "constant" here means after final transform to executable code,
|
||||||
// the value consumed will be a constant, so includes specialization.
|
// the value consumed will be a constant, so includes specialization.
|
||||||
bool SpvEmitter::IsConstantOpCode(Op opcode) const {
|
bool SpirvEmitter::IsConstantOpCode(Op opcode) const {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Op::OpUndef:
|
case Op::OpUndef:
|
||||||
case Op::OpConstantTrue:
|
case Op::OpConstantTrue:
|
||||||
|
@ -535,7 +535,7 @@ bool SpvEmitter::IsConstantOpCode(Op opcode) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeBoolConstant(bool value, bool is_spec_constant) {
|
Id SpirvEmitter::MakeBoolConstant(bool value, bool is_spec_constant) {
|
||||||
Id type_id = MakeBoolType();
|
Id type_id = MakeBoolType();
|
||||||
Op opcode = is_spec_constant
|
Op opcode = is_spec_constant
|
||||||
? (value ? Op::OpSpecConstantTrue : Op::OpSpecConstantFalse)
|
? (value ? Op::OpSpecConstantTrue : Op::OpSpecConstantFalse)
|
||||||
|
@ -559,7 +559,7 @@ Id SpvEmitter::MakeBoolConstant(bool value, bool is_spec_constant) {
|
||||||
return c->result_id();
|
return c->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeIntegerConstant(Id type_id, uint32_t value,
|
Id SpirvEmitter::MakeIntegerConstant(Id type_id, uint32_t value,
|
||||||
bool is_spec_constant) {
|
bool is_spec_constant) {
|
||||||
Op opcode = is_spec_constant ? Op::OpSpecConstant : Op::OpConstant;
|
Op opcode = is_spec_constant ? Op::OpSpecConstant : Op::OpConstant;
|
||||||
Id existing = FindScalarConstant(Op::OpTypeInt, opcode, type_id, value);
|
Id existing = FindScalarConstant(Op::OpTypeInt, opcode, type_id, value);
|
||||||
|
@ -576,7 +576,7 @@ Id SpvEmitter::MakeIntegerConstant(Id type_id, uint32_t value,
|
||||||
return c->result_id();
|
return c->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeFloatConstant(float value, bool is_spec_constant) {
|
Id SpirvEmitter::MakeFloatConstant(float value, bool is_spec_constant) {
|
||||||
Op opcode = is_spec_constant ? Op::OpSpecConstant : Op::OpConstant;
|
Op opcode = is_spec_constant ? Op::OpSpecConstant : Op::OpConstant;
|
||||||
Id type_id = MakeFloatType(32);
|
Id type_id = MakeFloatType(32);
|
||||||
uint32_t uint32_value = *reinterpret_cast<uint32_t*>(&value);
|
uint32_t uint32_value = *reinterpret_cast<uint32_t*>(&value);
|
||||||
|
@ -595,7 +595,7 @@ Id SpvEmitter::MakeFloatConstant(float value, bool is_spec_constant) {
|
||||||
return c->result_id();
|
return c->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeDoubleConstant(double value, bool is_spec_constant) {
|
Id SpirvEmitter::MakeDoubleConstant(double value, bool is_spec_constant) {
|
||||||
Op opcode = is_spec_constant ? Op::OpSpecConstant : Op::OpConstant;
|
Op opcode = is_spec_constant ? Op::OpSpecConstant : Op::OpConstant;
|
||||||
Id type_id = MakeFloatType(64);
|
Id type_id = MakeFloatType(64);
|
||||||
uint64_t uint64_value = *reinterpret_cast<uint64_t*>(&value);
|
uint64_t uint64_value = *reinterpret_cast<uint64_t*>(&value);
|
||||||
|
@ -616,7 +616,7 @@ Id SpvEmitter::MakeDoubleConstant(double value, bool is_spec_constant) {
|
||||||
return c->result_id();
|
return c->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::FindCompositeConstant(
|
Id SpirvEmitter::FindCompositeConstant(
|
||||||
Op type_class, std::initializer_list<Id> components) const {
|
Op type_class, std::initializer_list<Id> components) const {
|
||||||
auto& grouped_constant = grouped_constants_[static_cast<int>(type_class)];
|
auto& grouped_constant = grouped_constants_[static_cast<int>(type_class)];
|
||||||
for (auto& constant : grouped_constant) {
|
for (auto& constant : grouped_constant) {
|
||||||
|
@ -641,7 +641,7 @@ Id SpvEmitter::FindCompositeConstant(
|
||||||
return NoResult;
|
return NoResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::MakeCompositeConstant(Id type_id,
|
Id SpirvEmitter::MakeCompositeConstant(Id type_id,
|
||||||
std::initializer_list<Id> components) {
|
std::initializer_list<Id> components) {
|
||||||
assert(type_id);
|
assert(type_id);
|
||||||
Op type_class = GetTypeClass(type_id);
|
Op type_class = GetTypeClass(type_id);
|
||||||
|
@ -672,7 +672,7 @@ Id SpvEmitter::MakeCompositeConstant(Id type_id,
|
||||||
return c->result_id();
|
return c->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction* SpvEmitter::AddEntryPoint(spv::ExecutionModel execution_model,
|
Instruction* SpirvEmitter::AddEntryPoint(spv::ExecutionModel execution_model,
|
||||||
Function* entry_point,
|
Function* entry_point,
|
||||||
const char* name) {
|
const char* name) {
|
||||||
auto instr = new Instruction(Op::OpEntryPoint);
|
auto instr = new Instruction(Op::OpEntryPoint);
|
||||||
|
@ -687,9 +687,9 @@ Instruction* SpvEmitter::AddEntryPoint(spv::ExecutionModel execution_model,
|
||||||
|
|
||||||
// Currently relying on the fact that all 'value' of interest are small
|
// Currently relying on the fact that all 'value' of interest are small
|
||||||
// non-negative values.
|
// non-negative values.
|
||||||
void SpvEmitter::AddExecutionMode(Function* entry_point,
|
void SpirvEmitter::AddExecutionMode(Function* entry_point,
|
||||||
spv::ExecutionMode execution_mode, int value1,
|
spv::ExecutionMode execution_mode,
|
||||||
int value2, int value3) {
|
int value1, int value2, int value3) {
|
||||||
auto instr = new Instruction(Op::OpExecutionMode);
|
auto instr = new Instruction(Op::OpExecutionMode);
|
||||||
instr->AddIdOperand(entry_point->id());
|
instr->AddIdOperand(entry_point->id());
|
||||||
instr->AddImmediateOperand(execution_mode);
|
instr->AddImmediateOperand(execution_mode);
|
||||||
|
@ -706,7 +706,7 @@ void SpvEmitter::AddExecutionMode(Function* entry_point,
|
||||||
execution_modes_.push_back(instr);
|
execution_modes_.push_back(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::AddName(Id target_id, const char* value) {
|
void SpirvEmitter::AddName(Id target_id, const char* value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -717,7 +717,7 @@ void SpvEmitter::AddName(Id target_id, const char* value) {
|
||||||
names_.push_back(instr);
|
names_.push_back(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::AddMemberName(Id target_id, int member, const char* value) {
|
void SpirvEmitter::AddMemberName(Id target_id, int member, const char* value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -729,7 +729,7 @@ void SpvEmitter::AddMemberName(Id target_id, int member, const char* value) {
|
||||||
names_.push_back(instr);
|
names_.push_back(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::AddLine(Id target_id, Id file_name, int line_number,
|
void SpirvEmitter::AddLine(Id target_id, Id file_name, int line_number,
|
||||||
int column_number) {
|
int column_number) {
|
||||||
auto instr = new Instruction(Op::OpLine);
|
auto instr = new Instruction(Op::OpLine);
|
||||||
instr->AddIdOperand(target_id);
|
instr->AddIdOperand(target_id);
|
||||||
|
@ -740,7 +740,7 @@ void SpvEmitter::AddLine(Id target_id, Id file_name, int line_number,
|
||||||
lines_.push_back(instr);
|
lines_.push_back(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::AddDecoration(Id target_id, spv::Decoration decoration,
|
void SpirvEmitter::AddDecoration(Id target_id, spv::Decoration decoration,
|
||||||
int num) {
|
int num) {
|
||||||
if (decoration == static_cast<spv::Decoration>(BadValue)) {
|
if (decoration == static_cast<spv::Decoration>(BadValue)) {
|
||||||
return;
|
return;
|
||||||
|
@ -755,7 +755,7 @@ void SpvEmitter::AddDecoration(Id target_id, spv::Decoration decoration,
|
||||||
decorations_.push_back(instr);
|
decorations_.push_back(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::AddMemberDecoration(Id target_id, int member,
|
void SpirvEmitter::AddMemberDecoration(Id target_id, int member,
|
||||||
spv::Decoration decoration, int num) {
|
spv::Decoration decoration, int num) {
|
||||||
auto instr = new Instruction(Op::OpMemberDecorate);
|
auto instr = new Instruction(Op::OpMemberDecorate);
|
||||||
instr->AddIdOperand(target_id);
|
instr->AddIdOperand(target_id);
|
||||||
|
@ -768,14 +768,14 @@ void SpvEmitter::AddMemberDecoration(Id target_id, int member,
|
||||||
decorations_.push_back(instr);
|
decorations_.push_back(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Function* SpvEmitter::MakeMainEntry() {
|
Function* SpirvEmitter::MakeMainEntry() {
|
||||||
assert(!main_function_);
|
assert(!main_function_);
|
||||||
Block* entry = nullptr;
|
Block* entry = nullptr;
|
||||||
main_function_ = MakeFunctionEntry(MakeVoidType(), "main", {}, &entry);
|
main_function_ = MakeFunctionEntry(MakeVoidType(), "main", {}, &entry);
|
||||||
return main_function_;
|
return main_function_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Function* SpvEmitter::MakeFunctionEntry(Id return_type, const char* name,
|
Function* SpirvEmitter::MakeFunctionEntry(Id return_type, const char* name,
|
||||||
std::initializer_list<Id> param_types,
|
std::initializer_list<Id> param_types,
|
||||||
Block** entry) {
|
Block** entry) {
|
||||||
Id type_id = MakeFunctionType(return_type, param_types);
|
Id type_id = MakeFunctionType(return_type, param_types);
|
||||||
|
@ -792,7 +792,7 @@ Function* SpvEmitter::MakeFunctionEntry(Id return_type, const char* name,
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::MakeReturn(bool implicit, Id return_value) {
|
void SpirvEmitter::MakeReturn(bool implicit, Id return_value) {
|
||||||
if (return_value) {
|
if (return_value) {
|
||||||
auto inst = new Instruction(NoResult, NoType, Op::OpReturnValue);
|
auto inst = new Instruction(NoResult, NoType, Op::OpReturnValue);
|
||||||
inst->AddIdOperand(return_value);
|
inst->AddIdOperand(return_value);
|
||||||
|
@ -807,7 +807,7 @@ void SpvEmitter::MakeReturn(bool implicit, Id return_value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::LeaveFunction() {
|
void SpirvEmitter::LeaveFunction() {
|
||||||
Block* block = build_point_;
|
Block* block = build_point_;
|
||||||
Function& function = build_point_->parent();
|
Function& function = build_point_->parent();
|
||||||
assert(block);
|
assert(block);
|
||||||
|
@ -836,12 +836,12 @@ void SpvEmitter::LeaveFunction() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::MakeDiscard() {
|
void SpirvEmitter::MakeDiscard() {
|
||||||
build_point_->AddInstruction(new Instruction(Op::OpKill));
|
build_point_->AddInstruction(new Instruction(Op::OpKill));
|
||||||
CreateAndSetNoPredecessorBlock("post-discard");
|
CreateAndSetNoPredecessorBlock("post-discard");
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateVariable(spv::StorageClass storage_class, Id type,
|
Id SpirvEmitter::CreateVariable(spv::StorageClass storage_class, Id type,
|
||||||
const char* name) {
|
const char* name) {
|
||||||
Id pointer_type = MakePointer(storage_class, type);
|
Id pointer_type = MakePointer(storage_class, type);
|
||||||
auto instr =
|
auto instr =
|
||||||
|
@ -864,20 +864,20 @@ Id SpvEmitter::CreateVariable(spv::StorageClass storage_class, Id type,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateUndefined(Id type) {
|
Id SpirvEmitter::CreateUndefined(Id type) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), type, Op::OpUndef);
|
auto instr = new Instruction(AllocateUniqueId(), type, Op::OpUndef);
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateStore(Id pointer_id, Id value_id) {
|
void SpirvEmitter::CreateStore(Id pointer_id, Id value_id) {
|
||||||
auto instr = new Instruction(Op::OpStore);
|
auto instr = new Instruction(Op::OpStore);
|
||||||
instr->AddIdOperand(pointer_id);
|
instr->AddIdOperand(pointer_id);
|
||||||
instr->AddIdOperand(value_id);
|
instr->AddIdOperand(value_id);
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateLoad(Id pointer_id) {
|
Id SpirvEmitter::CreateLoad(Id pointer_id) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), GetDerefTypeId(pointer_id),
|
auto instr = new Instruction(AllocateUniqueId(), GetDerefTypeId(pointer_id),
|
||||||
Op::OpLoad);
|
Op::OpLoad);
|
||||||
instr->AddIdOperand(pointer_id);
|
instr->AddIdOperand(pointer_id);
|
||||||
|
@ -886,7 +886,7 @@ Id SpvEmitter::CreateLoad(Id pointer_id) {
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateAccessChain(spv::StorageClass storage_class, Id base_id,
|
Id SpirvEmitter::CreateAccessChain(spv::StorageClass storage_class, Id base_id,
|
||||||
std::vector<Id> index_ids) {
|
std::vector<Id> index_ids) {
|
||||||
// Figure out the final resulting type.
|
// Figure out the final resulting type.
|
||||||
auto base_type_id = GetTypeId(base_id);
|
auto base_type_id = GetTypeId(base_id);
|
||||||
|
@ -912,7 +912,7 @@ Id SpvEmitter::CreateAccessChain(spv::StorageClass storage_class, Id base_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateArrayLength(Id struct_id, int array_member) {
|
Id SpirvEmitter::CreateArrayLength(Id struct_id, int array_member) {
|
||||||
auto instr =
|
auto instr =
|
||||||
new Instruction(AllocateUniqueId(), MakeIntType(32), Op::OpArrayLength);
|
new Instruction(AllocateUniqueId(), MakeIntType(32), Op::OpArrayLength);
|
||||||
instr->AddIdOperand(struct_id);
|
instr->AddIdOperand(struct_id);
|
||||||
|
@ -922,7 +922,7 @@ Id SpvEmitter::CreateArrayLength(Id struct_id, int array_member) {
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateCompositeExtract(Id composite, Id type_id,
|
Id SpirvEmitter::CreateCompositeExtract(Id composite, Id type_id,
|
||||||
uint32_t index) {
|
uint32_t index) {
|
||||||
auto instr =
|
auto instr =
|
||||||
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeExtract);
|
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeExtract);
|
||||||
|
@ -933,7 +933,7 @@ Id SpvEmitter::CreateCompositeExtract(Id composite, Id type_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateCompositeExtract(Id composite, Id type_id,
|
Id SpirvEmitter::CreateCompositeExtract(Id composite, Id type_id,
|
||||||
std::vector<uint32_t> indices) {
|
std::vector<uint32_t> indices) {
|
||||||
auto instr =
|
auto instr =
|
||||||
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeExtract);
|
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeExtract);
|
||||||
|
@ -944,7 +944,7 @@ Id SpvEmitter::CreateCompositeExtract(Id composite, Id type_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateCompositeInsert(Id object, Id composite, Id type_id,
|
Id SpirvEmitter::CreateCompositeInsert(Id object, Id composite, Id type_id,
|
||||||
uint32_t index) {
|
uint32_t index) {
|
||||||
auto instr =
|
auto instr =
|
||||||
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeInsert);
|
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeInsert);
|
||||||
|
@ -956,7 +956,7 @@ Id SpvEmitter::CreateCompositeInsert(Id object, Id composite, Id type_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateCompositeInsert(Id object, Id composite, Id type_id,
|
Id SpirvEmitter::CreateCompositeInsert(Id object, Id composite, Id type_id,
|
||||||
std::vector<uint32_t> indices) {
|
std::vector<uint32_t> indices) {
|
||||||
auto instr =
|
auto instr =
|
||||||
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeInsert);
|
new Instruction(AllocateUniqueId(), type_id, Op::OpCompositeInsert);
|
||||||
|
@ -968,7 +968,7 @@ Id SpvEmitter::CreateCompositeInsert(Id object, Id composite, Id type_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateVectorExtractDynamic(Id vector, Id type_id,
|
Id SpirvEmitter::CreateVectorExtractDynamic(Id vector, Id type_id,
|
||||||
Id component_index) {
|
Id component_index) {
|
||||||
auto instr =
|
auto instr =
|
||||||
new Instruction(AllocateUniqueId(), type_id, Op::OpVectorExtractDynamic);
|
new Instruction(AllocateUniqueId(), type_id, Op::OpVectorExtractDynamic);
|
||||||
|
@ -979,7 +979,7 @@ Id SpvEmitter::CreateVectorExtractDynamic(Id vector, Id type_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateVectorInsertDynamic(Id vector, Id type_id, Id component,
|
Id SpirvEmitter::CreateVectorInsertDynamic(Id vector, Id type_id, Id component,
|
||||||
Id component_index) {
|
Id component_index) {
|
||||||
auto instr =
|
auto instr =
|
||||||
new Instruction(AllocateUniqueId(), type_id, Op::OpVectorInsertDynamic);
|
new Instruction(AllocateUniqueId(), type_id, Op::OpVectorInsertDynamic);
|
||||||
|
@ -991,12 +991,12 @@ Id SpvEmitter::CreateVectorInsertDynamic(Id vector, Id type_id, Id component,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateNop() {
|
void SpirvEmitter::CreateNop() {
|
||||||
auto instr = new Instruction(spv::Op::OpNop);
|
auto instr = new Instruction(spv::Op::OpNop);
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateControlBarrier(
|
void SpirvEmitter::CreateControlBarrier(
|
||||||
spv::Scope execution_scope, spv::Scope memory_scope,
|
spv::Scope execution_scope, spv::Scope memory_scope,
|
||||||
spv::MemorySemanticsMask memory_semantics) {
|
spv::MemorySemanticsMask memory_semantics) {
|
||||||
auto instr = new Instruction(Op::OpControlBarrier);
|
auto instr = new Instruction(Op::OpControlBarrier);
|
||||||
|
@ -1006,7 +1006,7 @@ void SpvEmitter::CreateControlBarrier(
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateMemoryBarrier(
|
void SpirvEmitter::CreateMemoryBarrier(
|
||||||
spv::Scope execution_scope, spv::MemorySemanticsMask memory_semantics) {
|
spv::Scope execution_scope, spv::MemorySemanticsMask memory_semantics) {
|
||||||
auto instr = new Instruction(Op::OpMemoryBarrier);
|
auto instr = new Instruction(Op::OpMemoryBarrier);
|
||||||
instr->AddImmediateOperand(MakeUintConstant(execution_scope));
|
instr->AddImmediateOperand(MakeUintConstant(execution_scope));
|
||||||
|
@ -1014,7 +1014,7 @@ void SpvEmitter::CreateMemoryBarrier(
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateUnaryOp(Op opcode, Id type_id, Id operand) {
|
Id SpirvEmitter::CreateUnaryOp(Op opcode, Id type_id, Id operand) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
||||||
instr->AddIdOperand(operand);
|
instr->AddIdOperand(operand);
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
|
@ -1022,7 +1022,7 @@ Id SpvEmitter::CreateUnaryOp(Op opcode, Id type_id, Id operand) {
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateBinOp(Op opcode, Id type_id, Id left, Id right) {
|
Id SpirvEmitter::CreateBinOp(Op opcode, Id type_id, Id left, Id right) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
||||||
instr->AddIdOperand(left);
|
instr->AddIdOperand(left);
|
||||||
instr->AddIdOperand(right);
|
instr->AddIdOperand(right);
|
||||||
|
@ -1031,7 +1031,7 @@ Id SpvEmitter::CreateBinOp(Op opcode, Id type_id, Id left, Id right) {
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateTriOp(Op opcode, Id type_id, Id op1, Id op2, Id op3) {
|
Id SpirvEmitter::CreateTriOp(Op opcode, Id type_id, Id op1, Id op2, Id op3) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
||||||
instr->AddIdOperand(op1);
|
instr->AddIdOperand(op1);
|
||||||
instr->AddIdOperand(op2);
|
instr->AddIdOperand(op2);
|
||||||
|
@ -1041,7 +1041,7 @@ Id SpvEmitter::CreateTriOp(Op opcode, Id type_id, Id op1, Id op2, Id op3) {
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateOp(Op opcode, Id type_id,
|
Id SpirvEmitter::CreateOp(Op opcode, Id type_id,
|
||||||
const std::vector<Id>& operands) {
|
const std::vector<Id>& operands) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
auto instr = new Instruction(AllocateUniqueId(), type_id, opcode);
|
||||||
instr->AddIdOperands(operands);
|
instr->AddIdOperands(operands);
|
||||||
|
@ -1050,7 +1050,7 @@ Id SpvEmitter::CreateOp(Op opcode, Id type_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateFunctionCall(Function* function,
|
Id SpirvEmitter::CreateFunctionCall(Function* function,
|
||||||
std::vector<spv::Id> args) {
|
std::vector<spv::Id> args) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), function->return_type(),
|
auto instr = new Instruction(AllocateUniqueId(), function->return_type(),
|
||||||
Op::OpFunctionCall);
|
Op::OpFunctionCall);
|
||||||
|
@ -1061,7 +1061,7 @@ Id SpvEmitter::CreateFunctionCall(Function* function,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateSwizzle(Id type_id, Id source,
|
Id SpirvEmitter::CreateSwizzle(Id type_id, Id source,
|
||||||
std::vector<uint32_t> channels) {
|
std::vector<uint32_t> channels) {
|
||||||
if (channels.size() == 1) {
|
if (channels.size() == 1) {
|
||||||
return CreateCompositeExtract(source, type_id, channels.front());
|
return CreateCompositeExtract(source, type_id, channels.front());
|
||||||
|
@ -1077,7 +1077,7 @@ Id SpvEmitter::CreateSwizzle(Id type_id, Id source,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateLvalueSwizzle(Id type_id, Id target, Id source,
|
Id SpirvEmitter::CreateLvalueSwizzle(Id type_id, Id target, Id source,
|
||||||
std::vector<uint32_t> channels) {
|
std::vector<uint32_t> channels) {
|
||||||
assert(GetComponentCount(source) == channels.size());
|
assert(GetComponentCount(source) == channels.size());
|
||||||
if (channels.size() == 1 && GetComponentCount(source) == 1) {
|
if (channels.size() == 1 && GetComponentCount(source) == 1) {
|
||||||
|
@ -1109,7 +1109,8 @@ Id SpvEmitter::CreateLvalueSwizzle(Id type_id, Id target, Id source,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::PromoteScalar(spv::Decoration precision, Id& left, Id& right) {
|
void SpirvEmitter::PromoteScalar(spv::Decoration precision, Id& left,
|
||||||
|
Id& right) {
|
||||||
int direction = GetComponentCount(right) - GetComponentCount(left);
|
int direction = GetComponentCount(right) - GetComponentCount(left);
|
||||||
if (direction > 0) {
|
if (direction > 0) {
|
||||||
left = SmearScalar(precision, left, GetTypeId(right));
|
left = SmearScalar(precision, left, GetTypeId(right));
|
||||||
|
@ -1118,7 +1119,7 @@ void SpvEmitter::PromoteScalar(spv::Decoration precision, Id& left, Id& right) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::SmearScalar(spv::Decoration precision, Id scalar_value,
|
Id SpirvEmitter::SmearScalar(spv::Decoration precision, Id scalar_value,
|
||||||
Id vector_type_id) {
|
Id vector_type_id) {
|
||||||
assert(GetComponentCount(scalar_value) == 1);
|
assert(GetComponentCount(scalar_value) == 1);
|
||||||
int component_count = GetTypeComponentCount(vector_type_id);
|
int component_count = GetTypeComponentCount(vector_type_id);
|
||||||
|
@ -1136,8 +1137,9 @@ Id SpvEmitter::SmearScalar(spv::Decoration precision, Id scalar_value,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateExtendedInstructionCall(spv::Decoration precision,
|
Id SpirvEmitter::CreateExtendedInstructionCall(spv::Decoration precision,
|
||||||
Id result_type, Id instruction_set,
|
Id result_type,
|
||||||
|
Id instruction_set,
|
||||||
int instruction_ordinal,
|
int instruction_ordinal,
|
||||||
std::initializer_list<Id> args) {
|
std::initializer_list<Id> args) {
|
||||||
auto instr = new Instruction(AllocateUniqueId(), result_type, Op::OpExtInst);
|
auto instr = new Instruction(AllocateUniqueId(), result_type, Op::OpExtInst);
|
||||||
|
@ -1151,7 +1153,7 @@ Id SpvEmitter::CreateExtendedInstructionCall(spv::Decoration precision,
|
||||||
|
|
||||||
// Accept all parameters needed to create a texture instruction.
|
// Accept all parameters needed to create a texture instruction.
|
||||||
// Create the correct instruction based on the inputs, and make the call.
|
// Create the correct instruction based on the inputs, and make the call.
|
||||||
Id SpvEmitter::CreateTextureCall(spv::Decoration precision, Id result_type,
|
Id SpirvEmitter::CreateTextureCall(spv::Decoration precision, Id result_type,
|
||||||
bool fetch, bool proj, bool gather,
|
bool fetch, bool proj, bool gather,
|
||||||
const TextureParameters& parameters) {
|
const TextureParameters& parameters) {
|
||||||
static const int kMaxTextureArgs = 10;
|
static const int kMaxTextureArgs = 10;
|
||||||
|
@ -1295,7 +1297,7 @@ Id SpvEmitter::CreateTextureCall(spv::Decoration precision, Id result_type,
|
||||||
return result_id;
|
return result_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateTextureQueryCall(Op opcode,
|
Id SpirvEmitter::CreateTextureQueryCall(Op opcode,
|
||||||
const TextureParameters& parameters) {
|
const TextureParameters& parameters) {
|
||||||
// Figure out the result type.
|
// Figure out the result type.
|
||||||
Id result_type = 0;
|
Id result_type = 0;
|
||||||
|
@ -1358,7 +1360,7 @@ Id SpvEmitter::CreateTextureQueryCall(Op opcode,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateCompare(spv::Decoration precision, Id value1, Id value2,
|
Id SpirvEmitter::CreateCompare(spv::Decoration precision, Id value1, Id value2,
|
||||||
bool is_equal) {
|
bool is_equal) {
|
||||||
Id bool_type_id = MakeBoolType();
|
Id bool_type_id = MakeBoolType();
|
||||||
Id value_type_id = GetTypeId(value1);
|
Id value_type_id = GetTypeId(value1);
|
||||||
|
@ -1440,7 +1442,7 @@ Id SpvEmitter::CreateCompare(spv::Decoration precision, Id value1, Id value2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpCompositeConstruct
|
// OpCompositeConstruct
|
||||||
Id SpvEmitter::CreateCompositeConstruct(Id type_id,
|
Id SpirvEmitter::CreateCompositeConstruct(Id type_id,
|
||||||
std::vector<Id> constituent_ids) {
|
std::vector<Id> constituent_ids) {
|
||||||
assert(IsAggregateType(type_id) ||
|
assert(IsAggregateType(type_id) ||
|
||||||
(GetTypeComponentCount(type_id) > 1 &&
|
(GetTypeComponentCount(type_id) > 1 &&
|
||||||
|
@ -1454,7 +1456,7 @@ Id SpvEmitter::CreateCompositeConstruct(Id type_id,
|
||||||
return instr->result_id();
|
return instr->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateConstructor(spv::Decoration precision,
|
Id SpirvEmitter::CreateConstructor(spv::Decoration precision,
|
||||||
std::vector<Id> source_ids,
|
std::vector<Id> source_ids,
|
||||||
Id result_type_id) {
|
Id result_type_id) {
|
||||||
Id result = 0;
|
Id result = 0;
|
||||||
|
@ -1504,7 +1506,7 @@ Id SpvEmitter::CreateConstructor(spv::Decoration precision,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateMatrixConstructor(spv::Decoration precision,
|
Id SpirvEmitter::CreateMatrixConstructor(spv::Decoration precision,
|
||||||
std::vector<Id> sources,
|
std::vector<Id> sources,
|
||||||
Id result_type_id) {
|
Id result_type_id) {
|
||||||
Id component_type_id = GetScalarTypeId(result_type_id);
|
Id component_type_id = GetScalarTypeId(result_type_id);
|
||||||
|
@ -1594,7 +1596,7 @@ Id SpvEmitter::CreateMatrixConstructor(spv::Decoration precision,
|
||||||
return CreateCompositeConstruct(result_type_id, matrix_columns);
|
return CreateCompositeConstruct(result_type_id, matrix_columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvEmitter::If::If(SpvEmitter& emitter, Id condition)
|
SpirvEmitter::If::If(SpirvEmitter& emitter, Id condition)
|
||||||
: emitter_(emitter), condition_(condition) {
|
: emitter_(emitter), condition_(condition) {
|
||||||
function_ = &emitter_.build_point()->parent();
|
function_ = &emitter_.build_point()->parent();
|
||||||
|
|
||||||
|
@ -1612,7 +1614,7 @@ SpvEmitter::If::If(SpvEmitter& emitter, Id condition)
|
||||||
emitter_.set_build_point(then_block_);
|
emitter_.set_build_point(then_block_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::If::MakeBeginElse() {
|
void SpirvEmitter::If::MakeBeginElse() {
|
||||||
// Close out the "then" by having it jump to the merge_block
|
// Close out the "then" by having it jump to the merge_block
|
||||||
emitter_.CreateBranch(merge_block_);
|
emitter_.CreateBranch(merge_block_);
|
||||||
|
|
||||||
|
@ -1624,7 +1626,7 @@ void SpvEmitter::If::MakeBeginElse() {
|
||||||
emitter_.set_build_point(else_block_);
|
emitter_.set_build_point(else_block_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::If::MakeEndIf() {
|
void SpirvEmitter::If::MakeEndIf() {
|
||||||
// jump to the merge block
|
// jump to the merge block
|
||||||
emitter_.CreateBranch(merge_block_);
|
emitter_.CreateBranch(merge_block_);
|
||||||
|
|
||||||
|
@ -1643,7 +1645,7 @@ void SpvEmitter::If::MakeEndIf() {
|
||||||
emitter_.set_build_point(merge_block_);
|
emitter_.set_build_point(merge_block_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::MakeSwitch(Id selector, int segment_count,
|
void SpirvEmitter::MakeSwitch(Id selector, int segment_count,
|
||||||
std::vector<int> case_values,
|
std::vector<int> case_values,
|
||||||
std::vector<int> value_index_to_segment,
|
std::vector<int> value_index_to_segment,
|
||||||
int default_segment,
|
int default_segment,
|
||||||
|
@ -1676,13 +1678,13 @@ void SpvEmitter::MakeSwitch(Id selector, int segment_count,
|
||||||
switch_merges_.push(merge_block);
|
switch_merges_.push(merge_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::AddSwitchBreak() {
|
void SpirvEmitter::AddSwitchBreak() {
|
||||||
// Branch to the top of the merge block stack.
|
// Branch to the top of the merge block stack.
|
||||||
CreateBranch(switch_merges_.top());
|
CreateBranch(switch_merges_.top());
|
||||||
CreateAndSetNoPredecessorBlock("post-switch-break");
|
CreateAndSetNoPredecessorBlock("post-switch-break");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::NextSwitchSegment(std::vector<Block*>& segment_block,
|
void SpirvEmitter::NextSwitchSegment(std::vector<Block*>& segment_block,
|
||||||
int next_segment) {
|
int next_segment) {
|
||||||
int last_segment = next_segment - 1;
|
int last_segment = next_segment - 1;
|
||||||
if (last_segment >= 0) {
|
if (last_segment >= 0) {
|
||||||
|
@ -1696,7 +1698,7 @@ void SpvEmitter::NextSwitchSegment(std::vector<Block*>& segment_block,
|
||||||
set_build_point(block);
|
set_build_point(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::EndSwitch(std::vector<Block*>& segment_block) {
|
void SpirvEmitter::EndSwitch(std::vector<Block*>& segment_block) {
|
||||||
// Close out previous segment by jumping, if necessary, to next segment.
|
// Close out previous segment by jumping, if necessary, to next segment.
|
||||||
if (!build_point_->is_terminated()) {
|
if (!build_point_->is_terminated()) {
|
||||||
AddSwitchBreak();
|
AddSwitchBreak();
|
||||||
|
@ -1708,7 +1710,7 @@ void SpvEmitter::EndSwitch(std::vector<Block*>& segment_block) {
|
||||||
switch_merges_.pop();
|
switch_merges_.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::MakeNewLoop(bool test_first) {
|
void SpirvEmitter::MakeNewLoop(bool test_first) {
|
||||||
loops_.push(Loop(*this, test_first));
|
loops_.push(Loop(*this, test_first));
|
||||||
const Loop& loop = loops_.top();
|
const Loop& loop = loops_.top();
|
||||||
|
|
||||||
|
@ -1765,7 +1767,7 @@ void SpvEmitter::MakeNewLoop(bool test_first) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateLoopTestBranch(Id condition) {
|
void SpirvEmitter::CreateLoopTestBranch(Id condition) {
|
||||||
const Loop& loop = loops_.top();
|
const Loop& loop = loops_.top();
|
||||||
|
|
||||||
// Generate the merge instruction. If the loop test executes before
|
// Generate the merge instruction. If the loop test executes before
|
||||||
|
@ -1797,7 +1799,7 @@ void SpvEmitter::CreateLoopTestBranch(Id condition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateBranchToBody() {
|
void SpirvEmitter::CreateBranchToBody() {
|
||||||
const Loop& loop = loops_.top();
|
const Loop& loop = loops_.top();
|
||||||
assert(loop.body);
|
assert(loop.body);
|
||||||
|
|
||||||
|
@ -1808,19 +1810,19 @@ void SpvEmitter::CreateBranchToBody() {
|
||||||
set_build_point(loop.body);
|
set_build_point(loop.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateLoopContinue() {
|
void SpirvEmitter::CreateLoopContinue() {
|
||||||
CreateBranchToLoopHeaderFromInside(loops_.top());
|
CreateBranchToLoopHeaderFromInside(loops_.top());
|
||||||
// Set up a block for dead code.
|
// Set up a block for dead code.
|
||||||
CreateAndSetNoPredecessorBlock("post-loop-continue");
|
CreateAndSetNoPredecessorBlock("post-loop-continue");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateLoopExit() {
|
void SpirvEmitter::CreateLoopExit() {
|
||||||
CreateBranch(loops_.top().merge);
|
CreateBranch(loops_.top().merge);
|
||||||
// Set up a block for dead code.
|
// Set up a block for dead code.
|
||||||
CreateAndSetNoPredecessorBlock("post-loop-break");
|
CreateAndSetNoPredecessorBlock("post-loop-break");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CloseLoop() {
|
void SpirvEmitter::CloseLoop() {
|
||||||
const Loop& loop = loops_.top();
|
const Loop& loop = loops_.top();
|
||||||
|
|
||||||
// Branch back to the top.
|
// Branch back to the top.
|
||||||
|
@ -1833,7 +1835,7 @@ void SpvEmitter::CloseLoop() {
|
||||||
loops_.pop();
|
loops_.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::ClearAccessChain() {
|
void SpirvEmitter::ClearAccessChain() {
|
||||||
access_chain_.base = NoResult;
|
access_chain_.base = NoResult;
|
||||||
access_chain_.index_chain.clear();
|
access_chain_.index_chain.clear();
|
||||||
access_chain_.instr = NoResult;
|
access_chain_.instr = NoResult;
|
||||||
|
@ -1848,7 +1850,7 @@ void SpvEmitter::ClearAccessChain() {
|
||||||
// be handled after this is called, but it does include swizzles that select
|
// be handled after this is called, but it does include swizzles that select
|
||||||
// an individual element, as a single address of a scalar type can be
|
// an individual element, as a single address of a scalar type can be
|
||||||
// computed by an OpAccessChain instruction.
|
// computed by an OpAccessChain instruction.
|
||||||
Id SpvEmitter::CollapseAccessChain() {
|
Id SpirvEmitter::CollapseAccessChain() {
|
||||||
assert(access_chain_.is_rvalue == false);
|
assert(access_chain_.is_rvalue == false);
|
||||||
|
|
||||||
if (!access_chain_.index_chain.empty()) {
|
if (!access_chain_.index_chain.empty()) {
|
||||||
|
@ -1867,7 +1869,7 @@ Id SpvEmitter::CollapseAccessChain() {
|
||||||
|
|
||||||
// Clear out swizzle if it is redundant, that is reselecting the same components
|
// Clear out swizzle if it is redundant, that is reselecting the same components
|
||||||
// that would be present without the swizzle.
|
// that would be present without the swizzle.
|
||||||
void SpvEmitter::SimplifyAccessChainSwizzle() {
|
void SpirvEmitter::SimplifyAccessChainSwizzle() {
|
||||||
// If the swizzle has fewer components than the vector, it is subsetting, and
|
// If the swizzle has fewer components than the vector, it is subsetting, and
|
||||||
// must stay to preserve that fact.
|
// must stay to preserve that fact.
|
||||||
if (GetTypeComponentCount(access_chain_.pre_swizzle_base_type) >
|
if (GetTypeComponentCount(access_chain_.pre_swizzle_base_type) >
|
||||||
|
@ -1898,7 +1900,7 @@ void SpvEmitter::SimplifyAccessChainSwizzle() {
|
||||||
// for external storage, they should only be integer types,
|
// for external storage, they should only be integer types,
|
||||||
// function-local bool vectors could use sub-word indexing,
|
// function-local bool vectors could use sub-word indexing,
|
||||||
// so keep that as a separate Insert/Extract on a loaded vector.
|
// so keep that as a separate Insert/Extract on a loaded vector.
|
||||||
void SpvEmitter::TransferAccessChainSwizzle(bool dynamic) {
|
void SpirvEmitter::TransferAccessChainSwizzle(bool dynamic) {
|
||||||
// too complex?
|
// too complex?
|
||||||
if (access_chain_.swizzle.size() > 1) {
|
if (access_chain_.swizzle.size() > 1) {
|
||||||
return;
|
return;
|
||||||
|
@ -1933,7 +1935,7 @@ void SpvEmitter::TransferAccessChainSwizzle(bool dynamic) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::PushAccessChainSwizzle(std::vector<uint32_t> swizzle,
|
void SpirvEmitter::PushAccessChainSwizzle(std::vector<uint32_t> swizzle,
|
||||||
Id pre_swizzle_base_type) {
|
Id pre_swizzle_base_type) {
|
||||||
// Swizzles can be stacked in GLSL, but simplified to a single
|
// Swizzles can be stacked in GLSL, but simplified to a single
|
||||||
// one here; the base type doesn't change.
|
// one here; the base type doesn't change.
|
||||||
|
@ -1956,7 +1958,7 @@ void SpvEmitter::PushAccessChainSwizzle(std::vector<uint32_t> swizzle,
|
||||||
SimplifyAccessChainSwizzle();
|
SimplifyAccessChainSwizzle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateAccessChainStore(Id rvalue) {
|
void SpirvEmitter::CreateAccessChainStore(Id rvalue) {
|
||||||
assert(access_chain_.is_rvalue == false);
|
assert(access_chain_.is_rvalue == false);
|
||||||
|
|
||||||
TransferAccessChainSwizzle(true);
|
TransferAccessChainSwizzle(true);
|
||||||
|
@ -1992,7 +1994,7 @@ void SpvEmitter::CreateAccessChainStore(Id rvalue) {
|
||||||
CreateStore(source, base);
|
CreateStore(source, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateAccessChainLoad(Id result_type_id) {
|
Id SpirvEmitter::CreateAccessChainLoad(Id result_type_id) {
|
||||||
Id id;
|
Id id;
|
||||||
|
|
||||||
if (access_chain_.is_rvalue) {
|
if (access_chain_.is_rvalue) {
|
||||||
|
@ -2068,7 +2070,7 @@ Id SpvEmitter::CreateAccessChainLoad(Id result_type_id) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id SpvEmitter::CreateAccessChainLValue() {
|
Id SpirvEmitter::CreateAccessChainLValue() {
|
||||||
assert(access_chain_.is_rvalue == false);
|
assert(access_chain_.is_rvalue == false);
|
||||||
|
|
||||||
TransferAccessChainSwizzle(true);
|
TransferAccessChainSwizzle(true);
|
||||||
|
@ -2083,7 +2085,7 @@ Id SpvEmitter::CreateAccessChainLValue() {
|
||||||
return lvalue;
|
return lvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::Serialize(std::vector<uint32_t>& out) const {
|
void SpirvEmitter::Serialize(std::vector<uint32_t>& out) const {
|
||||||
// Header, before first instructions:
|
// Header, before first instructions:
|
||||||
out.push_back(spv::MagicNumber);
|
out.push_back(spv::MagicNumber);
|
||||||
out.push_back(spv::Version);
|
out.push_back(spv::Version);
|
||||||
|
@ -2134,7 +2136,7 @@ void SpvEmitter::Serialize(std::vector<uint32_t>& out) const {
|
||||||
module_.Serialize(out);
|
module_.Serialize(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::SerializeInstructions(
|
void SpirvEmitter::SerializeInstructions(
|
||||||
std::vector<unsigned int>& out,
|
std::vector<unsigned int>& out,
|
||||||
const std::vector<Instruction*>& instructions) const {
|
const std::vector<Instruction*>& instructions) const {
|
||||||
for (auto instruction : instructions) {
|
for (auto instruction : instructions) {
|
||||||
|
@ -2145,7 +2147,7 @@ void SpvEmitter::SerializeInstructions(
|
||||||
// Utility method for creating a new block and setting the insert point to
|
// Utility method for creating a new block and setting the insert point to
|
||||||
// be in it. This is useful for flow-control operations that need a "dummy"
|
// be in it. This is useful for flow-control operations that need a "dummy"
|
||||||
// block proceeding them (e.g. instructions after a discard, etc).
|
// block proceeding them (e.g. instructions after a discard, etc).
|
||||||
void SpvEmitter::CreateAndSetNoPredecessorBlock(const char* name) {
|
void SpirvEmitter::CreateAndSetNoPredecessorBlock(const char* name) {
|
||||||
Block* block = new Block(AllocateUniqueId(), build_point_->parent());
|
Block* block = new Block(AllocateUniqueId(), build_point_->parent());
|
||||||
block->set_unreachable(true);
|
block->set_unreachable(true);
|
||||||
build_point_->parent().push_block(block);
|
build_point_->parent().push_block(block);
|
||||||
|
@ -2154,14 +2156,14 @@ void SpvEmitter::CreateAndSetNoPredecessorBlock(const char* name) {
|
||||||
AddName(block->id(), name);
|
AddName(block->id(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateBranch(Block* block) {
|
void SpirvEmitter::CreateBranch(Block* block) {
|
||||||
auto instr = new Instruction(Op::OpBranch);
|
auto instr = new Instruction(Op::OpBranch);
|
||||||
instr->AddIdOperand(block->id());
|
instr->AddIdOperand(block->id());
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
block->AddPredecessor(build_point_);
|
block->AddPredecessor(build_point_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateSelectionMerge(Block* merge_block,
|
void SpirvEmitter::CreateSelectionMerge(Block* merge_block,
|
||||||
spv::SelectionControlMask control) {
|
spv::SelectionControlMask control) {
|
||||||
auto instr = new Instruction(Op::OpSelectionMerge);
|
auto instr = new Instruction(Op::OpSelectionMerge);
|
||||||
instr->AddIdOperand(merge_block->id());
|
instr->AddIdOperand(merge_block->id());
|
||||||
|
@ -2169,7 +2171,7 @@ void SpvEmitter::CreateSelectionMerge(Block* merge_block,
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateLoopMerge(Block* merge_block, Block* continueBlock,
|
void SpirvEmitter::CreateLoopMerge(Block* merge_block, Block* continueBlock,
|
||||||
spv::LoopControlMask control) {
|
spv::LoopControlMask control) {
|
||||||
auto instr = new Instruction(Op::OpLoopMerge);
|
auto instr = new Instruction(Op::OpLoopMerge);
|
||||||
instr->AddIdOperand(merge_block->id());
|
instr->AddIdOperand(merge_block->id());
|
||||||
|
@ -2178,7 +2180,7 @@ void SpvEmitter::CreateLoopMerge(Block* merge_block, Block* continueBlock,
|
||||||
build_point_->AddInstruction(instr);
|
build_point_->AddInstruction(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CreateConditionalBranch(Id condition, Block* then_block,
|
void SpirvEmitter::CreateConditionalBranch(Id condition, Block* then_block,
|
||||||
Block* else_block) {
|
Block* else_block) {
|
||||||
auto instr = new Instruction(Op::OpBranchConditional);
|
auto instr = new Instruction(Op::OpBranchConditional);
|
||||||
instr->AddIdOperand(condition);
|
instr->AddIdOperand(condition);
|
||||||
|
@ -2189,7 +2191,7 @@ void SpvEmitter::CreateConditionalBranch(Id condition, Block* then_block,
|
||||||
else_block->AddPredecessor(build_point_);
|
else_block->AddPredecessor(build_point_);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvEmitter::Loop::Loop(SpvEmitter& emitter, bool testFirstArg)
|
SpirvEmitter::Loop::Loop(SpirvEmitter& emitter, bool testFirstArg)
|
||||||
: function(&emitter.build_point()->parent()),
|
: function(&emitter.build_point()->parent()),
|
||||||
header(new Block(emitter.AllocateUniqueId(), *function)),
|
header(new Block(emitter.AllocateUniqueId(), *function)),
|
||||||
merge(new Block(emitter.AllocateUniqueId(), *function)),
|
merge(new Block(emitter.AllocateUniqueId(), *function)),
|
||||||
|
@ -2211,7 +2213,7 @@ SpvEmitter::Loop::Loop(SpvEmitter& emitter, bool testFirstArg)
|
||||||
// Create a branch to the header of the given loop, from inside
|
// Create a branch to the header of the given loop, from inside
|
||||||
// the loop body.
|
// the loop body.
|
||||||
// Adjusts the phi node for the first-iteration value if needeed.
|
// Adjusts the phi node for the first-iteration value if needeed.
|
||||||
void SpvEmitter::CreateBranchToLoopHeaderFromInside(const Loop& loop) {
|
void SpirvEmitter::CreateBranchToLoopHeaderFromInside(const Loop& loop) {
|
||||||
CreateBranch(loop.header);
|
CreateBranch(loop.header);
|
||||||
if (loop.is_first_iteration) {
|
if (loop.is_first_iteration) {
|
||||||
loop.is_first_iteration->AddIdOperand(MakeBoolConstant(false));
|
loop.is_first_iteration->AddIdOperand(MakeBoolConstant(false));
|
||||||
|
@ -2219,10 +2221,10 @@ void SpvEmitter::CreateBranchToLoopHeaderFromInside(const Loop& loop) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpvEmitter::CheckNotImplemented(const char* message) {
|
void SpirvEmitter::CheckNotImplemented(const char* message) {
|
||||||
xe::FatalError("Missing functionality: %s", message);
|
xe::FatalError("Missing functionality: %s", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
|
@ -43,8 +43,8 @@
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#ifndef XENIA_GPU_SPIRV_SPV_EMITTER_H_
|
#ifndef XENIA_UI_SPIRV_SPIRV_EMITTER_H_
|
||||||
#define XENIA_GPU_SPIRV_SPV_EMITTER_H_
|
#define XENIA_UI_SPIRV_SPIRV_EMITTER_H_
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -52,17 +52,17 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
#include "xenia/ui/spirv/spirv_ir.h"
|
||||||
#include "xenia/gpu/spirv/spv_ir.h"
|
#include "xenia/ui/spirv/spirv_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
class SpvEmitter {
|
class SpirvEmitter {
|
||||||
public:
|
public:
|
||||||
SpvEmitter();
|
SpirvEmitter();
|
||||||
~SpvEmitter();
|
~SpirvEmitter();
|
||||||
|
|
||||||
// Document what source language and text this module was translated from.
|
// Document what source language and text this module was translated from.
|
||||||
void SetSourceLanguage(spv::SourceLanguage language, int version) {
|
void SetSourceLanguage(spv::SourceLanguage language, int version) {
|
||||||
|
@ -423,7 +423,7 @@ class SpvEmitter {
|
||||||
// Helper to use for building nested control flow with if-then-else.
|
// Helper to use for building nested control flow with if-then-else.
|
||||||
class If {
|
class If {
|
||||||
public:
|
public:
|
||||||
If(SpvEmitter& emitter, Id condition);
|
If(SpirvEmitter& emitter, Id condition);
|
||||||
~If() = default;
|
~If() = default;
|
||||||
|
|
||||||
void MakeBeginElse();
|
void MakeBeginElse();
|
||||||
|
@ -433,7 +433,7 @@ class SpvEmitter {
|
||||||
If(const If&) = delete;
|
If(const If&) = delete;
|
||||||
If& operator=(If&) = delete;
|
If& operator=(If&) = delete;
|
||||||
|
|
||||||
SpvEmitter& emitter_;
|
SpirvEmitter& emitter_;
|
||||||
Id condition_;
|
Id condition_;
|
||||||
Function* function_ = nullptr;
|
Function* function_ = nullptr;
|
||||||
Block* header_block_ = nullptr;
|
Block* header_block_ = nullptr;
|
||||||
|
@ -685,7 +685,7 @@ class SpvEmitter {
|
||||||
// also create a phi instruction whose value indicates whether we're on
|
// also create a phi instruction whose value indicates whether we're on
|
||||||
// the first iteration of the loop. The phi instruction is initialized
|
// the first iteration of the loop. The phi instruction is initialized
|
||||||
// with no values or predecessor operands.
|
// with no values or predecessor operands.
|
||||||
Loop(SpvEmitter& emitter, bool test_first);
|
Loop(SpirvEmitter& emitter, bool test_first);
|
||||||
|
|
||||||
// The function containing the loop.
|
// The function containing the loop.
|
||||||
Function* const function;
|
Function* const function;
|
||||||
|
@ -720,7 +720,7 @@ class SpvEmitter {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_GPU_SPIRV_SPV_EMITTER_H_
|
#endif // XENIA_UI_SPIRV_SPIRV_EMITTER_H_
|
|
@ -53,16 +53,16 @@
|
||||||
// - Instruction
|
// - Instruction
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef XENIA_GPU_SPIRV_SPV_IR_H_
|
#ifndef XENIA_UI_SPIRV_SPIRV_IR_H_
|
||||||
#define XENIA_GPU_SPIRV_SPV_IR_H_
|
#define XENIA_UI_SPIRV_SPIRV_IR_H_
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
#include "xenia/ui/spirv/spirv_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
using spv::Id;
|
using spv::Id;
|
||||||
|
@ -415,7 +415,7 @@ inline void Block::AddInstruction(Instruction* inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_GPU_SPIRV_SPV_IR_H_
|
#endif // XENIA_UI_SPIRV_SPIRV_IR_H_
|
|
@ -7,16 +7,16 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spv_optimizer.h"
|
#include "xenia/ui/spirv/spirv_optimizer.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
SpvOptimizer::SpvOptimizer() = default;
|
SpirvOptimizer::SpirvOptimizer() = default;
|
||||||
|
|
||||||
SpvOptimizer::~SpvOptimizer() = default;
|
SpirvOptimizer::~SpirvOptimizer() = default;
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
|
@ -7,25 +7,25 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_GPU_SPIRV_SPV_OPTIMIZER_H_
|
#ifndef XENIA_UI_SPIRV_SPIRV_OPTIMIZER_H_
|
||||||
#define XENIA_GPU_SPIRV_SPV_OPTIMIZER_H_
|
#define XENIA_UI_SPIRV_SPIRV_OPTIMIZER_H_
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
#include "xenia/ui/spirv/spirv_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
class SpvOptimizer {
|
class SpirvOptimizer {
|
||||||
public:
|
public:
|
||||||
SpvOptimizer();
|
SpirvOptimizer();
|
||||||
~SpvOptimizer();
|
~SpirvOptimizer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_GPU_SPIRV_SPV_OPTIMIZER_H_
|
#endif // XENIA_UI_SPIRV_SPIRV_OPTIMIZER_H_
|
|
@ -7,14 +7,14 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/gpu/spirv/spirv_util.h"
|
#include "xenia/ui/spirv/spirv_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_GPU_SPIRV_SPIRV_UTIL_H_
|
#ifndef XENIA_UI_SPIRV_SPIRV_UTIL_H_
|
||||||
#define XENIA_GPU_SPIRV_SPIRV_UTIL_H_
|
#define XENIA_UI_SPIRV_SPIRV_UTIL_H_
|
||||||
|
|
||||||
#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"
|
||||||
|
@ -24,13 +24,13 @@ struct spv_text_t;
|
||||||
typedef spv_text_t* spv_text;
|
typedef spv_text_t* spv_text;
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace ui {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace gpu
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_GPU_SPIRV_SPIRV_UTIL_H_
|
#endif // XENIA_UI_SPIRV_SPIRV_UTIL_H_
|
Loading…
Reference in New Issue