Load image from file and fix image creation

This commit is contained in:
abdelrahman committed 2026-10-26 00:15:56 +00:00
1 parent 042fb309f6
commit cb6429e21d
3 files changed
+172 -16

No files matched your search

+43 -10
View File
@@ -305,6 +305,13 @@ typedef struct GpuImageCreateRequest {
GpuImageSubresourceRange subresource; GpuImageSubresourceRange subresource;
} GpuImageCreateRequest; } GpuImageCreateRequest;
typedef struct GpuCommandPool GpuCommandPool;
typedef struct GpuLoadImageFromFileRequest {
GpuCommandPool *command_pool;
WpStr8RO filename;
} GpuLoadImageFromFileRequest;
typedef enum GpuBufferUsage { typedef enum GpuBufferUsage {
GPU_BUFFER_USAGE_TRANSFER_SRC = wpU32Const(1) << 0, GPU_BUFFER_USAGE_TRANSFER_SRC = wpU32Const(1) << 0,
GPU_BUFFER_USAGE_TRANSFER_DST = wpU32Const(1) << 1, GPU_BUFFER_USAGE_TRANSFER_DST = wpU32Const(1) << 1,
@@ -403,8 +410,6 @@ typedef struct GpuSwapchainsPresentResult {
GpuSwapchainPresentErrorArray errors; GpuSwapchainPresentErrorArray errors;
} GpuSwapchainsPresentResult; } GpuSwapchainsPresentResult;
typedef struct GpuCommandPool GpuCommandPool;
typedef struct GpuCommandBuffer GpuCommandBuffer; typedef struct GpuCommandBuffer GpuCommandBuffer;
typedef GpuCommandBuffer **GpuCommandBufferPtrArray; typedef GpuCommandBuffer **GpuCommandBufferPtrArray;
@@ -1095,14 +1100,30 @@ typedef struct GpuCmdPushConstantsRequest {
u32 total_size_in_bytes; u32 total_size_in_bytes;
} GpuCmdPushConstantsRequest; } GpuCmdPushConstantsRequest;
typedef struct GpuCmdDrawIndexedRequest { typedef struct GpuImageSubresourceLayers {
GpuImageAspect aspect_mask;
u32 mip_level;
u32 base_array_layer;
u32 layer_count;
} GpuImageSubresourceLayers;
typedef struct GpuImageBlit {
GpuOffset3d src_offsets[2];
GpuOffset3d dst_offsets[2];
GpuImageSubresourceLayers src_subresource;
GpuImageSubresourceLayers dst_subresource;
} GpuImageBlit;
typedef GpuImageBlit *GpuImageBlitArray;
typedef struct GpuCmdBlitImageRequest {
GpuCommandBuffer *command_buffer; GpuCommandBuffer *command_buffer;
u32 index_count; GpuImage *src_image;
u32 instance_count; GpuImage *dst_image;
u32 first_index; GpuImageBlitArray regions;
i32 vertex_offset; GpuImageLayout src_image_layout;
u32 first_instance; GpuImageLayout dst_image_layout;
} GpuCmdDrawIndexedRequest; GpuFilter filter;
} GpuCmdBlitImageRequest;
typedef struct GpuCmdDrawRequest { typedef struct GpuCmdDrawRequest {
GpuCommandBuffer *command_buffer; GpuCommandBuffer *command_buffer;
@@ -1112,6 +1133,15 @@ typedef struct GpuCmdDrawRequest {
u32 first_instance; u32 first_instance;
} GpuCmdDrawRequest; } GpuCmdDrawRequest;
typedef struct GpuCmdDrawIndexedRequest {
GpuCommandBuffer *command_buffer;
u32 index_count;
u32 instance_count;
u32 first_index;
i32 vertex_offset;
u32 first_instance;
} GpuCmdDrawIndexedRequest;
typedef struct GpuCmdDispatchRequest { typedef struct GpuCmdDispatchRequest {
GpuCommandBuffer *command_buffer; GpuCommandBuffer *command_buffer;
u32 group_count_x; u32 group_count_x;
@@ -1157,7 +1187,9 @@ GpuSampler *gpuCreateSampler(const WpAllocator *allocator, Gp
void gpuDestroySampler(GpuSampler *sampler); void gpuDestroySampler(GpuSampler *sampler);
GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest request); GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest request);
void gpuDestroyImage(GpuImage *image); void gpuDestroyImage(GpuImage *image);
ivec3s gpuImageGetSize(GpuImage *image); GpuImage *gpuLoadImageFromFile(const WpAllocator *allocator, const WpAllocator *temp,
GpuLoadImageFromFileRequest request);
ivec3s gpuGetImageSize(GpuImage *image);
GpuBuffer gpuCreateBuffer(const WpAllocator *allocator, GpuBufferCreateRequest request); GpuBuffer gpuCreateBuffer(const WpAllocator *allocator, GpuBufferCreateRequest request);
void gpuDestroyBuffer(GpuBuffer *buffer); void gpuDestroyBuffer(GpuBuffer *buffer);
GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device); GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device);
@@ -1207,6 +1239,7 @@ void gpuCmdBindDescriptorSets(const WpAllocator *temp,
void gpuCmdBindVertexBuffers(const WpAllocator *temp, GpuCmdBindVertexBuffersRequest request); void gpuCmdBindVertexBuffers(const WpAllocator *temp, GpuCmdBindVertexBuffersRequest request);
void gpuCmdBindIndexBuffer(GpuCmdBindIndexBufferRequest request); void gpuCmdBindIndexBuffer(GpuCmdBindIndexBufferRequest request);
void gpuCmdPushConstants(GpuCmdPushConstantsRequest request); void gpuCmdPushConstants(GpuCmdPushConstantsRequest request);
void gpuCmdBlitImage(const WpAllocator *temp, GpuCmdBlitImageRequest request);
void gpuCmdDraw(GpuCmdDrawRequest request); void gpuCmdDraw(GpuCmdDrawRequest request);
void gpuCmdDrawIndexed(GpuCmdDrawIndexedRequest request); void gpuCmdDrawIndexed(GpuCmdDrawIndexedRequest request);
void gpuCmdDispatch(GpuCmdDispatchRequest request); void gpuCmdDispatch(GpuCmdDispatchRequest request);
+122 -6
View File
@@ -7,6 +7,9 @@
#include "../../window/window_inc.h" #include "../../window/window_inc.h"
#include "../../wapp/wapp.h" #include "../../wapp/wapp.h"
#include "../../cglm/struct.h" #include "../../cglm/struct.h"
#include <stdio.h>
#define STB_IMAGE_IMPLEMENTATION
#include "../../stb_image/stb_image.h"
#include <stdint.h> #include <stdint.h>
#ifdef USE_SDL_WINDOW_BACKEND #ifdef USE_SDL_WINDOW_BACKEND
@@ -73,6 +76,7 @@ typedef VkImageMemoryBarrier2 *VkImageMemoryBarrier
typedef VkRenderingAttachmentInfo *VkRenderingAttachmentInfoArray; typedef VkRenderingAttachmentInfo *VkRenderingAttachmentInfoArray;
typedef VkSemaphoreSubmitInfo *VkSemaphoreSubmitInfoArray; typedef VkSemaphoreSubmitInfo *VkSemaphoreSubmitInfoArray;
typedef VkCommandBufferSubmitInfo *VkCommandBufferSubmitInfoArray; typedef VkCommandBufferSubmitInfo *VkCommandBufferSubmitInfoArray;
typedef VkImageBlit2 *VkImageBlit2Array;
struct GpuInstance { struct GpuInstance {
VkInstance vk_instance; VkInstance vk_instance;
@@ -486,9 +490,25 @@ GpuDevice *gpuCreateDevice(const WpAllocator *allocator, GpuPhysicalDevice physi
0, &device->vk_queue); 0, &device->vk_queue);
VmaVulkanFunctions vk_functions = { VmaVulkanFunctions vk_functions = {
.vkGetInstanceProcAddr = vkGetInstanceProcAddr, vkGetInstanceProcAddr = vkGetInstanceProcAddr,
.vkGetDeviceProcAddr = vkGetDeviceProcAddr, vkGetDeviceProcAddr = vkGetDeviceProcAddr,
.vkCreateImage = vkCreateImage, vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties,
vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties,
vkAllocateMemory = vkAllocateMemory,
vkFreeMemory = vkFreeMemory,
vkMapMemory = vkMapMemory,
vkUnmapMemory = vkUnmapMemory,
vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges,
vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges,
vkBindBufferMemory = vkBindBufferMemory,
vkBindImageMemory = vkBindImageMemory,
vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements,
vkGetImageMemoryRequirements = vkGetImageMemoryRequirements,
vkCreateBuffer = vkCreateBuffer,
vkDestroyBuffer = vkDestroyBuffer,
vkCreateImage = vkCreateImage,
vkDestroyImage = vkDestroyImage,
vkCmdCopyBuffer = vkCmdCopyBuffer,
}; };
VmaAllocatorCreateInfo allocator_create_info = { VmaAllocatorCreateInfo allocator_create_info = {
@@ -875,7 +895,7 @@ GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest req
vk_result = vmaCreateImage(request.device->allocator, &image_create_info, &alloc_create_info, vk_result = vmaCreateImage(request.device->allocator, &image_create_info, &alloc_create_info,
&output->vk_image, &output->allocation, NULL); &output->vk_image, &output->allocation, NULL);
assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create depth image"); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create image");
VkImageViewCreateInfo view_create_info = { VkImageViewCreateInfo view_create_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@@ -888,10 +908,11 @@ GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest req
}; };
vk_result = vkCreateImageView(request.device->vk_device, &view_create_info, NULL, &output->vk_view); vk_result = vkCreateImageView(request.device->vk_device, &view_create_info, NULL, &output->vk_view);
assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create depth image view"); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create image view");
output->size = request.size; output->size = request.size;
output->format = format; output->format = format;
output->device = request.device;
wpLogDebug(&logger, wpStr8Lit("Created Vulkan image")); wpLogDebug(&logger, wpStr8Lit("Created Vulkan image"));
@@ -903,7 +924,42 @@ void gpuDestroyImage(GpuImage *image) {
vmaDestroyImage(image->device->allocator, image->vk_image, image->allocation); vmaDestroyImage(image->device->allocator, image->vk_image, image->allocation);
} }
ivec3s gpuImageGetSize(GpuImage *image) { GpuImage *gpuLoadImageFromFile(const WpAllocator *allocator, const WpAllocator *temp,
GpuLoadImageFromFileRequest request) {
char *buf = wpMemAllocatorAlloc(temp, request.filename.size + 1);
assertWithLogger(buf != NULL, &logger, "Failed to allocate temp filename buffer");
wpStr8CopyToCstr(buf, &request.filename, request.filename.size + 1);
i32 width, height, channels;
const u8 *data = stbi_load(buf, &width, &height, &channels, 4);
assertWithLogger(data != NULL, &logger, "Failed to load image data");
GpuImageCreateRequest img_request = {
.device = request.command_pool->device,
.size = { .x = width, .y = height, .z = 1 },
.type = GPU_IMAGE_TYPE_2D,
.format = GPU_FORMAT_R8G8B8A8_SRGB,
.samples = GPU_SAMPLE_COUNT_1,
.tiling = GPU_IMAGE_TILING_OPTIMAL,
.usage = GPU_IMAGE_USAGE_SAMPLED | GPU_IMAGE_USAGE_TRANSFER_SRC | GPU_IMAGE_USAGE_TRANSFER_DST,
.layout = GPU_IMAGE_LAYOUT_UNDEFINED,
.subresource = {
.aspect = GPU_IMAGE_ASPECT_COLOR,
.base_mip_level = 0,
.level_count = 1,
.base_array_layer = 0,
.layer_count = 1,
},
};
GpuImage *output = gpuCreateImage(allocator, img_request);
stbi_image_free((void *)data);
return output;
}
ivec3s gpuGetImageSize(GpuImage *image) {
return image->size; return image->size;
} }
@@ -2031,6 +2087,66 @@ void gpuCmdPushConstants(GpuCmdPushConstantsRequest request) {
request.total_size_in_bytes, request.values); request.total_size_in_bytes, request.values);
} }
void gpuCmdBlitImage(const WpAllocator *temp, GpuCmdBlitImageRequest request) {
u64 region_count = wpArrayCount(request.regions);
VkImageBlit2Array regions = wpArrayAllocCapacity(VkImageBlit2, temp, region_count, WP_ARRAY_INIT_FILLED);
assertWithLogger(regions != NULL, &logger, "Failed to allocate temp blit regions array");
for (u64 i = 0; i < region_count; ++i) {
regions[i] = (VkImageBlit2){
.sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
.srcSubresource = {
.aspectMask = vkImageAspectFromGpuImageAspect(request.regions[i].src_subresource.aspect_mask),
.mipLevel = request.regions[i].src_subresource.mip_level,
.baseArrayLayer = request.regions[i].src_subresource.base_array_layer,
.layerCount = request.regions[i].src_subresource.layer_count,
},
.srcOffsets = {
[0] = {
.x = request.regions[i].src_offsets[0].x,
.y = request.regions[i].src_offsets[0].y,
.z = request.regions[i].src_offsets[0].z,
},
[1] = {
.x = request.regions[i].src_offsets[1].x,
.y = request.regions[i].src_offsets[1].y,
.z = request.regions[i].src_offsets[1].z,
},
},
.dstSubresource = {
.aspectMask = vkImageAspectFromGpuImageAspect(request.regions[i].dst_subresource.aspect_mask),
.mipLevel = request.regions[i].dst_subresource.mip_level,
.baseArrayLayer = request.regions[i].dst_subresource.base_array_layer,
.layerCount = request.regions[i].dst_subresource.layer_count,
},
.dstOffsets = {
[0] = {
.x = request.regions[i].dst_offsets[0].x,
.y = request.regions[i].dst_offsets[0].y,
.z = request.regions[i].dst_offsets[0].z,
},
[1] = {
.x = request.regions[i].dst_offsets[1].x,
.y = request.regions[i].dst_offsets[1].y,
.z = request.regions[i].dst_offsets[1].z,
},
},
};
}
VkBlitImageInfo2 info = {
.sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
.srcImage = request.src_image->vk_image,
.srcImageLayout = vkImageLayoutFromGpuImageLayout(request.src_image_layout),
.dstImage = request.dst_image->vk_image,
.dstImageLayout = vkImageLayoutFromGpuImageLayout(request.dst_image_layout),
.regionCount = region_count,
.pRegions = regions,
.filter = vkFilterFromGpuFilter(request.filter),
};
vkCmdBlitImage2(request.command_buffer->vk_buffer, &info);
}
void gpuCmdDraw(GpuCmdDrawRequest request) { void gpuCmdDraw(GpuCmdDrawRequest request) {
vkCmdDraw(request.command_buffer->vk_buffer, request.vertex_count, request.instance_count, vkCmdDraw(request.command_buffer->vk_buffer, request.vertex_count, request.instance_count,
request.first_vertex, request.first_instance); request.first_vertex, request.first_instance);
+7
View File
@@ -160,6 +160,12 @@ i32 main(void) {
wpFileRead(code, spirv, code_size); wpFileRead(code, spirv, code_size);
GpuLoadImageFromFileRequest load_img_req = {
.command_pool = pool,
.filename = wpStr8LitRo("/home/abdelrahman/Pictures/800px-Trumpets02262006.jpg"),
};
GpuImage *texture = gpuLoadImageFromFile(&arena, &temp_arena, load_img_req);
GpuShaderCreateRequest shader_request = { GpuShaderCreateRequest shader_request = {
.device = device, .device = device,
.code = (void *)code, .code = (void *)code,
@@ -517,6 +523,7 @@ i32 main(void) {
gpuDestroyPipelineLayout(layout); gpuDestroyPipelineLayout(layout);
gpuDestroyBuffer(&shader_data); gpuDestroyBuffer(&shader_data);
gpuDestroyShader(shader); gpuDestroyShader(shader);
gpuDestroyImage(texture);
gpuDestroyCommandPool(pool); gpuDestroyCommandPool(pool);
gpuDestroyBuffer(&vertex_buffer); gpuDestroyBuffer(&vertex_buffer);
gpuDestroySwapchain(swapchain); gpuDestroySwapchain(swapchain);