mirror of
https://github.com/yuzu-emu/sirit
synced 2024-11-22 15:13:41 +00:00
Add ellipsis overloads for instructions ending in vectors
This commit is contained in:
parent
ee4ce61e62
commit
4b1c1d1e38
3 changed files with 122 additions and 33 deletions
|
@ -9,8 +9,8 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <set>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <spirv/unified1/spirv.hpp11>
|
#include <spirv/unified1/spirv.hpp11>
|
||||||
|
@ -52,10 +52,23 @@ public:
|
||||||
void AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point, const std::string& name,
|
void AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point, const std::string& name,
|
||||||
const std::vector<Id>& interfaces = {});
|
const std::vector<Id>& interfaces = {});
|
||||||
|
|
||||||
|
/// Adds an entry point.
|
||||||
|
template <typename... Ts>
|
||||||
|
void AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point, const std::string& name,
|
||||||
|
Ts&&... interfaces) {
|
||||||
|
AddEntryPoint(execution_model, entry_point, name, {interfaces...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Declare an execution mode for an entry point.
|
/// Declare an execution mode for an entry point.
|
||||||
void AddExecutionMode(Id entry_point, spv::ExecutionMode mode,
|
void AddExecutionMode(Id entry_point, spv::ExecutionMode mode,
|
||||||
const std::vector<Literal>& literals = {});
|
const std::vector<Literal>& literals = {});
|
||||||
|
|
||||||
|
/// Declare an execution mode for an entry point.
|
||||||
|
template <typename... Ts>
|
||||||
|
void AddExecutionMode(Id entry_point, spv::ExecutionMode mode, Ts&&... literals) {
|
||||||
|
AddExecutionMode(entry_point, mode, {literals...});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an instruction to module's code
|
* Adds an instruction to module's code
|
||||||
* @param op Instruction to insert into code. Types and constants must not
|
* @param op Instruction to insert into code. Types and constants must not
|
||||||
|
@ -111,6 +124,12 @@ public:
|
||||||
/// Returns type struct.
|
/// Returns type struct.
|
||||||
Id OpTypeStruct(const std::vector<Id>& members = {});
|
Id OpTypeStruct(const std::vector<Id>& members = {});
|
||||||
|
|
||||||
|
/// Returns type struct.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpTypeStruct(Ts&&... members) {
|
||||||
|
return OpTypeStruct({members...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns type opaque.
|
/// Returns type opaque.
|
||||||
Id OpTypeOpaque(const std::string& name);
|
Id OpTypeOpaque(const std::string& name);
|
||||||
|
|
||||||
|
@ -120,6 +139,12 @@ public:
|
||||||
/// Returns type function.
|
/// Returns type function.
|
||||||
Id OpTypeFunction(Id return_type, const std::vector<Id>& arguments = {});
|
Id OpTypeFunction(Id return_type, const std::vector<Id>& arguments = {});
|
||||||
|
|
||||||
|
/// Returns type function.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpTypeFunction(Id return_type, Ts&&... arguments) {
|
||||||
|
return OpTypeFunction(return_type, {arguments...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns type event.
|
/// Returns type event.
|
||||||
Id OpTypeEvent();
|
Id OpTypeEvent();
|
||||||
|
|
||||||
|
@ -149,6 +174,12 @@ public:
|
||||||
/// Returns a numeric scalar constant.
|
/// Returns a numeric scalar constant.
|
||||||
Id ConstantComposite(Id result_type, const std::vector<Id>& constituents);
|
Id ConstantComposite(Id result_type, const std::vector<Id>& constituents);
|
||||||
|
|
||||||
|
/// Returns a numeric scalar constant.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id ConstantComposite(Id result_type, Ts&&... constituents) {
|
||||||
|
return ConstantComposite(result_type, {constituents...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a sampler constant.
|
/// Returns a sampler constant.
|
||||||
Id ConstantSampler(Id result_type, spv::SamplerAddressingMode addressing_mode, bool normalized,
|
Id ConstantSampler(Id result_type, spv::SamplerAddressingMode addressing_mode, bool normalized,
|
||||||
spv::SamplerFilterMode filter_mode);
|
spv::SamplerFilterMode filter_mode);
|
||||||
|
@ -167,12 +198,25 @@ public:
|
||||||
/// Call a function.
|
/// Call a function.
|
||||||
Id OpFunctionCall(Id result_type, Id function, const std::vector<Id>& arguments = {});
|
Id OpFunctionCall(Id result_type, Id function, const std::vector<Id>& arguments = {});
|
||||||
|
|
||||||
|
/// Call a function.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpFunctionCall(Id result_type, Id function, Ts&&... arguments) {
|
||||||
|
return OpFunctionCall(result_type, function, {arguments...});
|
||||||
|
}
|
||||||
|
|
||||||
// Flow
|
// Flow
|
||||||
|
|
||||||
/// Declare a structured loop.
|
/// Declare a structured loop.
|
||||||
Id OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control,
|
Id OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control,
|
||||||
const std::vector<Id>& literals = {});
|
const std::vector<Id>& literals = {});
|
||||||
|
|
||||||
|
/// Declare a structured loop.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control,
|
||||||
|
Ts&&... literals) {
|
||||||
|
return OpLoopMerge(merge_block, continue_target, loop_control, {literals...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Declare a structured selection.
|
/// Declare a structured selection.
|
||||||
Id OpSelectionMerge(Id merge_block, spv::SelectionControlMask selection_control);
|
Id OpSelectionMerge(Id merge_block, spv::SelectionControlMask selection_control);
|
||||||
|
|
||||||
|
@ -232,29 +276,63 @@ public:
|
||||||
/// Store through a pointer.
|
/// Store through a pointer.
|
||||||
Id OpStore(Id pointer, Id object, std::optional<spv::MemoryAccessMask> memory_access = {});
|
Id OpStore(Id pointer, Id object, std::optional<spv::MemoryAccessMask> memory_access = {});
|
||||||
|
|
||||||
/// Create a pointer into a composite object that can be used with OpLoad
|
/// Create a pointer into a composite object that can be used with OpLoad and OpStore.
|
||||||
/// and OpStore.
|
|
||||||
Id OpAccessChain(Id result_type, Id base, const std::vector<Id>& indexes = {});
|
Id OpAccessChain(Id result_type, Id base, const std::vector<Id>& indexes = {});
|
||||||
|
|
||||||
|
/// Create a pointer into a composite object that can be used with OpLoad and OpStore.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpAccessChain(Id result_type, Id base, Ts&&... indexes) {
|
||||||
|
return OpAccessChain(result_type, base, {indexes...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Make a copy of a composite object, while modifying one part of it.
|
/// Make a copy of a composite object, while modifying one part of it.
|
||||||
Id OpCompositeInsert(Id result_type, Id object, Id composite,
|
Id OpCompositeInsert(Id result_type, Id object, Id composite,
|
||||||
const std::vector<Literal>& indexes = {});
|
const std::vector<Literal>& indexes = {});
|
||||||
|
|
||||||
|
/// Make a copy of a composite object, while modifying one part of it.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpCompositeInsert(Id result_type, Id object, Id composite, Ts&&... indexes) {
|
||||||
|
return OpCompositeInsert(result_type, object, composite, {indexes...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Extract a part of a composite object.
|
/// Extract a part of a composite object.
|
||||||
Id OpCompositeExtract(Id result_type, Id composite, const std::vector<Literal>& indexes = {});
|
Id OpCompositeExtract(Id result_type, Id composite, const std::vector<Literal>& indexes = {});
|
||||||
|
|
||||||
/// Construct a new composite object from a set of constituent objects that
|
/// Extract a part of a composite object.
|
||||||
/// will fully form it.
|
template <typename... Ts>
|
||||||
|
Id OpCompositeExtract(Id result_type, Id composite, Ts&&... indexes) {
|
||||||
|
return OpCompositeExtract(result_type, composite, {indexes...});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a new composite object from a set of constituent objects that will fully form it.
|
||||||
Id OpCompositeConstruct(Id result_type, const std::vector<Id>& ids);
|
Id OpCompositeConstruct(Id result_type, const std::vector<Id>& ids);
|
||||||
|
|
||||||
|
/// Construct a new composite object from a set of constituent objects that will fully form it.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpCompositeConstruct(Id result_type, Ts&&... ids) {
|
||||||
|
return OpCompositeConstruct(result_type, {ids...});
|
||||||
|
}
|
||||||
|
|
||||||
// Annotation
|
// Annotation
|
||||||
|
|
||||||
/// Add a decoration to target.
|
/// Add a decoration to target.
|
||||||
Id Decorate(Id target, spv::Decoration decoration, const std::vector<Literal>& literals = {});
|
Id Decorate(Id target, spv::Decoration decoration, const std::vector<Literal>& literals = {});
|
||||||
|
|
||||||
|
/// Add a decoration to target.
|
||||||
|
template <typename... Ts>
|
||||||
|
Id Decorate(Id target, spv::Decoration decoration, Ts&&... literals) {
|
||||||
|
return Decorate(target, decoration, {literals...});
|
||||||
|
}
|
||||||
|
|
||||||
Id MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration,
|
Id MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration,
|
||||||
const std::vector<Literal>& literals = {});
|
const std::vector<Literal>& literals = {});
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
Id MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration,
|
||||||
|
Ts&&... literals) {
|
||||||
|
return MemberDecorate(structure_type, member, decoration, {literals...});
|
||||||
|
}
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
|
|
||||||
/// Make an intermediate object whose value is undefined.
|
/// Make an intermediate object whose value is undefined.
|
||||||
|
@ -437,6 +515,11 @@ public:
|
||||||
Id OpExtInst(Id result_type, Id set, std::uint32_t instruction,
|
Id OpExtInst(Id result_type, Id set, std::uint32_t instruction,
|
||||||
const std::vector<Id>& operands);
|
const std::vector<Id>& operands);
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
Id OpExtInst(Id result_type, Id set, std::uint32_t instruction, Ts&&... operands) {
|
||||||
|
return OpExtInst(result_type, set, instruction, {operands...});
|
||||||
|
}
|
||||||
|
|
||||||
/// Result is x if x >= 0; otherwise result is -x.
|
/// Result is x if x >= 0; otherwise result is -x.
|
||||||
Id OpFAbs(Id result_type, Id x);
|
Id OpFAbs(Id result_type, Id x);
|
||||||
|
|
||||||
|
@ -595,14 +678,13 @@ private:
|
||||||
|
|
||||||
Id GetGLSLstd450();
|
Id GetGLSLstd450();
|
||||||
|
|
||||||
const std::uint32_t version;
|
std::uint32_t version{};
|
||||||
|
|
||||||
std::uint32_t bound{1};
|
std::uint32_t bound{1};
|
||||||
|
|
||||||
std::set<std::string> extensions;
|
std::unordered_set<std::string> extensions;
|
||||||
std::set<spv::Capability> capabilities;
|
std::unordered_set<spv::Capability> capabilities;
|
||||||
|
std::unordered_set<std::unique_ptr<Op>> ext_inst_import;
|
||||||
std::unique_ptr<Op> glsl_std_450;
|
std::unique_ptr<Op> glsl_std_450;
|
||||||
std::set<std::unique_ptr<Op>> ext_inst_import;
|
|
||||||
|
|
||||||
spv::AddressingModel addressing_model{spv::AddressingModel::Logical};
|
spv::AddressingModel addressing_model{spv::AddressingModel::Logical};
|
||||||
spv::MemoryModel memory_model{spv::MemoryModel::GLSL450};
|
spv::MemoryModel memory_model{spv::MemoryModel::GLSL450};
|
||||||
|
|
|
@ -22,17 +22,17 @@ Id Module::OpExtInst(Id result_type, Id set, u32 instruction, const std::vector<
|
||||||
|
|
||||||
#define DEFINE_UNARY(funcname, opcode) \
|
#define DEFINE_UNARY(funcname, opcode) \
|
||||||
Id Module::funcname(Id result_type, Id operand) { \
|
Id Module::funcname(Id result_type, Id operand) { \
|
||||||
return OpExtInst(result_type, GetGLSLstd450(), opcode, {operand}); \
|
return OpExtInst(result_type, GetGLSLstd450(), opcode, operand); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_BINARY(funcname, opcode) \
|
#define DEFINE_BINARY(funcname, opcode) \
|
||||||
Id Module::funcname(Id result_type, Id operand_1, Id operand_2) { \
|
Id Module::funcname(Id result_type, Id operand_1, Id operand_2) { \
|
||||||
return OpExtInst(result_type, GetGLSLstd450(), opcode, {operand_1, operand_2}); \
|
return OpExtInst(result_type, GetGLSLstd450(), opcode, operand_1, operand_2); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_TRINARY(funcname, opcode) \
|
#define DEFINE_TRINARY(funcname, opcode) \
|
||||||
Id Module::funcname(Id result_type, Id operand_1, Id operand_2, Id operand_3) { \
|
Id Module::funcname(Id result_type, Id operand_1, Id operand_2, Id operand_3) { \
|
||||||
return OpExtInst(result_type, GetGLSLstd450(), opcode, {operand_1, operand_2, operand_3}); \
|
return OpExtInst(result_type, GetGLSLstd450(), opcode, operand_1, operand_2, operand_3); \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_UNARY(OpFAbs, GLSLstd450FAbs)
|
DEFINE_UNARY(OpFAbs, GLSLstd450FAbs)
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Lesser General Public License version 3 or any later version.
|
* Lesser General Public License version 3 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sirit/sirit.h>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <sirit/sirit.h>
|
||||||
|
|
||||||
using u32 = uint32_t;
|
using u32 = uint32_t;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ public:
|
||||||
void Generate() {
|
void Generate() {
|
||||||
AddCapability(spv::Capability::Shader);
|
AddCapability(spv::Capability::Shader);
|
||||||
SetMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450);
|
SetMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450);
|
||||||
|
|
||||||
const auto t_void = Name(OpTypeVoid(), "void");
|
const auto t_void = Name(OpTypeVoid(), "void");
|
||||||
const auto t_uint = Name(OpTypeInt(32, false), "uint");
|
const auto t_uint = Name(OpTypeInt(32, false), "uint");
|
||||||
const auto t_float = Name(OpTypeFloat(32), "float");
|
const auto t_float = Name(OpTypeFloat(32), "float");
|
||||||
|
@ -26,45 +26,52 @@ public:
|
||||||
const auto float4 = Name(OpTypeVector(t_float, 4), "float4");
|
const auto float4 = Name(OpTypeVector(t_float, 4), "float4");
|
||||||
const auto in_float = Name(OpTypePointer(spv::StorageClass::Input, t_float), "in_float");
|
const auto in_float = Name(OpTypePointer(spv::StorageClass::Input, t_float), "in_float");
|
||||||
const auto in_float4 = Name(OpTypePointer(spv::StorageClass::Input, float4), "in_float4");
|
const auto in_float4 = Name(OpTypePointer(spv::StorageClass::Input, float4), "in_float4");
|
||||||
const auto out_float4 = Name(OpTypePointer(spv::StorageClass::Output, float4), "out_float4");
|
const auto out_float4 =
|
||||||
|
Name(OpTypePointer(spv::StorageClass::Output, float4), "out_float4");
|
||||||
|
|
||||||
|
const auto gl_per_vertex = Name(OpTypeStruct(float4), "gl_PerVertex");
|
||||||
|
const auto gl_per_vertex_ptr =
|
||||||
|
Name(OpTypePointer(spv::StorageClass::Output, gl_per_vertex), "out_gl_PerVertex");
|
||||||
|
|
||||||
const auto gl_per_vertex = Name(OpTypeStruct({float4}), "gl_PerVertex");
|
|
||||||
const auto gl_per_vertex_ptr = Name(OpTypePointer(spv::StorageClass::Output, gl_per_vertex), "out_gl_PerVertex");
|
|
||||||
|
|
||||||
const auto in_pos = Name(OpVariable(in_float4, spv::StorageClass::Input), "in_pos");
|
const auto in_pos = Name(OpVariable(in_float4, spv::StorageClass::Input), "in_pos");
|
||||||
const auto per_vertex = Name(OpVariable(gl_per_vertex_ptr, spv::StorageClass::Output), "per_vertex");
|
const auto per_vertex =
|
||||||
|
Name(OpVariable(gl_per_vertex_ptr, spv::StorageClass::Output), "per_vertex");
|
||||||
|
|
||||||
Decorate(in_pos, spv::Decoration::Location, {0});
|
Decorate(in_pos, spv::Decoration::Location, 0);
|
||||||
Decorate(gl_per_vertex, spv::Decoration::Block);
|
Decorate(gl_per_vertex, spv::Decoration::Block);
|
||||||
Decorate(gl_per_vertex, spv::Decoration::Block);
|
Decorate(gl_per_vertex, spv::Decoration::Block);
|
||||||
MemberDecorate(gl_per_vertex, 0, spv::Decoration::BuiltIn, {static_cast<u32>(spv::BuiltIn::Position)});
|
MemberDecorate(gl_per_vertex, 0, spv::Decoration::BuiltIn,
|
||||||
|
static_cast<u32>(spv::BuiltIn::Position));
|
||||||
|
|
||||||
AddGlobalVariable(in_pos);
|
AddGlobalVariable(in_pos);
|
||||||
AddGlobalVariable(per_vertex);
|
AddGlobalVariable(per_vertex);
|
||||||
|
|
||||||
const auto main_func = Emit(Name(OpFunction(t_void, spv::FunctionControlMask::MaskNone, OpTypeFunction(t_void)), "main"));
|
const auto main_func = Emit(
|
||||||
|
Name(OpFunction(t_void, spv::FunctionControlMask::MaskNone, OpTypeFunction(t_void)),
|
||||||
|
"main"));
|
||||||
Emit(OpLabel());
|
Emit(OpLabel());
|
||||||
|
|
||||||
const auto ptr_pos_x = Emit(OpAccessChain(in_float, in_pos, {Constant(t_uint, 0u)}));
|
const auto ptr_pos_x = Emit(OpAccessChain(in_float, in_pos, Constant(t_uint, 0u)));
|
||||||
const auto ptr_pos_y = Emit(OpAccessChain(in_float, in_pos, {Constant(t_uint, 1u)}));
|
const auto ptr_pos_y = Emit(OpAccessChain(in_float, in_pos, Constant(t_uint, 1u)));
|
||||||
|
|
||||||
const auto pos_x = Emit(OpLoad(t_float, ptr_pos_x));
|
const auto pos_x = Emit(OpLoad(t_float, ptr_pos_x));
|
||||||
const auto pos_y = Emit(OpLoad(t_float, ptr_pos_y));
|
const auto pos_y = Emit(OpLoad(t_float, ptr_pos_y));
|
||||||
|
|
||||||
auto tmp_position = Emit(OpUndef(float4));
|
auto tmp_position = Emit(OpUndef(float4));
|
||||||
Decorate(tmp_position, spv::Decoration::FPRoundingMode, {static_cast<u32>(spv::FPRoundingMode::RTE)});
|
Decorate(tmp_position, spv::Decoration::FPRoundingMode,
|
||||||
tmp_position = Emit(OpCompositeInsert(float4, pos_x, tmp_position, {0}));
|
static_cast<u32>(spv::FPRoundingMode::RTE));
|
||||||
tmp_position = Emit(OpCompositeInsert(float4, pos_y, tmp_position, {1}));
|
tmp_position = Emit(OpCompositeInsert(float4, pos_x, tmp_position, 0));
|
||||||
tmp_position = Emit(OpCompositeInsert(float4, Constant(t_float, 0.f), tmp_position, {2}));
|
tmp_position = Emit(OpCompositeInsert(float4, pos_y, tmp_position, 1));
|
||||||
tmp_position = Emit(OpCompositeInsert(float4, Constant(t_float, 1.f), tmp_position, {3}));
|
tmp_position = Emit(OpCompositeInsert(float4, Constant(t_float, 0.f), tmp_position, 2));
|
||||||
|
tmp_position = Emit(OpCompositeInsert(float4, Constant(t_float, 1.f), tmp_position, 3));
|
||||||
|
|
||||||
const auto gl_position = Emit(OpAccessChain(out_float4, per_vertex, {Constant(t_uint, 0u)}));
|
const auto gl_position = Emit(OpAccessChain(out_float4, per_vertex, Constant(t_uint, 0u)));
|
||||||
Emit(OpStore(gl_position, tmp_position));
|
Emit(OpStore(gl_position, tmp_position));
|
||||||
|
|
||||||
Emit(OpReturn());
|
Emit(OpReturn());
|
||||||
Emit(OpFunctionEnd());
|
Emit(OpFunctionEnd());
|
||||||
|
|
||||||
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main", {in_pos, per_vertex});
|
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main", in_pos, per_vertex);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue