Skip to content

Commit

Permalink
add getting allocation size & implicit views
Browse files Browse the repository at this point in the history
  • Loading branch information
martty committed Dec 26, 2024
1 parent d14ebca commit cf915ea
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 27 deletions.
55 changes: 51 additions & 4 deletions include/vuk/IR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "vuk/SourceLocation.hpp"
#include "vuk/SyncPoint.hpp"
#include "vuk/Types.hpp"
#include "vuk/runtime/vk/Allocation.hpp"
#include "vuk/runtime/vk/VkSwapchain.hpp" //TODO: leaking vk

#include <atomic>
Expand All @@ -31,6 +32,7 @@ namespace vuk {

struct Type {
enum TypeKind { MEMORY_TY = 1, INTEGER_TY, POINTER_TY, COMPOSITE_TY, ARRAY_TY, IMBUED_TY, ALIASED_TY, OPAQUE_FN_TY, SHADER_FN_TY } kind;
enum Tags { TAG_BUFFERLIKE_VIEW = 1, TAG_BUFFER = 2, TAG_IMAGE = 3, TAG_SWAPCHAIN = 4 };
size_t size = ~0ULL;

TypeDebugInfo debug_info;
Expand Down Expand Up @@ -149,6 +151,17 @@ namespace vuk {
return v;
}

bool is_bufferlike_view() const {
if (kind != COMPOSITE_TY) {
return false;
}
if (composite.tag == TAG_BUFFERLIKE_VIEW) {
return true;
}

return false;
}

// TODO: handle multiple flags
static std::string_view to_sv(Access acc) {
switch (acc) {
Expand Down Expand Up @@ -316,6 +329,7 @@ namespace vuk {
ACQUIRE_NEXT_IMAGE,
CAST,
MATH_BINARY,
GET_ALLOCATION_SIZE,
GARBAGE
} kind;
uint8_t flag = 0;
Expand Down Expand Up @@ -411,6 +425,9 @@ namespace vuk {
Ref b;
BinOp op;
} math_binary;
struct : Fixed<1> {
Ref ptr;
} get_allocation_size;
struct {
uint8_t arg_count;
} generic_node;
Expand Down Expand Up @@ -454,6 +471,8 @@ namespace vuk {
return "cast";
case GARBAGE:
return "garbage";
case GET_ALLOCATION_SIZE:
return "get_allocation_size";
}
assert(0);
return "";
Expand Down Expand Up @@ -1122,11 +1141,23 @@ namespace vuk {
}

std::shared_ptr<Type> make_pointer_ty(std::shared_ptr<Type> ty) {
auto t = new Type{ .kind = Type::POINTER_TY, .size = sizeof(uint64_t), .pointer = { } };
auto t = new Type{ .kind = Type::POINTER_TY, .size = sizeof(uint64_t), .pointer = {} };
t->pointer.T = &t->child_types.emplace_back(ty);
return emplace_type(std::shared_ptr<Type>(t));
}

std::shared_ptr<Type> make_bufferlike_view_ty(std::shared_ptr<Type> ty) {
auto buffer_ = std::vector<std::shared_ptr<Type>>{ make_pointer_ty(ty), u64() };
auto buffer_offsets = std::vector<size_t>{ sizeof(uint64_t) };
auto buffer_type = emplace_type(std::shared_ptr<Type>(new Type{ .kind = Type::COMPOSITE_TY,
.size = sizeof(view<BufferLike<void>>),
.debug_info = allocate_type_debug_info("view<b>"),
.offsets = buffer_offsets,
.composite = { .types = buffer_, .tag = Type::TAG_BUFFERLIKE_VIEW } }));
buffer_type->child_types = std::move(buffer_);
return buffer_type;
}

std::shared_ptr<Type> make_opaque_fn_ty(std::span<std::shared_ptr<Type> const> args,
std::span<std::shared_ptr<Type> const> ret_types,
DomainFlags execute_on,
Expand Down Expand Up @@ -1229,7 +1260,7 @@ namespace vuk {
.size = sizeof(ImageAttachment),
.debug_info = allocate_type_debug_info("image"),
.offsets = image_offsets,
.composite = { .types = image_, .tag = 0 } }));
.composite = { .types = image_, .tag = Type::TAG_IMAGE } }));
image_type->child_types = std::move(image_);
builtin_image = Type::hash(image_type.get());

