summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2025-01-06 22:04:55 +1100
committerquou <quou@disroot.org>2025-01-06 22:05:26 +1100
commit1006ccf490c473447498a5c1a290e4dd9b55b7c2 (patch)
tree48f86d6a08307a0c09a351bde35bfa746bcc3c30
parent0fc7b4180b21e965db94872c20ca57f1ec9cc40a (diff)
cubemap support
-rw-r--r--c2.cpp3
-rw-r--r--sc/sc.cpp12
-rw-r--r--ui.cpp3
-rw-r--r--video.cpp323
-rw-r--r--video.hpp26
5 files changed, 314 insertions, 53 deletions
diff --git a/c2.cpp b/c2.cpp
index b19c238..0c231eb 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -76,6 +76,9 @@ Texture_Id make_default_texture(Device* dev) {
Texture_Flags::sampleable | Texture_Flags::copy_dst,
1,
1,
+ 1,
+ 1,
+ 1,
buf
);
dev->destroy_bufferi(buf);
diff --git a/sc/sc.cpp b/sc/sc.cpp
index de39187..143c408 100644
--- a/sc/sc.cpp
+++ b/sc/sc.cpp
@@ -255,6 +255,7 @@ struct Desc {
return &b;
}
void read_texture(cfg_Object* desc) {
+ const char* sdem;
const char* sname = find_string_default(desc, "name", 0);
if (!sname) {
print_err("%s must have a name.\n", desc->name);
@@ -276,9 +277,12 @@ struct Desc {
t.stage = 0;
t.dimension = 0;
}
+ sdem = find_string_default(desc, "dimension", 0);
Texture& t = textures[n];
t.stage |= 1 << stage_from_string(sstage);
- t.dimension = find_int_default(desc, "dimension", 2);
+ t.dimension =
+ sdem && string_equal(sdem, "cube")? -6:
+ find_int_default(desc, "dimension", 2);
}
cfg_Object* read_struct(cfg_Object* desc) {
const char* sname = find_string_default(desc, "name", 0);
@@ -437,7 +441,11 @@ struct Desc {
Descriptor* d = find_desc(it.first.c_str());
assert(d != 0);
ss << "layout (binding = " << d->slot << ") ";
- ss << "uniform sampler" << texture.dimension << "D ";
+ ss << "uniform sampler";
+ if (texture.dimension == -6)
+ ss << "Cube ";
+ else
+ ss << texture.dimension << "D ";
ss << it.first << ";\n";
}
}
diff --git a/ui.cpp b/ui.cpp
index a3ed71b..54be1ff 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -109,6 +109,9 @@ static Texture_Id create_atlas(Device* d) {
Texture_Flags::sampleable | Texture_Flags::copy_dst,
w,
10,
+ 1,
+ 1,
+ 1,
buf
);
d->destroy_bufferi(buf);
diff --git a/video.cpp b/video.cpp
index 47b7685..8bb542a 100644
--- a/video.cpp
+++ b/video.cpp
@@ -28,6 +28,7 @@ extern "C" {
#include "glad_vk.h"
+#include <math.h>
#include <string.h>
#ifdef min /* use std::min and max instead */
@@ -215,6 +216,10 @@ struct Vram_Allocator {
assert(page->mapping != 0);
return (char*)page->mapping + offset() + off;
}
+ static Allocation null() {
+ Allocation r{};
+ return r;
+ }
};
struct Chunk {
VkDeviceSize offset;
@@ -341,15 +346,39 @@ static VkImageUsageFlags get_texture_usage(int flags) {
return f;
}
-static VkImageAspectFlags get_image_aspect(int flags) {
+static VkImageAspectFlags get_image_aspect(
+ Texture_Format fmt,
+ int flags
+) {
VkImageUsageFlags f = 0;
- if (flags & Texture_Flags::depth_stencil_target)
- f |= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
- else
+ if (flags & Texture_Flags::depth_stencil_target) {
+ if (fmt == texture_format_d24s8)
+ f |=
+ VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT;
+ else
+ f |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ } else
f |= VK_IMAGE_ASPECT_COLOR_BIT;
return f;
}
+static VkImageViewType get_view_type(int a, int d, int flags) {
+ VkImageViewType t = VK_IMAGE_VIEW_TYPE_2D;
+ if (flags & Texture_Flags::cubemap) {
+ if (a > 1)
+ t = VK_IMAGE_VIEW_TYPE_CUBE;
+ else
+ t = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+ } else if (d > 1) {
+ t = VK_IMAGE_VIEW_TYPE_3D;
+ assert(a == 1);
+ } else if (a > 1) {
+ t = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ }
+ return t;
+}
+
VkImageLayout state_to_image_layout(Resource_State s) {
switch (s) {
case undefined: return VK_IMAGE_LAYOUT_UNDEFINED;
@@ -622,6 +651,24 @@ struct Texture_Vk : public Texture, public Late_Terminated {
Vram_Allocator::Allocation memory;
Resource_State state;
+ static void init(
+ Texture_Vk* t,
+ Texture_Id id,
+ VkImage img,
+ VkImageView v,
+ Vram_Allocator::Allocation mem,
+ Resource_State state,
+ Texture_Format fmt,
+ int flags,
+ int w,
+ int h,
+ int d,
+ int mip_count,
+ int array_size,
+ int start_mip,
+ int start_array,
+ bool alias
+ );
void destroy(Device_Vk*) override;
void set_name(Device_Vk* dev, const char* name);
};
@@ -718,6 +765,7 @@ struct Renderpass_Vk {
struct Framebuffer_Vk {
VkFramebuffer fbo;
+ int w, h;
int age;
void on_submit() {
@@ -1432,6 +1480,9 @@ void Device_Vk::create_depth(int w, int h) {
Texture_Flags::sampleable | Texture_Flags::depth_stencil_target,
w,
h,
+ 1,
+ 1,
+ 1,
0
);
}
@@ -1720,7 +1771,7 @@ void Framebuffer_Vk::init(
const Render_Pass& rp
) {
bool has_depth = rp.depth.id;
- int i, count = 0, w, h;
+ int i, count = 0;
VkImageView atts[2];
VkResult r;
VkFramebufferCreateInfo fbi{};
@@ -1794,14 +1845,15 @@ static VkImageView make_view(
Device_Vk* dev,
VkImage image,
VkFormat fmt,
- VkImageAspectFlags flags
+ VkImageAspectFlags flags,
+ VkImageViewType type
) {
VkImageViewCreateInfo vi{};
VkResult r;
VkImageView view;
vi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
vi.image = image;
- vi.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ vi.viewType = type;
vi.format = fmt;
vi.subresourceRange.aspectMask = flags;
vi.subresourceRange.baseMipLevel = 0;
@@ -1879,12 +1931,24 @@ Texture_Id Swapchain::create_image(
) {
Texture_Id id = dev->alloc_texture();
Texture_Vk& tex = *(Texture_Vk*)&dev->get_texture(id);
- tex.image = image;
- tex.view = view;
- tex.w = w;
- tex.h = h;
- tex.fmt = texture_format_bgra8i_srgb;
- tex.alias = true;
+ Texture_Vk::init(
+ &tex,
+ id,
+ image,
+ view,
+ Vram_Allocator::Allocation::null(),
+ Resource_State::undefined,
+ texture_format_bgra8i_srgb,
+ Texture_Flags::swapchain,
+ w,
+ h,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ true
+ );
return id;
}
@@ -1908,7 +1972,8 @@ void Swapchain::get_images(Device_Vk* dev) {
VkImageView view = make_view(dev,
images[i],
format.format,
- VK_IMAGE_ASPECT_COLOR_BIT
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_VIEW_TYPE_2D
);
textures[i] = create_image(
dev,
@@ -2276,6 +2341,7 @@ void Context::transition(Texture_Id id, Resource_State state) {
VkImageLayout dst_layout = state_to_image_layout(state);
VkPipelineStageFlags src_stage, dst_stage;
if (tex.state == state) return;
+ ctx->check_end_rp();
tex.state = state;
b.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
b.oldLayout = src_layout;
@@ -2284,10 +2350,10 @@ void Context::transition(Texture_Id id, Resource_State state) {
b.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
b.image = tex.image;
b.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- b.subresourceRange.baseMipLevel = 0;
- b.subresourceRange.levelCount = 1;
- b.subresourceRange.baseArrayLayer = 0;
- b.subresourceRange.layerCount = 1;
+ b.subresourceRange.baseMipLevel = tex.start_mip;
+ b.subresourceRange.levelCount = tex.mip_count;
+ b.subresourceRange.baseArrayLayer = tex.start_array;
+ b.subresourceRange.layerCount = tex.array_size;
if (
tex.fmt == texture_format_d16 ||
tex.fmt == texture_format_d24s8 ||
@@ -2297,9 +2363,13 @@ void Context::transition(Texture_Id id, Resource_State state) {
src_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
if (dst_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
dst_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- b.subresourceRange.aspectMask =
- VK_IMAGE_ASPECT_DEPTH_BIT |
- VK_IMAGE_ASPECT_STENCIL_BIT;
+ if (tex.fmt == texture_format_d24s8) {
+ b.subresourceRange.aspectMask =
+ VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT;
+ } else
+ b.subresourceRange.aspectMask =
+ VK_IMAGE_ASPECT_DEPTH_BIT;
b.oldLayout = src_layout;
b.newLayout = dst_layout;
}
@@ -2365,6 +2435,22 @@ void Context::transition(Texture_Id id, Resource_State state) {
dst_stage =
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ } else if (
+ src_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL &&
+ dst_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ ) {
+ b.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ b.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ } else if (
+ src_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL &&
+ dst_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+ ) {
+ b.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ b.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
} else {
print_err("Bad resource transition.\n");
pbreak(389);
@@ -2409,13 +2495,14 @@ std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(
Framebuffer_Vk& fbo = dev->get_fbo(rpo, { rp });
VkRenderPassBeginInfo rpbi{};
VkClearValue clears[max_colour_attachments + 1];
+ VkExtent2D extent{ (uint32_t)fbo.w, (uint32_t)fbo.h };
int i, c = rp.colour_count, clear_count = 0;
bool has_depth = rp.depth.id;
if (last_rpo == rpo.rpo && last_fbo == fbo.fbo)
return { rpo, fbo };
check_end_rp();
- last_rpo = rpo.rpo;
- last_fbo = fbo.fbo;
+ last_rpo = 0;
+ last_fbo = 0;
for (i = 0; i < c; i++) {
VkClearValue clear{};
const auto& tar = rp.colours[i];
@@ -2437,7 +2524,7 @@ std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(
rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rpbi.renderPass = rpo.rpo;
rpbi.framebuffer = fbo.fbo;
- rpbi.renderArea.extent = dev->swapchain.size;
+ rpbi.renderArea.extent = extent;
rpbi.clearValueCount = clear_count;
rpbi.pClearValues = clears;
vkCmdBeginRenderPass(
@@ -2446,6 +2533,8 @@ std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(
VK_SUBPASS_CONTENTS_INLINE
);
dev->first_rp = false;
+ last_rpo = rpo.rpo;
+ last_fbo = fbo.fbo;
return { rpo, fbo };
}
@@ -3432,6 +3521,9 @@ Texture_Id Device::create_texture(
int flags,
int w,
int h,
+ int d,
+ int mip_count,
+ int array_size,
Buffer_Id init
) {
VkImageCreateInfo ii{};
@@ -3439,27 +3531,39 @@ Texture_Id Device::create_texture(
Device_Vk* dev = (Device_Vk*)this;
Texture_Id id = dev->alloc_texture();
Texture_Vk& tex = *(Texture_Vk*)&dev->get_texture(id);
+ VkImage image;
+ VkImageView view;
+ Vram_Allocator::Allocation mem;
VkMemoryRequirements req;
- VkImageAspectFlags aspect = get_image_aspect(flags);
- tex.state = Resource_State::undefined;
+ VkImageAspectFlags aspect = get_image_aspect(fmt, flags);
+ VkImageViewCreateInfo vi{};
+ VkImageCreateFlags image_flags = 0;
+ int array_count = array_size;
+ if (flags & Texture_Flags::cubemap) {
+ array_count *= 6;
+ image_flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+ }
+ if (mip_count == 0)
+ mip_count = (int)(std::floor(std::log2(std::max(w, h)))) + 1;
ii.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- ii.imageType = VK_IMAGE_TYPE_2D;
+ ii.imageType = d == 1? VK_IMAGE_TYPE_2D: VK_IMAGE_TYPE_3D;
ii.extent.width = w;
ii.extent.height = h;
- ii.extent.depth = 1;
- ii.mipLevels = 1;
- ii.arrayLayers = 1;
+ ii.extent.depth = d;
+ ii.mipLevels = mip_count;
+ ii.arrayLayers = array_count;
ii.format = get_vk_format(fmt);
ii.tiling = VK_IMAGE_TILING_OPTIMAL;
ii.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
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);
+ ii.flags = image_flags;
+ r = vkCreateImage(dev->dev, &ii, &dev->ac, &image);
if (r != VK_SUCCESS) {
print_err("Failed to create an image.\n");
}
- vkGetImageMemoryRequirements(dev->dev, tex.image, &req);
+ vkGetImageMemoryRequirements(dev->dev, image, &req);
{
VkMemoryPropertyFlags props =
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
@@ -3468,27 +3572,49 @@ Texture_Id Device::create_texture(
print("Failed to find a satisfying memory type index.\n");
pbreak(mt);
}
- tex.memory = dev->vrama.alloc(mt, req.size, req.alignment);
- if (!tex.memory.valid()) {
+ mem = dev->vrama.alloc(mt, req.size, req.alignment);
+ if (!mem.valid()) {
print_err("Failed to allocate memory for texture.\n");
pbreak(900);
}
}
vkBindImageMemory(
dev->dev,
- tex.image,
- tex.memory.mem,
- tex.memory.offset()
+ image,
+ mem.mem,
+ mem.offset()
);
- tex.w = w;
- tex.h = h;
- tex.fmt = fmt;
- tex.alias = false;
- tex.view = make_view(
- dev,
- tex.image,
- ii.format,
- aspect
+ vi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ vi.image = image;
+ vi.viewType = get_view_type(array_count, d, flags);
+ vi.format = ii.format;
+ vi.subresourceRange.aspectMask = aspect;
+ vi.subresourceRange.baseMipLevel = 0;
+ vi.subresourceRange.levelCount = mip_count;
+ vi.subresourceRange.baseArrayLayer = 0;
+ vi.subresourceRange.layerCount = array_count;
+ r = vkCreateImageView(dev->dev, &vi, &dev->ac, &view);
+ if (r != VK_SUCCESS) {
+ print_err("Failed to make image view.\n");
+ pbreak((int)r);
+ }
+ Texture_Vk::init(
+ &tex,
+ id,
+ image,
+ view,
+ mem,
+ Resource_State::undefined,
+ fmt,
+ flags,
+ w,
+ h,
+ d,
+ mip_count,
+ array_size,
+ 0,
+ 0,
+ false
);
if (init) {
Context& ctx = dev->acquire();
@@ -3501,17 +3627,76 @@ Texture_Id Device::create_texture(
return id;
}
+Texture_Id Device::alias_texture(
+ Texture_Id o,
+ const char* name,
+ Texture_Format fmt,
+ int flags,
+ int w,
+ int h,
+ int d,
+ int mip_count,
+ int array_size,
+ int start_mip,
+ int start_array
+) {
+ Device_Vk* dev = (Device_Vk*)this;
+ Texture_Vk& texture = *(Texture_Vk*)&dev->get_texture(o);
+ Texture_Id ntid = dev->alloc_texture();
+ Texture_Vk& nt = *(Texture_Vk*)&dev->get_texture(ntid);
+ VkImageViewCreateInfo vi{};
+ VkImageView view;
+ VkResult r;
+ assert(!texture.alias);
+ vi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ vi.image = texture.image;
+ vi.viewType = get_view_type(array_size, d, flags);
+ vi.format = get_vk_format(fmt);
+ vi.subresourceRange.aspectMask = get_image_aspect(fmt, flags);
+ vi.subresourceRange.baseMipLevel = start_mip;
+ vi.subresourceRange.levelCount = mip_count;
+ vi.subresourceRange.baseArrayLayer = start_array;
+ vi.subresourceRange.layerCount = array_size;
+ r = vkCreateImageView(dev->dev, &vi, &dev->ac, &view);
+ if (r != VK_SUCCESS) {
+ print_err("Failed to alias texture.\n");
+ pbreak(r);
+ }
+ Texture_Vk::init(
+ &nt,
+ ntid,
+ texture.image,
+ view,
+ Vram_Allocator::Allocation::null(),
+ Resource_State::undefined,
+ fmt,
+ flags,
+ w,
+ h,
+ d,
+ mip_count,
+ array_size,
+ start_mip,
+ start_array,
+ true
+ );
+ nt.set_name(dev, name);
+ return ntid;
+}
+
void Texture_Vk::set_name(Device_Vk* dev, const char* name) {
#ifdef DEBUG
VkDebugUtilsObjectNameInfoEXT i{};
i.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
i.pObjectName = name;
- i.objectType = VK_OBJECT_TYPE_IMAGE;
- i.objectHandle = (uint64_t)image;
- vkSetDebugUtilsObjectNameEXT(dev->dev, &i);
i.objectType = VK_OBJECT_TYPE_IMAGE_VIEW;
i.objectHandle = (uint64_t)view;
vkSetDebugUtilsObjectNameEXT(dev->dev, &i);
+ if (!alias) {
+ i.objectType = VK_OBJECT_TYPE_IMAGE;
+ i.objectHandle = (uint64_t)image;
+ vkSetDebugUtilsObjectNameEXT(dev->dev, &i);
+ }
#else
(void)dev;
(void)name;
@@ -3740,6 +3925,9 @@ Asset* Texture_Loader::load(
Texture_Flags::sampleable | Texture_Flags::copy_dst,
w,
h,
+ 1,
+ 1,
+ 1,
buf
);
dev->destroy_buffer(buf);
@@ -3752,6 +3940,43 @@ void Texture_Loader::unload(Asset* a) {
dev->destroy_texture(tex->id);
}
+void Texture_Vk::init(
+ Texture_Vk* t,
+ Texture_Id id,
+ VkImage img,
+ VkImageView v,
+ Vram_Allocator::Allocation mem,
+ Resource_State st,
+ Texture_Format fmt,
+ int flags,
+ int w,
+ int h,
+ int d,
+ int mip_count,
+ int array_size,
+ int start_mip,
+ int start_array,
+ bool alias
+) {
+ t->id = id;
+ t->image = img;
+ t->view = v;
+ t->memory = mem;
+ t->state = st;
+ t->w = w;
+ t->h = h;
+ t->d = d;
+ t->mip_count = mip_count;
+ t->array_size = array_size;
+ t->fmt = fmt;
+ t->flags = flags;
+ t->mip_count = mip_count;
+ t->array_size = array_size;
+ t->start_mip = start_mip;
+ t->start_array = start_array;
+ t->alias = alias;
+}
+
void Texture_Vk::destroy(Device_Vk* dev) {
if (!alias) {
vkDestroyImage(dev->dev, image, &dev->ac);
diff --git a/video.hpp b/video.hpp
index 52fffea..29c1445 100644
--- a/video.hpp
+++ b/video.hpp
@@ -335,7 +335,10 @@ enum Resource_State {
struct Texture : public Asset {
Texture_Id id;
Texture_Format fmt;
- int w, h;
+ int flags;
+ int w, h, d;
+ int mip_count, array_size;
+ int start_mip, start_array;
bool alias;
};
@@ -358,7 +361,9 @@ namespace Texture_Flags {
colour_target = 1 << 1,
depth_stencil_target = 1 << 2,
copy_src = 1 << 3,
- copy_dst = 1 << 4
+ copy_dst = 1 << 4,
+ cubemap = 1 << 5,
+ swapchain = 1 << 6
};
};
@@ -456,8 +461,25 @@ struct Device {
int flags,
int w,
int h,
+ int d,
+ int mip_count,
+ int array_size,
Buffer_Id init
);
+ Texture_Id alias_texture(
+ Texture_Id o,
+ const char* name,
+ Texture_Format fmt,
+ int flags,
+ int w,
+ int h,
+ int d,
+ int mip_count,
+ int array_size,
+ int start_mip,
+ int start_array
+ );
+
Texture_Id get_backbuffer();
Texture_Id get_depth_target();
Texture& get_texture(Texture_Id id);