mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
refactor(shader): emit SPIR-V declarations on demand
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
#include "graphics/shader/recompiler/backend/spirv/SpirvBuilder.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::Spirv {
|
||||
|
||||
static constexpr size_t InitialSpirvSectionReserve = 4096;
|
||||
static constexpr size_t InitialSpirvFunctionSectionReserve = 450000;
|
||||
static constexpr size_t InitialSpirvFunctionSectionReserve = 32768;
|
||||
|
||||
static void AppendInstructionWords(std::vector<uint32_t>& section, const uint32_t* words,
|
||||
size_t words_num) {
|
||||
@@ -22,7 +21,7 @@ static void AppendInstructionWords(std::vector<uint32_t>& section, const uint32_
|
||||
Builder::Builder(uint32_t version): m_version(version) {
|
||||
m_debug.reserve(InitialSpirvSectionReserve);
|
||||
m_annotations.reserve(InitialSpirvSectionReserve);
|
||||
m_types.reserve(InitialSpirvSectionReserve);
|
||||
m_declarations.reserve(InitialSpirvSectionReserve);
|
||||
m_functions.reserve(InitialSpirvFunctionSectionReserve);
|
||||
}
|
||||
|
||||
@@ -30,6 +29,110 @@ uint32_t Builder::AllocateId() {
|
||||
return m_next_id++;
|
||||
}
|
||||
|
||||
void Builder::RequireCapability(uint32_t capability) {
|
||||
if (m_required_capabilities.insert(capability).second) {
|
||||
AddCapability({capability});
|
||||
}
|
||||
}
|
||||
|
||||
void Builder::RequireExtension(const char* name) {
|
||||
if (m_required_extensions.emplace(name).second) {
|
||||
AddExtension(name);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Builder::Import(const char* name) {
|
||||
if (const auto it = m_import_ids.find(name); it != m_import_ids.end()) {
|
||||
return it->second;
|
||||
}
|
||||
const auto id = AllocateId();
|
||||
m_import_ids.emplace(name, id);
|
||||
AddExtInstImport(id, name);
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t Builder::Type(uint32_t opcode, std::initializer_list<uint32_t> operands) {
|
||||
return Type(opcode, std::vector<uint32_t>(operands));
|
||||
}
|
||||
|
||||
uint32_t Builder::Type(uint32_t opcode, const std::vector<uint32_t>& operands) {
|
||||
std::vector<uint32_t> key;
|
||||
key.reserve(operands.size() + 2u);
|
||||
key.push_back(opcode);
|
||||
key.push_back(static_cast<uint32_t>(operands.size()));
|
||||
key.insert(key.end(), operands.begin(), operands.end());
|
||||
if (const auto it = m_declaration_ids.find(key); it != m_declaration_ids.end()) {
|
||||
return it->second;
|
||||
}
|
||||
const auto id = AllocateId();
|
||||
m_declaration_ids.emplace(std::move(key), id);
|
||||
std::vector<uint32_t> words {opcode, id};
|
||||
words.insert(words.end(), operands.begin(), operands.end());
|
||||
AppendInstructionWords(m_declarations, words.data(), words.size());
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t Builder::DecoratedType(uint32_t opcode, std::initializer_list<uint32_t> operands,
|
||||
std::initializer_list<TypeAnnotation> annotations) {
|
||||
if (annotations.size() == 0) {
|
||||
return Type(opcode, operands);
|
||||
}
|
||||
std::vector<uint32_t> key {opcode, static_cast<uint32_t>(operands.size())};
|
||||
key.insert(key.end(), operands.begin(), operands.end());
|
||||
key.push_back(static_cast<uint32_t>(annotations.size()));
|
||||
for (const auto& annotation: annotations) {
|
||||
key.push_back(annotation.opcode);
|
||||
key.push_back(static_cast<uint32_t>(annotation.operands.size()));
|
||||
key.insert(key.end(), annotation.operands.begin(), annotation.operands.end());
|
||||
}
|
||||
if (const auto it = m_declaration_ids.find(key); it != m_declaration_ids.end()) {
|
||||
return it->second;
|
||||
}
|
||||
const auto id = AllocateId();
|
||||
m_declaration_ids.emplace(std::move(key), id);
|
||||
std::vector<uint32_t> words {opcode, id};
|
||||
words.insert(words.end(), operands.begin(), operands.end());
|
||||
AppendInstructionWords(m_declarations, words.data(), words.size());
|
||||
for (const auto& annotation: annotations) {
|
||||
words = {annotation.opcode, id};
|
||||
words.insert(words.end(), annotation.operands.begin(), annotation.operands.end());
|
||||
AppendInstructionWords(m_annotations, words.data(), words.size());
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t Builder::Constant(uint32_t opcode, uint32_t type,
|
||||
std::initializer_list<uint32_t> operands) {
|
||||
return Constant(opcode, type, std::vector<uint32_t>(operands));
|
||||
}
|
||||
|
||||
uint32_t Builder::Constant(uint32_t opcode, uint32_t type, const std::vector<uint32_t>& operands) {
|
||||
std::vector<uint32_t> key;
|
||||
key.reserve(operands.size() + 2u);
|
||||
key.push_back(opcode);
|
||||
key.push_back(type);
|
||||
key.insert(key.end(), operands.begin(), operands.end());
|
||||
if (const auto it = m_declaration_ids.find(key); it != m_declaration_ids.end()) {
|
||||
return it->second;
|
||||
}
|
||||
const auto id = AllocateId();
|
||||
m_declaration_ids.emplace(std::move(key), id);
|
||||
std::vector<uint32_t> words {opcode, type, id};
|
||||
words.insert(words.end(), operands.begin(), operands.end());
|
||||
AppendInstructionWords(m_declarations, words.data(), words.size());
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t Builder::DefineGlobalVariable(uint32_t pointer_type, uint32_t storage_class) {
|
||||
const auto id = AllocateId();
|
||||
DefineGlobalVariable(id, pointer_type, storage_class);
|
||||
return id;
|
||||
}
|
||||
|
||||
void Builder::DefineGlobalVariable(uint32_t id, uint32_t pointer_type, uint32_t storage_class) {
|
||||
AddType({59u, pointer_type, id, storage_class});
|
||||
}
|
||||
|
||||
void Builder::AppendString(std::vector<uint32_t>& words, const char* text) {
|
||||
const auto len = text != nullptr ? std::strlen(text) : 0;
|
||||
const auto word_count = (len + 1u + 3u) / 4u;
|
||||
@@ -103,7 +206,7 @@ void Builder::AddAnnotation(std::initializer_list<uint32_t> words) {
|
||||
}
|
||||
|
||||
void Builder::AddType(std::initializer_list<uint32_t> words) {
|
||||
AppendInstructionWords(m_types, words.begin(), words.size());
|
||||
AppendInstructionWords(m_declarations, words.begin(), words.size());
|
||||
}
|
||||
|
||||
void Builder::AddFunction(std::initializer_list<uint32_t> words) {
|
||||
@@ -115,27 +218,12 @@ void Builder::AddFunction(const std::vector<uint32_t>& words) {
|
||||
}
|
||||
|
||||
std::vector<uint32_t> Builder::Build() const {
|
||||
if (m_debug.size() > InitialSpirvSectionReserve) {
|
||||
std::printf("SPIR-V builder reserve exceeded: section=debug size=%zu reserve=%zu\n",
|
||||
m_debug.size(), InitialSpirvSectionReserve);
|
||||
}
|
||||
if (m_annotations.size() > InitialSpirvSectionReserve) {
|
||||
std::printf("SPIR-V builder reserve exceeded: section=annotations size=%zu reserve=%zu\n",
|
||||
m_annotations.size(), InitialSpirvSectionReserve);
|
||||
}
|
||||
if (m_types.size() > InitialSpirvSectionReserve) {
|
||||
std::printf("SPIR-V builder reserve exceeded: section=types size=%zu reserve=%zu\n",
|
||||
m_types.size(), InitialSpirvSectionReserve);
|
||||
}
|
||||
if (m_functions.size() > InitialSpirvFunctionSectionReserve) {
|
||||
std::printf("SPIR-V builder reserve exceeded: section=functions size=%zu reserve=%zu\n",
|
||||
m_functions.size(), InitialSpirvFunctionSectionReserve);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> module;
|
||||
module.reserve(5u + m_capabilities.size() + m_extensions.size() + m_ext_inst_imports.size() +
|
||||
m_memory_model.size() + m_entry_points.size() + m_execution_modes.size() +
|
||||
m_debug.size() + m_annotations.size() + m_types.size() + m_functions.size());
|
||||
m_debug.size() + m_annotations.size() + m_declarations.size() +
|
||||
m_functions.size());
|
||||
|
||||
module.push_back(0x07230203u);
|
||||
module.push_back(m_version);
|
||||
@@ -151,7 +239,7 @@ std::vector<uint32_t> Builder::Build() const {
|
||||
module.insert(module.end(), m_execution_modes.begin(), m_execution_modes.end());
|
||||
module.insert(module.end(), m_debug.begin(), m_debug.end());
|
||||
module.insert(module.end(), m_annotations.begin(), m_annotations.end());
|
||||
module.insert(module.end(), m_types.begin(), m_types.end());
|
||||
module.insert(module.end(), m_declarations.begin(), m_declarations.end());
|
||||
module.insert(module.end(), m_functions.begin(), m_functions.end());
|
||||
|
||||
return module;
|
||||
|
||||
Reference in New Issue
Block a user