-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
407 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
#include <vull/container/vector.hh> | ||
#include <vull/support/variant.hh> | ||
|
||
#include <stdint.h> | ||
|
||
namespace vull::shaderc::hir { | ||
|
||
using ExprId = uint32_t; | ||
|
||
class BinaryExpr {}; | ||
|
||
using Expr = Variant<BinaryExpr>; | ||
|
||
class Root { | ||
Vector<Expr, ExprId> m_expressions; | ||
|
||
public: | ||
template <typename T, typename... Args> | ||
ExprId create_expr(Args &&... args) { | ||
m_expressions.push(T(vull::forward<Args>(args)...)); | ||
return m_expressions.size() - 1; | ||
} | ||
}; | ||
|
||
} // namespace vull::shaderc::hir |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
#pragma once | ||
|
||
#include <vull/container/hash_set.hh> | ||
#include <vull/container/vector.hh> | ||
#include <vull/support/hash.hh> | ||
#include <vull/support/string_view.hh> | ||
#include <vull/support/unique_ptr.hh> | ||
#include <vull/vulkan/spirv.hh> | ||
|
||
namespace vull::shaderc::spv { | ||
|
||
using namespace vull::vk::spv; | ||
|
||
class Builder; | ||
|
||
class Instruction { | ||
const Op m_op; | ||
const Id m_id; | ||
const Id m_type; | ||
|
||
// TODO(small-vector) | ||
Vector<Word> m_operands; | ||
|
||
public: | ||
static bool constant_equals(const Instruction &lhs, const Instruction &rhs) { return lhs.constant_equals(rhs); } | ||
static bool type_equals(const Instruction &lhs, const Instruction &rhs) { return lhs.type_equals(rhs); } | ||
static hash_t constant_hash(const Instruction &inst) { return inst.constant_hash(); } | ||
static hash_t type_hash(const Instruction &inst) { return inst.type_hash(); } | ||
|
||
Instruction() : Instruction(Op::Nop) {} | ||
Instruction(Op op, Id id = 0, Id type = 0) : m_op(op), m_id(id), m_type(type) {} | ||
|
||
template <typename T> | ||
void append_operand(T operand) requires(sizeof(T) <= sizeof(Word)) { | ||
append_operand(static_cast<Word>(operand)); | ||
} | ||
|
||
void append_operand(Word operand); | ||
void append_operand(StringView operand); | ||
void extend_operands(const Vector<Word> &operands); | ||
Word operand(uint32_t index) const { return m_operands[index]; } | ||
uint32_t operand_count() const { return m_operands.size(); } | ||
|
||
bool constant_equals(const Instruction &other) const; | ||
bool type_equals(const Instruction &other) const; | ||
hash_t constant_hash() const; | ||
hash_t type_hash() const; | ||
|
||
Op op() const { return m_op; } | ||
Id id() const { return m_id; } | ||
Id type() const { return m_type; } | ||
const Vector<Word> &operands() const { return m_operands; } | ||
}; | ||
|
||
class Block { | ||
Builder &m_builder; | ||
Instruction m_label; | ||
Vector<UniquePtr<Instruction>> m_instructions; | ||
|
||
public: | ||
explicit Block(Builder &builder); | ||
|
||
Instruction &append(Op op, Id type = 0); | ||
|
||
bool is_terminated() const; | ||
}; | ||
|
||
class Builder { | ||
Vector<Instruction> m_extension_imports; | ||
Vector<Instruction> m_decorations; | ||
HashSet<Instruction, &Instruction::type_hash, &Instruction::type_equals> m_types; | ||
HashSet<Instruction, &Instruction::constant_hash, &Instruction::constant_equals> m_constants; | ||
Id m_next_id{1}; | ||
|
||
Id ensure_constant(Instruction &&inst); | ||
Id ensure_type(Instruction &&inst); | ||
|
||
public: | ||
template <typename... Literals> | ||
void decorate(Id id, Decoration decoration, Literals... literals); | ||
template <typename... Literals> | ||
void decorate_member(Id struct_id, Word member, Decoration decoration, Literals... literals); | ||
|
||
Id import_extension(StringView name); | ||
|
||
Id scalar_constant(Id type, Word value); | ||
Id composite_constant(Id type, Vector<Id> &&elements); | ||
|
||
Id float_type(Word width); | ||
Id function_type(Id return_type, const Vector<Id> ¶meter_types); | ||
Id int_type(Word width, bool is_signed); | ||
Id matrix_type(Id column_type, Word column_count); | ||
Id pointer_type(StorageClass storage_class, Id pointee_type); | ||
Id struct_type(const Vector<Id> &member_types, bool is_block); | ||
Id vector_type(Id component_type, Word component_count); | ||
Id void_type(); | ||
|
||
Id make_id() { return m_next_id++; } | ||
}; | ||
|
||
template <typename... Literals> | ||
void Builder::decorate(Id id, Decoration decoration, Literals... literals) { | ||
auto &inst = m_decorations.emplace(Op::Decorate); | ||
inst.append_operand(id); | ||
inst.append_operand(decoration); | ||
(inst.append_operand(literals), ...); | ||
} | ||
|
||
template <typename... Literals> | ||
void Builder::decorate_member(Id struct_id, Word member, Decoration decoration, Literals... literals) { | ||
auto &inst = m_decorations.emplace(Op::MemberDecorate); | ||
inst.append_operand(struct_id); | ||
inst.append_operand(member); | ||
inst.append_operand(decoration); | ||
(inst.append_operand(literals), ...); | ||
} | ||
|
||
} // namespace vull::shaderc::spv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#include <vull/shaderc/spv_builder.hh> | ||
|
||
namespace vull::shaderc::spv { | ||
|
||
void Instruction::append_operand(Word operand) { | ||
m_operands.push(operand); | ||
} | ||
|
||
void Instruction::append_operand(StringView operand) { | ||
Word shift_amount = 0; | ||
Word word = 0; | ||
for (auto ch : operand) { | ||
word |= static_cast<Word>(ch) << shift_amount; | ||
if ((shift_amount += 8) == 32) { | ||
append_operand(vull::exchange(word, 0u)); | ||
shift_amount = 0; | ||
} | ||
} | ||
append_operand(word); | ||
} | ||
|
||
void Instruction::extend_operands(const Vector<Word> &operands) { | ||
m_operands.extend(operands); | ||
} | ||
|
||
bool Instruction::constant_equals(const Instruction &other) const { | ||
return type_equals(other) && m_type == other.m_type; | ||
} | ||
|
||
bool Instruction::type_equals(const Instruction &other) const { | ||
if (m_op != other.m_op) { | ||
return false; | ||
} | ||
if (m_operands.size() != other.m_operands.size()) { | ||
return false; | ||
} | ||
for (uint32_t i = 0; i < m_operands.size(); i++) { | ||
if (m_operands[i] != other.m_operands[i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
hash_t Instruction::constant_hash() const { | ||
return vull::hash_combine(type_hash(), m_type); | ||
} | ||
|
||
hash_t Instruction::type_hash() const { | ||
auto hash = vull::hash_of(m_op); | ||
for (Word operand : m_operands) { | ||
hash = vull::hash_combine(hash, operand); | ||
} | ||
return hash; | ||
} | ||
|
||
Block::Block(Builder &builder) : m_builder(builder), m_label(Op::Label, builder.make_id()) {} | ||
|
||
static bool op_has_id(Op op) { | ||
switch (op) { | ||
case Op::Store: | ||
case Op::Return: | ||
case Op::ReturnValue: | ||
return false; | ||
default: | ||
return true; | ||
} | ||
} | ||
|
||
Instruction &Block::append(Op op, Id type) { | ||
return *m_instructions.emplace(new Instruction(op, op_has_id(op) ? m_builder.make_id() : 0, type)); | ||
} | ||
|
||
bool Block::is_terminated() const { | ||
return !m_instructions.empty() && spv::is_terminator(m_instructions.last()->op()); | ||
} | ||
|
||
Id Builder::import_extension(StringView name) { | ||
auto &inst = m_extension_imports.emplace(Op::ExtInstImport, m_next_id++); | ||
inst.append_operand(name); | ||
return inst.id(); | ||
} | ||
|
||
Id Builder::ensure_constant(Instruction &&inst) { | ||
if (auto existing = m_constants.add(vull::move(inst))) { | ||
return existing->id(); | ||
} | ||
return m_next_id++; | ||
} | ||
|
||
Id Builder::scalar_constant(Id type, Word value) { | ||
Instruction inst(Op::Constant, m_next_id, type); | ||
inst.append_operand(value); | ||
return ensure_constant(vull::move(inst)); | ||
} | ||
|
||
Id Builder::composite_constant(Id type, Vector<Id> &&elements) { | ||
Instruction inst(Op::ConstantComposite, m_next_id, type); | ||
inst.extend_operands(elements); | ||
return ensure_constant(vull::move(inst)); | ||
} | ||
|
||
Id Builder::ensure_type(Instruction &&inst) { | ||
if (auto existing = m_types.add(vull::move(inst))) { | ||
return existing->id(); | ||
} | ||
return m_next_id++; | ||
} | ||
|
||
Id Builder::float_type(Word width) { | ||
Instruction inst(Op::TypeFloat, m_next_id); | ||
inst.append_operand(width); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
Id Builder::function_type(Id return_type, const Vector<Id> ¶meter_types) { | ||
Instruction inst(Op::TypeFunction, m_next_id); | ||
inst.append_operand(return_type); | ||
inst.extend_operands(parameter_types); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
Id Builder::int_type(Word width, bool is_signed) { | ||
Instruction inst(Op::TypeInt, m_next_id); | ||
inst.append_operand(width); | ||
inst.append_operand(is_signed ? 1 : 0); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
Id Builder::matrix_type(Id column_type, Word column_count) { | ||
Instruction inst(Op::TypeMatrix, m_next_id); | ||
inst.append_operand(column_type); | ||
inst.append_operand(column_count); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
Id Builder::pointer_type(StorageClass storage_class, Id pointee_type) { | ||
Instruction inst(Op::TypePointer, m_next_id); | ||
inst.append_operand(static_cast<Word>(storage_class)); | ||
inst.append_operand(pointee_type); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
Id Builder::struct_type(const Vector<Id> &member_types, bool is_block) { | ||
VULL_ENSURE(!is_block); | ||
Instruction inst(Op::TypeStruct, m_next_id); | ||
inst.extend_operands(member_types); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
Id Builder::vector_type(Id component_type, Word component_count) { | ||
Instruction inst(Op::TypeVector, m_next_id); | ||
inst.append_operand(component_type); | ||
inst.append_operand(component_count); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
Id Builder::void_type() { | ||
Instruction inst(Op::TypeVoid, m_next_id); | ||
return ensure_type(vull::move(inst)); | ||
} | ||
|
||
} // namespace vull::shaderc::spv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.