Expand All @@ -1252,7 +1283,7 @@ namespace vuk {
.size = sizeof(Buffer),
.debug_info = allocate_type_debug_info("buffer"),
.offsets = buffer_offsets,
.composite = { .types = buffer_, .tag = 1 } }));
.composite = { .types = buffer_, .tag = Type::TAG_BUFFER } }));
buffer_type->child_types = std::move(buffer_);

builtin_buffer = Type::hash(buffer_type.get());
Expand All @@ -1276,7 +1307,7 @@ namespace vuk {
.size = sizeof(Swapchain*),
.debug_info = allocate_type_debug_info("swapchain"),
.offsets = offsets,
.composite = { .types = swp_, .tag = 2 } }));
.composite = { .types = swp_, .tag = Type::TAG_SWAPCHAIN } }));
builtin_swapchain = Type::hash(swapchain_type.get());
return swapchain_type;
}
Expand Down Expand Up @@ -1624,6 +1655,15 @@ namespace vuk {
.construct = { .args = std::span(args_ptr, 3) } }));
}

Ref make_construct(std::shared_ptr<Type> type, std::span<Ref> args) {
auto ty = new std::shared_ptr<Type>[1]{ type };
auto args_ptr = new Ref[args.size() + 1];
auto mem_ty = new std::shared_ptr<Type>[1]{ types.memory(0) };
args_ptr[0] = first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ mem_ty, 1 }, .constant = { .value = nullptr } }));
std::copy(args.begin(), args.end(), args_ptr + 1);
return first(emplace_op(Node{ .kind = Node::CONSTRUCT, .type = std::span{ ty, 1 }, .construct = { .args = std::span(args_ptr, args.size() + 1) } }));
}

Ref make_extract(Ref composite, Ref index) {
auto stripped = Type::stripped(composite.type());
assert(stripped->kind == Type::ARRAY_TY);
Expand All @@ -1643,6 +1683,13 @@ namespace vuk {
Node{ .kind = Node::EXTRACT, .type = std::span{ ty, 1 }, .extract = { .composite = composite, .index = make_constant<uint64_t>(index) } }));
}

Ref make_get_allocation_size(Ref ptr) {
auto ty = new std::shared_ptr<Type>[1]{ types.u64() };
return first(emplace_op(Node{ .kind = Node::GET_ALLOCATION_SIZE,
.type = std::span{ ty, 1 },
.get_allocation_size = { .ptr = ptr } }));
}

