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:
Ben Vanik 2015-11-24 19:49:05 -08:00
parent cf68d02142
commit 6a546ebe4d
18 changed files with 333 additions and 334 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,8 +178,8 @@ 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,8 +295,8 @@ 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)];
for (auto& type : grouped_type) { for (auto& type : grouped_type) {
@ -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,14 +479,14 @@ 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) {
if (constant->opcode() == opcode && constant->type_id() == type_id && if (constant->opcode() == opcode && constant->type_id() == type_id &&
@ -499,8 +499,8 @@ 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) {
if (constant->opcode() == opcode && constant->type_id() == type_id && if (constant->opcode() == opcode && constant->type_id() == type_id &&
@ -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,8 +559,8 @@ 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);
if (existing) { if (existing) {
@ -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,8 +641,8 @@ 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,9 +672,9 @@ 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);
instr->AddImmediateOperand(execution_model); instr->AddImmediateOperand(execution_model);
instr->AddIdOperand(entry_point->id()); instr->AddIdOperand(entry_point->id());
@ -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,8 +729,8 @@ 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);
instr->AddIdOperand(file_name); instr->AddIdOperand(file_name);
@ -740,8 +740,8 @@ 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,8 +755,8 @@ 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);
instr->AddImmediateOperand(member); instr->AddImmediateOperand(member);
@ -768,16 +768,16 @@ 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);
Id first_param_id = Id first_param_id =
param_types.size() ? AllocateUniqueIds((int)param_types.size()) : 0; param_types.size() ? AllocateUniqueIds((int)param_types.size()) : 0;
@ -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,13 +836,13 @@ 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 =
new Instruction(AllocateUniqueId(), pointer_type, Op::OpVariable); new Instruction(AllocateUniqueId(), pointer_type, Op::OpVariable);
@ -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,8 +886,8 @@ 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);
assert(IsPointerType(base_type_id) && index_ids.size()); assert(IsPointerType(base_type_id) && index_ids.size());
@ -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,8 +922,8 @@ 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);
instr->AddIdOperand(composite); instr->AddIdOperand(composite);
@ -933,8 +933,8 @@ 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);
instr->AddIdOperand(composite); instr->AddIdOperand(composite);
@ -944,8 +944,8 @@ 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);
instr->AddIdOperand(object); instr->AddIdOperand(object);
@ -956,8 +956,8 @@ 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);
instr->AddIdOperand(object); instr->AddIdOperand(object);
@ -968,8 +968,8 @@ 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);
instr->AddIdOperand(vector); instr->AddIdOperand(vector);
@ -979,8 +979,8 @@ 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);
instr->AddIdOperand(vector); instr->AddIdOperand(vector);
@ -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,8 +1041,8 @@ 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);
build_point_->AddInstruction(instr); build_point_->AddInstruction(instr);
@ -1050,8 +1050,8 @@ 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);
instr->AddIdOperand(function->id()); instr->AddIdOperand(function->id());
@ -1061,8 +1061,8 @@ 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,8 +1077,8 @@ 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) {
return CreateCompositeInsert(source, target, type_id, channels.front()); return CreateCompositeInsert(source, target, type_id, channels.front());
@ -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,8 +1119,8 @@ 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);
if (component_count == 1) { if (component_count == 1) {
@ -1136,10 +1137,11 @@ 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,
int instruction_ordinal, Id instruction_set,
std::initializer_list<Id> args) { int instruction_ordinal,
std::initializer_list<Id> args) {
auto instr = new Instruction(AllocateUniqueId(), result_type, Op::OpExtInst); auto instr = new Instruction(AllocateUniqueId(), result_type, Op::OpExtInst);
instr->AddIdOperand(instruction_set); instr->AddIdOperand(instruction_set);
instr->AddImmediateOperand(instruction_ordinal); instr->AddImmediateOperand(instruction_ordinal);
@ -1151,9 +1153,9 @@ 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;
Id tex_args[kMaxTextureArgs] = {}; Id tex_args[kMaxTextureArgs] = {};
@ -1295,8 +1297,8 @@ 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;
switch (opcode) { switch (opcode) {
@ -1358,8 +1360,8 @@ 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,8 +1442,8 @@ 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 &&
GetTypeComponentCount(type_id) == constituent_ids.size())); GetTypeComponentCount(type_id) == constituent_ids.size()));
@ -1454,9 +1456,9 @@ 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;
int target_component_count = GetTypeComponentCount(result_type_id); int target_component_count = GetTypeComponentCount(result_type_id);
int target_component = 0; int target_component = 0;
@ -1504,9 +1506,9 @@ 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);
int column_count = GetTypeColumnCount(result_type_id); int column_count = GetTypeColumnCount(result_type_id);
int row_count = GetTypeRowCount(result_type_id); int row_count = GetTypeRowCount(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,11 +1645,11 @@ 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,
std::vector<Block*>& segment_blocks) { std::vector<Block*>& segment_blocks) {
Function& function = build_point_->parent(); Function& function = build_point_->parent();
// Make all the blocks. // Make all the blocks.
@ -1676,14 +1678,14 @@ 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) {
// Close out previous segment by jumping, if necessary, to next segment. // Close out previous segment by jumping, if necessary, to next segment.
@ -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,8 +1935,8 @@ 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.
if (access_chain_.pre_swizzle_base_type == NoType) { if (access_chain_.pre_swizzle_base_type == NoType) {
@ -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,23 +2156,23 @@ 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());
instr->AddImmediateOperand(control); instr->AddImmediateOperand(control);
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());
instr->AddIdOperand(continueBlock->id()); instr->AddIdOperand(continueBlock->id());
@ -2178,8 +2180,8 @@ 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);
instr->AddIdOperand(then_block->id()); instr->AddIdOperand(then_block->id());
@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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