summaryrefslogtreecommitdiff
path: root/video.cpp
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-12-23 14:41:01 +1100
committerquou <quou@disroot.org>2024-12-23 14:41:01 +1100
commitb293168cc158d65f1a5146f155921ff82119d1bc (patch)
tree08cc5ee235b4b7ca6ead45c43f9b407664971613 /video.cpp
parent58245585cbe77e6c03ebe13f29e10393ff3c45b4 (diff)
Texture conversion and loading
Diffstat (limited to 'video.cpp')
-rw-r--r--video.cpp584
1 files changed, 476 insertions, 108 deletions
diff --git a/video.cpp b/video.cpp
index 1670a61..8bc5080 100644
--- a/video.cpp
+++ b/video.cpp
@@ -176,6 +176,35 @@ struct Hash_Map {
}
};
+static VkFormat get_vk_format(Texture_Format fmt) {
+ switch (fmt) {
+ case texture_format_r8i: return VK_FORMAT_R8_UNORM;
+ case texture_format_r16f: return VK_FORMAT_R16_SFLOAT;
+ case texture_format_r32f: return VK_FORMAT_R32_SFLOAT;
+ case texture_format_rg8i: return VK_FORMAT_R8G8_UNORM;
+ case texture_format_rg16f: return VK_FORMAT_R16G16_SFLOAT;
+ case texture_format_rg32f: return VK_FORMAT_R32G32_SFLOAT;
+ case texture_format_rgb8i: return VK_FORMAT_R8G8B8_UNORM;
+ 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_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;
+ }
+}
+
+VkImageLayout state_to_image_layout(Resource_State s) {
+ switch (s) {
+ case undefined: return VK_IMAGE_LAYOUT_UNDEFINED;
+ case copy_dst: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ case copy_src: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ case shader_read: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ default: assert(0); return VK_IMAGE_LAYOUT_UNDEFINED;
+ }
+}
+
static void* vk_alloc(
void* uptr,
size_t size,
@@ -295,6 +324,12 @@ static void deinit_swap_cap(
if (cap->pms) heap_free(d->heap, cap->pms);
}
+struct Late_Terminated {
+ Late_Terminated* next;
+
+ virtual void destroy(Device_Vk* dev) = 0;
+};
+
struct Swapchain {
VkSwapchainKHR swapchain;
Texture_Id* textures;
@@ -308,6 +343,14 @@ struct Swapchain {
void recreate(const App& app, Device_Vk* dev);
void get_images(Device_Vk* dev);
void destroy(Device_Vk* dev);
+
+ Texture_Id create_image(
+ Device_Vk* dev,
+ VkImage image,
+ VkImageView view,
+ int w,
+ int h
+ );
};
#define max_contexts 16
@@ -317,7 +360,7 @@ enum {
context_state_init = 1 << 1
};
-struct Shader_Vk : public Shader {
+struct Shader_Vk : public Shader, public Late_Terminated {
struct Attribute {
char name[28];
SVariable_Type type;
@@ -361,7 +404,7 @@ struct Shader_Vk : public Shader {
Device_Vk* dev,
FILE* f
);
- void destroy_internal(Device_Vk* dev);
+ void destroy(Device_Vk* dev) override;
static VkShaderStageFlagBits stage(Shader_Type type) {
switch (type) {
@@ -379,37 +422,42 @@ struct Shader_Vk : public Shader {
struct Renderpass_Vk;
struct Context_Vk : public Context {
int state;
+ Device_Vk* dev;
VkCommandBuffer cb;
VkCommandPool pool;
VkFence fence;
VkSemaphore semaphore;
- void init_pool(Device_Vk* dev);
- void init_cb(Device_Vk* dev);
- void init_sync(Device_Vk* dev);
- void init(Device_Vk* dev);
- void begin_record(Device_Vk* dev);
- Context_Vk& acquire(Device_Vk* dev);
+ void init_pool();
+ void init_cb();
+ void init_sync();
+ void init(Device_Vk* device);
+ void begin_record();
+ Context_Vk& acquire(Device_Vk* device);
void release();
- void destroy(Device_Vk* dev);
+ void destroy();
- Renderpass_Vk& begin_rp(Device& d, const Render_Pass& rp);
+ Renderpass_Vk& begin_rp(const Render_Pass& rp);
void end_rp(Renderpass_Vk& rpo);
};
-struct Texture_Vk : public Texture {
+struct Texture_Vk : public Texture, public Late_Terminated {
VkImage image;
VkImageView view;
+ VkDeviceMemory memory;
+ Resource_State state;
+
+ void destroy(Device_Vk*) override;
};
-struct Buffer_Vk : public Buffer {
+struct Buffer_Vk : public Buffer, public Late_Terminated {
VkBuffer buf;
VkDeviceMemory memory;
VkDeviceSize size;
int flags;
void init(Device_Vk* dev, int flags, VkDeviceSize size);
- void destroy(Device_Vk* dev);
+ void destroy(Device_Vk* dev) override;
static VkBufferUsageFlags get_usage(int flags) {
VkBufferUsageFlags r = 0;
@@ -600,7 +648,44 @@ struct std::hash<Render_Pass> {
struct Shader_Loader : public Asset_Loader {
Device_Vk* dev;
void init(Device_Vk* d);
- Asset* load(Arena* a, Pack_File* f) override;
+ Asset* load(Arena* a, Arena* s, Pack_File* f) override;
+ void unload(Asset* a) override;
+};
+
+struct Texture_Loader : public Asset_Loader {
+ Device_Vk* dev;
+ static size_t calc_size(Texture_Format fmt, int w, int h);
+ void init(Device_Vk* d);
+ Asset* load(Arena* a, Arena* s, Pack_File* f) override;
+ void unload(Asset* a) override;
+
+ Buffer_Id upload(void* buf, size_t size);
+ Texture_Id create_tex(
+ Texture_Format fmt,
+ int w,
+ int h
+ );
+};
+
+struct Terminator {
+ Late_Terminated* queue;
+
+ void execute(Device_Vk* dev) {
+ Late_Terminated* obj = queue;
+ for (; obj; obj = obj->next)
+ obj->destroy(dev);
+ queue = 0;
+ }
+
+ void add(Late_Terminated* obj) {
+ if (queue) {
+ obj->next = queue;
+ queue = obj;
+ } else {
+ obj->next = 0;
+ queue = obj;
+ }
+ }
};
struct Device_Vk : public Device {
@@ -619,6 +704,7 @@ struct Device_Vk : public Device {
Context_Vk contexts[max_contexts];
Context_Vk* current_ctx;
Shader_Loader shader_loader;
+ Texture_Loader texture_loader;
#ifdef DEBUG
VkDebugUtilsMessengerEXT msg;
#endif
@@ -639,11 +725,10 @@ struct Device_Vk : public Device {
Hash_Map<Render_Pass, Renderpass_Vk, max_rpos> rpo_cache;
Hash_Map<Pso_Key, Pipeline_Vk, max_pipelines> pso_cache;
- Texture_Id alloc_texture(
- VkImage img,
- VkImageView view,
- const Texture& copy
- );
+ Terminator* terminators;
+ uint32_t terminator_index;
+
+ Texture_Id alloc_texture();
Buffer_Id alloc_buffer();
Vertex_Format_Id alloc_vf();
Vertex_Format_Id create_vf(Shader_Vk& shader);
@@ -669,6 +754,8 @@ struct Device_Vk : public Device {
Pipeline_Vk& get_pso(const Pso_Key& pop);
void collect_garbage();
+ void queue_destroy(Late_Terminated* obj);
+ void create_terminators();
int find_memory_type(
uint32_t filter,
@@ -980,7 +1067,9 @@ void Device_Vk::init_internal() {
rpo_cache.init();
pso_cache.init();
shader_loader.init(this);
+ texture_loader.init(this);
register_asset_loader("CSH2", &shader_loader);
+ register_asset_loader("TXTR", &texture_loader);
find_exts(exts, ext_count);
init_ac();
create_inst(exts, ext_count);
@@ -993,12 +1082,31 @@ void Device_Vk::init_internal() {
gladLoaderLoadVulkan(inst, phys_dev, dev);
vkGetDeviceQueue(dev, (uint32_t)queue_index, 0, &queue);
swapchain.init(*app, this);
+ terminators = 0;
+ terminator_index = 0;
+ create_terminators();
for (i = 0; i < max_contexts; i++)
contexts[i].state = context_state_avail;
}
+void Device_Vk::create_terminators() {
+ int i, count = swapchain.image_count;
+ if (terminators) {
+ for (i = 0; i < count; i++)
+ terminators[i].execute(this);
+ heap_free(heap, terminators);
+ }
+ terminators = (Terminator*)heap_alloc(
+ heap,
+ count * sizeof *terminators
+ );
+ for (i = 0; i < count; i++) {
+ terminators[i].queue = 0;
+ }
+}
+
void Device_Vk::deinit_internal() {
- int i;
+ int i, image_count = swapchain.image_count;
vkDeviceWaitIdle(dev);
swapchain.destroy(this);
deinit_swap_cap(this, &swap_cap);
@@ -1010,7 +1118,10 @@ void Device_Vk::deinit_internal() {
for (i = 0; i < max_contexts; i++) {
auto& context = contexts[i];
if (context.state & context_state_init)
- context.destroy(this);
+ context.destroy();
+ }
+ for (i = 0; i < image_count; i++) {
+ terminators[i].execute(this);
}
vkDestroyDevice(dev, &ac);
#ifdef DEBUG
@@ -1030,6 +1141,7 @@ void Device_Vk::on_resize_internal(int w, int h) {
deinit_swap_cap(this, &swap_cap);
get_swap_cap(this, phys_dev, surf, &swap_cap);
swapchain.recreate(*app, this);
+ create_terminators();
}
Renderpass_Vk& Device_Vk::create_rpo(const Render_Pass& rp) {
@@ -1073,10 +1185,11 @@ void Renderpass_Vk::destroy(Device_Vk* dev) {
}
void Device_Vk::collect_garbage() {
+ int max_age = swapchain.image_count + 3;
for (const auto& i: rpo_cache) {
auto& rp = i.second;
rp.age++;
- if (rp.age > 3) {
+ if (rp.age > max_age) {
rp.destroy(this);
rpo_cache.remove(i.first);
}
@@ -1084,13 +1197,17 @@ void Device_Vk::collect_garbage() {
for (const auto& i: pso_cache) {
auto& pip = i.second;
pip.age++;
- if (pip.age > 3) {
+ if (pip.age > max_age) {
pip.destroy(this);
pso_cache.remove(i.first);
}
}
}
+void Device_Vk::queue_destroy(Late_Terminated* obj) {
+ terminators[terminator_index].add(obj);
+}
+
int Device_Vk::find_memory_type(
uint32_t filter,
VkMemoryPropertyFlags flags
@@ -1271,14 +1388,27 @@ void Swapchain::recreate(const App& app, Device_Vk* dev) {
old.destroy(dev);
}
+Texture_Id Swapchain::create_image(
+ Device_Vk* dev,
+ VkImage image,
+ VkImageView view,
+ int w,
+ int h
+) {
+ 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.alias = true;
+ return id;
+}
+
void Swapchain::get_images(Device_Vk* dev) {
unsigned count;
int i;
VkImage* images;
- Texture info{};
- info.w = size.width;
- info.h = size.height;
- info.alias = true;
vkGetSwapchainImagesKHR(dev->dev, swapchain, &count, 0);
image_count = count;
images = (VkImage*)heap_alloc(
@@ -1296,7 +1426,13 @@ void Swapchain::get_images(Device_Vk* dev) {
format.format,
VK_IMAGE_ASPECT_COLOR_BIT
);
- textures[i] = dev->alloc_texture(images[i], view, info);
+ textures[i] = create_image(
+ dev,
+ images[i],
+ view,
+ size.width,
+ size.height
+ );
}
heap_free(dev->heap, images);
}
@@ -1339,6 +1475,9 @@ void Device::begin_frame() {
Device_Vk* dev = (Device_Vk*)this;
dev->collect_garbage();
dev->current_ctx = (Context_Vk*)&acquire();
+ dev->terminator_index++;
+ dev->terminator_index %= dev->swapchain.image_count;
+ dev->terminators[dev->terminator_index].execute(dev);
vkAcquireNextImageKHR(
dev->dev,
dev->swapchain.swapchain,
@@ -1353,20 +1492,18 @@ void Device::begin_frame() {
void Device::submit(Context& ctx_) {
Context_Vk* ctx = (Context_Vk*)&ctx_;
Device_Vk* dev = (Device_Vk*)this;
- VkPipelineStageFlags stage =
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo si{};
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- si.waitSemaphoreCount = 1;
+/* si.waitSemaphoreCount = 1;
si.pWaitSemaphores = &ctx->semaphore;
si.pWaitDstStageMask = &stage;
si.signalSemaphoreCount = 1;
- si.pSignalSemaphores = &ctx->semaphore;
+ si.pSignalSemaphores = &ctx->semaphore;*/
si.commandBufferCount = 1;
si.pCommandBuffers = &ctx->cb;
vkEndCommandBuffer(ctx->cb);
vkQueueSubmit(dev->queue, 1, &si, ctx->fence);
- ctx->wait(*dev);
+ ctx->wait();
ctx->release();
}
@@ -1374,18 +1511,27 @@ void Device::present() {
Device_Vk* dev = (Device_Vk*)this;
Context_Vk* ctx = dev->current_ctx;
VkPresentInfoKHR pi{};
- VkSemaphore s[1];
- VkSwapchainKHR sw[1];
- submit(*ctx);
- s[0] = ctx->semaphore;
- sw[0] = dev->swapchain.swapchain;
+ VkSubmitInfo si{};
+ VkPipelineStageFlags stage =
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ si.waitSemaphoreCount = 1;
+ si.pWaitSemaphores = &ctx->semaphore;
+ si.pWaitDstStageMask = &stage;
+ si.signalSemaphoreCount = 1;
+ si.pSignalSemaphores = &ctx->semaphore;
+ si.commandBufferCount = 1;
+ si.pCommandBuffers = &ctx->cb;
+ vkEndCommandBuffer(ctx->cb);
+ vkQueueSubmit(dev->queue, 1, &si, ctx->fence);
pi.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
pi.waitSemaphoreCount = 1;
- pi.pWaitSemaphores = s;
+ pi.pWaitSemaphores = &ctx->semaphore;
pi.swapchainCount = 1;
- pi.pSwapchains = sw;
+ pi.pSwapchains = &dev->swapchain.swapchain;
pi.pImageIndices = &dev->backbuffer_index;
vkQueuePresentKHR(dev->queue, &pi);
+ ctx->release();
}
Texture_Id Device::get_backbuffer() {
@@ -1396,16 +1542,9 @@ Texture& Device::get_texture(Texture_Id id) {
return ((Device_Vk*)this)->textures[id];
}
-Texture_Id Device_Vk::alloc_texture(
- VkImage img,
- VkImageView view,
- const Texture& copy
-) {
+Texture_Id Device_Vk::alloc_texture() {
Texture_Vk tex{};
Texture_Id id(texture_count++);
- memcpy(&tex, &copy, sizeof(Texture));
- tex.image = img;
- tex.view = view;
textures.set(id, tex);
return id;
}
@@ -1445,16 +1584,12 @@ Shader_Id Device_Vk::alloc_shader() {
void Device::destroy_texture(Texture_Id id) {
Device_Vk* dev = (Device_Vk*)this;
- Texture_Vk& tex = dev->textures[id];
- if (!tex.alias)
- vkDestroyImage(dev->dev, tex.image, &dev->ac);
- vkDestroyImageView(dev->dev, tex.view, &dev->ac);
- dev->textures.remove(id);
+ dev->queue_destroy((Texture_Vk*)&dev->get_texture(id));
}
-void Context::wait(Device& d) {
+void Context::wait() {
Context_Vk* ctx = (Context_Vk*)this;
- Device_Vk* dev = (Device_Vk*)&d;
+ Device_Vk* dev = ctx->dev;
vkWaitForFences(
dev->dev,
1,
@@ -1465,17 +1600,16 @@ void Context::wait(Device& d) {
}
void Context::submit(
- Device& d,
const Draw& draw,
const Pipeline& p,
const Render_Pass& rp
) {
- Device_Vk* dev = (Device_Vk*)&d;
Context_Vk* ctx = (Context_Vk*)this;
+ Device_Vk* dev = ctx->dev;
Vertex_Buffer_Binding* binding;
Pso_Key pso_key = { p, rp };
Pipeline_Vk& pso = dev->get_pso(pso_key);
- auto& rpo = ctx->begin_rp(d, rp);
+ auto& rpo = ctx->begin_rp(rp);
vkCmdBindPipeline(
ctx->cb,
VK_PIPELINE_BIND_POINT_GRAPHICS,
@@ -1498,13 +1632,13 @@ void Context::submit(
}
void Context::submit(
- Device& d,
const Draw* draws,
int count,
const Pipeline& p,
const Render_Pass& rp
) {
- Device_Vk* dev = (Device_Vk*)&d;
+ Context_Vk* ctx = (Context_Vk*)this;
+ Device_Vk* dev = ctx->dev;
(void)draws;
(void)count;
(void)p;
@@ -1514,8 +1648,115 @@ void Context::submit(
/* todo */
}
-Renderpass_Vk& Context_Vk::begin_rp(Device& d, const Render_Pass& rp) {
- Device_Vk* dev = (Device_Vk*)&d;
+void Context::copy(Buffer_Id dst, Buffer_Id src) {
+ Context_Vk* ctx = (Context_Vk*)this;
+ Device_Vk* dev = ctx->dev;
+ Buffer_Vk& a = *(Buffer_Vk*)&dev->get_buffer(dst);
+ Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(src);
+ VkBufferCopy region{};
+ region.srcOffset = 0;
+ region.dstOffset = 0;
+ region.size = b.size;
+ vkCmdCopyBuffer(
+ ctx->cb,
+ b.buf,
+ a.buf,
+ 1,
+ &region
+ );
+}
+
+void Context::copy(Texture_Id dst, Buffer_Id src) {
+ Context_Vk* ctx = (Context_Vk*)this;
+ Device_Vk* dev = ctx->dev;
+ Texture_Vk& a = *(Texture_Vk*)&dev->get_texture(dst);
+ Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(src);
+ VkBufferImageCopy c{};
+ c.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ c.imageSubresource.layerCount = 1;
+ c.imageExtent.width = a.w;
+ c.imageExtent.height = a.h;
+ c.imageExtent.depth = 1;
+ vkCmdCopyBufferToImage(
+ ctx->cb,
+ b.buf,
+ a.image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1,
+ &c
+ );
+}
+
+void Context::transition(Texture_Id id, Resource_State state) {
+ Context_Vk* ctx = (Context_Vk*)this;
+ Device_Vk* dev = ctx->dev;
+ Texture_Vk& tex = *(Texture_Vk*)&dev->get_texture(id);
+ VkImageMemoryBarrier b{};
+ VkImageLayout src_layout = state_to_image_layout(tex.state);
+ VkImageLayout dst_layout = state_to_image_layout(state);
+ VkPipelineStageFlags src_stage, dst_stage;
+ b.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ b.oldLayout = src_layout;
+ b.newLayout = dst_layout;
+ b.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ 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;
+ if (
+ src_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
+ dst_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ ) {
+ b.srcAccessMask = 0;
+ b.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ dst_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ } else if (
+ src_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL &&
+ dst_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ ) {
+ b.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ b.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ src_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ } else if (
+ src_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
+ dst_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+ ) {
+ b.srcAccessMask = 0;
+ b.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ } else if (
+ src_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
+ dst_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ ) {
+ b.srcAccessMask = 0;
+ b.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ } else {
+ print_err("Bad resource transition.\n");
+ pbreak(389);
+ }
+ vkCmdPipelineBarrier(
+ ctx->cb,
+ src_stage,
+ dst_stage,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ &b
+ );
+}
+
+Renderpass_Vk& Context_Vk::begin_rp(const Render_Pass& rp) {
Renderpass_Vk& rpo = dev->get_rpo(rp);
VkRenderPassBeginInfo rpbi{};
rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -1537,13 +1778,13 @@ void Context_Vk::end_rp(Renderpass_Vk& rpo) {
rpo.on_submit();
}
-void Context::submit(Device& d, const Render_Pass& rp) {
+void Context::submit(const Render_Pass& rp) {
Context_Vk* ctx = (Context_Vk*)this;
- auto& rpo = ctx->begin_rp(d, rp);
+ auto& rpo = ctx->begin_rp(rp);
ctx->end_rp(rpo);
}
-void Context_Vk::init_pool(Device_Vk* dev) {
+void Context_Vk::init_pool() {
VkCommandPoolCreateInfo pi{};
VkResult r;
pi.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
@@ -1556,7 +1797,7 @@ void Context_Vk::init_pool(Device_Vk* dev) {
}
}
-void Context_Vk::init_cb(Device_Vk* dev) {
+void Context_Vk::init_cb() {
VkCommandBufferAllocateInfo ci{};
VkResult r;
ci.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@@ -1570,7 +1811,7 @@ void Context_Vk::init_cb(Device_Vk* dev) {
}
}
-void Context_Vk::init_sync(Device_Vk* dev) {
+void Context_Vk::init_sync() {
VkFenceCreateInfo fi{};
VkSemaphoreCreateInfo si{};
VkResult r;
@@ -1589,26 +1830,28 @@ void Context_Vk::init_sync(Device_Vk* dev) {
}
}
-void Context_Vk::init(Device_Vk* dev) {
- init_pool(dev);
- init_cb(dev);
- init_sync(dev);
+void Context_Vk::init(Device_Vk* device) {
+ dev = device;
+ init_pool();
+ init_cb();
+ init_sync();
state |= context_state_init;
}
-void Context_Vk::begin_record(Device_Vk* dev) {
+void Context_Vk::begin_record() {
VkCommandBufferBeginInfo bi{};
bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ wait();
vkResetFences(dev->dev, 1, &fence);
vkResetCommandBuffer(cb, 0);
vkBeginCommandBuffer(cb, &bi);
}
-Context_Vk& Context_Vk::acquire(Device_Vk* dev) {
+Context_Vk& Context_Vk::acquire(Device_Vk* device) {
if (~state & context_state_init)
- init(dev);
+ init(device);
state &= ~context_state_avail;
- begin_record(dev);
+ begin_record();
return *this;
}
@@ -1616,7 +1859,7 @@ void Context_Vk::release() {
state |= context_state_avail;
}
-void Context_Vk::destroy(Device_Vk* dev) {
+void Context_Vk::destroy() {
state &= ~context_state_init;
vkDestroyCommandPool(dev->dev, pool, &dev->ac);
vkDestroySemaphore(dev->dev, semaphore, &dev->ac);
@@ -2116,17 +2359,14 @@ void Shader_Vk::Vertex_Format::destroy(Device_Vk* dev) {
heap_free(dev->heap, attributes);
}
-void Shader_Vk::destroy_internal(Device_Vk* dev) {
+void Shader_Vk::destroy(Device_Vk* dev) {
int i;
for (i = 0; i < shader_type_count; i++)
if (modules[i])
vkDestroyShaderModule(dev->dev, modules[i], &dev->ac);
vfd.destroy(dev);
dev->destroy_vf(vf);
-}
-
-void Shader::destroy(Device* dev) {
- ((Shader_Vk*)this)->destroy_internal((Device_Vk*)dev);
+ dev->shaders.remove(id);
}
int Shader::binding_index(const char* name) {
@@ -2148,11 +2388,12 @@ int Shader::attribute_index(const char* name) {
void Buffer_Vk::init(
Device_Vk* dev,
int flags,
- VkDeviceSize size
+ VkDeviceSize s
) {
VkBufferCreateInfo bi{};
VkMemoryRequirements req;
VkResult r;
+ size = s;
bi.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bi.size = size;
bi.usage = get_usage(flags);
@@ -2190,6 +2431,7 @@ void Buffer_Vk::init(
void Buffer_Vk::destroy(Device_Vk* dev) {
vkDestroyBuffer(dev->dev, buf, &dev->ac);
vkFreeMemory(dev->dev, memory, &dev->ac);
+ dev->buffers.remove(id);
}
Buffer_Id Device::create_buffer(size_t size, int flags) {
@@ -2202,9 +2444,8 @@ Buffer_Id Device::create_buffer(size_t size, int flags) {
void Device::destroy_buffer(Buffer_Id id) {
Device_Vk* dev = (Device_Vk*)this;
- Buffer_Vk& buf = *(Buffer_Vk*)&get_buffer(id);
- buf.destroy(dev);
- dev->buffers.remove(id);
+ Buffer_Vk* buf = (Buffer_Vk*)&get_buffer(id);
+ dev->queue_destroy(buf);
}
void* Device::map_buffer(
@@ -2240,42 +2481,32 @@ Shader& Device::get_shader(Shader_Id id) {
return ((Device_Vk*)this)->shaders[id];
}
-bool Shader::load(
- Asset_Loader* loader,
- Arena* a,
- Pack_File* f
-) {
- Device_Vk* dev = ((Shader_Loader*)loader)->dev;
- Shader_Vk& sh = *(Shader_Vk*)this;
- return sh.init(dev, f);
-}
-
-void Shader::unload(Asset_Loader* loader_) {
- Shader_Loader* loader = (Shader_Loader*)loader_;
- Device_Vk* dev = loader->dev;
- Shader_Vk& sh = *(Shader_Vk*)this;
- sh.destroy(dev);
- dev->shaders.remove(id);
-}
-
void Shader_Loader::init(Device_Vk* d) {
dev = d;
}
Asset* Shader_Loader::load(
Arena* a,
+ Arena* s,
Pack_File* f
) {
- Shader_Vk* s;
+ Shader_Vk* shader;
Shader_Id id;
+ (void)s;
+ (void)a;
id = dev->alloc_shader();
- s = (Shader_Vk*)&dev->get_shader(id);
- s->id = id;
- if (!s->load(this, a, f)) {
+ shader = (Shader_Vk*)&dev->get_shader(id);
+ shader->id = id;
+ if (!shader->init(dev, f)) {
dev->shaders.remove(id);
return 0;
}
- return s;
+ return shader;
+}
+
+void Shader_Loader::unload(Asset* a) {
+ Shader_Vk* sh = (Shader_Vk*)a;
+ dev->queue_destroy(sh);
}
bool Shader_Vk::init(Device_Vk* dev, Pack_File* f) {
@@ -2323,3 +2554,140 @@ bool Shader_Vk::init(Device_Vk* dev, Pack_File* f) {
return true;
}
+void Texture_Loader::init(Device_Vk* d) {
+ dev = d;
+}
+
+size_t Texture_Loader::calc_size(
+ Texture_Format fmt,
+ int w,
+ int h
+) {
+ switch (fmt) {
+ case texture_format_bc1:
+ return (w / 4) * (h / 4) * 8;
+ default:
+ print_err("Can't load this texture format.\n");
+ pbreak(45498);
+ return 0;
+ }
+}
+
+Buffer_Id Texture_Loader::upload(void* buf, size_t size) {
+ void* mem;
+ Buffer_Id id = dev->create_buffer(
+ size,
+ Buffer_Flags::copy_src |
+ Buffer_Flags::cpu_readwrite
+ );
+ mem = dev->map_buffer(id, 0, size);
+ memcpy(mem, buf, size);
+ dev->unmap_buffer(id);
+ return id;
+}
+
+Texture_Id Texture_Loader::create_tex(
+ Texture_Format fmt,
+ int w,
+ int h
+) {
+ VkImageCreateInfo ii{};
+ VkResult r;
+ Texture_Id id = dev->alloc_texture();
+ Texture_Vk& tex = *(Texture_Vk*)&dev->get_texture(id);
+ VkMemoryRequirements req;
+ ii.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ ii.imageType = VK_IMAGE_TYPE_2D;
+ ii.extent.width = w;
+ ii.extent.height = h;
+ ii.extent.depth = 1;
+ ii.mipLevels = 1;
+ ii.arrayLayers = 1;
+ 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.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ ii.samples = VK_SAMPLE_COUNT_1_BIT;
+ r = vkCreateImage(dev->dev, &ii, &dev->ac, &tex.image);
+ if (r != VK_SUCCESS) {
+ print_err("Failed to create an image.\n");
+ }
+ vkGetImageMemoryRequirements(dev->dev, tex.image, &req);
+ {
+ VkMemoryPropertyFlags props =
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ int mt = dev->find_memory_type(req.memoryTypeBits, props);
+ VkMemoryAllocateInfo ai{};
+ if (mt < 0) {
+ print("Failed to find a satisfying memory type index.\n");
+ pbreak(mt);
+ }
+ ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ ai.allocationSize = req.size;
+ ai.memoryTypeIndex = mt;
+ r = vkAllocateMemory(dev->dev, &ai, &dev->ac, &tex.memory);
+ if (r == VK_ERROR_OUT_OF_DEVICE_MEMORY) {
+ print_err("Out of video memory.\n");
+ pbreak(r);
+ }
+ if (r != VK_SUCCESS) {
+ print_err("VRAM allocation failed.\n");
+ pbreak(r);
+ }
+ }
+ vkBindImageMemory(dev->dev, tex.image, tex.memory, 0);
+ tex.w = w;
+ tex.h = h;
+ tex.alias = false;
+ tex.view = make_view(
+ dev,
+ tex.image,
+ ii.format,
+ VK_IMAGE_ASPECT_COLOR_BIT
+ );
+ return id;
+}
+
+Asset* Texture_Loader::load(Arena* a, Arena* s, Pack_File* f) {
+ char magic[4];
+ void* data;
+ int w, h;
+ size_t size;
+ Texture_Format fmt;
+ pack_read(f, magic, 4);
+ pack_read(f, &w, 4);
+ pack_read(f, &h, 4);
+ pack_read(f, &fmt, 4);
+ size = calc_size(fmt, w, h);
+ data = arena_alloc(s, size);
+ pack_read(f, data, size);
+ {
+ Buffer_Id buf = upload(data, size);
+ Texture_Id tex = create_tex(fmt, w, h);
+ {
+ Context& ctx = dev->acquire();
+ ctx.transition(tex, Resource_State::copy_dst);
+ ctx.copy(tex, buf);
+ ctx.transition(tex, Resource_State::shader_read);
+ dev->submit(ctx);
+ dev->destroy_buffer(buf);
+ }
+ return &dev->get_texture(tex);
+ }
+}
+
+void Texture_Loader::unload(Asset* a) {
+ Texture_Vk* tex = (Texture_Vk*)a;
+ tex->destroy(dev);
+}
+
+void Texture_Vk::destroy(Device_Vk* dev) {
+ if (!alias) {
+ vkDestroyImage(dev->dev, image, &dev->ac);
+ vkFreeMemory(dev->dev, memory, &dev->ac);
+ }
+ vkDestroyImageView(dev->dev, view, &dev->ac);
+ dev->textures.remove(id);
+}
+