Ref make_slice(Ref image, Ref base_level, Ref level_count, Ref base_layer, Ref layer_count) {
auto stripped = Type::stripped(image.type());
auto ty = new std::shared_ptr<Type>[2]{ stripped, stripped };
Expand Down
24 changes: 22 additions & 2 deletions include/vuk/RenderGraph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ private:

// when this function is called, we weave in this call into the IR
return [untyped_cb = std::move(callback), name, scheduling_info, opaque_fn_ty, inner_scope = VUK_CALL](Value<typename T::type>... args,
VUK_CALLSTACK) mutable {
VUK_CALLSTACK) mutable {
auto& first = First(args...);

bool reuse_node = first.node.use_count() == 1 && first.node->acqrel->status == Signal::Status::eDisarmed;
Expand Down Expand Up @@ -450,7 +450,7 @@ private:
case DescriptorType::eUniformBuffer:
case DescriptorType::eStorageBuffer:
acc = b->non_writable ? Access::eComputeRead : (b->non_readable ? Access::eComputeWrite : Access::eComputeRW);
base_ty = current_module->types.make_pointer_ty(current_module->types.u32()); // TODO: become view
base_ty = current_module->types.make_bufferlike_view_ty(current_module->types.u32());
break;
case DescriptorType::eSampler:
acc = Access::eNone;
Expand Down Expand Up @@ -565,6 +565,26 @@ private:
return { std::move(ext_ref) };
}

template<class T>
[[nodiscard]] inline val_view<BufferLike<T>> acquire_view(Name name, view<BufferLike<T>> buf, Access access, VUK_CALLSTACK) {
assert(buf);
Ref ref = current_module->acquire(current_module->types.make_bufferlike_view_ty(current_module->types.u32()), nullptr, buf);
auto ext_ref = ExtRef(std::make_shared<ExtNode>(ref.node, to_use(access)), ref);
current_module->name_output(ref, name.c_str());
current_module->set_source_location(ref.node, VUK_CALL);
return { std::move(ext_ref) };
}

template<class T>
[[nodiscard]] inline val_view<BufferLike<T>> make_view(Name name, val_ptr<BufferLike<T>> buf, Value<size_t> size, VUK_CALLSTACK) {
assert(buf);
Ref ref = current_module->make_construct(current_module->types.make_bufferlike_view_ty(current_module->types.u32()), buf.get_head(), size.get_head());
auto ext_ref = make_ext_ref(ref, {buf.node, size.node});
current_module->name_output(ref, name.c_str());
current_module->set_source_location(ref.node, VUK_CALL);
return { std::move(ext_ref) };
}

// TODO: due to the pack, we can't do the source_location::current() trick
template<class T, class... Args>
[[nodiscard]] inline Value<T[]> declare_array(Name name, Value<T> arg, Args... args) {
Expand Down
39 changes: 24 additions & 15 deletions include/vuk/Value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace vuk {
Result<void> wait(Allocator& allocator, Compiler& compiler, RenderGraphCompileOptions options = {});

std::shared_ptr<ExtNode> node;

protected:
size_t index;
};
Expand Down Expand Up @@ -183,21 +184,21 @@ namespace vuk {
requires std::is_same_v<T, ImageAttachment>
{
Ref item = current_module->make_slice(get_head(),
current_module->make_constant(mip),
current_module->make_constant(1u),
current_module->make_constant(0u),
current_module->make_constant(VK_REMAINING_ARRAY_LAYERS));
current_module->make_constant(mip),
current_module->make_constant(1u),
current_module->make_constant(0u),
current_module->make_constant(VK_REMAINING_ARRAY_LAYERS));
return Value(ExtRef(std::make_shared<ExtNode>(item, node), item));
}

auto layer(uint32_t layer)
requires std::is_same_v<T, ImageAttachment>
{
Ref item = current_module->make_slice(get_head(),
current_module->make_constant(0u),
current_module->make_constant(VK_REMAINING_MIP_LEVELS),
current_module->make_constant(layer),
current_module->make_constant(1u));
current_module->make_constant(0u),
current_module->make_constant(VK_REMAINING_MIP_LEVELS),
current_module->make_constant(layer),
current_module->make_constant(1u));
return Value(ExtRef(std::make_shared<ExtNode>(item, node), item));
}

Expand All @@ -224,7 +225,7 @@ namespace vuk {
candidate_node.extract.composite = composite; // writing these out for clang workaround
candidate_node.extract.index = first(&constant_node);
current_module->garbage.push_back(def.node->construct.args[index + 1].node);
auto res = [&]() -> Result<void>{
auto res = [&]() -> Result<void> {
if (ty->kind == Type::INTEGER_TY && ty->integer.width == 64) {
auto result_ = eval<uint64_t>(first(&candidate_node));
if (!result_) {
Expand All @@ -244,19 +245,27 @@ namespace vuk {
}
return { expected_value };
}();
if(!res) {
if (!res) {
(void)res.error();
def.node->construct.args[index + 1] = current_module->make_extract(composite, index);
}
}

Value<view<T>> implicit_view()
requires std::is_base_of_v<ptr_base, T>
{
std::array args = { get_head(), current_module->make_get_allocation_size(get_head()) };
auto imp_view = current_module->make_construct(current_module->types.make_bufferlike_view_ty(current_module->types.u32()), args);
return { make_ext_ref(imp_view) };
}
};
template<class T, class...Ctrs>

template<class T, class... Ctrs>
using val_ptr = Value<ptr<T, Ctrs...>>;
/*
template<class T, class...Ctrs>

template<class T, class... Ctrs>
using val_view = Value<view<T, Ctrs...>>;
*/

inline Value<uint64_t> operator+(Value<uint64_t> a, uint64_t b) {
Ref ref = current_module->make_math_binary_op(Node::BinOp::ADD, a.get_head(), current_module->make_constant(b));
return std::move(a).transmute<uint64_t>(ref);
Expand Down
23 changes: 21 additions & 2 deletions include/vuk/runtime/vk/Allocation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ namespace vuk {

template<class Type = void, class... Constraints>
struct view : generic_view_base {
Type& operator[](size_t index)
auto& operator[](size_t index)
requires(!std::is_same_v<Type, void>)
{
if ((key & 0x3) == 0) { // generic memory view
Expand All @@ -76,7 +76,7 @@ namespace vuk {
}
}

const Type& operator[](size_t index) const
const auto& operator[](size_t index) const
requires(!std::is_same_v<Type, void>)
{
if ((key & 0x3) == 0) { // generic memory view
Expand All @@ -96,6 +96,15 @@ namespace vuk {
return reinterpret_cast<view<BufferLike<Type>>*>(key & ~0x3)->size();
}
}

auto& data() {
if ((key & 0x3) == 0) { // generic memory view
auto& ve = Resolver::per_thread->resolve_view(*this);
return static_cast<ptr<Type>&>(ve.ptr);
} else if ((key & 0x3) == 0x2) { // specific memory view
return reinterpret_cast<view<BufferLike<Type>>*>(key & ~0x3)->ptr;
}
}
};

template<class Type, class... Constraints>
Expand Down Expand Up @@ -131,6 +140,16 @@ namespace vuk {
v.key = reinterpret_cast<uintptr_t>(this) | 0x2;
return v;
}

explicit operator bool() const noexcept {
return !!ptr;
}

auto& data() {
return ptr;
}

std::strong_ordering operator<=>(const view<BufferLike<Type>, Constraints...>&) const noexcept = default;
};

template<class... Constraints>
Expand Down
5 changes: 5 additions & 0 deletions src/IRPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,11 @@ namespace vuk {
first(node).link().def = first(node);
break;

case Node::GET_ALLOCATION_SIZE:
add_read(node, node->get_allocation_size.ptr, 0);
add_breaking_result(node, 0);
break;

case Node::GARBAGE:
break;

Expand Down
39 changes: 36 additions & 3 deletions src/runtime/vk/Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,23 @@ namespace vuk {
}
node->construct.args[0].node->constant.value = arr_mem;
sched.done(node, host_stream, (void*)arr_mem);
} else if (node->type[0]->is_bufferlike_view()) {
for (size_t i = 1; i < node->construct.args.size(); i++) {
auto arg_ty = node->construct.args[i].type();
auto& parm = node->construct.args[i];

recorder.add_sync(sched.base_type(parm).get(), sched.get_dependency_info(parm, arg_ty.get(), RW::eWrite, nullptr), sched.get_value(parm));
}
auto p = sched.get_value<ptr<>>(node->construct.args[1]);
auto s = sched.get_value<size_t>(node->construct.args[2]);
#ifdef VUK_DUMP_EXEC
print_results(node);
fmt::print(" = construct<view<b>> ");
print_args(node->construct.args.subspan(1));
fmt::print("\n");
#endif
sched.done(node, host_stream, view<BufferLike<void>>{ p, s });
recorder.init_sync(node->type[0].get(), { to_use(eNone), host_stream }, sched.get_value(first(node)));
} else if (node->type[0]->hash_value == current_module->types.builtin_sampled_image) {
for (size_t i = 1; i < node->construct.args.size(); i++) {
auto arg_ty = node->construct.args[i].type();
Expand Down Expand Up @@ -1468,9 +1485,9 @@ namespace vuk {
break;
case DescriptorType::eUniformBuffer:
case DescriptorType::eStorageBuffer: {
auto ptr = *reinterpret_cast<ptr_base*>(val);
auto& ae = alloc.get_context().resolve_ptr(ptr);
Buffer buf{ nullptr, ae.buffer.buffer, ae.buffer.offset, ae.buffer.size };
auto& v = *reinterpret_cast<view<BufferLike<void>>*>(val);
auto& ae = alloc.get_context().resolve_ptr(v.data());
Buffer buf{ nullptr, ae.buffer.buffer, ae.buffer.offset, v.size() };
cobuf.bind_buffer(set, binding->binding, buf);
break;
}
Expand Down Expand Up @@ -1846,6 +1863,22 @@ namespace vuk {
}
break;
}
case Node::GET_ALLOCATION_SIZE: {
if (sched.process(item)) {
#ifdef VUK_DUMP_EXEC
print_results(node);
fmt::print(" = get_allocation_size ");
print_args({ &node->get_allocation_size.ptr, 1 });
fmt::print("\n");
#endif
auto ptr = sched.get_value<ptr_base>(node->get_allocation_size.ptr);
auto size = alloc.get_context().resolve_ptr(ptr).buffer.size;
sched.done(node, item.scheduled_stream, size); // converge doesn't execute
} else {
sched.schedule_dependency(node->get_allocation_size.ptr, RW::eRead);
}
break;
}
default:
assert(0);
}
Expand Down
Loading

0 comments on commit cf915ea

Please sign in to comment.