From dfd95c6e29c25c3ad9acc3e63a790da866339015 Mon Sep 17 00:00:00 2001 From: quou Date: Sun, 29 Dec 2024 11:28:19 +1100 Subject: seperate framebuffers and renderpasses; depth buffering. --- video.cpp | 363 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 284 insertions(+), 79 deletions(-) (limited to 'video.cpp') diff --git a/video.cpp b/video.cpp index 4a79adb..ba6fd7c 100644 --- a/video.cpp +++ b/video.cpp @@ -6,6 +6,7 @@ #define max_buffers 1024 #define max_vertex_formats 64 #define max_rpos 64 +#define max_fbos 64 #define max_pipelines 64 #define max_descriptor_sets 64 #define max_shaders 32 @@ -203,11 +204,42 @@ static VkFormat get_vk_format(Texture_Format fmt) { case texture_format_rgb16f: return VK_FORMAT_R16G16B16_SFLOAT; case texture_format_rgb32f: return VK_FORMAT_R32G32B32_SFLOAT; case texture_format_rgba8i: return VK_FORMAT_R8G8B8A8_UNORM; + case texture_format_rgba8i_srgb: return VK_FORMAT_R8G8B8A8_SRGB; + case texture_format_bgra8i_srgb: return VK_FORMAT_B8G8R8A8_SRGB; case texture_format_rgba16f: return VK_FORMAT_R16G16B16A16_SFLOAT; case texture_format_rgba32f: return VK_FORMAT_R32G32B32A32_SFLOAT; case texture_format_bc1: return VK_FORMAT_BC1_RGB_UNORM_BLOCK; - default: assert(0); return VK_FORMAT_UNDEFINED; + case texture_format_d16: return VK_FORMAT_D16_UNORM; + case texture_format_d24s8: return VK_FORMAT_D24_UNORM_S8_UINT; + case texture_format_d32: return VK_FORMAT_D32_SFLOAT; + case texture_format_count: break; } + assert(0); + return VK_FORMAT_UNDEFINED; +} + +static VkImageUsageFlags get_texture_usage(int flags) { + VkImageUsageFlags f = 0; + if (flags & Texture_Flags::sampleable) + f |= VK_IMAGE_USAGE_SAMPLED_BIT; + if (flags & Texture_Flags::colour_target) + f |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + if (flags & Texture_Flags::depth_stencil_target) + f |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + if (flags & Texture_Flags::copy_src) + f |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + if (flags & Texture_Flags::copy_dst) + f |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + return f; +} + +static VkImageAspectFlags get_image_aspect(int flags) { + VkImageUsageFlags f = 0; + if (flags & Texture_Flags::depth_stencil_target) + f |= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + else + f |= VK_IMAGE_ASPECT_COLOR_BIT; + return f; } VkImageLayout state_to_image_layout(Resource_State s) { @@ -446,6 +478,7 @@ struct Shader_Vk : public Shader, public Late_Terminated { }; struct Renderpass_Vk; +struct Framebuffer_Vk; struct Context_Vk : public Context { int state; Device_Vk* dev; @@ -463,8 +496,10 @@ struct Context_Vk : public Context { void release(); void destroy(); - Renderpass_Vk& begin_rp(const Render_Pass& rp); - void end_rp(Renderpass_Vk& rpo); + std::pair begin_rp( + const Render_Pass& rp + ); + void end_rp(Renderpass_Vk& rpo, Framebuffer_Vk& fbo); }; struct Texture_Vk : public Texture, public Late_Terminated { @@ -520,7 +555,14 @@ struct Rpo_Key { bool operator==(const Rpo_Key& other) const { return is_first == other.is_first && - rpo == other.rpo; + rpo.layout_eq(other.rpo); + } +}; + +struct Fbo_Key { + Render_Pass rpo; + bool operator==(const Fbo_Key& other) const { + return rpo.resources_eq(other.rpo); } }; @@ -546,8 +588,6 @@ struct Dso_Key { struct Renderpass_Vk { VkRenderPass rpo; - VkFramebuffer fbo; - VkClearValue clear; int age; void on_submit() { @@ -556,8 +596,23 @@ struct Renderpass_Vk { VkAttachmentLoadOp load_op_from_mode(Clear_Mode m); - void init_rp(Device_Vk* dev, const Rpo_Key& rp); - void init_fb(Device_Vk* dev, const Render_Pass& rp); + void init(Device_Vk* dev, const Rpo_Key& rp); + void destroy(Device_Vk* dev); +}; + +struct Framebuffer_Vk { + VkFramebuffer fbo; + int age; + + void on_submit() { + age = 0; + } + + void init( + Device_Vk* dev, + const Renderpass_Vk& rpo, + const Render_Pass& rp + ); void destroy(Device_Vk* dev); }; @@ -626,6 +681,8 @@ struct Pipeline_Vk { const Pipeline& desc ); + static VkCompareOp get_compare_op(Depth_Mode m); + void on_submit() { age = 0; } @@ -673,10 +730,18 @@ struct Sampler_Vk : public Late_Terminated { template<> struct Hash_Function { size_t operator()(const Rpo_Key& k) const { - return (size_t)fnv1a64_2(fnv1a64( - (uint8_t*)&k.rpo, - sizeof k.rpo - ), (uint8_t*)&k.is_first, 1); + return (size_t)fnv1a64_2( + k.rpo.layout_hash, + (uint8_t*)&k.is_first, + 1 + ); + } +}; + +template<> +struct Hash_Function { + size_t operator()(const Fbo_Key& k) const { + return k.rpo.resource_hash; } }; @@ -736,13 +801,6 @@ struct Hash_Function { } }; -template<> -struct std::hash { - size_t operator()(const Render_Pass& rp) const { - return (size_t)fnv1a64((uint8_t*)&rp, sizeof rp); - } -}; - struct Shader_Loader : public Asset_Loader { Device_Vk* dev; void init(Device_Vk* d); @@ -818,6 +876,7 @@ struct Device_Vk : public Device { uint32_t sampler_count; Hash_Map rpo_cache; + Hash_Map fbo_cache; Hash_Map pso_cache; Hash_Map dso_cache; @@ -825,6 +884,8 @@ struct Device_Vk : public Device { uint32_t terminator_index; bool first_rp; + Texture_Id depth; + Texture_Id alloc_texture(); Buffer_Id alloc_buffer(); Vertex_Format_Id alloc_vf(); @@ -846,6 +907,14 @@ struct Device_Vk : public Device { Renderpass_Vk& create_rpo(const Rpo_Key& rp); Renderpass_Vk& get_rpo(const Rpo_Key& rp); + Framebuffer_Vk& create_fbo( + const Renderpass_Vk& rpo, + const Fbo_Key& fb + ); + Framebuffer_Vk& get_fbo( + const Renderpass_Vk& rpo, + const Fbo_Key& fb + ); Pipeline_Vk& create_pso(const Pso_Key& pip); Pipeline_Vk& get_pso(const Pso_Key& pop); Descriptor_Set_Vk& create_dso( @@ -860,6 +929,7 @@ struct Device_Vk : public Device { void collect_garbage(); void queue_destroy(Late_Terminated* obj); void create_terminators(); + void create_depth(int w, int h); int find_memory_type( uint32_t filter, @@ -1175,6 +1245,7 @@ void Device_Vk::init_internal() { samplers.init(); sampler_count = 1; rpo_cache.init(); + fbo_cache.init(); pso_cache.init(); dso_cache.init(); shader_loader.init(this); @@ -1198,6 +1269,8 @@ void Device_Vk::init_internal() { contexts[i].state = context_state_avail; swapchain.init(*app, this); create_terminators(); + depth = 0; + create_depth(app->w, app->h); } void Device_Vk::create_terminators() { @@ -1216,14 +1289,29 @@ void Device_Vk::create_terminators() { } } +void Device_Vk::create_depth(int w, int h) { + if (depth) + destroy_texture(depth); + depth = create_texture( + texture_format_d24s8, + Texture_Flags::sampleable | Texture_Flags::depth_stencil_target, + w, + h, + 0 + ); +} + void Device_Vk::deinit_internal() { int i, image_count = swapchain.image_count; vkDeviceWaitIdle(dev); + destroy_texture(depth); swapchain.destroy(this); deinit_swap_cap(this, &swap_cap); app_destroy_vk_surface(app, inst, surf); for (auto i : rpo_cache) i.second.destroy(this); + for (auto i : fbo_cache) + i.second.destroy(this); for (auto i : pso_cache) i.second.destroy(this); for (auto i : dso_cache) @@ -1255,20 +1343,13 @@ void Device_Vk::on_resize_internal(int w, int h) { get_swap_cap(this, phys_dev, surf, &swap_cap); swapchain.recreate(*app, this); create_terminators(); + create_depth(w, h); } Renderpass_Vk& Device_Vk::create_rpo(const Rpo_Key& k) { - VkClearValue clear{}; - auto& rp = k.rpo; - clear.color.float32[0] = (float)rp.clear.r / 255.0f; - clear.color.float32[1] = (float)rp.clear.g / 255.0f; - clear.color.float32[2] = (float)rp.clear.b / 255.0f; - clear.color.float32[3] = (float)rp.clear.a / 255.0f; Renderpass_Vk rpo; - rpo.init_rp(this, k); - rpo.init_fb(this, rp); + rpo.init(this, k); rpo.age = 0; - rpo.clear = clear; return rpo_cache.set(k, rpo); } @@ -1279,6 +1360,27 @@ Renderpass_Vk& Device_Vk::get_rpo(const Rpo_Key& rp) { return *rpo; } +Framebuffer_Vk& Device_Vk::create_fbo( + const Renderpass_Vk& rpo, + const Fbo_Key& k +) { + auto& fb = k.rpo; + Framebuffer_Vk fbo; + fbo.init(this, rpo, fb); + fbo.age = 0; + return fbo_cache.set(k, fbo); +} + +Framebuffer_Vk& Device_Vk::get_fbo( + const Renderpass_Vk& rpo, + const Fbo_Key& fb +) { + Framebuffer_Vk* fbo = fbo_cache.get(fb); + if (!fbo) + return create_fbo(rpo, fb); + return *fbo; +} + Pipeline_Vk& Device_Vk::create_pso(const Pso_Key& pip) { Pipeline_Vk pso; pso.age = 0; @@ -1313,11 +1415,6 @@ Descriptor_Set_Vk& Device_Vk::get_dso( return *dso; } -void Renderpass_Vk::destroy(Device_Vk* dev) { - vkDestroyRenderPass(dev->dev, rpo, &dev->ac); - vkDestroyFramebuffer(dev->dev, fbo, &dev->ac); -} - void Device_Vk::collect_garbage() { int max_age = swapchain.image_count + 3; for (const auto& i: rpo_cache) { @@ -1328,6 +1425,14 @@ void Device_Vk::collect_garbage() { rpo_cache.remove(i.first); } } + for (const auto& i: fbo_cache) { + auto& fb = i.second; + fb.age++; + if (fb.age > max_age) { + fb.destroy(this); + fbo_cache.remove(i.first); + } + } for (const auto& i: pso_cache) { auto& pip = i.second; pip.age++; @@ -1377,39 +1482,63 @@ VkAttachmentLoadOp Renderpass_Vk::load_op_from_mode( return VK_ATTACHMENT_LOAD_OP_DONT_CARE; } -void Renderpass_Vk::init_rp( +void Renderpass_Vk::init( Device_Vk* dev, const Rpo_Key& rpk ) { VkRenderPassCreateInfo ri{}; - VkAttachmentDescription ad{}; - VkAttachmentReference ar{}; + VkAttachmentDescription ads[2]; + VkAttachmentReference car, dar; VkSubpassDescription sd{}; VkResult r; auto& rp = rpk.rpo; - - ad.format = dev->swapchain.format.format; - ad.samples = VK_SAMPLE_COUNT_1_BIT; - ad.loadOp = load_op_from_mode(rp.mode); - ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - if (rpk.is_first) - ad.initialLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - else - ad.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - ad.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - ar.attachment = 0; - ar.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + bool has_depth = rp.depth.id; + int count = 0, i, c = rp.colour_count; + zero(ads, sizeof ads); + for (i = 0; i < c; i++) { + int index = count++; + auto& colour = rp.colours[i]; + auto& ad = ads[index]; + ad.format = get_vk_format(colour.fmt); + ad.samples = VK_SAMPLE_COUNT_1_BIT; + ad.loadOp = load_op_from_mode(colour.mode); + ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + if (rpk.is_first) + ad.initialLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + else + ad.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + ad.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + car.attachment = index; + car.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + if (has_depth) { + int i = count++; + auto& ad = ads[i]; + ad.format = get_vk_format(dev->get_texture(rp.depth.id).fmt); + ad.samples = VK_SAMPLE_COUNT_1_BIT; + ad.loadOp = load_op_from_mode(rp.depth.mode); + ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + ad.stencilLoadOp = ad.loadOp; + ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + if (rpk.is_first) + ad.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + else + ad.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + ad.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + dar.attachment = i; + dar.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + } sd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; sd.colorAttachmentCount = 1; - sd.pColorAttachments = &ar; + sd.pColorAttachments = &car; + sd.pDepthStencilAttachment = has_depth? &dar: 0; ri.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - ri.attachmentCount = 1; - ri.pAttachments = &ad; + ri.attachmentCount = count; + ri.pAttachments = ads; ri.subpassCount = 1; ri.pSubpasses = &sd; @@ -1420,21 +1549,42 @@ void Renderpass_Vk::init_rp( } } -void Renderpass_Vk::init_fb( +void Renderpass_Vk::destroy(Device_Vk* dev) { + vkDestroyRenderPass(dev->dev, rpo, &dev->ac); +} + +void Framebuffer_Vk::init( Device_Vk* dev, + const Renderpass_Vk& rpo, const Render_Pass& rp ) { - const Texture_Vk& texture = - *(const Texture_Vk*)&dev->get_texture(rp.target); + bool has_depth = rp.depth.id; + int i, count = 0, w, h; + VkImageView atts[2]; VkResult r; VkFramebufferCreateInfo fbi{}; + for (i = 0; i < rp.colour_count; i++) { + const auto& tar = rp.colours[i]; + const Texture_Vk& texture = + *(const Texture_Vk*)&dev->get_texture(tar.id); + atts[count++] = texture.view; + w = texture.w; + h = texture.h; + } + if (has_depth) { + const Texture_Vk& texture = + *(const Texture_Vk*)&dev->get_texture(rp.depth.id); + atts[count++] = texture.view; + w = texture.w; + h = texture.h; + } fbi.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbi.renderPass = rpo; - fbi.width = texture.w; - fbi.height = texture.h; + fbi.renderPass = rpo.rpo; + fbi.width = w; + fbi.height = h; fbi.layers = 1; - fbi.attachmentCount = 1; - fbi.pAttachments = &texture.view; + fbi.attachmentCount = count; + fbi.pAttachments = atts; r = vkCreateFramebuffer(dev->dev, &fbi, &dev->ac, &fbo); if (r != VK_SUCCESS) { print_err("Failed to create a framebuffer.\n"); @@ -1442,6 +1592,10 @@ void Renderpass_Vk::init_fb( } } +void Framebuffer_Vk::destroy(Device_Vk* dev) { + vkDestroyFramebuffer(dev->dev, fbo, &dev->ac); +} + static int get_image_count(const Swap_Cap& s) { const VkSurfaceCapabilitiesKHR& cap = s.cap; return cap.minImageCount + (cap.minImageCount < cap.maxImageCount); @@ -1479,7 +1633,7 @@ static VkImageView make_view( Device_Vk* dev, VkImage image, VkFormat fmt, - VkImageAspectFlagBits flags + VkImageAspectFlags flags ) { VkImageViewCreateInfo vi{}; VkResult r; @@ -1568,6 +1722,7 @@ Texture_Id Swapchain::create_image( tex.view = view; tex.w = w; tex.h = h; + tex.fmt = texture_format_bgra8i_srgb; tex.alias = true; return id; } @@ -1716,6 +1871,10 @@ Texture_Id Device::get_backbuffer() { return ((Device_Vk*)this)->backbuffer_id; } +Texture_Id Device::get_depth_target() { + return ((Device_Vk*)this)->depth; +} + Texture& Device::get_texture(Texture_Id id) { return ((Device_Vk*)this)->textures[id]; } @@ -1802,7 +1961,7 @@ void Context::submit( Descriptor_Set_Vk* dso = 0; if (p.descriptor_count) dso = &dev->get_dso(pso, *(Dso_Key*)&p); - auto& rpo = ctx->begin_rp(rp); + auto [rpo, fbo] = ctx->begin_rp(rp); Texture_Vk& target = *(Texture_Vk*)&dev->get_texture( dev->get_backbuffer() ); @@ -1855,7 +2014,7 @@ void Context::submit( draw.first_instance ); } - ctx->end_rp(rpo); + ctx->end_rp(rpo, fbo); pso.on_submit(); if (dso) dso->on_submit(); @@ -2003,33 +2162,56 @@ void Context::transition(Texture_Id id, Resource_State state) { ); } -Renderpass_Vk& Context_Vk::begin_rp(const Render_Pass& rp) { +std::pair Context_Vk::begin_rp( + const Render_Pass& rp +) { Renderpass_Vk& rpo = dev->get_rpo({ dev->first_rp, rp}); + Framebuffer_Vk& fbo = dev->get_fbo(rpo, { rp }); VkRenderPassBeginInfo rpbi{}; + VkClearValue clears[max_colour_attachments + 1]; + int i, c = rp.colour_count, clear_count = 0; + bool has_depth = rp.depth.id; + for (i = 0; i < c; i++) { + VkClearValue clear{}; + const auto& tar = rp.colours[i]; + const auto col = tar.clear.colour; + clear.color.float32[0] = (float)col.r / 255.0f; + clear.color.float32[1] = (float)col.g / 255.0f; + clear.color.float32[2] = (float)col.b / 255.0f; + clear.color.float32[3] = (float)col.a / 255.0f; + clears[clear_count++] = clear; + } + if (has_depth) { + VkClearValue dc{}; + dc.depthStencil.depth = rp.depth.clear.depth; + dc.depthStencil.stencil = 0; /* todo */ + clears[clear_count++] = dc; + } rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rpbi.renderPass = rpo.rpo; - rpbi.framebuffer = rpo.fbo; + rpbi.framebuffer = fbo.fbo; rpbi.renderArea.extent = dev->swapchain.size; - rpbi.clearValueCount = rp.mode == Clear_Mode::clear? 1: 0; - rpbi.pClearValues = &rpo.clear; + rpbi.clearValueCount = clear_count; + rpbi.pClearValues = clears; vkCmdBeginRenderPass( cb, &rpbi, VK_SUBPASS_CONTENTS_INLINE ); dev->first_rp = false; - return rpo; + return { rpo, fbo }; } -void Context_Vk::end_rp(Renderpass_Vk& rpo) { +void Context_Vk::end_rp(Renderpass_Vk& rpo, Framebuffer_Vk& fbo) { vkCmdEndRenderPass(cb); rpo.on_submit(); + fbo.on_submit(); } void Context::submit(const Render_Pass& rp) { Context_Vk* ctx = (Context_Vk*)this; - auto& rpo = ctx->begin_rp(rp); - ctx->end_rp(rpo); + auto [rpo, fbo] = ctx->begin_rp(rp); + ctx->end_rp(rpo, fbo); } void Context_Vk::init_pool() { @@ -2305,9 +2487,9 @@ void Pipeline_Vk::init_depthstencil( (void)desc; zero(&ds, sizeof ds); ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - ds.depthTestEnable = VK_FALSE; - ds.depthWriteEnable = VK_FALSE; - ds.depthCompareOp = VK_COMPARE_OP_LESS; + ds.depthTestEnable = desc.depth_test; + ds.depthWriteEnable = desc.depth_write; + ds.depthCompareOp = get_compare_op(desc.depth_mode); ds.depthBoundsTestEnable = VK_FALSE; ds.stencilTestEnable = VK_FALSE; info.pDepthStencilState = &ds; @@ -2403,6 +2585,20 @@ void Pipeline_Vk::init_descriptors( } } +VkCompareOp Pipeline_Vk::get_compare_op(Depth_Mode m) { + switch (m) { + case Depth_Mode::less: return VK_COMPARE_OP_LESS; + case Depth_Mode::less_equal: return VK_COMPARE_OP_LESS_OR_EQUAL; + case Depth_Mode::equal: return VK_COMPARE_OP_EQUAL; + case Depth_Mode::greater: return VK_COMPARE_OP_GREATER; + case Depth_Mode::greater_equal: return VK_COMPARE_OP_GREATER_OR_EQUAL; + case Depth_Mode::always: return VK_COMPARE_OP_ALWAYS; + case Depth_Mode::never: return VK_COMPARE_OP_NEVER; + } + assert(0); + return VK_COMPARE_OP_LESS; +} + void Pipeline_Vk::init_layout( Device_Vk* dev, const Pipeline& desc @@ -2903,6 +3099,7 @@ Buffer& Device::get_buffer(Buffer_Id id) { Texture_Id Device::create_texture( Texture_Format fmt, + int flags, int w, int h, Buffer_Id init @@ -2913,6 +3110,7 @@ Texture_Id Device::create_texture( Texture_Id id = dev->alloc_texture(); Texture_Vk& tex = *(Texture_Vk*)&dev->get_texture(id); VkMemoryRequirements req; + VkImageAspectFlags aspect = get_image_aspect(flags); tex.state = Resource_State::undefined; ii.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; ii.imageType = VK_IMAGE_TYPE_2D; @@ -2924,7 +3122,7 @@ Texture_Id Device::create_texture( ii.format = get_vk_format(fmt); ii.tiling = VK_IMAGE_TILING_OPTIMAL; ii.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - ii.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + ii.usage = get_texture_usage(flags); ii.sharingMode = VK_SHARING_MODE_EXCLUSIVE; ii.samples = VK_SAMPLE_COUNT_1_BIT; r = vkCreateImage(dev->dev, &ii, &dev->ac, &tex.image); @@ -2957,12 +3155,13 @@ Texture_Id Device::create_texture( vkBindImageMemory(dev->dev, tex.image, tex.memory, 0); tex.w = w; tex.h = h; + tex.fmt = fmt; tex.alias = false; tex.view = make_view( dev, tex.image, ii.format, - VK_IMAGE_ASPECT_COLOR_BIT + aspect ); if (init) { Context& ctx = dev->acquire(); @@ -3170,7 +3369,13 @@ Asset* Texture_Loader::load(Arena* a, Arena* s, Pack_File* f) { pack_read(f, data, size); { Buffer_Id buf = upload(data, size); - Texture_Id tex = dev->create_texture(fmt, w, h, buf); + Texture_Id tex = dev->create_texture( + fmt, + Texture_Flags::sampleable | Texture_Flags::copy_dst, + w, + h, + buf + ); dev->destroy_buffer(buf); return &dev->get_texture(tex); } -- cgit v1.2.3-54-g00ecf