diff --git a/include/vuk/Flags.hpp b/include/vuk/Flags.hpp index 4a6126f9..ac2c2270 100644 --- a/include/vuk/Flags.hpp +++ b/include/vuk/Flags.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include namespace vuk { @@ -15,7 +15,8 @@ namespace vuk { constexpr Flags(BitType bit) noexcept : m_mask(static_cast(bit)) {} - constexpr Flags(Flags const& rhs) noexcept : m_mask(rhs.m_mask) {} + constexpr Flags(Flags const& rhs) noexcept = default; + constexpr Flags& operator=(Flags const& rhs) noexcept = default; constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {} diff --git a/include/vuk/IR.hpp b/include/vuk/IR.hpp index 3ff4210b..80be6a70 100644 --- a/include/vuk/IR.hpp +++ b/include/vuk/IR.hpp @@ -1,23 +1,18 @@ #pragma once #include "vuk/Buffer.hpp" +#include "vuk/Exception.hpp" #include "vuk/ImageAttachment.hpp" #include "vuk/RelSpan.hpp" #include "vuk/ResourceUse.hpp" -#include "vuk/runtime/vk/VkSwapchain.hpp" //TODO: leaking vk -#include "vuk/ShortAlloc.hpp" -#include "vuk/SourceLocation.hpp" -#include "vuk/SyncPoint.hpp" -#include "vuk/Types.hpp" +#include "vuk/Result.hpp" +#include "vuk/runtime/vk/Allocator.hpp" #include -#include #include #include #include -#include #include -#include #include // #define VUK_GARBAGE_SAN @@ -32,8 +27,13 @@ namespace vuk { using UserCallbackType = fu2::unique_function, std::span, std::span)>; struct Type { - enum TypeKind { VOID_TY = 0, MEMORY_TY = 1, INTEGER_TY, COMPOSITE_TY, ARRAY_TY, UNION_TY, IMBUED_TY, ALIASED_TY, OPAQUE_FN_TY, SHADER_FN_TY } kind; + enum struct TypeKind { VOID_TY = 0, MEMORY_TY = 1, INTEGER_TY, COMPOSITE_TY, ARRAY_TY, UNION_TY, IMBUED_TY, ALIASED_TY, OPAQUE_FN_TY, SHADER_FN_TY } kind; + using enum TypeKind; + + using Hash = uint32_t; + size_t size = ~0ULL; + Hash hash_value; TypeDebugInfo debug_info; @@ -76,193 +76,17 @@ namespace vuk { } composite; }; - ~Type() {} + ~Type() = default; - static std::shared_ptr stripped(std::shared_ptr t) { - switch (t->kind) { - case IMBUED_TY: - return stripped(*t->imbued.T); - case ALIASED_TY: - return stripped(*t->aliased.T); - default: - return t; - } - } + [[nodiscard]] static std::shared_ptr stripped(std::shared_ptr t); - static std::shared_ptr extract(std::shared_ptr t, size_t index) { - assert(t->kind == COMPOSITE_TY); - assert(index < t->composite.types.size()); - return t->composite.types[index]; - } + [[nodiscard]] static std::shared_ptr extract(std::shared_ptr t, size_t index); - using Hash = uint32_t; - Hash hash_value; - - static Hash hash_integer(size_t width) { - Hash v = (Hash)Type::INTEGER_TY; - hash_combine_direct(v, width); - return v; - } + [[nodiscard]] static Hash hash_integer(size_t width); + [[nodiscard]] static Hash hash(Type const* t); - static Hash hash(Type const* t) { - Hash v = (Hash)t->kind; - switch (t->kind) { - case VOID_TY: - return v; - case IMBUED_TY: - hash_combine_direct(v, Type::hash(t->imbued.T->get())); - hash_combine_direct(v, (uint32_t)t->imbued.access); - return v; - case ALIASED_TY: - hash_combine_direct(v, Type::hash(t->aliased.T->get())); - hash_combine_direct(v, (uint32_t)t->aliased.ref_idx); - return v; - case MEMORY_TY: - hash_combine_direct(v, (uint32_t)t->size); - return v; - case INTEGER_TY: - hash_combine_direct(v, t->integer.width); - return v; - case ARRAY_TY: - hash_combine_direct(v, Type::hash(t->array.T->get())); - hash_combine_direct(v, (uint32_t)t->array.count); - return v; - case UNION_TY: - case COMPOSITE_TY: { - for (int i = 0; i < t->composite.types.size(); i++) { - hash_combine_direct(v, Type::hash(t->composite.types[i].get())); - } - hash_combine_direct(v, (uint32_t)t->composite.tag); - return v; - } - case OPAQUE_FN_TY: - hash_combine_direct(v, (uintptr_t)t->opaque_fn.hash_code >> 32); - hash_combine_direct(v, (uintptr_t)t->opaque_fn.hash_code & 0xffffffff); - return v; - case SHADER_FN_TY: - hash_combine_direct(v, (uintptr_t)t->shader_fn.shader >> 32); - hash_combine_direct(v, (uintptr_t)t->shader_fn.shader & 0xffffffff); - return v; - } - assert(0); - return v; - } - - // TODO: handle multiple flags - static std::string_view to_sv(Access acc) { - switch (acc) { - case eNone: - return "None"; - case eClear: - return "Clear"; - case eColorWrite: - return "ColorW"; - case eColorRead: - return "ColorR"; - case eColorRW: - return "ColorRW"; - case eDepthStencilRead: - return "DSRead"; - case eDepthStencilWrite: - return "DSWrite"; - case eDepthStencilRW: - return "DSRW"; - case eVertexSampled: - return "VtxS"; - case eVertexRead: - return "VtxR"; - case eAttributeRead: - return "AttrR"; - case eIndexRead: - return "IdxR"; - case eIndirectRead: - return "IndirR"; - case eFragmentSampled: - return "FragS"; - case eFragmentRead: - return "FragR"; - case eFragmentWrite: - return "FragW"; - case eFragmentRW: - return "FragRW"; - case eTransferRead: - return "XferR"; - case eTransferWrite: - return "XferW"; - case eTransferRW: - return "XferRW"; - case eComputeRead: - return "CompR"; - case eComputeWrite: - return "CompW"; - case eComputeRW: - return "CompRW"; - case eComputeSampled: - return "CompS"; - case eRayTracingRead: - return "RTR"; - case eRayTracingWrite: - return "RTW"; - case eRayTracingRW: - return "RTRW"; - case eRayTracingSampled: - return "RTS"; - case eAccelerationStructureBuildRead: - return "ASBuildR"; - case eAccelerationStructureBuildWrite: - return "ASBuildW"; - case eAccelerationStructureBuildRW: - return "ASBuildRW"; - case eHostRead: - return "HostR"; - case eHostWrite: - return "HostW"; - case eHostRW: - return "HostRW"; - case eMemoryRead: - return "MemR"; - case eMemoryWrite: - return "MemW"; - case eMemoryRW: - return "MemRW"; - default: - return ""; - } - } - - static std::string to_string(Type* t) { - switch (t->kind) { - case VOID_TY: - return "void"; - case IMBUED_TY: - return to_string(t->imbued.T->get()) + std::string(":") + std::string(to_sv(t->imbued.access)); - case ALIASED_TY: - return to_string(t->aliased.T->get()) + std::string("@") + std::to_string(t->aliased.ref_idx); - case MEMORY_TY: - return "mem"; - case INTEGER_TY: - return t->integer.width == 32 ? "i32" : "i64"; - case ARRAY_TY: - return to_string(t->array.T->get()) + "[" + std::to_string(t->array.count) + "]"; - case COMPOSITE_TY: - if (!t->debug_info.name.empty()) { - return std::string(t->debug_info.name); - } - return "composite:" + std::to_string(t->composite.tag); - case UNION_TY: - if (!t->debug_info.name.empty()) { - return std::string(t->debug_info.name); - } - return "union:" + std::to_string(t->composite.tag); - case OPAQUE_FN_TY: - return "ofn"; - case SHADER_FN_TY: - return "sfn"; - default: - assert(0); - return "?"; - } - } + [[nodiscard]] static std::string_view to_sv(Access acc); + [[nodiscard]] static std::string to_string(Type* t); }; template @@ -447,48 +271,7 @@ namespace vuk { } variable_node; }; - static std::string_view kind_to_sv(Node::Kind kind) { - switch (kind) { - case PLACEHOLDER: - return "placeholder"; - case CONSTANT: - return "constant"; - case IMPORT: - return "import"; - case CONSTRUCT: - return "construct"; - case ACQUIRE_NEXT_IMAGE: - return "acquire_next_image"; - case CALL: - return "call"; - case MATH_BINARY: - return "math_b"; - case SLICE: - return "slice"; - case CONVERGE: - return "converge"; - case CLEAR: - return "clear"; - case CAST: - return "cast"; - case GARBAGE: - return "garbage"; - case RELEASE: - return "release"; - case ACQUIRE: - return "acquire"; - case USE: - return "use"; - case SET: - return "set"; - case LOGICAL_COPY: - return "lcopy"; - case COMPILE_PIPELINE: - return "compile_pipeline"; - } - assert(0); - return ""; - } + [[nodiscard]] static std::string_view kind_to_sv(Node::Kind kind); }; inline Ref first(Node* node) noexcept { @@ -656,7 +439,7 @@ namespace vuk { return reinterpret_cast(a_->ensure_space(n * sizeof(T))); } - void deallocate(T* p, std::size_t n) noexcept {} + void deallocate([[maybe_unused]] T* p, [[maybe_unused]] std::size_t n) noexcept {} template friend bool operator==(const inline_alloc& x, const inline_alloc& y) noexcept; @@ -705,410 +488,43 @@ namespace vuk { size_t union_tag_type_counter = 0; // TYPES - std::shared_ptr make_void_ty() { - auto t = new Type{ .kind = Type::VOID_TY }; - return emplace_type(std::shared_ptr(t)); - } - - std::shared_ptr make_imbued_ty(std::shared_ptr ty, Access access) { - auto t = new Type{ .kind = Type::IMBUED_TY, .size = ty->size, .imbued = { .access = access } }; - t->imbued.T = &t->child_types.emplace_back(ty); - return emplace_type(std::shared_ptr(t)); - } - - std::shared_ptr make_aliased_ty(std::shared_ptr ty, size_t ref_idx) { - auto t = new Type{ .kind = Type::ALIASED_TY, .size = ty->size, .aliased = { .ref_idx = ref_idx } }; - t->imbued.T = &t->child_types.emplace_back(ty); - return emplace_type(std::shared_ptr(t)); - } - - std::shared_ptr make_array_ty(std::shared_ptr ty, size_t count) { - auto t = new Type{ .kind = Type::ARRAY_TY, .size = count * ty->size, .array = { .count = count, .stride = ty->size } }; - t->array.T = &t->child_types.emplace_back(ty); - return emplace_type(std::shared_ptr(t)); - } - - std::shared_ptr make_union_ty(std::vector> types) { - std::vector offsets; - size_t offset = 0; - for (auto& t : types) { - offsets.push_back(offset); - offset += t->size; - } - auto union_type = emplace_type(std::shared_ptr( - new Type{ .kind = Type::UNION_TY, .size = offset, .offsets = offsets, .composite = { .types = types, .tag = union_tag_type_counter++ } })); - union_type->child_types = std::move(types); - return union_type; - } - + std::shared_ptr make_void_ty(); + std::shared_ptr make_imbued_ty(std::shared_ptr ty, Access access); + std::shared_ptr make_aliased_ty(std::shared_ptr ty, size_t ref_idx); + std::shared_ptr make_array_ty(std::shared_ptr ty, size_t count); + std::shared_ptr make_union_ty(std::vector> types); std::shared_ptr make_opaque_fn_ty(std::span const> args, std::span const> ret_types, DomainFlags execute_on, size_t hash_code, UserCallbackType callback, - std::string_view name) { - auto arg_ptr_ret_ty_ptr = std::vector>(args.size() + ret_types.size()); - auto it = std::copy(args.begin(), args.end(), arg_ptr_ret_ty_ptr.begin()); - std::copy(ret_types.begin(), ret_types.end(), it); - auto t = new Type{ .kind = Type::OPAQUE_FN_TY, - .opaque_fn = { .args = std::span{ arg_ptr_ret_ty_ptr.data(), args.size() }, - .return_types = std::span{ arg_ptr_ret_ty_ptr.data() + args.size(), ret_types.size() }, - .hash_code = hash_code, - .execute_on = execute_on.m_mask } }; - t->callback = std::make_unique(std::move(callback)); - t->child_types = std::move(arg_ptr_ret_ty_ptr); - t->debug_info = allocate_type_debug_info(std::string(name)); - return emplace_type(std::shared_ptr(t)); - } - + std::string_view name); std::shared_ptr make_shader_fn_ty(std::span const> args, std::span const> ret_types, DomainFlags execute_on, void* shader, - std::string_view name) { - auto arg_ptr_ret_ty_ptr = std::vector>(args.size() + ret_types.size()); - auto it = std::copy(args.begin(), args.end(), arg_ptr_ret_ty_ptr.begin()); - std::copy(ret_types.begin(), ret_types.end(), it); - auto t = new Type{ .kind = Type::SHADER_FN_TY, - .shader_fn = { .shader = shader, - .args = std::span{ arg_ptr_ret_ty_ptr.data(), args.size() }, - .return_types = std::span{ arg_ptr_ret_ty_ptr.data() + args.size(), ret_types.size() }, - .execute_on = execute_on.m_mask } }; - t->child_types = std::move(arg_ptr_ret_ty_ptr); - t->debug_info = allocate_type_debug_info(std::string(name)); - return emplace_type(std::shared_ptr(t)); - } - - std::shared_ptr u64() { - auto hash = Type::hash_integer(64); - auto it = type_map.find(hash); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - - return emplace_type(std::shared_ptr(new Type{ .kind = Type::INTEGER_TY, .size = sizeof(uint64_t), .integer = { .width = 64 } })); - } - - std::shared_ptr u32() { - auto hash = Type::hash_integer(32); - auto it = type_map.find(hash); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - - return emplace_type(std::shared_ptr(new Type{ .kind = Type::INTEGER_TY, .size = sizeof(uint32_t), .integer = { .width = 32 } })); - } - - std::shared_ptr memory(size_t size) { - Type ty{ .kind = Type::MEMORY_TY, .size = size }; - auto it = type_map.find(Type::hash(&ty)); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - return emplace_type(std::shared_ptr(new Type{ .kind = Type::MEMORY_TY, .size = size })); - } - - std::shared_ptr get_builtin_image() { - if (builtin_image) { - auto it = type_map.find(builtin_image); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - } - - auto u32_t = u32(); - auto image_ = std::vector>{ u32_t, u32_t, u32_t, memory(sizeof(Format)), memory(sizeof(Samples)), u32_t, u32_t, u32_t, u32_t }; - // TODO: crimes -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Winvalid-offsetof" -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Winvalid-offsetof" - auto image_offsets = std::vector{ offsetof(ImageAttachment, extent) + offsetof(Extent3D, width), - offsetof(ImageAttachment, extent) + offsetof(Extent3D, height), - offsetof(ImageAttachment, extent) + offsetof(Extent3D, depth), - offsetof(ImageAttachment, format), - offsetof(ImageAttachment, sample_count), - offsetof(ImageAttachment, base_layer), - offsetof(ImageAttachment, layer_count), - offsetof(ImageAttachment, base_level), - offsetof(ImageAttachment, level_count) }; -#pragma GCC diagnostic pop -#pragma clang diagnostic pop - auto image_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, - .size = sizeof(ImageAttachment), - .debug_info = allocate_type_debug_info("image"), - .offsets = image_offsets, - .composite = { .types = image_, .tag = 0 } })); - image_type->child_types = std::move(image_); - builtin_image = Type::hash(image_type.get()); - - return image_type; - } - - std::shared_ptr get_builtin_buffer() { - if (builtin_buffer) { - auto it = type_map.find(builtin_buffer); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - } - - auto buffer_ = std::vector>{ u64() }; - auto buffer_offsets = std::vector{ offsetof(Buffer, size) }; - auto buffer_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, - .size = sizeof(Buffer), - .debug_info = allocate_type_debug_info("buffer"), - .offsets = buffer_offsets, - .composite = { .types = buffer_, .tag = 1 } })); - buffer_type->child_types = std::move(buffer_); - - builtin_buffer = Type::hash(buffer_type.get()); - return buffer_type; - } - - std::shared_ptr get_builtin_swapchain() { - if (builtin_swapchain) { - auto it = type_map.find(builtin_swapchain); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - } - auto arr_ty = make_array_ty(get_builtin_image(), 16); - auto swp_ = std::vector>{ arr_ty }; - auto offsets = std::vector{ 0 }; - - auto swapchain_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, - .size = sizeof(Swapchain*), - .debug_info = allocate_type_debug_info("swapchain"), - .offsets = offsets, - .composite = { .types = swp_, .tag = 2 } })); - builtin_swapchain = Type::hash(swapchain_type.get()); - return swapchain_type; - } - - std::shared_ptr get_builtin_sampler() { - if (builtin_sampler) { - auto it = type_map.find(builtin_sampler); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - } - auto sampler_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, - .size = sizeof(SamplerCreateInfo), - .debug_info = allocate_type_debug_info("sampler"), - .offsets = {}, - .composite = { .types = {}, .tag = 3 } })); - builtin_sampler = Type::hash(sampler_type.get()); - return sampler_type; - } - - std::shared_ptr get_builtin_sampled_image() { - if (builtin_sampled_image) { - auto it = type_map.find(builtin_sampled_image); - if (it != type_map.end()) { - if (auto ty = it->second.lock()) { - return ty; - } - } - } - auto sampled_image_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, - .size = sizeof(SampledImage), - .debug_info = allocate_type_debug_info("sampled_image"), - .offsets = {}, - .composite = { .types = {}, .tag = 4 } })); - builtin_sampled_image = Type::hash(sampled_image_type.get()); - return sampled_image_type; - } - - std::shared_ptr emplace_type(std::shared_ptr t) { - auto unify_type = [&](std::shared_ptr& t) { - auto th = Type::hash(t.get()); - auto [v, succ] = type_map.try_emplace(th, t); - if (succ) { - t->hash_value = th; - } else if (!v->second.lock()) { - type_map[th] = t; - } - t->hash_value = th; - }; - - if (t->kind == Type::ALIASED_TY) { - assert((*t->aliased.T)->kind != Type::ALIASED_TY); - unify_type(*t->aliased.T); - } else if (t->kind == Type::IMBUED_TY) { - unify_type(*t->imbued.T); - } else if (t->kind == Type::ARRAY_TY) { - unify_type(*t->array.T); - } else if (t->kind == Type::COMPOSITE_TY) { - for (auto& elem_ty : t->composite.types) { - unify_type(elem_ty); - } - } - unify_type(t); - - return t; - } - - TypeDebugInfo allocate_type_debug_info(std::string name) { - return TypeDebugInfo{ name }; - } - - void collect() { - for (auto it = type_map.begin(); it != type_map.end();) { - if (it->second.expired()) { - it = type_map.erase(it); - } else { - ++it; - } - } - } - - void destroy(Type* t, void* v) { - if (t->hash_value == builtin_buffer) { - std::destroy_at((Buffer*)v); - } else if (t->hash_value == builtin_image) { - std::destroy_at((ImageAttachment*)v); - } else if (t->hash_value == builtin_sampled_image) { - std::destroy_at((SampledImage*)v); - } else if (t->hash_value == builtin_sampler) { - std::destroy_at((SamplerCreateInfo*)v); - } else if (t->hash_value == builtin_swapchain) { - std::destroy_at((Swapchain**)v); - } else if (t->kind == Type::INTEGER_TY) { - // nothing to do - } else if (t->kind == Type::MEMORY_TY) { - // nothing to do - } else if (t->kind == Type::IMBUED_TY) { - destroy(t->imbued.T->get(), v); - } else if (t->kind == Type::ALIASED_TY) { - destroy(t->aliased.T->get(), v); - } else if (t->kind == Type::ARRAY_TY || t->kind == Type::UNION_TY) { - // currently arrays and unions don't own their values - /* auto cv = (char*)v; - for (auto i = 0; i < t->array.count; i++) { - destroy(t->array.T->get(), cv); - cv += t->array.stride; - }*/ - } else { - assert(0); - } - delete[] (std::byte*)v; - } + std::string_view name); + std::shared_ptr u64(); + std::shared_ptr u32(); + std::shared_ptr memory(size_t size); + std::shared_ptr get_builtin_image(); + std::shared_ptr get_builtin_buffer(); + std::shared_ptr get_builtin_swapchain(); + std::shared_ptr get_builtin_sampler(); + std::shared_ptr get_builtin_sampled_image(); + std::shared_ptr emplace_type(std::shared_ptr t); + TypeDebugInfo allocate_type_debug_info(std::string name); + void collect(); + void destroy(Type* t, void* v); } types; - Node* emplace_op(Node v) { - v.index = module_id << 32 | node_counter++; - return &*op_arena.emplace(std::move(v)); - } - - void name_output(Ref ref, std::string_view name) { - auto node = ref.node; - if (!node->debug_info) { - node->debug_info = new NodeDebugInfo; - } - auto& names = ref.node->debug_info->result_names; - if (names.size() <= ref.index) { - names.resize(ref.index + 1); - } - names[ref.index] = name; - } - - void set_source_location(Node* node, SourceLocationAtFrame loc) { - if (!node->debug_info) { - node->debug_info = new NodeDebugInfo; - } - auto p = &loc; - size_t cnt = 0; - do { - cnt++; - p = p->parent; - } while (p != nullptr); - if (node->debug_info->trace.data()) { - delete[] node->debug_info->trace.data(); - } - node->debug_info->trace = std::span(new vuk::source_location[cnt], cnt); - p = &loc; - cnt = 0; - do { - node->debug_info->trace[cnt] = p->location; - cnt++; - p = p->parent; - } while (p != nullptr); - } - - std::optional::iterator> destroy_node(Node* node) { - delete node->rel_acq; - switch (node->kind) { - case Node::CONSTANT: { - if (node->constant.owned) { - delete[] (char*)node->constant.value; - } - break; - } - case Node::ACQUIRE: { - for (auto i = 0; i < node->acquire.values.size(); i++) { - auto& v = node->acquire.values[i]; - types.destroy(Type::stripped(node->type[i]).get(), v); - } - delete[] node->acquire.values.data(); - break; - } - default: // nothing extra to be done here - break; - } - delete[] node->type.data(); - if (node->generic_node.arg_count == (uint8_t)~0u) { - delete[] node->variable_node.args.data(); - } - if (node->scheduling_info) - delete node->scheduling_info; - if (node->debug_info) { - if (node->debug_info->trace.size() > 0) { - delete[] node->debug_info->trace.data(); - } - - delete node->debug_info; - } - - auto it = op_arena.get_iterator(node); - if (it != op_arena.end()) { -#ifdef VUK_GARBAGE_SAN - node->kind = Node::GARBAGE; - node->generic_node.arg_count = 0; - node->type = {}; -#else - return op_arena.erase(it); -#endif - } else { - node->kind = Node::GARBAGE; - node->generic_node.arg_count = 0; - node->type = {}; - } - return {}; - } - + Node* emplace_op(Node v); + void name_output(Ref ref, std::string_view name); + void set_source_location(Node* node, SourceLocationAtFrame loc); + std::optional::iterator> destroy_node(Node* node); // OPS - Ref make_constant(std::shared_ptr type, void* value) { - std::shared_ptr* ty = new std::shared_ptr[1]{ type }; - auto value_ptr = new char[type->size]; - memcpy(value_ptr, value, type->size); - return first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ ty, 1 }, .constant = { .value = value_ptr, .owned = true } })); - } + Ref make_constant(std::shared_ptr type, void* value); template Ref make_constant(T value) { @@ -1137,9 +553,7 @@ namespace vuk { return first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ ty, 1 }, .constant = { .value = value, .owned = false } })); } - void set_value(Ref ref, size_t index, Ref value) { - emplace_op(Node{ .kind = Node::SET, .set = { .dst = ref, .value = value, .index = index } }); - } + void set_value(Ref ref, size_t index, Ref value); template void set_value(Ref ref, size_t index, T value) { @@ -1147,202 +561,26 @@ namespace vuk { emplace_op(Node{ .kind = Node::SET, .set = { .dst = ref, .value = co, .index = index } }); } - Ref make_declare_image(ImageAttachment value) { - auto ptr = new (new char[sizeof(ImageAttachment)]) - ImageAttachment(value); /* rest extent_x extent_y extent_z format samples base_layer layer_count base_level level_count */ - auto args_ptr = new Ref[10]; - auto mem_ty = new std::shared_ptr[1]{ types.memory(sizeof(ImageAttachment)) }; - args_ptr[0] = first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ mem_ty, 1 }, .constant = { .value = ptr, .owned = true } })); - if (value.extent.width > 0) { - args_ptr[1] = make_constant(&ptr->extent.width); - } else { - args_ptr[1] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); - } - if (value.extent.height > 0) { - args_ptr[2] = make_constant(&ptr->extent.height); - } else { - args_ptr[2] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); - } - if (value.extent.depth > 0) { - args_ptr[3] = make_constant(&ptr->extent.depth); - } else { - args_ptr[3] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); - } - if (value.format != Format::eUndefined) { - args_ptr[4] = make_constant(&ptr->format); - } else { - args_ptr[4] = - first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.memory(sizeof(Format)) }, 1 } })); - } - if (value.sample_count != Samples::eInfer) { - args_ptr[5] = make_constant(&ptr->sample_count); - } else { - args_ptr[5] = - first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.memory(sizeof(Samples)) }, 1 } })); - } - if (value.base_layer != VK_REMAINING_ARRAY_LAYERS) { - args_ptr[6] = make_constant(&ptr->base_layer); - } else { - args_ptr[6] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); - } - if (value.layer_count != VK_REMAINING_ARRAY_LAYERS) { - args_ptr[7] = make_constant(&ptr->layer_count); - } else { - args_ptr[7] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); - } - if (value.base_level != VK_REMAINING_MIP_LEVELS) { - args_ptr[8] = make_constant(&ptr->base_level); - } else { - args_ptr[8] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); - } - if (value.level_count != VK_REMAINING_MIP_LEVELS) { - args_ptr[9] = make_constant(&ptr->level_count); - } else { - args_ptr[9] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); - } - - return first(emplace_op(Node{ .kind = Node::CONSTRUCT, - .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_image() }, 1 }, - .construct = { .args = std::span(args_ptr, 10) } })); - } - - Ref make_declare_buffer(Buffer value) { - auto buf_ptr = new (new char[sizeof(Buffer)]) Buffer(value); /* rest size */ - auto args_ptr = new Ref[2]; - auto mem_ty = new std::shared_ptr[1]{ types.memory(sizeof(Buffer)) }; - args_ptr[0] = first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ mem_ty, 1 }, .constant = { .value = buf_ptr, .owned = true } })); - if (value.size != ~(0ULL)) { - args_ptr[1] = make_constant(&buf_ptr->size); - } else { - args_ptr[1] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u64() }, 1 } })); - } - - return first(emplace_op(Node{ .kind = Node::CONSTRUCT, - .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_buffer() }, 1 }, - .construct = { .args = std::span(args_ptr, 2) } })); - } - - Ref make_declare_array(std::shared_ptr type, std::span args) { - auto arr_ty = new std::shared_ptr[1]{ types.make_array_ty(type, args.size()) }; - auto args_ptr = new Ref[args.size() + 1]; - auto mem_ty = new std::shared_ptr[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{ arr_ty, 1 }, .construct = { .args = std::span(args_ptr, args.size() + 1) } })); - } - - Ref make_declare_union(std::span args) { - std::vector> child_types; - for (auto& arg : args) { - child_types.push_back(Type::stripped(arg.type())); - } - auto union_ty = new std::shared_ptr[1]{ types.make_union_ty(std::move(child_types)) }; - auto args_ptr = new Ref[args.size() + 1]; - auto mem_ty = new std::shared_ptr[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{ union_ty, 1 }, .construct = { .args = std::span(args_ptr, args.size() + 1) } })); - } - - Ref make_declare_swapchain(Swapchain& bundle) { - auto swpptr = new (new char[sizeof(Swapchain*)]) void*(&bundle); - auto args_ptr = new Ref[2]; - auto mem_ty = new std::shared_ptr[1]{ types.memory(sizeof(Swapchain*)) }; - args_ptr[0] = first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ mem_ty, 1 }, .constant = { .value = swpptr, .owned = true } })); - std::vector imgs; - for (auto i = 0; i < bundle.images.size(); i++) { - imgs.push_back(make_declare_image(bundle.images[i])); - } - args_ptr[1] = make_declare_array(types.get_builtin_image(), imgs); - return first(emplace_op(Node{ .kind = Node::CONSTRUCT, - .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_swapchain() }, 1 }, - .construct = { .args = std::span(args_ptr, 2) } })); - } - - Ref make_sampled_image(Ref image, Ref sampler) { - auto args_ptr = new Ref[3]{ make_constant(0), image, sampler }; - return first(emplace_op(Node{ .kind = Node::CONSTRUCT, - .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_sampled_image() }, 1 }, - .construct = { .args = std::span(args_ptr, 3) } })); - } - - Ref make_extract(Ref composite, Ref index) { - auto stripped = Type::stripped(composite.type()); - assert(stripped->kind == Type::ARRAY_TY); - auto ty = new std::shared_ptr[3]{ *stripped->array.T, stripped, stripped }; - return first(emplace_op(Node{ - .kind = Node::SLICE, .type = std::span{ ty, 3 }, .slice = { .src = composite, .start = index, .count = make_constant(1), .axis = 0 } })); - } - - Ref make_extract(Ref composite, uint64_t index) { - auto ty = new std::shared_ptr[3]; - auto stripped = Type::stripped(composite.type()); - uint8_t axis = 0; - if (stripped->kind == Type::ARRAY_TY) { - ty[0] = *stripped->array.T; - } else if (stripped->kind == Type::COMPOSITE_TY || stripped->kind == Type::UNION_TY) { - ty[0] = stripped->composite.types[index]; - axis = Node::NamedAxis::FIELD; - } else { - assert(0); - } - ty[1] = ty[2] = stripped; - return first( - emplace_op(Node{ .kind = Node::SLICE, - .type = std::span{ ty, 3 }, - .slice = { .src = composite, .start = make_constant(index), .count = make_constant(1), .axis = axis } })); - } - - Ref make_slice(Ref src, uint8_t axis, Ref base, Ref count) { - auto stripped = Type::stripped(src.type()); - auto ty = new std::shared_ptr[3]{ stripped, stripped, stripped }; - return first(emplace_op(Node{ .kind = Node::SLICE, .type = std::span{ ty, 3 }, .slice = { .src = src, .start = base, .count = count, .axis = axis } })); - } - - Ref make_slice(std::shared_ptr type_ex, Ref src, uint8_t axis, Ref base, Ref count) { - auto ty = new std::shared_ptr[3]{ Type::stripped(type_ex), Type::stripped(src.type()), Type::stripped(src.type()) }; - return first(emplace_op(Node{ .kind = Node::SLICE, .type = std::span{ ty, 3 }, .slice = { .src = src, .start = base, .count = count, .axis = axis } })); - } + Ref make_declare_image(ImageAttachment value); + Ref make_declare_buffer(Buffer value); + Ref make_declare_array(std::shared_ptr type, std::span args); + Ref make_declare_union(std::span args); + Ref make_declare_swapchain(Swapchain& bundle); + Ref make_sampled_image(Ref image, Ref sampler); + Ref make_extract(Ref composite, Ref index); + Ref make_extract(Ref composite, uint64_t index); + Ref make_slice(Ref src, uint8_t axis, Ref base, Ref count); + Ref make_slice(std::shared_ptr type_ex, Ref src, uint8_t axis, Ref base, Ref count); // slice splits a range into two halves // converge is essentially an unslice -> it returns back to before the slice was made // since a slice source is always a single range, converge produces a single range too - Ref make_converge(std::shared_ptr type, std::span deps) { - auto stripped = Type::stripped(type); - auto ty = new std::shared_ptr[1]{ stripped }; - - auto deps_ptr = new Ref[deps.size()]; - std::copy(deps.begin(), deps.end(), deps_ptr); - return first(emplace_op(Node{ .kind = Node::CONVERGE, .type = std::span{ ty, 1 }, .converge = { .diverged = std::span{ deps_ptr, deps.size() } } })); - } - - Ref make_use(Ref src, Access acc) { - auto ty = new std::shared_ptr[1]{ src.type() }; - return first(emplace_op(Node{ .kind = Node::USE, .type = std::span{ ty, 1 }, .use = { .src = src, .access = acc } })); - } - - Ref make_cast(std::shared_ptr dst_type, Ref src) { - auto ty = new std::shared_ptr[1]{ dst_type }; - return first(emplace_op(Node{ .kind = Node::CAST, .type = std::span{ ty, 1 }, .cast = { .src = src } })); - } - - Ref make_acquire_next_image(Ref swapchain) { - return first(emplace_op(Node{ .kind = Node::ACQUIRE_NEXT_IMAGE, - .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_image() }, 1 }, - .acquire_next_image = { .swapchain = swapchain } })); - } - - Ref make_clear_image(Ref dst, Clear cv) { - return first(emplace_op(Node{ .kind = Node::CLEAR, - .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_image() }, 1 }, - .clear = { .dst = dst, .cv = new Clear(cv) } })); - } - - Ref make_declare_fn(std::shared_ptr const fn_ty) { - auto ty = new std::shared_ptr[1]{ fn_ty }; - return first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ ty, 1 }, .constant = { .value = nullptr } })); - } + Ref make_converge(std::shared_ptr type, std::span deps); + Ref make_use(Ref src, Access acc); + Ref make_cast(std::shared_ptr dst_type, Ref src); + Ref make_acquire_next_image(Ref swapchain); + Ref make_clear_image(Ref dst, Clear cv); + Ref make_declare_fn(std::shared_ptr const fn_ty); template Node* make_call(Ref fn, Refs... args) { @@ -1367,13 +605,8 @@ namespace vuk { return emplace_op(n); } - Ref make_release(Ref src, Access dst_access = Access::eNone, DomainFlagBits dst_domain = DomainFlagBits::eAny) { - Ref* args_ptr = new Ref[1]{ src }; - auto tys = new std::shared_ptr[1]{ Type::stripped(src.type()) }; - return first(emplace_op(Node{ .kind = Node::RELEASE, - .type = std::span{ tys, 1 }, - .release = { .src = std::span{ args_ptr, 1 }, .dst_access = dst_access, .dst_domain = dst_domain } })); - } + Ref make_release(Ref src, Access dst_access = Access::eNone, DomainFlagBits dst_domain = DomainFlagBits::eAny); + template Ref acquire(std::shared_ptr type, AcquireRelease* acq_rel, T value) { auto val_ptr = new (new std::byte[sizeof(T)]) T(value); @@ -1391,20 +624,14 @@ namespace vuk { return first(emplace_op(std::move(node))); } - Ref make_compile_pipeline(Ref src) { - auto tys = new std::shared_ptr[1]{ types.memory(sizeof(PipelineBaseInfo*)) }; - return first(emplace_op(Node{ .kind = Node::COMPILE_PIPELINE, .type = std::span{ tys, 1 }, .compile_pipeline = { .src = src } })); - } + Ref make_compile_pipeline(Ref src); // MATH - Ref make_math_binary_op(Node::BinOp op, Ref a, Ref b) { - std::shared_ptr* tys = new std::shared_ptr[1]{ a.type() }; - - return first(emplace_op(Node{ .kind = Node::MATH_BINARY, .type = std::span{ tys, 1 }, .math_binary = { .a = a, .b = b, .op = op } })); - } + Ref make_math_binary_op(Node::BinOp op, Ref a, Ref b); // GC + void collect_garbage(); void collect_garbage(std::pmr::polymorphic_allocator allocator); }; @@ -1412,69 +639,21 @@ namespace vuk { extern thread_local std::shared_ptr current_module; struct ExtNode { - ExtNode(Node* node) : node(node) { - acqrel = new AcquireRelease; - node->rel_acq = acqrel; - this->node->held = true; - source_module = current_module; - } - - ExtNode(Node* node, std::vector> deps) : node(node), deps(std::move(deps)) { - acqrel = new AcquireRelease; - node->rel_acq = acqrel; - this->node->held = true; - source_module = current_module; - } - - ExtNode(Node* node, std::shared_ptr dep) : node(node) { - acqrel = new AcquireRelease; - node->rel_acq = acqrel; - this->node->held = true; - deps.push_back(std::move(dep)); - - source_module = current_module; - } - - ExtNode(Ref ref, std::shared_ptr dep, Access access = Access::eNone, DomainFlagBits domain = DomainFlagBits::eAny) { - acqrel = new AcquireRelease; - this->node = current_module->make_release(ref, access, domain).node; - node->rel_acq = acqrel; - this->node->held = true; - deps.push_back(std::move(dep)); - - source_module = current_module; - } - + ExtNode(Node* node); + ExtNode(Node* node, std::vector> deps); + ExtNode(Node* node, std::shared_ptr dep); + ExtNode(Ref ref, std::shared_ptr dep, Access access = Access::eNone, DomainFlagBits domain = DomainFlagBits::eAny); // for acquires - adopt the node - ExtNode(Node* node, ResourceUse use) : node(node) { - acqrel = new AcquireRelease; - acqrel->status = Signal::Status::eHostAvailable; - acqrel->last_use.resize(1); - acqrel->last_use[0] = use; - - node->rel_acq = acqrel; - this->node->held = true; - source_module = current_module; - } - - ~ExtNode() { - if (acqrel) { - node->held = false; - } - } - + ExtNode(Node* node, ResourceUse use); + ~ExtNode(); ExtNode(ExtNode&& o) = delete; ExtNode& operator=(ExtNode&& o) = delete; - Node* get_node() { + [[nodiscard]] Node* get_node() { return node; } - void mutate(Node* new_node) { - node->held = false; - node = new_node; - new_node->held = true; - } + void mutate(Node* new_node); AcquireRelease* acqrel; std::vector> deps; @@ -1504,5 +683,5 @@ namespace vuk { Node::Kind kind; }; - std::string exec_to_string(ScheduledItem& item); + [[nodiscard]] std::string exec_to_string(ScheduledItem& item); } // namespace vuk diff --git a/include/vuk/IRProcess.hpp b/include/vuk/IRProcess.hpp index 814716a3..1170fb7a 100644 --- a/include/vuk/IRProcess.hpp +++ b/include/vuk/IRProcess.hpp @@ -198,7 +198,7 @@ namespace vuk { f(node->fixed_node.args[i]); } } else { - for (int i = 0; i < node->variable_node.args.size(); i++) { + for (size_t i = 0; i < node->variable_node.args.size(); i++) { f(node->variable_node.args[i]); } } @@ -644,4 +644,4 @@ namespace vuk { RenderGraphException make_cbuf_references_unknown_resource(PassInfo& pass_info, Resource::Type type, Name name); RenderGraphException make_cbuf_references_undeclared_resource(PassInfo& pass_info, Resource::Type type, Name name);*/ } // namespace errors -}; // namespace vuk \ No newline at end of file +}; // namespace vuk diff --git a/include/vuk/RenderGraph.hpp b/include/vuk/RenderGraph.hpp index 31a442fe..3d34a338 100644 --- a/include/vuk/RenderGraph.hpp +++ b/include/vuk/RenderGraph.hpp @@ -35,8 +35,9 @@ namespace vuk { #define VUK_ARG(type, access) vuk::Arg> #endif -#define VUK_CALLSTACK vuk::SourceLocationAtFrame _pscope = VUK_HERE_AND_NOW(), vuk::SourceLocationAtFrame _scope = VUK_HERE_AND_NOW() -#define VUK_CALL (_pscope != _scope ? _scope.parent = &_pscope, _scope : _scope) +#define VUK_CALLSTACK \ + [[maybe_unused]] vuk::SourceLocationAtFrame _pscope = VUK_HERE_AND_NOW(), [[maybe_unused]] vuk::SourceLocationAtFrame _scope = VUK_HERE_AND_NOW() +#define VUK_CALL (_pscope != _scope ? _scope.parent = &_pscope, _scope : _scope) namespace vuk { ResourceUse to_use(Access acc); @@ -108,7 +109,7 @@ private: template struct tuple_to_typelist { - DELAYED_ERROR("tuple_to_typelist expects a std::tuple"); + DELAYED_ERROR("tuple_to_typelist expects a std::tuple") }; template @@ -121,7 +122,7 @@ private: template struct typelist_to_tuple { - DELAYED_ERROR("typelist_to_tuple expects a type_list"); + DELAYED_ERROR("typelist_to_tuple expects a type_list") }; template @@ -197,7 +198,7 @@ private: inline constexpr std::size_t tuple_element_index_v = tuple_element_index::value; template - auto make_indices(const Tuple& tuple, type_list) { + auto make_indices([[maybe_unused]] const Tuple& tuple, type_list) { return std::array{ tuple_element_index_v... }; } @@ -278,7 +279,7 @@ private: struct is_tuple> : std::true_type {}; template - static auto make_ret(std::shared_ptr extnode, const std::tuple& us) { + static auto make_ret(std::shared_ptr extnode, [[maybe_unused]] const std::tuple& us) { if constexpr (sizeof...(T) > 0) { size_t i = 0; // FIXME: I think this is well defined but seems like compilers don't agree on the result @@ -340,7 +341,6 @@ private: if (!opaque_fn_ty) { std::array, arg_count> arg_types = { current_module->types.make_imbued_ty(T{ nullptr, args.get_head() }.src.type(), T::access)... }; - fixed_vector, arg_count> ret_types; if constexpr (is_tuple::value) { auto [idxs, ret_tuple] = intersect_tuples, Ret>(arg_tuple_as_a); @@ -371,7 +371,7 @@ private: std::span opaque_meta, std::span opaque_rets) mutable -> void { cb(cbuf, opaque_args, opaque_meta, opaque_rets.subspan(0, old_ret_cnt)); - for (auto i = 0; i < maps_to_add.size(); i++) { + for (size_t i = 0; i < maps_to_add.size(); i++) { opaque_rets[old_ret_cnt + i] = opaque_args[maps_to_add[i]]; } }; diff --git a/include/vuk/vsl/Core.hpp b/include/vuk/vsl/Core.hpp index 2732c047..4793eba1 100644 --- a/include/vuk/vsl/Core.hpp +++ b/include/vuk/vsl/Core.hpp @@ -15,7 +15,8 @@ namespace vuk { /// @param buffer Buffer to fill /// @param src_data pointer to source data /// @param size size of source data - inline Value host_data_to_buffer(Allocator& allocator, DomainFlagBits copy_domain, Buffer dst, const void* src_data, size_t size, VUK_CALLSTACK) { + inline Value + host_data_to_buffer(Allocator& allocator, [[maybe_unused]] DomainFlagBits copy_domain, Buffer dst, const void* src_data, size_t size, VUK_CALLSTACK) { // host-mapped buffers just get memcpys if (dst.mapped_ptr) { memcpy(dst.mapped_ptr, src_data, size); @@ -49,11 +50,10 @@ namespace vuk { inline Value download_buffer(Value buffer_src, VUK_CALLSTACK) { auto dst = declare_buf("dst", Buffer{ .memory_usage = MemoryUsage::eGPUtoCPU }, VUK_CALL); dst.same_size(buffer_src); - auto download = - make_pass("download buffer", [](CommandBuffer& command_buffer, VUK_BA(Access::eTransferRead) src, VUK_BA(Access::eTransferWrite) dst) { - command_buffer.copy_buffer(src, dst); - return dst; - }); + auto download = make_pass("download buffer", [](CommandBuffer& command_buffer, VUK_BA(Access::eTransferRead) src, VUK_BA(Access::eTransferWrite) dst) { + command_buffer.copy_buffer(src, dst); + return dst; + }); return download(std::move(buffer_src), std::move(dst), VUK_CALL); } @@ -63,7 +63,7 @@ namespace vuk { /// @param image ImageAttachment to fill /// @param src_data pointer to source data inline Value - host_data_to_image(Allocator& allocator, DomainFlagBits copy_domain, ImageAttachment image, const void* src_data, VUK_CALLSTACK) { + host_data_to_image(Allocator& allocator, [[maybe_unused]] DomainFlagBits copy_domain, ImageAttachment image, const void* src_data, VUK_CALLSTACK) { size_t alignment = format_to_texel_block_size(image.format); size_t size = compute_image_size(image.format, image.extent); auto src = *allocate_buffer(allocator, BufferCreateInfo{ MemoryUsage::eCPUonly, size, alignment }); @@ -83,11 +83,10 @@ namespace vuk { auto srcbuf = acquire_buf("src", *src, Access::eNone, VUK_CALL); auto dst = declare_ia("dst", image, VUK_CALL); - auto image_upload = - make_pass("image upload", [bc](CommandBuffer& command_buffer, VUK_BA(Access::eTransferRead) src, VUK_IA(Access::eTransferWrite) dst) { - command_buffer.copy_buffer_to_image(src, dst, bc); - return dst; - }); + auto image_upload = make_pass("image upload", [bc](CommandBuffer& command_buffer, VUK_BA(Access::eTransferRead) src, VUK_IA(Access::eTransferWrite) dst) { + command_buffer.copy_buffer_to_image(src, dst, bc); + return dst; + }); return image_upload(std::move(srcbuf), std::move(dst), VUK_CALL); } @@ -197,9 +196,9 @@ namespace vuk { inline Value copy(Value src, Value dst, VUK_CALLSTACK) { auto buf2buf = vuk::make_pass("copy buffer to buffer", [](vuk::CommandBuffer& command_buffer, VUK_BA(vuk::eCopyRead) src, VUK_BA(vuk::eCopyWrite) dst) { - command_buffer.copy_buffer(src, dst); - return dst; - }); + command_buffer.copy_buffer(src, dst); + return dst; + }); return buf2buf(src, dst, VUK_CALL); } @@ -208,9 +207,8 @@ namespace vuk { uint32_t value_as_uint; static_assert(sizeof(T) == sizeof(uint32_t), "T must be 4 bytes"); memcpy(&value_as_uint, &value, sizeof(T)); - auto buf2buf = vuk::make_pass("fill buffer", [value_as_uint](vuk::CommandBuffer& command_buffer, VUK_BA(vuk::eClear) dst) { - command_buffer.fill_buffer(dst, value_as_uint); - }); + auto buf2buf = vuk::make_pass( + "fill buffer", [value_as_uint](vuk::CommandBuffer& command_buffer, VUK_BA(vuk::eClear) dst) { command_buffer.fill_buffer(dst, value_as_uint); }); buf2buf(dst, VUK_CALL); } @@ -234,7 +232,7 @@ namespace vuk { return buf2img(src, dst, VUK_CALL); } - inline Value copy(Value src, Value dst, VUK_CALLSTACK) { + inline Value copy(Value src, Value dst, VUK_CALLSTACK) { auto img2img = make_pass("copy image to image", [](CommandBuffer& cbuf, VUK_IA(Access::eCopyRead) src, VUK_IA(Access::eCopyWrite) dst) { assert(src->level_count == dst->level_count); diff --git a/src/GraphDumper.cpp b/src/GraphDumper.cpp index 20e4b024..87bee570 100644 --- a/src/GraphDumper.cpp +++ b/src/GraphDumper.cpp @@ -3,8 +3,8 @@ #if VUK_OS_WINDOWS #include -#include #include +#include #endif #include "vuk/IR.hpp" @@ -54,7 +54,7 @@ namespace vuk { return; } } - if (node->kind == Node::PLACEHOLDER || (bridge_slices && node->kind == Node::SLICE)) { + if (node->kind == Node::PLACEHOLDER || (bridge_slices && node->kind == Node::SLICE)) { return; } @@ -78,8 +78,6 @@ namespace vuk { ss << (node->index & 0xffff) << " "; ss << Node::kind_to_sv(node->kind); if (node->kind == Node::CALL) { - auto opaque_fn_ty = node->call.args[0].type()->opaque_fn; - if (!node->call.args[0].type()->debug_info.name.empty()) { ss << " "; ss << node->call.args[0].type()->debug_info.name; @@ -142,7 +140,7 @@ namespace vuk { ss << current_cluster << uintptr_t(bridged_arg.node) << " :r" << bridged_arg.index << " -> " << current_cluster << uintptr_t(node) << " :a" << i << " :n [color=green, label=\""; /* if (r.base_level > 0 || r.level_count != VK_REMAINING_MIP_LEVELS) { - ss << fmt::format("[m{}:{}]", r.base_level, r.base_level + r.level_count - 1); + ss << fmt::format("[m{}:{}]", r.base_level, r.base_level + r.level_count - 1); }*/ ss << "\"]\n"; } else { diff --git a/src/IR.cpp b/src/IR.cpp index e7cb6ab7..1ff7c08c 100644 --- a/src/IR.cpp +++ b/src/IR.cpp @@ -1,5 +1,908 @@ #include +#include "vuk/runtime/vk/VkSwapchain.hpp" + namespace vuk { thread_local std::shared_ptr current_module = std::make_shared(); + + auto Type::stripped(std::shared_ptr const t) -> std::shared_ptr { + switch (t->kind) { + case Type::IMBUED_TY: + return stripped(*t->imbued.T); + case Type::ALIASED_TY: + return stripped(*t->aliased.T); + default: + return t; + } + } + + auto Type::extract(std::shared_ptr const t, size_t const index) -> std::shared_ptr { + assert(t->kind == COMPOSITE_TY); + assert(index < t->composite.types.size()); + return t->composite.types[index]; + } + + auto Type::hash_integer(size_t const width) -> Hash { + Hash v = (Hash)Type::INTEGER_TY; + hash_combine_direct(v, width); + return v; + } + + auto Type::hash(Type const* const t) -> Hash { + Hash v = (Hash)t->kind; + switch (t->kind) { + case Type::VOID_TY: + return v; + case Type::IMBUED_TY: + hash_combine_direct(v, Type::hash(t->imbued.T->get())); + hash_combine_direct(v, (uint32_t)t->imbued.access); + return v; + case Type::ALIASED_TY: + hash_combine_direct(v, Type::hash(t->aliased.T->get())); + hash_combine_direct(v, (uint32_t)t->aliased.ref_idx); + return v; + case Type::MEMORY_TY: + hash_combine_direct(v, (uint32_t)t->size); + return v; + case Type::INTEGER_TY: + hash_combine_direct(v, t->integer.width); + return v; + case Type::ARRAY_TY: + hash_combine_direct(v, Type::hash(t->array.T->get())); + hash_combine_direct(v, (uint32_t)t->array.count); + return v; + case Type::UNION_TY: + case Type::COMPOSITE_TY: { + for (size_t i = 0; i < t->composite.types.size(); i++) { + hash_combine_direct(v, Type::hash(t->composite.types[i].get())); + } + hash_combine_direct(v, (uint32_t)t->composite.tag); + return v; + } + case Type::OPAQUE_FN_TY: + hash_combine_direct(v, (uintptr_t)t->opaque_fn.hash_code >> 32); + hash_combine_direct(v, (uintptr_t)t->opaque_fn.hash_code & 0xffffffff); + return v; + case Type::SHADER_FN_TY: + hash_combine_direct(v, (uintptr_t)t->shader_fn.shader >> 32); + hash_combine_direct(v, (uintptr_t)t->shader_fn.shader & 0xffffffff); + return v; + } + assert(0); + return v; + } + + auto Type::to_sv(Access const acc) -> std::string_view { + // TODO: handle multiple flags + switch (acc) { + case eNone: + return "None"; + case eClear: + return "Clear"; + case eColorWrite: + return "ColorW"; + case eColorRead: + return "ColorR"; + case eColorRW: + return "ColorRW"; + case eDepthStencilRead: + return "DSRead"; + case eDepthStencilWrite: + return "DSWrite"; + case eDepthStencilRW: + return "DSRW"; + case eVertexSampled: + return "VtxS"; + case eVertexRead: + return "VtxR"; + case eAttributeRead: + return "AttrR"; + case eIndexRead: + return "IdxR"; + case eIndirectRead: + return "IndirR"; + case eFragmentSampled: + return "FragS"; + case eFragmentRead: + return "FragR"; + case eFragmentWrite: + return "FragW"; + case eFragmentRW: + return "FragRW"; + case eTransferRead: + return "XferR"; + case eTransferWrite: + return "XferW"; + case eTransferRW: + return "XferRW"; + case eComputeRead: + return "CompR"; + case eComputeWrite: + return "CompW"; + case eComputeRW: + return "CompRW"; + case eComputeSampled: + return "CompS"; + case eRayTracingRead: + return "RTR"; + case eRayTracingWrite: + return "RTW"; + case eRayTracingRW: + return "RTRW"; + case eRayTracingSampled: + return "RTS"; + case eAccelerationStructureBuildRead: + return "ASBuildR"; + case eAccelerationStructureBuildWrite: + return "ASBuildW"; + case eAccelerationStructureBuildRW: + return "ASBuildRW"; + case eHostRead: + return "HostR"; + case eHostWrite: + return "HostW"; + case eHostRW: + return "HostRW"; + case eMemoryRead: + return "MemR"; + case eMemoryWrite: + return "MemW"; + case eMemoryRW: + return "MemRW"; + default: + return ""; + } + } + + auto Type::to_string(Type* t) -> std::string { + switch (t->kind) { + case Type::VOID_TY: + return "void"; + case Type::IMBUED_TY: + return to_string(t->imbued.T->get()) + std::string(":") + std::string(to_sv(t->imbued.access)); + case Type::ALIASED_TY: + return to_string(t->aliased.T->get()) + std::string("@") + std::to_string(t->aliased.ref_idx); + case Type::MEMORY_TY: + return "mem"; + case Type::INTEGER_TY: + return t->integer.width == 32 ? "i32" : "i64"; + case Type::ARRAY_TY: + return to_string(t->array.T->get()) + "[" + std::to_string(t->array.count) + "]"; + case Type::COMPOSITE_TY: + if (!t->debug_info.name.empty()) { + return std::string(t->debug_info.name); + } + return "composite:" + std::to_string(t->composite.tag); + case Type::UNION_TY: + if (!t->debug_info.name.empty()) { + return std::string(t->debug_info.name); + } + return "union:" + std::to_string(t->composite.tag); + case Type::OPAQUE_FN_TY: + return "ofn"; + case Type::SHADER_FN_TY: + return "sfn"; + default: + assert(0); + return "?"; + } + } + + auto Node::kind_to_sv(Node::Kind const kind) -> std::string_view { + switch (kind) { + case Node::PLACEHOLDER: + return "placeholder"; + case Node::CONSTANT: + return "constant"; + case Node::IMPORT: + return "import"; + case Node::CONSTRUCT: + return "construct"; + case Node::ACQUIRE_NEXT_IMAGE: + return "acquire_next_image"; + case Node::CALL: + return "call"; + case Node::MATH_BINARY: + return "math_b"; + case Node::SLICE: + return "slice"; + case Node::CONVERGE: + return "converge"; + case Node::CLEAR: + return "clear"; + case Node::CAST: + return "cast"; + case Node::GARBAGE: + return "garbage"; + case Node::RELEASE: + return "release"; + case Node::ACQUIRE: + return "acquire"; + case Node::USE: + return "use"; + case Node::SET: + return "set"; + case Node::LOGICAL_COPY: + return "lcopy"; + case Node::COMPILE_PIPELINE: + return "compile_pipeline"; + } + assert(0); + return ""; + } + + std::shared_ptr IRModule::Types::make_void_ty() { + auto t = new Type{ .kind = Type::VOID_TY }; + return emplace_type(std::shared_ptr(t)); + } + + std::shared_ptr IRModule::Types::make_imbued_ty(std::shared_ptr ty, Access access) { + auto t = new Type{ .kind = Type::IMBUED_TY, .size = ty->size, .imbued = { .access = access } }; + t->imbued.T = &t->child_types.emplace_back(ty); + return emplace_type(std::shared_ptr(t)); + } + + std::shared_ptr IRModule::Types::make_aliased_ty(std::shared_ptr ty, size_t ref_idx) { + auto t = new Type{ .kind = Type::ALIASED_TY, .size = ty->size, .aliased = { .ref_idx = ref_idx } }; + t->imbued.T = &t->child_types.emplace_back(ty); + return emplace_type(std::shared_ptr(t)); + } + + std::shared_ptr IRModule::Types::make_array_ty(std::shared_ptr ty, size_t count) { + auto t = new Type{ .kind = Type::ARRAY_TY, .size = count * ty->size, .array = { .count = count, .stride = ty->size } }; + t->array.T = &t->child_types.emplace_back(ty); + return emplace_type(std::shared_ptr(t)); + } + + std::shared_ptr IRModule::Types::make_union_ty(std::vector> types) { + std::vector offsets; + size_t offset = 0; + for (auto& t : types) { + offsets.push_back(offset); + offset += t->size; + } + auto union_type = emplace_type(std::shared_ptr( + new Type{ .kind = Type::UNION_TY, .size = offset, .offsets = offsets, .composite = { .types = types, .tag = union_tag_type_counter++ } })); + union_type->child_types = std::move(types); + return union_type; + } + + std::shared_ptr IRModule::Types::make_opaque_fn_ty(std::span const> args, + std::span const> ret_types, + DomainFlags execute_on, + size_t hash_code, + UserCallbackType callback, + std::string_view name) { + auto arg_ptr_ret_ty_ptr = std::vector>(args.size() + ret_types.size()); + auto it = std::copy(args.begin(), args.end(), arg_ptr_ret_ty_ptr.begin()); + std::copy(ret_types.begin(), ret_types.end(), it); + auto t = new Type{ .kind = Type::OPAQUE_FN_TY, + .opaque_fn = { .args = std::span{ arg_ptr_ret_ty_ptr.data(), args.size() }, + .return_types = std::span{ arg_ptr_ret_ty_ptr.data() + args.size(), ret_types.size() }, + .hash_code = hash_code, + .execute_on = execute_on.m_mask } }; + t->callback = std::make_unique(std::move(callback)); + t->child_types = std::move(arg_ptr_ret_ty_ptr); + t->debug_info = allocate_type_debug_info(std::string(name)); + return emplace_type(std::shared_ptr(t)); + } + + std::shared_ptr IRModule::Types::make_shader_fn_ty(std::span const> args, + std::span const> ret_types, + DomainFlags execute_on, + void* shader, + std::string_view name) { + auto arg_ptr_ret_ty_ptr = std::vector>(args.size() + ret_types.size()); + auto it = std::copy(args.begin(), args.end(), arg_ptr_ret_ty_ptr.begin()); + std::copy(ret_types.begin(), ret_types.end(), it); + auto t = new Type{ .kind = Type::SHADER_FN_TY, + .shader_fn = { .shader = shader, + .args = std::span{ arg_ptr_ret_ty_ptr.data(), args.size() }, + .return_types = std::span{ arg_ptr_ret_ty_ptr.data() + args.size(), ret_types.size() }, + .execute_on = execute_on.m_mask } }; + t->child_types = std::move(arg_ptr_ret_ty_ptr); + t->debug_info = allocate_type_debug_info(std::string(name)); + return emplace_type(std::shared_ptr(t)); + } + + std::shared_ptr IRModule::Types::u64() { + auto hash = Type::hash_integer(64); + auto it = type_map.find(hash); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + + return emplace_type(std::shared_ptr(new Type{ .kind = Type::INTEGER_TY, .size = sizeof(uint64_t), .integer = { .width = 64 } })); + } + + std::shared_ptr IRModule::Types::u32() { + auto hash = Type::hash_integer(32); + auto it = type_map.find(hash); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + + return emplace_type(std::shared_ptr(new Type{ .kind = Type::INTEGER_TY, .size = sizeof(uint32_t), .integer = { .width = 32 } })); + } + + std::shared_ptr IRModule::Types::memory(size_t size) { + Type ty{ .kind = Type::MEMORY_TY, .size = size }; + auto it = type_map.find(Type::hash(&ty)); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + return emplace_type(std::shared_ptr(new Type{ .kind = Type::MEMORY_TY, .size = size })); + } + + std::shared_ptr IRModule::Types::get_builtin_image() { + if (builtin_image) { + auto it = type_map.find(builtin_image); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + } + + auto u32_t = u32(); + auto image_ = std::vector>{ u32_t, u32_t, u32_t, memory(sizeof(Format)), memory(sizeof(Samples)), u32_t, u32_t, u32_t, u32_t }; + // TODO: crimes +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winvalid-offsetof" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" + auto image_offsets = std::vector{ offsetof(ImageAttachment, extent) + offsetof(Extent3D, width), + offsetof(ImageAttachment, extent) + offsetof(Extent3D, height), + offsetof(ImageAttachment, extent) + offsetof(Extent3D, depth), + offsetof(ImageAttachment, format), + offsetof(ImageAttachment, sample_count), + offsetof(ImageAttachment, base_layer), + offsetof(ImageAttachment, layer_count), + offsetof(ImageAttachment, base_level), + offsetof(ImageAttachment, level_count) }; +#pragma GCC diagnostic pop +#pragma clang diagnostic pop + auto image_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, + .size = sizeof(ImageAttachment), + .debug_info = allocate_type_debug_info("image"), + .offsets = image_offsets, + .composite = { .types = image_, .tag = 0 } })); + image_type->child_types = std::move(image_); + builtin_image = Type::hash(image_type.get()); + + return image_type; + } + + std::shared_ptr IRModule::Types::get_builtin_buffer() { + if (builtin_buffer) { + auto it = type_map.find(builtin_buffer); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + } + + auto buffer_ = std::vector>{ u64() }; + auto buffer_offsets = std::vector{ offsetof(Buffer, size) }; + auto buffer_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, + .size = sizeof(Buffer), + .debug_info = allocate_type_debug_info("buffer"), + .offsets = buffer_offsets, + .composite = { .types = buffer_, .tag = 1 } })); + buffer_type->child_types = std::move(buffer_); + + builtin_buffer = Type::hash(buffer_type.get()); + return buffer_type; + } + + std::shared_ptr IRModule::Types::get_builtin_swapchain() { + if (builtin_swapchain) { + auto it = type_map.find(builtin_swapchain); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + } + auto arr_ty = make_array_ty(get_builtin_image(), 16); + auto swp_ = std::vector>{ arr_ty }; + auto offsets = std::vector{ 0 }; + + auto swapchain_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, + .size = sizeof(Swapchain*), + .debug_info = allocate_type_debug_info("swapchain"), + .offsets = offsets, + .composite = { .types = swp_, .tag = 2 } })); + builtin_swapchain = Type::hash(swapchain_type.get()); + return swapchain_type; + } + + std::shared_ptr IRModule::Types::get_builtin_sampler() { + if (builtin_sampler) { + auto it = type_map.find(builtin_sampler); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + } + auto sampler_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, + .size = sizeof(SamplerCreateInfo), + .debug_info = allocate_type_debug_info("sampler"), + .offsets = {}, + .composite = { .types = {}, .tag = 3 } })); + builtin_sampler = Type::hash(sampler_type.get()); + return sampler_type; + } + + std::shared_ptr IRModule::Types::get_builtin_sampled_image() { + if (builtin_sampled_image) { + auto it = type_map.find(builtin_sampled_image); + if (it != type_map.end()) { + if (auto ty = it->second.lock()) { + return ty; + } + } + } + auto sampled_image_type = emplace_type(std::shared_ptr(new Type{ .kind = Type::COMPOSITE_TY, + .size = sizeof(SampledImage), + .debug_info = allocate_type_debug_info("sampled_image"), + .offsets = {}, + .composite = { .types = {}, .tag = 4 } })); + builtin_sampled_image = Type::hash(sampled_image_type.get()); + return sampled_image_type; + } + + std::shared_ptr IRModule::Types::emplace_type(std::shared_ptr t) { + auto unify_type = [&](std::shared_ptr& t) { + auto th = Type::hash(t.get()); + auto [v, succ] = type_map.try_emplace(th, t); + if (succ) { + t->hash_value = th; + } else if (!v->second.lock()) { + type_map[th] = t; + } + t->hash_value = th; + }; + + if (t->kind == Type::ALIASED_TY) { + assert((*t->aliased.T)->kind != Type::ALIASED_TY); + unify_type(*t->aliased.T); + } else if (t->kind == Type::IMBUED_TY) { + unify_type(*t->imbued.T); + } else if (t->kind == Type::ARRAY_TY) { + unify_type(*t->array.T); + } else if (t->kind == Type::COMPOSITE_TY) { + for (auto& elem_ty : t->composite.types) { + unify_type(elem_ty); + } + } + unify_type(t); + + return t; + } + + TypeDebugInfo IRModule::Types::allocate_type_debug_info(std::string name) { + return TypeDebugInfo{ name }; + } + + void IRModule::Types::collect() { + for (auto it = type_map.begin(); it != type_map.end();) { + if (it->second.expired()) { + it = type_map.erase(it); + } else { + ++it; + } + } + } + + void IRModule::Types::destroy(Type* t, void* v) { + if (t->hash_value == builtin_buffer) { + std::destroy_at((Buffer*)v); + } else if (t->hash_value == builtin_image) { + std::destroy_at((ImageAttachment*)v); + } else if (t->hash_value == builtin_sampled_image) { + std::destroy_at((SampledImage*)v); + } else if (t->hash_value == builtin_sampler) { + std::destroy_at((SamplerCreateInfo*)v); + } else if (t->hash_value == builtin_swapchain) { + std::destroy_at((Swapchain**)v); + } else if (t->kind == Type::INTEGER_TY) { + // nothing to do + } else if (t->kind == Type::MEMORY_TY) { + // nothing to do + } else if (t->kind == Type::IMBUED_TY) { + destroy(t->imbued.T->get(), v); + } else if (t->kind == Type::ALIASED_TY) { + destroy(t->aliased.T->get(), v); + } else if (t->kind == Type::ARRAY_TY || t->kind == Type::UNION_TY) { + // currently arrays and unions don't own their values + /* auto cv = (char*)v; + for (auto i = 0; i < t->array.count; i++) { + destroy(t->array.T->get(), cv); + cv += t->array.stride; + }*/ + } else { + assert(0); + } + delete[] (std::byte*)v; + } + + Node* IRModule::emplace_op(Node v) { + v.index = module_id << 32 | node_counter++; + return &*op_arena.emplace(std::move(v)); + } + + void IRModule::name_output(Ref ref, std::string_view name) { + auto node = ref.node; + if (!node->debug_info) { + node->debug_info = new NodeDebugInfo; + } + auto& names = ref.node->debug_info->result_names; + if (names.size() <= ref.index) { + names.resize(ref.index + 1); + } + names[ref.index] = name; + } + + void IRModule::set_source_location(Node* node, SourceLocationAtFrame loc) { + if (!node->debug_info) { + node->debug_info = new NodeDebugInfo; + } + auto p = &loc; + size_t cnt = 0; + do { + cnt++; + p = p->parent; + } while (p != nullptr); + if (node->debug_info->trace.data()) { + delete[] node->debug_info->trace.data(); + } + node->debug_info->trace = std::span(new vuk::source_location[cnt], cnt); + p = &loc; + cnt = 0; + do { + node->debug_info->trace[cnt] = p->location; + cnt++; + p = p->parent; + } while (p != nullptr); + } + + std::optional::iterator> IRModule::destroy_node(Node* node) { + delete node->rel_acq; + switch (node->kind) { + case Node::CONSTANT: { + if (node->constant.owned) { + delete[] (char*)node->constant.value; + } + break; + } + case Node::ACQUIRE: { + for (size_t i = 0; i < node->acquire.values.size(); i++) { + auto& v = node->acquire.values[i]; + types.destroy(Type::stripped(node->type[i]).get(), v); + } + delete[] node->acquire.values.data(); + break; + } + default: // nothing extra to be done here + break; + } + delete[] node->type.data(); + if (node->generic_node.arg_count == (uint8_t)~0u) { + delete[] node->variable_node.args.data(); + } + if (node->scheduling_info) + delete node->scheduling_info; + if (node->debug_info) { + if (node->debug_info->trace.size() > 0) { + delete[] node->debug_info->trace.data(); + } + + delete node->debug_info; + } + + auto it = op_arena.get_iterator(node); + if (it != op_arena.end()) { +#ifdef VUK_GARBAGE_SAN + node->kind = Node::GARBAGE; + node->generic_node.arg_count = 0; + node->type = {}; +#else + return op_arena.erase(it); +#endif + } else { + node->kind = Node::GARBAGE; + node->generic_node.arg_count = 0; + node->type = {}; + } + return {}; + } + + // OPS + + Ref IRModule::make_constant(std::shared_ptr type, void* value) { + std::shared_ptr* ty = new std::shared_ptr[1]{ type }; + auto value_ptr = new char[type->size]; + memcpy(value_ptr, value, type->size); + return first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ ty, 1 }, .constant = { .value = value_ptr, .owned = true } })); + } + + void IRModule::set_value(Ref ref, size_t index, Ref value) { + emplace_op(Node{ .kind = Node::SET, .set = { .dst = ref, .value = value, .index = index } }); + } + + Ref IRModule::make_declare_image(ImageAttachment value) { + auto ptr = new (new char[sizeof(ImageAttachment)]) + ImageAttachment(value); /* rest extent_x extent_y extent_z format samples base_layer layer_count base_level level_count */ + auto args_ptr = new Ref[10]; + auto mem_ty = new std::shared_ptr[1]{ types.memory(sizeof(ImageAttachment)) }; + args_ptr[0] = first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ mem_ty, 1 }, .constant = { .value = ptr, .owned = true } })); + if (value.extent.width > 0) { + args_ptr[1] = make_constant(&ptr->extent.width); + } else { + args_ptr[1] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); + } + if (value.extent.height > 0) { + args_ptr[2] = make_constant(&ptr->extent.height); + } else { + args_ptr[2] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); + } + if (value.extent.depth > 0) { + args_ptr[3] = make_constant(&ptr->extent.depth); + } else { + args_ptr[3] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); + } + if (value.format != Format::eUndefined) { + args_ptr[4] = make_constant(&ptr->format); + } else { + args_ptr[4] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.memory(sizeof(Format)) }, 1 } })); + } + if (value.sample_count != Samples::eInfer) { + args_ptr[5] = make_constant(&ptr->sample_count); + } else { + args_ptr[5] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.memory(sizeof(Samples)) }, 1 } })); + } + if (value.base_layer != VK_REMAINING_ARRAY_LAYERS) { + args_ptr[6] = make_constant(&ptr->base_layer); + } else { + args_ptr[6] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); + } + if (value.layer_count != VK_REMAINING_ARRAY_LAYERS) { + args_ptr[7] = make_constant(&ptr->layer_count); + } else { + args_ptr[7] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); + } + if (value.base_level != VK_REMAINING_MIP_LEVELS) { + args_ptr[8] = make_constant(&ptr->base_level); + } else { + args_ptr[8] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); + } + if (value.level_count != VK_REMAINING_MIP_LEVELS) { + args_ptr[9] = make_constant(&ptr->level_count); + } else { + args_ptr[9] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u32() }, 1 } })); + } + + return first(emplace_op(Node{ .kind = Node::CONSTRUCT, + .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_image() }, 1 }, + .construct = { .args = std::span(args_ptr, 10) } })); + } + + Ref IRModule::make_declare_buffer(Buffer value) { + auto buf_ptr = new (new char[sizeof(Buffer)]) Buffer(value); /* rest size */ + auto args_ptr = new Ref[2]; + auto mem_ty = new std::shared_ptr[1]{ types.memory(sizeof(Buffer)) }; + args_ptr[0] = first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ mem_ty, 1 }, .constant = { .value = buf_ptr, .owned = true } })); + if (value.size != ~(0ULL)) { + args_ptr[1] = make_constant(&buf_ptr->size); + } else { + args_ptr[1] = first(emplace_op(Node{ .kind = Node::PLACEHOLDER, .type = std::span{ new std::shared_ptr[1]{ types.u64() }, 1 } })); + } + + return first(emplace_op(Node{ .kind = Node::CONSTRUCT, + .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_buffer() }, 1 }, + .construct = { .args = std::span(args_ptr, 2) } })); + } + + Ref IRModule::make_declare_array(std::shared_ptr type, std::span args) { + auto arr_ty = new std::shared_ptr[1]{ types.make_array_ty(type, args.size()) }; + auto args_ptr = new Ref[args.size() + 1]; + auto mem_ty = new std::shared_ptr[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{ arr_ty, 1 }, .construct = { .args = std::span(args_ptr, args.size() + 1) } })); + } + + Ref IRModule::make_declare_union(std::span args) { + std::vector> child_types; + for (auto& arg : args) { + child_types.push_back(Type::stripped(arg.type())); + } + auto union_ty = new std::shared_ptr[1]{ types.make_union_ty(std::move(child_types)) }; + auto args_ptr = new Ref[args.size() + 1]; + auto mem_ty = new std::shared_ptr[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{ union_ty, 1 }, .construct = { .args = std::span(args_ptr, args.size() + 1) } })); + } + + Ref IRModule::make_declare_swapchain(Swapchain& bundle) { + auto swpptr = new (new char[sizeof(Swapchain*)]) void*(&bundle); + auto args_ptr = new Ref[2]; + auto mem_ty = new std::shared_ptr[1]{ types.memory(sizeof(Swapchain*)) }; + args_ptr[0] = first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ mem_ty, 1 }, .constant = { .value = swpptr, .owned = true } })); + std::vector imgs; + for (size_t i = 0; i < bundle.images.size(); i++) { + imgs.push_back(make_declare_image(bundle.images[i])); + } + args_ptr[1] = make_declare_array(types.get_builtin_image(), imgs); + return first(emplace_op(Node{ .kind = Node::CONSTRUCT, + .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_swapchain() }, 1 }, + .construct = { .args = std::span(args_ptr, 2) } })); + } + + Ref IRModule::make_sampled_image(Ref image, Ref sampler) { + auto args_ptr = new Ref[3]{ make_constant(0), image, sampler }; + return first(emplace_op(Node{ .kind = Node::CONSTRUCT, + .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_sampled_image() }, 1 }, + .construct = { .args = std::span(args_ptr, 3) } })); + } + + Ref IRModule::make_extract(Ref composite, Ref index) { + auto stripped = Type::stripped(composite.type()); + assert(stripped->kind == Type::ARRAY_TY); + auto ty = new std::shared_ptr[3]{ *stripped->array.T, stripped, stripped }; + return first(emplace_op(Node{ + .kind = Node::SLICE, .type = std::span{ ty, 3 }, .slice = { .src = composite, .start = index, .count = make_constant(1), .axis = 0 } })); + } + + Ref IRModule::make_extract(Ref composite, uint64_t index) { + auto ty = new std::shared_ptr[3]; + auto stripped = Type::stripped(composite.type()); + uint8_t axis = 0; + if (stripped->kind == Type::ARRAY_TY) { + ty[0] = *stripped->array.T; + } else if (stripped->kind == Type::COMPOSITE_TY || stripped->kind == Type::UNION_TY) { + ty[0] = stripped->composite.types[index]; + axis = Node::NamedAxis::FIELD; + } else { + assert(0); + } + ty[1] = ty[2] = stripped; + return first(emplace_op(Node{ .kind = Node::SLICE, + .type = std::span{ ty, 3 }, + .slice = { .src = composite, .start = make_constant(index), .count = make_constant(1), .axis = axis } })); + } + + Ref IRModule::make_slice(Ref src, uint8_t axis, Ref base, Ref count) { + auto stripped = Type::stripped(src.type()); + auto ty = new std::shared_ptr[3]{ stripped, stripped, stripped }; + return first(emplace_op(Node{ .kind = Node::SLICE, .type = std::span{ ty, 3 }, .slice = { .src = src, .start = base, .count = count, .axis = axis } })); + } + + Ref IRModule::make_slice(std::shared_ptr type_ex, Ref src, uint8_t axis, Ref base, Ref count) { + auto ty = new std::shared_ptr[3]{ Type::stripped(type_ex), Type::stripped(src.type()), Type::stripped(src.type()) }; + return first(emplace_op(Node{ .kind = Node::SLICE, .type = std::span{ ty, 3 }, .slice = { .src = src, .start = base, .count = count, .axis = axis } })); + } + + Ref IRModule::make_converge(std::shared_ptr type, std::span deps) { + auto stripped = Type::stripped(type); + auto ty = new std::shared_ptr[1]{ stripped }; + + auto deps_ptr = new Ref[deps.size()]; + std::copy(deps.begin(), deps.end(), deps_ptr); + return first(emplace_op(Node{ .kind = Node::CONVERGE, .type = std::span{ ty, 1 }, .converge = { .diverged = std::span{ deps_ptr, deps.size() } } })); + } + + Ref IRModule::make_use(Ref src, Access acc) { + auto ty = new std::shared_ptr[1]{ src.type() }; + return first(emplace_op(Node{ .kind = Node::USE, .type = std::span{ ty, 1 }, .use = { .src = src, .access = acc } })); + } + + Ref IRModule::make_cast(std::shared_ptr dst_type, Ref src) { + auto ty = new std::shared_ptr[1]{ dst_type }; + return first(emplace_op(Node{ .kind = Node::CAST, .type = std::span{ ty, 1 }, .cast = { .src = src } })); + } + + Ref IRModule::make_acquire_next_image(Ref swapchain) { + return first(emplace_op(Node{ .kind = Node::ACQUIRE_NEXT_IMAGE, + .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_image() }, 1 }, + .acquire_next_image = { .swapchain = swapchain } })); + } + + Ref IRModule::make_clear_image(Ref dst, Clear cv) { + return first(emplace_op(Node{ .kind = Node::CLEAR, + .type = std::span{ new std::shared_ptr[1]{ types.get_builtin_image() }, 1 }, + .clear = { .dst = dst, .cv = new Clear(cv) } })); + } + + Ref IRModule::make_declare_fn(std::shared_ptr const fn_ty) { + auto ty = new std::shared_ptr[1]{ fn_ty }; + return first(emplace_op(Node{ .kind = Node::CONSTANT, .type = std::span{ ty, 1 }, .constant = { .value = nullptr } })); + } + + Ref IRModule::make_release(Ref src, Access dst_access, DomainFlagBits dst_domain) { + Ref* args_ptr = new Ref[1]{ src }; + auto tys = new std::shared_ptr[1]{ Type::stripped(src.type()) }; + return first(emplace_op(Node{ .kind = Node::RELEASE, + .type = std::span{ tys, 1 }, + .release = { .src = std::span{ args_ptr, 1 }, .dst_access = dst_access, .dst_domain = dst_domain } })); + } + + Ref IRModule::make_compile_pipeline(Ref src) { + auto tys = new std::shared_ptr[1]{ types.memory(sizeof(PipelineBaseInfo*)) }; + return first(emplace_op(Node{ .kind = Node::COMPILE_PIPELINE, .type = std::span{ tys, 1 }, .compile_pipeline = { .src = src } })); + } + + // MATH + + Ref IRModule::make_math_binary_op(Node::BinOp op, Ref a, Ref b) { + std::shared_ptr* tys = new std::shared_ptr[1]{ a.type() }; + + return first(emplace_op(Node{ .kind = Node::MATH_BINARY, .type = std::span{ tys, 1 }, .math_binary = { .a = a, .b = b, .op = op } })); + } + + ExtNode::ExtNode(Node* node) : node(node) { + acqrel = new AcquireRelease; + node->rel_acq = acqrel; + this->node->held = true; + source_module = current_module; + } + + ExtNode::ExtNode(Node* node, std::vector> deps) : deps(std::move(deps)), node(node) { + acqrel = new AcquireRelease; + node->rel_acq = acqrel; + this->node->held = true; + source_module = current_module; + } + + ExtNode::ExtNode(Node* node, std::shared_ptr dep) : node(node) { + acqrel = new AcquireRelease; + node->rel_acq = acqrel; + this->node->held = true; + deps.push_back(std::move(dep)); + + source_module = current_module; + } + + ExtNode::ExtNode(Ref ref, std::shared_ptr dep, Access access, DomainFlagBits domain) { + acqrel = new AcquireRelease; + this->node = current_module->make_release(ref, access, domain).node; + node->rel_acq = acqrel; + this->node->held = true; + deps.push_back(std::move(dep)); + + source_module = current_module; + } + + ExtNode::ExtNode(Node* node, ResourceUse use) : node(node) { + acqrel = new AcquireRelease; + acqrel->status = Signal::Status::eHostAvailable; + acqrel->last_use.resize(1); + acqrel->last_use[0] = use; + + node->rel_acq = acqrel; + this->node->held = true; + source_module = current_module; + } + + ExtNode::~ExtNode() { + if (acqrel) { + node->held = false; + } + } + + void ExtNode::mutate(Node* new_node) { + node->held = false; + node = new_node; + new_node->held = true; + } } // namespace vuk diff --git a/src/IRPasses.cpp b/src/IRPasses.cpp index 7a536f59..ebb957d6 100644 --- a/src/IRPasses.cpp +++ b/src/IRPasses.cpp @@ -85,16 +85,11 @@ namespace vuk { ++it; } - int outer_loops = 0; - int inner_loops = 0; - int steps = 0; // compute live set bool change = false; do { - outer_loops++; change = false; for (auto it = op_arena.begin(), end = op_arena.end(); it != end; ++it) { - inner_loops++; auto orig_node = &*it; if (orig_node->flag != ALIVE) { continue; @@ -113,7 +108,6 @@ namespace vuk { node->flag = ALIVE; step = true; change = true; - steps++; break; } } @@ -121,14 +115,13 @@ namespace vuk { continue; } } else { - for (int i = 0; i < node->variable_node.args.size(); i++) { + for (size_t i = 0; i < node->variable_node.args.size(); i++) { auto snode = node->variable_node.args[i].node; if (snode->flag == DEAD) { // turn it ALIVE and start from there node = snode; node->flag = ALIVE; step = true; change = true; - steps++; break; } } @@ -200,7 +193,7 @@ namespace vuk { } } } else { - for (int i = 0; i < node->variable_node.args.size(); i++) { + for (size_t i = 0; i < node->variable_node.args.size(); i++) { auto arg = node->variable_node.args[i].node; if (arg->flag == 0) { arg->flag = 1; @@ -250,7 +243,7 @@ namespace vuk { } } } else { - for (int i = 0; i < node->variable_node.args.size(); i++) { + for (size_t i = 0; i < node->variable_node.args.size(); i++) { auto arg = node->variable_node.args[i].node; if (arg->flag == 0) { arg->flag = 1; @@ -883,7 +876,7 @@ namespace vuk { // collect chains by looking at links without a prev for (auto& node : nodes) { size_t result_count = node->type.size(); - for (auto i = 0; i < result_count; i++) { + for (size_t i = 0; i < result_count; i++) { auto link = &node->links[i]; if (!link->prev) { // head, add to chains chains.push_back(link); @@ -932,7 +925,7 @@ namespace vuk { bool need_general = false; dst_use.layout = ImageLayout::eReadOnlyOptimalKHR; - for (int read_idx = 0; read_idx < reads.size(); read_idx++) { + for (size_t read_idx = 0; read_idx < reads.size(); read_idx++) { auto& r = reads[read_idx]; if (r.node->kind == Node::CALL) { if (r.node->call.args[0].type()->kind == Type::OPAQUE_FN_TY) { @@ -1467,7 +1460,7 @@ namespace vuk { args.push_back(arg); } } else { - for (int i = 0; i < node->variable_node.args.size(); i++) { + for (size_t i = 0; i < node->variable_node.args.size(); i++) { auto arg = &(*(Ref**)&node->variable_node.args)[i]; args.push_back(arg); } @@ -1497,7 +1490,7 @@ namespace vuk { impl->naming_index_counter = 0; impl->scheduled.clear(); impl->item_list.clear(); - std::vector initial_set(impl->scheduled_execables.begin(), impl->scheduled_execables.end()); + std::vector initial_set(impl->scheduled_execables.begin(), impl->scheduled_execables.end()); // these are the items that were determined to run for (auto& i : initial_set) { @@ -1768,7 +1761,7 @@ namespace vuk { new_nodes.clear(); VUK_DO_OR_RETURN(impl->collect_chains()); - + impl->scheduled_execables.clear(); for (auto& node : impl->ref_nodes) { diff --git a/src/extra/init/SimpleInit.cpp b/src/extra/init/SimpleInit.cpp index c115cb80..6b748da1 100644 --- a/src/extra/init/SimpleInit.cpp +++ b/src/extra/init/SimpleInit.cpp @@ -142,7 +142,7 @@ namespace vuk::extra { old_swapchain->images.clear(); - for (auto i = 0; i < images.size(); i++) { + for (size_t i = 0; i < images.size(); i++) { ImageAttachment ia; ia.extent = { vkswapchain->extent.width, vkswapchain->extent.height, 1 }; ia.format = (Format)vkswapchain->image_format; @@ -239,4 +239,4 @@ namespace vuk::extra { vkb::destroy_device(vkbdevice); vkb::destroy_instance(vkbinstance); } -} // namespace vuk::extra \ No newline at end of file +} // namespace vuk::extra diff --git a/src/runtime/vk/Backend.cpp b/src/runtime/vk/Backend.cpp index 59004893..14afe34d 100644 --- a/src/runtime/vk/Backend.cpp +++ b/src/runtime/vk/Backend.cpp @@ -1405,7 +1405,7 @@ namespace vuk { assert(node->construct.args[0].type()->kind == Type::MEMORY_TY); char* arr_mem = static_cast(sched.arena.ensure_space(elem_ty->size * array_size)); - for (auto i = 0; i < array_size; i++) { + for (size_t i = 0; i < array_size; i++) { auto& elem = node->construct.args[i + 1]; assert(Type::stripped(elem.type())->hash_value == elem_ty->hash_value); @@ -1437,7 +1437,7 @@ namespace vuk { char* arr_mem = static_cast(sched.arena.ensure_space(node->type[0]->size)); size_t offset = 0; - for (auto i = 0; i < node->construct.args.size() - 1; i++) { + for (size_t i = 0; i < node->construct.args.size() - 1; i++) { auto sz = node->type[0]->composite.types[i]->size; auto& elem = node->construct.args[i + 1]; memcpy(arr_mem + offset, sched.get_value(elem), sz); diff --git a/src/runtime/vk/BufferAllocator.cpp b/src/runtime/vk/BufferAllocator.cpp index f6c393f4..fd72aa3e 100644 --- a/src/runtime/vk/BufferAllocator.cpp +++ b/src/runtime/vk/BufferAllocator.cpp @@ -45,7 +45,7 @@ namespace vuk { if (!result) { return result; } - for (auto i = 0; i < num_blocks; i++) { + for (size_t i = 0; i < num_blocks; i++) { used_allocations[used_allocation_count + i] = { alloc, i > 0 ? 0 : num_blocks, 0 }; } current_buffer += (int)num_blocks; @@ -55,7 +55,7 @@ namespace vuk { available_allocation_count--; auto& alloc = used_allocations[used_allocation_count]; - for (auto i = 1; i < alloc.num_blocks; i++) { + for (size_t i = 1; i < alloc.num_blocks; i++) { // create 1 entry per block in used_allocations used_allocations[used_allocation_count + i] = { alloc.buffer, 0, 0 }; } @@ -63,7 +63,7 @@ namespace vuk { actual_blocks = used_allocations[used_allocation_count].num_blocks; } used_allocations[0].base_address = 0; - for (auto i = 0; i < actual_blocks; i++) { + for (size_t i = 0; i < actual_blocks; i++) { if (used_allocation_count + i == 0) { continue; } @@ -282,4 +282,4 @@ namespace vuk { vmaDestroyVirtualBlock(virtual_alloc); } -} // namespace vuk \ No newline at end of file +} // namespace vuk diff --git a/src/runtime/vk/DeviceFrameResource.cpp b/src/runtime/vk/DeviceFrameResource.cpp index 92bbaa27..494001d8 100644 --- a/src/runtime/vk/DeviceFrameResource.cpp +++ b/src/runtime/vk/DeviceFrameResource.cpp @@ -5,8 +5,8 @@ #include "vuk/runtime/vk/PipelineInstance.hpp" #include "vuk/runtime/vk/Query.hpp" #include "vuk/runtime/vk/RenderPass.hpp" -#include "vuk/runtime/vk/VkRuntime.hpp" #include "vuk/runtime/vk/VkQueueExecutor.hpp" +#include "vuk/runtime/vk/VkRuntime.hpp" #include #include @@ -67,9 +67,7 @@ namespace vuk { { &iv, 1 }, { &ivci, 1 }, VUK_HERE_AND_NOW()); // TODO: dropping error return iv; }, - +[](void* allocator, const ImageView& iv) { - reinterpret_cast(allocator)->sfr->deallocate_image_views({ &iv, 1 }); - }), + +[](void* allocator, const ImageView& iv) { reinterpret_cast(allocator)->sfr->deallocate_image_views({ &iv, 1 }); }), graphics_pipeline_cache( this, +[](void* allocator, const GraphicsPipelineInstanceCreateInfo& ci) { @@ -199,7 +197,7 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_semaphores(std::span src) {} // noop + void DeviceFrameResource::deallocate_semaphores([[maybe_unused]] [[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_fences(std::span dst, SourceLocationAtFrame loc) { VUK_DO_OR_RETURN(upstream->allocate_fences(dst, loc)); @@ -209,7 +207,7 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_fences(std::span src) {} // noop + void DeviceFrameResource::deallocate_fences([[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_command_buffers(std::span dst, std::span cis, @@ -271,14 +269,14 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_framebuffers(std::span src) {} // noop + void DeviceFrameResource::deallocate_framebuffers([[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_images(std::span dst, std::span cis, SourceLocationAtFrame loc) { VUK_DO_OR_RETURN(static_cast(upstream)->allocate_cached_images(dst, cis, loc)); return { expected_value }; } - void DeviceFrameResource::deallocate_images(std::span src) {} // noop + void DeviceFrameResource::deallocate_images([[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_image_views(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -289,7 +287,7 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_image_views(std::span src) {} // noop + void DeviceFrameResource::deallocate_image_views([[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_persistent_descriptor_sets(std::span dst, std::span cis, @@ -302,7 +300,7 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_persistent_descriptor_sets(std::span src) {} // noop + void DeviceFrameResource::deallocate_persistent_descriptor_sets([[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_descriptor_sets_with_value(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -315,7 +313,7 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_descriptor_sets(std::span src) {} // noop + void DeviceFrameResource::deallocate_descriptor_sets([[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_descriptor_sets(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -382,7 +380,7 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_timestamp_query_pools(std::span src) {} // noop + void DeviceFrameResource::deallocate_timestamp_query_pools([[maybe_unused]] std::span src) {} // noop Result DeviceFrameResource::allocate_timestamp_queries(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -422,7 +420,7 @@ namespace vuk { return { expected_value }; } - void DeviceFrameResource::deallocate_timestamp_queries(std::span src) {} // noop + void DeviceFrameResource::deallocate_timestamp_queries([[maybe_unused]] std::span src) {} // noop void DeviceFrameResource::wait_sync_points(std::span src) { std::unique_lock _(impl->syncpoints_mutex); @@ -501,7 +499,7 @@ namespace vuk { void DeviceFrameResource::wait() { if (impl->fences.size() > 0) { if (impl->fences.size() > 64) { - int i = 0; + size_t i = 0; for (; i < impl->fences.size() - 64; i += 64) { impl->ctx->vkWaitForFences(device, 64, impl->fences.data() + i, true, UINT64_MAX); } @@ -518,7 +516,7 @@ namespace vuk { std::vector values; values.reserve(impl->syncpoints.size()); - for (uint64_t i = 0; i < impl->syncpoints.size(); i++) { + for (size_t i = 0; i < impl->syncpoints.size(); i++) { auto& sp = impl->syncpoints[i]; if (sp.executor->type == Executor::Type::eVulkanDeviceQueue) { auto dev_queue = static_cast(sp.executor); @@ -722,7 +720,7 @@ namespace vuk { vec.insert(vec.end(), src.begin(), src.end()); } - void DeviceSuperFrameResource::deallocate_timestamp_queries(std::span src) {} // noop + void DeviceSuperFrameResource::deallocate_timestamp_queries([[maybe_unused]] std::span src) {} // noop void DeviceSuperFrameResource::wait_sync_points(std::span src) { std::shared_lock _s(impl->new_frame_mutex); @@ -923,7 +921,7 @@ namespace vuk { impl->ray_tracing_pipeline_cache.clear(); impl->render_pass_cache.clear(); - for (auto i = 0; i < frames_in_flight; i++) { + for (uint64_t i = 0; i < frames_in_flight; i++) { auto lframe = (impl->frame_counter + i) % frames_in_flight; auto& f = impl->frames[lframe]; f.wait(); @@ -934,7 +932,7 @@ namespace vuk { f.impl->linear_gpu_only.free(); } - for (auto i = 0; i < frames_in_flight; i++) { + for (uint64_t i = 0; i < frames_in_flight; i++) { auto lframe = (impl->frame_counter + i) % frames_in_flight; auto& f = impl->frames[lframe]; deallocate_frame(f); @@ -951,4 +949,4 @@ namespace vuk { } delete impl; } -} // namespace vuk \ No newline at end of file +} // namespace vuk diff --git a/src/runtime/vk/DeviceLinearResource.cpp b/src/runtime/vk/DeviceLinearResource.cpp index 693aedc5..151ec38c 100644 --- a/src/runtime/vk/DeviceLinearResource.cpp +++ b/src/runtime/vk/DeviceLinearResource.cpp @@ -63,7 +63,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_semaphores(std::span src) {} // noop + void DeviceLinearResource::deallocate_semaphores([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_fences(std::span dst, SourceLocationAtFrame loc) { VUK_DO_OR_RETURN(upstream->allocate_fences(dst, loc)); @@ -72,7 +72,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_fences(std::span src) {} // noop + void DeviceLinearResource::deallocate_fences([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_command_buffers(std::span dst, std::span cis, @@ -83,7 +83,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_command_buffers(std::span src) {} // no-op, deallocated with pools + void DeviceLinearResource::deallocate_command_buffers([[maybe_unused]] std::span src) {} // no-op, deallocated with pools Result DeviceLinearResource::allocate_command_pools(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -93,7 +93,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_command_pools(std::span dst) {} // no-op + void DeviceLinearResource::deallocate_command_pools([[maybe_unused]] std::span dst) {} // no-op Result DeviceLinearResource::allocate_buffers(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -121,7 +121,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_buffers(std::span src) {} // no-op, linear + void DeviceLinearResource::deallocate_buffers([[maybe_unused]] std::span src) {} // no-op, linear Result DeviceLinearResource::allocate_framebuffers(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -131,7 +131,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_framebuffers(std::span src) {} // noop + void DeviceLinearResource::deallocate_framebuffers([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_images(std::span dst, std::span cis, SourceLocationAtFrame loc) { VUK_DO_OR_RETURN(upstream->allocate_images(dst, cis, loc)); @@ -140,7 +140,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_images(std::span src) {} // noop + void DeviceLinearResource::deallocate_images([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_image_views(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -150,7 +150,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_image_views(std::span src) {} // noop + void DeviceLinearResource::deallocate_image_views([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_persistent_descriptor_sets(std::span dst, std::span cis, @@ -161,7 +161,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_persistent_descriptor_sets(std::span src) {} // noop + void DeviceLinearResource::deallocate_persistent_descriptor_sets([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_descriptor_sets_with_value(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -171,7 +171,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_descriptor_sets(std::span src) {} // noop + void DeviceLinearResource::deallocate_descriptor_sets([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_descriptor_sets(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -231,7 +231,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_timestamp_query_pools(std::span src) {} // noop + void DeviceLinearResource::deallocate_timestamp_query_pools([[maybe_unused]] std::span src) {} // noop Result DeviceLinearResource::allocate_timestamp_queries(std::span dst, std::span cis, SourceLocationAtFrame loc) { @@ -269,7 +269,7 @@ namespace vuk { return { expected_value }; } - void DeviceLinearResource::deallocate_timestamp_queries(std::span src) {} // noop + void DeviceLinearResource::deallocate_timestamp_queries([[maybe_unused]] std::span src) {} // noop void DeviceLinearResource::wait_sync_points(std::span src) { auto& vec = impl->syncpoints; @@ -279,7 +279,7 @@ namespace vuk { void DeviceLinearResource::wait() { if (impl->fences.size() > 0) { if (impl->fences.size() > 64) { - int i = 0; + size_t i = 0; for (; i < impl->fences.size() - 64; i += 64) { impl->ctx->vkWaitForFences(impl->device, 64, impl->fences.data() + i, true, UINT64_MAX); } @@ -336,4 +336,4 @@ namespace vuk { upstream->deallocate_descriptor_pools({ &p, 1 }); } } -} // namespace vuk \ No newline at end of file +} // namespace vuk diff --git a/src/runtime/vk/DeviceVkResource.cpp b/src/runtime/vk/DeviceVkResource.cpp index b667871a..6d558fde 100644 --- a/src/runtime/vk/DeviceVkResource.cpp +++ b/src/runtime/vk/DeviceVkResource.cpp @@ -533,9 +533,9 @@ namespace vuk { return { expected_value }; } - void DeviceVkResource::deallocate_timestamp_queries(std::span src) {} + void DeviceVkResource::deallocate_timestamp_queries([[maybe_unused]] std::span src) {} - void DeviceVkResource::wait_sync_points(std::span src) {} // noop + void DeviceVkResource::wait_sync_points([[maybe_unused]] std::span src) {} // noop Result DeviceVkResource::allocate_acceleration_structures(std::span dst, std::span cis, @@ -587,7 +587,7 @@ namespace vuk { gpci.renderPass = cinfo.render_pass; gpci.layout = cinfo.base->pipeline_layout; auto psscis = cinfo.base->psscis; - for (auto i = 0; i < psscis.size(); i++) { + for (size_t i = 0; i < psscis.size(); i++) { psscis[i].pName = cinfo.base->entry_point_names[i].c_str(); } gpci.pStages = psscis.data(); @@ -919,7 +919,7 @@ namespace vuk { uint32_t callable_count = 0; auto psscis = cinfo.base->psscis; - for (auto i = 0; i < psscis.size(); i++) { + for (size_t i = 0; i < psscis.size(); i++) { psscis[i].pName = cinfo.base->entry_point_names[i].c_str(); } diff --git a/src/runtime/vk/Program.cpp b/src/runtime/vk/Program.cpp index 4f4cad28..5e01adf5 100644 --- a/src/runtime/vk/Program.cpp +++ b/src/runtime/vk/Program.cpp @@ -487,7 +487,7 @@ namespace vuk { if (o.sets.size() > sets.size()) { sets.resize(o.sets.size()); } - for (auto index = 0; index < o.sets.size(); index++) { + for (size_t index = 0; index < o.sets.size(); index++) { auto& os = o.sets[index]; if (!os) { continue; diff --git a/src/runtime/vk/VkRuntime.cpp b/src/runtime/vk/VkRuntime.cpp index cb86619d..513ef04a 100644 --- a/src/runtime/vk/VkRuntime.cpp +++ b/src/runtime/vk/VkRuntime.cpp @@ -381,7 +381,7 @@ namespace vuk { // accumulate descriptors from all stages Program accumulated_reflection; std::string pipe_name = "Pipeline:"; - for (auto i = 0; i < cinfo.shaders.size(); i++) { + for (size_t i = 0; i < cinfo.shaders.size(); i++) { auto& source = cinfo.shaders[i]; if (source.data_ptr == nullptr) { continue; @@ -758,7 +758,6 @@ namespace vuk { auto& [executor, v] = sp; assert(executor->type == Executor::Type::eVulkanDeviceQueue); auto vkq = static_cast(executor); - auto idx = vkq->get_queue_family_index(); auto val = vkq->get_sync_value(); if (!val) { return val; @@ -784,7 +783,7 @@ namespace vuk { surface(surface) { semaphores.resize(image_count); allocator.allocate_semaphores(std::span(semaphores)); - for (auto i = 0; i < images.size(); i++) { + for (size_t i = 0; i < images.size(); i++) { ImageAttachment ia; ia.extent = { extent.width, extent.height, 1 }; ia.format = (Format)format; diff --git a/tests/02_rg_errors.cpp b/tests/02_rg_errors.cpp index a9496a0b..9633e088 100644 --- a/tests/02_rg_errors.cpp +++ b/tests/02_rg_errors.cpp @@ -34,7 +34,7 @@ TEST_CASE("error: can't construct incomplete") { REQUIRE_THROWS(download_buffer(copy(std::move(buf0), std::move(buf3))).get(*test_context.allocator, test_context.compiler)); } -auto image2buf = make_pass("copy image to buffer", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead) src, VUK_BA(Access::eTransferWrite) dst) { +static auto image2buf = make_pass("copy image to buffer", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead) src, VUK_BA(Access::eTransferWrite) dst) { BufferImageCopy bc; bc.imageOffset = { 0, 0, 0 }; bc.bufferRowLength = 0; @@ -50,7 +50,7 @@ auto image2buf = make_pass("copy image to buffer", [](CommandBuffer& cbuf, VUK_I return dst; }); -auto blit_down = make_pass("blit down", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead | Access::eTransferWrite) img) { +static auto blit_down = make_pass("blit down", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead | Access::eTransferWrite) img) { ImageBlit region = {}; region.srcOffsets[0] = Offset3D{}; region.srcOffsets[1] = Offset3D{ 2, 2, 1 }; @@ -96,15 +96,15 @@ TEST_CASE("error: attaching something twice decl/decl") { } /* TEST_CASE("not an error: attaching something twice acq/acq") { - { - auto dst = *allocate_buffer(*test_context.allocator, BufferCreateInfo{ MemoryUsage::eCPUonly, 100, 1 }); - auto buf_a = vuk::acquire_buf("a", *dst, vuk::Access::eNone); - auto buf_b = vuk::acquire_buf("a again", *dst, vuk::Access::eNone); + { + auto dst = *allocate_buffer(*test_context.allocator, BufferCreateInfo{ MemoryUsage::eCPUonly, 100, 1 }); + auto buf_a = vuk::acquire_buf("a", *dst, vuk::Access::eNone); + auto buf_b = vuk::acquire_buf("a again", *dst, vuk::Access::eNone); - auto wr_buf = vuk::make_pass("wr", [](CommandBuffer&, VUK_BA(vuk::eTransferWrite) buf, VUK_BA(vuk::eTransferWrite) bufb) { return buf; }); + auto wr_buf = vuk::make_pass("wr", [](CommandBuffer&, VUK_BA(vuk::eTransferWrite) buf, VUK_BA(vuk::eTransferWrite) bufb) { return buf; }); - REQUIRE_NOTHROW(wr_buf(buf_a, buf_b).get(*test_context.allocator, test_context.compiler)); - } + REQUIRE_NOTHROW(wr_buf(buf_a, buf_b).get(*test_context.allocator, test_context.compiler)); + } }*/ TEST_CASE("error: attaching something twice decl/acq") { @@ -130,6 +130,5 @@ TEST_CASE("error: passing same things with different access") { } } - #pragma clang diagnostic pop -#pragma warning(pop) \ No newline at end of file +#pragma warning(pop) diff --git a/tests/04_arrays.cpp b/tests/04_arrays.cpp index 2ffab5ad..be65d050 100644 --- a/tests/04_arrays.cpp +++ b/tests/04_arrays.cpp @@ -168,7 +168,7 @@ TEST_CASE("image slicing, mips") { } } -auto blit_down = make_pass("blit down", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead | Access::eTransferWrite) img) { +static auto blit_down = make_pass("blit down", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead | Access::eTransferWrite) img) { ImageBlit region = {}; region.srcOffsets[0] = Offset3D{}; region.srcOffsets[1] = Offset3D{ 2, 2, 1 }; @@ -628,37 +628,37 @@ auto frw_pass = make_pass("frw", [](CommandBuffer& cbuf, VUK_IA(Access::eTransfe }); TEST_CASE("alienated subresource") { - auto data = { 1u, 2u, 3u, 4u }; - auto ia = ImageAttachment::from_preset(ImageAttachment::Preset::eGeneric2D, Format::eR32Uint, { 2, 2, 1 }, Samples::e1); - ia.level_count = 2; - auto [img, fut] = create_image_with_data(*test_context.allocator, DomainFlagBits::eAny, ia, std::span(data)); - - size_t alignment = format_to_texel_block_size(fut->format); - size_t size = compute_image_size(fut->format, fut->extent); - auto dst = *allocate_buffer(*test_context.allocator, BufferCreateInfo{ MemoryUsage::eCPUonly, size, alignment }); - - auto mip0 = fut.mip(0); - auto mip1 = fut.mip(1); - auto dst_buf = discard_buf("dst", *dst); - auto res = download_buffer(copy(fut, std::move(dst_buf))).get(*test_context.allocator, test_context.compiler); - - { - auto futc = clear_image(mip0, vuk::ClearColor(5u, 5u, 5u, 5u)); - auto futc2 = clear_image(mip1, vuk::ClearColor(6u, 6u, 6u, 6u)); - frw_pass(mip1); - auto dst_buf = discard_buf("dst", *dst); - auto res = download_buffer(copy(mip1, std::move(dst_buf))).get(*test_context.allocator, test_context.compiler); - auto updata = std::span((uint32_t*)res->mapped_ptr, 1); - CHECK(std::all_of(updata.begin(), updata.end(), [](auto& elem) { return elem == 6; })); - } - - { - frw_pass(fut); - auto dst_buf = discard_buf("dst", *dst); - auto res = download_buffer(copy(fut.mip(0), std::move(dst_buf))).get(*test_context.allocator, test_context.compiler); - auto updata = std::span((uint32_t*)res->mapped_ptr, 1); - CHECK(std::all_of(updata.begin(), updata.end(), [](auto& elem) { return elem == 5; })); - } + auto data = { 1u, 2u, 3u, 4u }; + auto ia = ImageAttachment::from_preset(ImageAttachment::Preset::eGeneric2D, Format::eR32Uint, { 2, 2, 1 }, Samples::e1); + ia.level_count = 2; + auto [img, fut] = create_image_with_data(*test_context.allocator, DomainFlagBits::eAny, ia, std::span(data)); + + size_t alignment = format_to_texel_block_size(fut->format); + size_t size = compute_image_size(fut->format, fut->extent); + auto dst = *allocate_buffer(*test_context.allocator, BufferCreateInfo{ MemoryUsage::eCPUonly, size, alignment }); + + auto mip0 = fut.mip(0); + auto mip1 = fut.mip(1); + auto dst_buf = discard_buf("dst", *dst); + auto res = download_buffer(copy(fut, std::move(dst_buf))).get(*test_context.allocator, test_context.compiler); + + { + auto futc = clear_image(mip0, vuk::ClearColor(5u, 5u, 5u, 5u)); + auto futc2 = clear_image(mip1, vuk::ClearColor(6u, 6u, 6u, 6u)); + frw_pass(mip1); + auto dst_buf = discard_buf("dst", *dst); + auto res = download_buffer(copy(mip1, std::move(dst_buf))).get(*test_context.allocator, test_context.compiler); + auto updata = std::span((uint32_t*)res->mapped_ptr, 1); + CHECK(std::all_of(updata.begin(), updata.end(), [](auto& elem) { return elem == 6; })); + } + + { + frw_pass(fut); + auto dst_buf = discard_buf("dst", *dst); + auto res = download_buffer(copy(fut.mip(0), std::move(dst_buf))).get(*test_context.allocator, test_context.compiler); + auto updata = std::span((uint32_t*)res->mapped_ptr, 1); + CHECK(std::all_of(updata.begin(), updata.end(), [](auto& elem) { return elem == 5; })); + } } -*/ \ No newline at end of file +*/ diff --git a/tests/05_renderpass.cpp b/tests/05_renderpass.cpp index f52ea148..e0c96e13 100644 --- a/tests/05_renderpass.cpp +++ b/tests/05_renderpass.cpp @@ -5,7 +5,7 @@ using namespace vuk; -auto image2buf = make_pass("copy image to buffer", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead) src, VUK_BA(Access::eTransferWrite) dst) { +static auto image2buf = make_pass("copy image to buffer", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead) src, VUK_BA(Access::eTransferWrite) dst) { BufferImageCopy bc; bc.imageOffset = { 0, 0, 0 }; bc.bufferRowLength = 0; @@ -373,4 +373,4 @@ void main() { auto res = download_buffer(buf0).get(*test_context.allocator, test_context.compiler); auto test = { 2u, 4u, 6u }; CHECK(std::span((uint32_t*)res->mapped_ptr, 3) == std::span(test)); -} \ No newline at end of file +} diff --git a/tests/06_mt.cpp b/tests/06_mt.cpp index 954da48f..b630df56 100644 --- a/tests/06_mt.cpp +++ b/tests/06_mt.cpp @@ -7,7 +7,7 @@ using namespace vuk; -auto blit_down = make_pass("blit down", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead | Access::eTransferWrite) img) { +static auto blit_down = make_pass("blit down", [](CommandBuffer& cbuf, VUK_IA(Access::eTransferRead | Access::eTransferWrite) img) { ImageBlit region = {}; region.srcOffsets[0] = Offset3D{}; region.srcOffsets[1] = Offset3D{ 2, 2, 1 }; @@ -75,4 +75,4 @@ TEST_CASE("MT reconvergence") { auto updata = std::span((uint32_t*)res->mapped_ptr, 1); CHECK(std::all_of(updata.begin(), updata.end(), [](auto& elem) { return elem == 7; })); } -} \ No newline at end of file +}