first working version
uses stb to load the image, currently all images have their texture replaced with the texture of the first image gonna try to fix that soon
This commit is contained in:
parent
3a2a80f70a
commit
97ca8319c3
14 changed files with 719 additions and 134 deletions
4
Makefile
4
Makefile
|
@ -4,8 +4,8 @@ CC = clang
|
|||
CFLAGS = -std=c11 -Wall -Wextra -Wpedantic
|
||||
CFLAGS += -Werror -Wfloat-equal -Wshadow
|
||||
CFLAGS += -fPIC -fstrict-aliasing
|
||||
CFLAGS += $(shell pkg-config --cflags glfw3 vulkan)
|
||||
LDFLAGS = $(shell pkg-config --libs glfw3 vulkan)
|
||||
CFLAGS += $(shell pkg-config --cflags glfw3 stb vulkan)
|
||||
LDFLAGS = $(shell pkg-config --libs glfw3 stb vulkan)
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS += -DDEBUG -g
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
gnumake,
|
||||
pkg-config,
|
||||
shaderc,
|
||||
stb,
|
||||
vulkan-headers,
|
||||
vulkan-loader,
|
||||
vulkan-validation-layers,
|
||||
|
@ -20,6 +21,7 @@ in stdenv.mkDerivation {
|
|||
|
||||
buildInputs = [
|
||||
glfw
|
||||
stb
|
||||
vulkan-headers
|
||||
vulkan-loader
|
||||
vulkan-validation-layers
|
||||
|
|
BIN
examples/:3.png
Normal file
BIN
examples/:3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
15
examples/image.c
Normal file
15
examples/image.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright (jacekpoz 2024). Licensed under the EUPL-1.2 or later.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ptk.h>
|
||||
|
||||
int main(void) {
|
||||
if (!ptk_init(800, 600, "image", (PtkVersion){ .major = 0, .minor = 1, .patch = 0 })) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return ptk_run(PTK_BOX(
|
||||
ptk_image("examples/papiezWasap.png", (PtkPos){ .x = 200.0f, .y = 200.0f }, (PtkSize){ .w = 128.0f, .h = 128.0f }),
|
||||
ptk_image("examples/:3.png", (PtkPos){ .x = 200.0f, .y = 400.0f }, (PtkSize){ .w = 128.0f, .h = 128.0f })
|
||||
));
|
||||
}
|
BIN
examples/papiezWasap.png
Normal file
BIN
examples/papiezWasap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -26,6 +26,7 @@ typedef enum {
|
|||
PTK_COMPONENT_TYPE_RECT = 2,
|
||||
PTK_COMPONENT_TYPE_ELLIPSE = 3,
|
||||
PTK_COMPONENT_TYPE_CLICKABLE = 4,
|
||||
PTK_COMPONENT_TYPE_IMAGE = 5,
|
||||
} PtkComponentType;
|
||||
|
||||
const char *ptk_component_type_to_str(PtkComponentType type);
|
||||
|
@ -67,6 +68,12 @@ PTK_COMPONENT_DEFINE(PtkClickable,
|
|||
MouseButtonCallback on_press;
|
||||
);
|
||||
|
||||
PTK_COMPONENT_DEFINE(PtkImage,
|
||||
const char *path;
|
||||
PtkPos top_left;
|
||||
PtkSize size;
|
||||
);
|
||||
|
||||
PtkHandle ptk_box(const size_t child_count, PtkHandle *children);
|
||||
PtkHandle ptk_triangle(const PtkPos vertices[3], const PtkRGB color);
|
||||
PtkHandle ptk_rect(const PtkPos top_left, const PtkSize size, const PtkRGB color);
|
||||
|
@ -74,6 +81,7 @@ PtkHandle ptk_square(const PtkPos top_left, const float size, const PtkRGB color
|
|||
PtkHandle ptk_ellipse(const PtkPos center, const PtkSize radii, const PtkRGB color);
|
||||
PtkHandle ptk_circle(const PtkPos center, const float radius, const PtkRGB color);
|
||||
PtkHandle ptk_clickable(PtkHandle hitbox, const MouseButtonCallback on_press);
|
||||
PtkHandle ptk_image(const char *path, const PtkPos top_left, const PtkSize size);
|
||||
|
||||
#define PTK_BOX(...) ptk_box(sizeof((PtkHandle []){ __VA_ARGS__ }) / sizeof(PtkHandle), (PtkHandle []) { __VA_ARGS__ })
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#version 450
|
||||
|
||||
layout(constant_id = 0) const int PTK_COMPONENT_TYPE_ELLIPSE = 0;
|
||||
layout(constant_id = 1) const int PTK_COMPONENT_TYPE_IMAGE = 0;
|
||||
|
||||
layout(location = 0) in vec3 fragColor;
|
||||
layout(location = 1) flat in int shapeType;
|
||||
|
@ -10,11 +11,17 @@ layout(location = 2) in vec2 uv;
|
|||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D texSampler;
|
||||
|
||||
void main() {
|
||||
if (shapeType == PTK_COMPONENT_TYPE_ELLIPSE) {
|
||||
if (length(uv - vec2(0.5)) > 0.5) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
outColor = vec4(fragColor, 1.0);
|
||||
if (shapeType == PTK_COMPONENT_TYPE_IMAGE) {
|
||||
outColor = texture(texSampler, uv);
|
||||
} else {
|
||||
outColor = vec4(fragColor, 1.0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,6 +191,10 @@ PtkHandle ptk_clickable(PtkHandle hitbox, const MouseButtonCallback on_press) {
|
|||
return clickable_component(get_component_id(), hitbox, on_press);
|
||||
}
|
||||
|
||||
PtkHandle ptk_image(const char *path, const PtkPos top_left, const PtkSize size) {
|
||||
return image_component(get_component_id(), path, top_left, size);
|
||||
}
|
||||
|
||||
int ptk_run(PtkHandle root) {
|
||||
vk_init_components(root);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <ptk_log.h>
|
||||
#include <ptk_vk/components.h>
|
||||
#include <ptk_vk/init.h>
|
||||
#include <ptk_vk/image.h>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <string.h>
|
||||
|
@ -119,6 +120,19 @@ PtkHandle clickable_component(const uint64_t id, PtkHandle hitbox, const MouseBu
|
|||
return (PtkHandle)ret;
|
||||
}
|
||||
|
||||
PtkHandle image_component(const uint64_t id, const char *path, const PtkPos top_left, const PtkSize size) {
|
||||
PtkImage *ret = malloc(sizeof(PtkImage));
|
||||
*ret = (PtkImage){
|
||||
.id = id,
|
||||
.type = PTK_COMPONENT_TYPE_IMAGE,
|
||||
.path = path,
|
||||
.top_left = top_left,
|
||||
.size = size,
|
||||
};
|
||||
|
||||
return (PtkHandle)ret;
|
||||
}
|
||||
|
||||
void triangle(const PtkTriangle *triangle) {
|
||||
PTK_LIST_SET(Vertices, m_vertices_cache, triangle->id, PTK_LIST_NEW(Vertex, 3));
|
||||
PTK_LIST_SET(Indices, m_indices_cache, triangle->id, PTK_LIST_NEW(uint32_t, 3));
|
||||
|
@ -213,6 +227,15 @@ void rect(const PtkRect *rect) {
|
|||
PTK_LIST_ADD(uint32_t, m_indices_cache.data[rect->id], bottom_right_index);
|
||||
}
|
||||
|
||||
void image(const PtkImage *image) {
|
||||
vk_create_image(image->path);
|
||||
|
||||
PtkRect *r = (PtkRect *)rect_component(image->id, image->top_left, image->size, (PtkRGB){ .r = 0.0f, .g = 0.0f, .b = 0.0f });
|
||||
r->type = image->type;
|
||||
|
||||
rect(r);
|
||||
}
|
||||
|
||||
void ellipse(const PtkEllipse *ellipse) {
|
||||
const PtkPos top_left = {
|
||||
.x = ellipse->center.x - ellipse->radii.w,
|
||||
|
@ -251,6 +274,9 @@ void component(PtkHandle c) {
|
|||
case PTK_COMPONENT_TYPE_ELLIPSE: {
|
||||
ellipse((PtkEllipse *)c);
|
||||
} break;
|
||||
case PTK_COMPONENT_TYPE_IMAGE: {
|
||||
image((PtkImage *)c);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -310,10 +336,10 @@ inline bool ellipse_intersects(const PtkEllipse e, const PtkPos p) {
|
|||
return ((x * x) / (rx * rx)) + ((y * y) / (ry * ry)) <= 1.0f;
|
||||
}
|
||||
|
||||
bool intersects(const PtkHandle component, const PtkPos point) {
|
||||
switch (component->type) {
|
||||
bool intersects(const PtkHandle c, const PtkPos point) {
|
||||
switch (c->type) {
|
||||
case PTK_COMPONENT_TYPE_BOX: {
|
||||
PTK_LIST_FOR_EACH(const PtkHandle, component->children, child, {
|
||||
PTK_LIST_FOR_EACH(const PtkHandle, c->children, child, {
|
||||
if (intersects(child, point)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -322,13 +348,15 @@ bool intersects(const PtkHandle component, const PtkPos point) {
|
|||
return false;
|
||||
}
|
||||
case PTK_COMPONENT_TYPE_TRIANGLE:
|
||||
return triangle_intersects(*(PtkTriangle *)component, point);
|
||||
return triangle_intersects(*(PtkTriangle *)c, point);
|
||||
case PTK_COMPONENT_TYPE_RECT:
|
||||
return rect_intersects(*(PtkRect *)component, point);
|
||||
return rect_intersects(*(PtkRect *)c, point);
|
||||
case PTK_COMPONENT_TYPE_ELLIPSE:
|
||||
return ellipse_intersects(*(PtkEllipse *)component, point);
|
||||
return ellipse_intersects(*(PtkEllipse *)c, point);
|
||||
case PTK_COMPONENT_TYPE_CLICKABLE:
|
||||
return intersects(component->children.data[0], point);
|
||||
return intersects(c->children.data[0], point);
|
||||
case PTK_COMPONENT_TYPE_IMAGE:
|
||||
return rect_intersects(*(PtkRect *)rect_component(c->id, ((PtkImage *)c)->top_left, ((PtkImage *)c)->size, (PtkRGB){ .r = 0.0f, .g = 0.0f, .b = 0.0f }), point);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ PtkHandle square_component(const uint64_t id, const PtkPos top_left, const float
|
|||
PtkHandle ellipse_component(const uint64_t id, const PtkPos center, const PtkSize radii, const PtkRGB color);
|
||||
PtkHandle circle_component(const uint64_t id, const PtkPos center, const float radius, const PtkRGB color);
|
||||
PtkHandle clickable_component(const uint64_t id, PtkHandle hitbox, const MouseButtonCallback on_press);
|
||||
PtkHandle image_component(const uint64_t id, const char *path, const PtkPos top_left, const PtkSize size);
|
||||
|
||||
void vk_init_components(PtkHandle root);
|
||||
|
||||
|
|
373
src/ptk_vk/image.c
Normal file
373
src/ptk_vk/image.c
Normal file
|
@ -0,0 +1,373 @@
|
|||
// Copyright (jacekpoz 2024). Licensed under the EUPL-1.2 or later.
|
||||
|
||||
#include <ptk_vk/image.h>
|
||||
|
||||
#include <ptk_vk/init.h>
|
||||
#include <ptk_vk/utils.h>
|
||||
|
||||
#include <ptk_log.h>
|
||||
#include <ptk_option.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
PTK_LIST_DEFINE(VkImage);
|
||||
PTK_LIST_DEFINE(VkDeviceMemory);
|
||||
|
||||
const size_t g_max_images = 64;
|
||||
|
||||
size_t g_image_count = 0;
|
||||
|
||||
static PTK_LIST(VkImage) m_images;
|
||||
static PTK_LIST(VkDeviceMemory) m_image_memories;
|
||||
PTK_LIST(VkImageView) g_image_views;
|
||||
VkSampler g_sampler;
|
||||
|
||||
bool create_image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags props, VkImage *image, VkDeviceMemory *image_memory) {
|
||||
VK_TRY(false,
|
||||
vkCreateImage(
|
||||
g_dev,
|
||||
&(VkImageCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = format,
|
||||
.extent = (VkExtent3D){
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = tiling,
|
||||
.usage = usage,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = NULL,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
},
|
||||
NULL,
|
||||
image
|
||||
)
|
||||
);
|
||||
|
||||
VkMemoryRequirements mem_reqs;
|
||||
vkGetImageMemoryRequirements(g_dev, *image, &mem_reqs);
|
||||
|
||||
PTK_OPTION(uint32_t) mem_type = vk_find_memory_type(mem_reqs.memoryTypeBits, props);
|
||||
|
||||
if (!mem_type.exists) {
|
||||
PTK_ERR("failed to find suitable memory type");
|
||||
return false;
|
||||
}
|
||||
|
||||
VK_TRY(false,
|
||||
vkAllocateMemory(
|
||||
g_dev,
|
||||
&(VkMemoryAllocateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = NULL,
|
||||
.allocationSize = mem_reqs.size,
|
||||
.memoryTypeIndex = mem_type.value,
|
||||
},
|
||||
NULL,
|
||||
image_memory
|
||||
)
|
||||
);
|
||||
|
||||
VK_TRY(false,
|
||||
vkBindImageMemory(
|
||||
g_dev,
|
||||
*image,
|
||||
*image_memory,
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool transition_image_layout(VkImage image, VkFormat format, VkImageLayout old_layout, VkImageLayout new_layout) {
|
||||
(void)format;
|
||||
PTK_OPTION(VkCommandBuffer) command_buffer = vk_begin_single_time_commands();
|
||||
|
||||
if (!command_buffer.exists) {
|
||||
PTK_ERR("failed to create command buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
VkAccessFlags source_access_mask;
|
||||
VkAccessFlags destination_access_mask;
|
||||
VkPipelineStageFlags source_stage;
|
||||
VkPipelineStageFlags destination_stage;
|
||||
|
||||
if (
|
||||
old_layout == VK_IMAGE_LAYOUT_UNDEFINED
|
||||
&& new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
||||
) {
|
||||
source_access_mask = 0;
|
||||
destination_access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
destination_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
} else if (
|
||||
old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
||||
&& new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
) {
|
||||
source_access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
destination_access_mask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
destination_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
} else {
|
||||
PTK_ERR("unsupported layer transition");
|
||||
return false;
|
||||
}
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
command_buffer.value,
|
||||
source_stage,
|
||||
destination_stage,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
1,
|
||||
&(VkImageMemoryBarrier){
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = NULL,
|
||||
.srcAccessMask = source_access_mask,
|
||||
.dstAccessMask = destination_access_mask,
|
||||
.oldLayout = old_layout,
|
||||
.newLayout = new_layout,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange = (VkImageSubresourceRange){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!vk_end_single_time_commands(command_buffer.value)) {
|
||||
PTK_ERR("failed to end command buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool copy_buffer_to_image(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {
|
||||
PTK_OPTION(VkCommandBuffer) command_buffer = vk_begin_single_time_commands();
|
||||
|
||||
if (!command_buffer.exists) {
|
||||
PTK_ERR("failed to create command buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
vkCmdCopyBufferToImage(
|
||||
command_buffer.value,
|
||||
buffer,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
&(VkBufferImageCopy){
|
||||
.bufferOffset = 0,
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource = (VkImageSubresourceLayers){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.imageOffset = (VkOffset3D){
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.z = 0,
|
||||
},
|
||||
.imageExtent = (VkExtent3D){
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!vk_end_single_time_commands(command_buffer.value)) {
|
||||
PTK_ERR("failed to end command buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool create_image_view(VkImage image) {
|
||||
PTK_OPTION(VkImageView) image_view = vk_create_image_view(image, VK_FORMAT_R8G8B8A8_SRGB);
|
||||
|
||||
if (!image_view.exists) {
|
||||
PTK_ERR("failed creating texture image view");
|
||||
return false;
|
||||
}
|
||||
|
||||
PTK_LIST_ADD(VkImageView, g_image_views, image_view.value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vk_create_sampler(void) {
|
||||
VkPhysicalDeviceProperties props;
|
||||
vkGetPhysicalDeviceProperties(g_physical_dev, &props);
|
||||
|
||||
VK_TRY(false,
|
||||
vkCreateSampler(
|
||||
g_dev,
|
||||
&(VkSamplerCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.magFilter = VK_FILTER_LINEAR,
|
||||
.minFilter = VK_FILTER_LINEAR,
|
||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
.mipLodBias = 0.0f,
|
||||
.anisotropyEnable = VK_TRUE,
|
||||
.maxAnisotropy = props.limits.maxSamplerAnisotropy,
|
||||
.compareEnable = VK_FALSE,
|
||||
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||
.minLod = 0.0f,
|
||||
.maxLod = 0.0f,
|
||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE,
|
||||
},
|
||||
NULL,
|
||||
&g_sampler
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vk_create_image(const char *path) {
|
||||
int texture_width, texture_height;
|
||||
int texture_channels;
|
||||
|
||||
stbi_uc *pixels = stbi_load(path, &texture_width, &texture_height, &texture_channels, STBI_rgb_alpha);
|
||||
|
||||
VkDeviceSize image_size = texture_width * texture_height * 4;
|
||||
|
||||
if (pixels == NULL) {
|
||||
PTK_ERR("failed to load image %s", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
VkBuffer staging_buffer;
|
||||
VkDeviceMemory staging_buffer_memory;
|
||||
|
||||
if (
|
||||
!vk_create_buffer(
|
||||
image_size,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&staging_buffer,
|
||||
&staging_buffer_memory
|
||||
)
|
||||
) {
|
||||
PTK_ERR("failed creating staging image buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
void *data;
|
||||
vkMapMemory(g_dev, staging_buffer_memory, 0, image_size, 0, &data);
|
||||
memcpy(data, pixels, image_size);
|
||||
vkUnmapMemory(g_dev, staging_buffer_memory);
|
||||
|
||||
stbi_image_free(pixels);
|
||||
|
||||
VkImage image;
|
||||
VkDeviceMemory image_memory;
|
||||
|
||||
if (
|
||||
!create_image(
|
||||
texture_width,
|
||||
texture_height,
|
||||
VK_FORMAT_R8G8B8A8_SRGB,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
&image,
|
||||
&image_memory
|
||||
)
|
||||
) {
|
||||
PTK_ERR("failed creating image");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!transition_image_layout(
|
||||
image,
|
||||
VK_FORMAT_R8G8B8A8_SRGB,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
||||
)
|
||||
) {
|
||||
PTK_ERR("failed transitioning image layout to optimal");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!copy_buffer_to_image(staging_buffer, image, texture_width, texture_height)) {
|
||||
PTK_ERR("failed copying buffer to image");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!transition_image_layout(
|
||||
image,
|
||||
VK_FORMAT_R8G8B8A8_SRGB,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
)
|
||||
) {
|
||||
PTK_ERR("failed transitioning image layout to shader optimal");
|
||||
return false;
|
||||
}
|
||||
|
||||
vkDestroyBuffer(g_dev, staging_buffer, NULL);
|
||||
vkFreeMemory(g_dev, staging_buffer_memory, NULL);
|
||||
|
||||
PTK_LIST_ADD(VkImage, m_images, image);
|
||||
create_image_view(image);
|
||||
|
||||
g_image_count += 1;
|
||||
|
||||
vk_update_descriptor_sets();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void vk_image_cleanup(void) {
|
||||
vkDestroySampler(g_dev, g_sampler, NULL);
|
||||
PTK_LIST_FOR_EACH(VkImageView, g_image_views, iv, {
|
||||
vkDestroyImageView(g_dev, iv, NULL);
|
||||
})
|
||||
PTK_LIST_FREE(g_image_views);
|
||||
|
||||
PTK_LIST_FOR_EACH(VkImage, m_images, i, {
|
||||
vkDestroyImage(g_dev, i, NULL);
|
||||
})
|
||||
PTK_LIST_FREE(m_images);
|
||||
|
||||
PTK_LIST_FOR_EACH(VkDeviceMemory, m_image_memories, m, {
|
||||
vkFreeMemory(g_dev, m, NULL);
|
||||
})
|
||||
PTK_LIST_FREE(m_image_memories);
|
||||
}
|
28
src/ptk_vk/image.h
Normal file
28
src/ptk_vk/image.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright (jacekpoz 2024). Licensed under the EUPL-1.2 or later.
|
||||
|
||||
#ifndef PTK_PTK_VK_IMAGE_H_
|
||||
#define PTK_PTK_VK_IMAGE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <ptk_list.h>
|
||||
#ifndef GLFW_INCLUDE_VULKAN
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#endif
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
PTK_LIST_DEFINE(VkImageView);
|
||||
|
||||
extern const size_t g_max_images;
|
||||
|
||||
extern size_t g_image_count;
|
||||
extern PTK_LIST(VkImageView) g_image_views;
|
||||
extern VkSampler g_sampler;
|
||||
|
||||
bool vk_create_image(const char *path);
|
||||
bool vk_create_sampler(void);
|
||||
|
||||
void vk_image_cleanup(void);
|
||||
|
||||
#endif // PTK_PTK_VK_IMAGE_H_
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <ptk_vk/components.h>
|
||||
#include <ptk_vk/draw.h>
|
||||
#include <ptk_vk/image.h>
|
||||
#include <ptk_vk/utils.h>
|
||||
|
||||
#include <ptk_log.h>
|
||||
|
@ -16,8 +17,6 @@
|
|||
#include <errno.h>
|
||||
|
||||
PTK_LIST_DEFINE(VkImage);
|
||||
PTK_LIST_DEFINE(VkImageView);
|
||||
PTK_OPTION_DEFINE(uint32_t);
|
||||
PTK_LIST_DEFINE(VkSurfaceFormatKHR);
|
||||
PTK_LIST_DEFINE(VkPresentModeKHR);
|
||||
PTK_LIST_DEFINE(VkFramebuffer);
|
||||
|
@ -47,7 +46,7 @@ typedef struct {
|
|||
static GLFWwindow *m_window = NULL;
|
||||
|
||||
static VkInstance m_instance = VK_NULL_HANDLE;
|
||||
static VkPhysicalDevice m_physical_dev = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice g_physical_dev = VK_NULL_HANDLE;
|
||||
VkDevice g_dev = VK_NULL_HANDLE;
|
||||
|
||||
static VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||
|
@ -284,7 +283,7 @@ bool select_physical_dev(void) {
|
|||
|
||||
PTK_DEBUG("total memory: %lu", dev_mem_totals[dev_best_index]);
|
||||
|
||||
m_physical_dev = devs[dev_best_index];
|
||||
g_physical_dev = devs[dev_best_index];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -432,11 +431,14 @@ bool is_device_suitable(const VkPhysicalDevice dev) {
|
|||
|
||||
PTK_LIST_FREE(queue_families);
|
||||
|
||||
return indices_found && extensions_supported && swapchain_adequate;
|
||||
VkPhysicalDeviceFeatures supported_features;
|
||||
vkGetPhysicalDeviceFeatures(dev, &supported_features);
|
||||
|
||||
return indices_found && extensions_supported && swapchain_adequate && supported_features.samplerAnisotropy;
|
||||
}
|
||||
|
||||
bool create_logical_dev(void) {
|
||||
if (!is_device_suitable(m_physical_dev)) {
|
||||
if (!is_device_suitable(g_physical_dev)) {
|
||||
PTK_ERR("physical device isn't suitable");
|
||||
return false;
|
||||
}
|
||||
|
@ -458,7 +460,7 @@ bool create_logical_dev(void) {
|
|||
|
||||
VK_TRY(false,
|
||||
vkCreateDevice(
|
||||
m_physical_dev,
|
||||
g_physical_dev,
|
||||
&(VkDeviceCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
|
@ -469,7 +471,9 @@ bool create_logical_dev(void) {
|
|||
.ppEnabledLayerNames = m_validation_layers.data,
|
||||
.enabledExtensionCount = m_device_extensions.size,
|
||||
.ppEnabledExtensionNames = m_device_extensions.data,
|
||||
.pEnabledFeatures = &(VkPhysicalDeviceFeatures){0},
|
||||
.pEnabledFeatures = &(VkPhysicalDeviceFeatures){
|
||||
.samplerAnisotropy = VK_TRUE,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&g_dev
|
||||
|
@ -483,7 +487,7 @@ bool create_logical_dev(void) {
|
|||
}
|
||||
|
||||
bool create_swapchain(void) {
|
||||
const SwapchainSupportInfo swapchain_support = query_swapchain_support(m_physical_dev);
|
||||
const SwapchainSupportInfo swapchain_support = query_swapchain_support(g_physical_dev);
|
||||
|
||||
const VkSurfaceFormatKHR surface_format = select_swap_surface_format(swapchain_support.formats);
|
||||
const VkPresentModeKHR present_mode = select_swap_present_mode(swapchain_support.present_modes);
|
||||
|
@ -551,39 +555,53 @@ bool create_swapchain(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
PTK_OPTION(VkImageView) vk_create_image_view(VkImage image, VkFormat format) {
|
||||
VkImageView image_view;
|
||||
|
||||
VK_TRY(PTK_OPTION_NONE(VkImageView),
|
||||
vkCreateImageView(
|
||||
g_dev,
|
||||
&(VkImageViewCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.image = image,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = format,
|
||||
.components = (VkComponentMapping){
|
||||
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
},
|
||||
.subresourceRange = (VkImageSubresourceRange){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&image_view
|
||||
)
|
||||
);
|
||||
|
||||
return PTK_OPTION_SOME(VkImageView, image_view);
|
||||
}
|
||||
|
||||
bool create_image_views(void) {
|
||||
m_swapchain_image_views = PTK_LIST_NEW(VkImageView, m_swapchain_images.size);
|
||||
|
||||
PTK_LIST_FOR_EACH_E(VkImage, m_swapchain_images, i, swapchain_image, {
|
||||
VK_TRY(false,
|
||||
vkCreateImageView(
|
||||
g_dev,
|
||||
&(VkImageViewCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.image = swapchain_image,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = m_swapchain_image_format,
|
||||
.components = (VkComponentMapping){
|
||||
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
},
|
||||
.subresourceRange = (VkImageSubresourceRange){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&m_swapchain_image_views.data[i]
|
||||
)
|
||||
);
|
||||
m_swapchain_image_views.size += 1;
|
||||
PTK_LIST_FOR_EACH(VkImage, m_swapchain_images, swapchain_image, {
|
||||
PTK_OPTION(VkImageView) image_view = vk_create_image_view(swapchain_image, m_swapchain_image_format);
|
||||
|
||||
if (!image_view.exists) {
|
||||
PTK_ERR("failed creating image view");
|
||||
return false;
|
||||
}
|
||||
|
||||
PTK_LIST_ADD(VkImageView, m_swapchain_image_views, image_view.value);
|
||||
})
|
||||
|
||||
return true;
|
||||
|
@ -711,13 +729,22 @@ bool create_descriptor_set_layout(void) {
|
|||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.bindingCount = 1,
|
||||
.pBindings = &(VkDescriptorSetLayoutBinding){
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.pImmutableSamplers = NULL,
|
||||
.bindingCount = 2,
|
||||
.pBindings = (VkDescriptorSetLayoutBinding []){
|
||||
(VkDescriptorSetLayoutBinding){
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.pImmutableSamplers = NULL,
|
||||
},
|
||||
(VkDescriptorSetLayoutBinding){
|
||||
.binding = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.pImmutableSamplers = &g_sampler,
|
||||
},
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
|
@ -747,14 +774,24 @@ bool create_graphics_pipeline(void) {
|
|||
}
|
||||
|
||||
const VkSpecializationInfo spec_info = {
|
||||
.mapEntryCount = 1,
|
||||
.pMapEntries = &(VkSpecializationMapEntry){
|
||||
.constantID = 0,
|
||||
.offset = 0,
|
||||
.size = sizeof(int),
|
||||
.mapEntryCount = 2,
|
||||
.pMapEntries = (VkSpecializationMapEntry []){
|
||||
(VkSpecializationMapEntry){
|
||||
.constantID = 0,
|
||||
.offset = 0,
|
||||
.size = sizeof(int),
|
||||
},
|
||||
(VkSpecializationMapEntry){
|
||||
.constantID = 1,
|
||||
.offset = sizeof(int),
|
||||
.size = sizeof(int),
|
||||
},
|
||||
},
|
||||
.dataSize = sizeof(int) * 2,
|
||||
.pData = (int []){
|
||||
PTK_COMPONENT_TYPE_ELLIPSE,
|
||||
PTK_COMPONENT_TYPE_IMAGE
|
||||
},
|
||||
.dataSize = sizeof(int),
|
||||
.pData = &(int){PTK_COMPONENT_TYPE_ELLIPSE},
|
||||
};
|
||||
|
||||
const VkPipelineShaderStageCreateInfo shader_stages[] = {
|
||||
|
@ -982,9 +1019,9 @@ bool create_command_pool(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
PTK_OPTION(uint32_t) find_memory_type(const uint32_t type_filter, const VkMemoryPropertyFlags props) {
|
||||
PTK_OPTION(uint32_t) vk_find_memory_type(const uint32_t type_filter, const VkMemoryPropertyFlags props) {
|
||||
VkPhysicalDeviceMemoryProperties mem_props;
|
||||
vkGetPhysicalDeviceMemoryProperties(m_physical_dev, &mem_props);
|
||||
vkGetPhysicalDeviceMemoryProperties(g_physical_dev, &mem_props);
|
||||
|
||||
for (uint32_t i = 0; i < mem_props.memoryTypeCount; ++i) {
|
||||
if (type_filter & (1 << i) && (mem_props.memoryTypes[i].propertyFlags & props) == props) {
|
||||
|
@ -995,7 +1032,7 @@ PTK_OPTION(uint32_t) find_memory_type(const uint32_t type_filter, const VkMemory
|
|||
return PTK_OPTION_NONE(uint32_t);
|
||||
}
|
||||
|
||||
bool create_buffer(const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags props, VkBuffer *buffer, VkDeviceMemory *buffer_memory) {
|
||||
bool vk_create_buffer(const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags props, VkBuffer *buffer, VkDeviceMemory *buffer_memory) {
|
||||
VK_TRY(false,
|
||||
vkCreateBuffer(
|
||||
g_dev,
|
||||
|
@ -1017,7 +1054,7 @@ bool create_buffer(const VkDeviceSize size, const VkBufferUsageFlags usage, cons
|
|||
VkMemoryRequirements mem_reqs;
|
||||
vkGetBufferMemoryRequirements(g_dev, *buffer, &mem_reqs);
|
||||
|
||||
const PTK_OPTION(uint32_t) memory_type = find_memory_type(mem_reqs.memoryTypeBits, props);
|
||||
const PTK_OPTION(uint32_t) memory_type = vk_find_memory_type(mem_reqs.memoryTypeBits, props);
|
||||
|
||||
if (!memory_type.exists) {
|
||||
PTK_ERR("failed to find suitable memory type");
|
||||
|
@ -1043,10 +1080,10 @@ bool create_buffer(const VkDeviceSize size, const VkBufferUsageFlags usage, cons
|
|||
return true;
|
||||
}
|
||||
|
||||
bool copy_buffer(const VkBuffer src, const VkBuffer dst, const VkDeviceSize size) {
|
||||
PTK_OPTION(VkCommandBuffer) vk_begin_single_time_commands(void) {
|
||||
VkCommandBuffer command_buffer;
|
||||
|
||||
VK_TRY(false,
|
||||
VK_TRY(PTK_OPTION_NONE(VkCommandBuffer),
|
||||
vkAllocateCommandBuffers(
|
||||
g_dev,
|
||||
&(VkCommandBufferAllocateInfo){
|
||||
|
@ -1060,45 +1097,68 @@ bool copy_buffer(const VkBuffer src, const VkBuffer dst, const VkDeviceSize size
|
|||
)
|
||||
);
|
||||
|
||||
VK_TRY(false,
|
||||
vkBeginCommandBuffer(command_buffer, &(VkCommandBufferBeginInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||
.pInheritanceInfo = NULL,
|
||||
})
|
||||
VK_TRY(PTK_OPTION_NONE(VkCommandBuffer),
|
||||
vkBeginCommandBuffer(
|
||||
command_buffer,
|
||||
&(VkCommandBufferBeginInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||
.pInheritanceInfo = NULL,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
vkCmdCopyBuffer(command_buffer, src, dst, 1, &(VkBufferCopy){
|
||||
return PTK_OPTION_SOME(VkCommandBuffer, command_buffer);
|
||||
}
|
||||
|
||||
bool vk_end_single_time_commands(VkCommandBuffer command_buffer) {
|
||||
VK_TRY(false, vkEndCommandBuffer(command_buffer));
|
||||
|
||||
VK_TRY(false,
|
||||
vkQueueSubmit(
|
||||
g_graphics_queue,
|
||||
1,
|
||||
&(VkSubmitInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = NULL,
|
||||
.waitSemaphoreCount = 0,
|
||||
.pWaitSemaphores = NULL,
|
||||
.pWaitDstStageMask = NULL,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &command_buffer,
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL,
|
||||
},
|
||||
VK_NULL_HANDLE
|
||||
);
|
||||
);
|
||||
|
||||
VK_TRY(false, vkQueueWaitIdle(g_graphics_queue));
|
||||
|
||||
vkFreeCommandBuffers(g_dev, m_command_pool, 1, &command_buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool copy_buffer(const VkBuffer src, const VkBuffer dst, const VkDeviceSize size) {
|
||||
PTK_OPTION(VkCommandBuffer) command_buffer = vk_begin_single_time_commands();
|
||||
|
||||
if (!command_buffer.exists) {
|
||||
PTK_ERR("failed to create command buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
vkCmdCopyBuffer(command_buffer.value, src, dst, 1, &(VkBufferCopy){
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0,
|
||||
.size = size,
|
||||
});
|
||||
|
||||
VK_TRY(false,
|
||||
vkEndCommandBuffer(command_buffer)
|
||||
);
|
||||
|
||||
vkQueueSubmit(
|
||||
g_graphics_queue,
|
||||
1,
|
||||
&(VkSubmitInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = NULL,
|
||||
.waitSemaphoreCount = 0,
|
||||
.pWaitSemaphores = NULL,
|
||||
.pWaitDstStageMask = NULL,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &command_buffer,
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL,
|
||||
},
|
||||
VK_NULL_HANDLE
|
||||
);
|
||||
|
||||
vkQueueWaitIdle(g_graphics_queue);
|
||||
|
||||
vkFreeCommandBuffers(g_dev, m_command_pool, 1, &command_buffer);
|
||||
if (!vk_end_single_time_commands(command_buffer.value)) {
|
||||
PTK_ERR("failed to end command buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1109,7 +1169,7 @@ bool transfer_to_buffer(void *src, size_t src_size, VkBuffer buffer) {
|
|||
VkBuffer staging_buffer;
|
||||
VkDeviceMemory staging_buffer_memory;
|
||||
if (
|
||||
!create_buffer(
|
||||
!vk_create_buffer(
|
||||
buffer_size,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
|
@ -1171,7 +1231,7 @@ bool create_vertex_buffer(void) {
|
|||
// const VkDeviceSize buffer_size = sizeof(g_vertices.data[0]) * g_vertices.size;
|
||||
const VkDeviceSize buffer_size = 65536;
|
||||
if (
|
||||
!create_buffer(
|
||||
!vk_create_buffer(
|
||||
buffer_size,
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
|
@ -1189,7 +1249,7 @@ bool create_vertex_buffer(void) {
|
|||
bool create_index_buffer(void) {
|
||||
const VkDeviceSize buffer_size = 65536;
|
||||
if (
|
||||
!create_buffer(
|
||||
!vk_create_buffer(
|
||||
buffer_size,
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
|
@ -1213,7 +1273,7 @@ bool create_uniform_buffers(void) {
|
|||
|
||||
for (size_t i = 0; i < g_max_frames_in_flight; ++i) {
|
||||
if (
|
||||
!create_buffer(
|
||||
!vk_create_buffer(
|
||||
buffer_size,
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
|
@ -1239,11 +1299,17 @@ bool create_descriptor_pool(void) {
|
|||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.maxSets = g_max_frames_in_flight,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = &(VkDescriptorPoolSize){
|
||||
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = g_max_frames_in_flight,
|
||||
.maxSets = g_max_frames_in_flight * g_max_images,
|
||||
.poolSizeCount = 2,
|
||||
.pPoolSizes = (VkDescriptorPoolSize []){
|
||||
(VkDescriptorPoolSize){
|
||||
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = g_max_frames_in_flight,
|
||||
},
|
||||
(VkDescriptorPoolSize){
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = g_max_images,
|
||||
},
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
|
@ -1256,6 +1322,58 @@ bool create_descriptor_pool(void) {
|
|||
|
||||
PTK_LIST_DEFINE(VkDescriptorSetLayout);
|
||||
|
||||
void vk_update_descriptor_sets(void) {
|
||||
VkDescriptorImageInfo image_infos[g_max_images];
|
||||
|
||||
PTK_DEBUG("g_image_count: %d", g_image_count);
|
||||
for (size_t i = 0; i < g_image_count; ++i) {
|
||||
image_infos[i] = (VkDescriptorImageInfo){
|
||||
.sampler = g_sampler,
|
||||
.imageView = g_image_views.data[i],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g_max_frames_in_flight; ++i) {
|
||||
vkUpdateDescriptorSets(
|
||||
g_dev,
|
||||
2,
|
||||
(VkWriteDescriptorSet []){
|
||||
(VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = NULL,
|
||||
.dstSet = m_descriptor_sets.data[i],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pImageInfo = NULL,
|
||||
.pBufferInfo = &(VkDescriptorBufferInfo){
|
||||
.buffer = m_uniform_buffers.data[i],
|
||||
.offset = 0,
|
||||
.range = sizeof(UniformBufferObject),
|
||||
},
|
||||
.pTexelBufferView = NULL,
|
||||
},
|
||||
(VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = NULL,
|
||||
.dstSet = m_descriptor_sets.data[i],
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = g_image_count,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = image_infos,
|
||||
.pBufferInfo = NULL,
|
||||
.pTexelBufferView = NULL,
|
||||
},
|
||||
},
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool create_descriptor_sets(void) {
|
||||
PTK_LIST(VkDescriptorSetLayout) layouts = PTK_LIST_NEW(VkDescriptorSetLayout, g_max_frames_in_flight);
|
||||
for (size_t i = 0; i < g_max_frames_in_flight; ++i) {
|
||||
|
@ -1278,30 +1396,7 @@ bool create_descriptor_sets(void) {
|
|||
)
|
||||
);
|
||||
|
||||
for (size_t i = 0; i < g_max_frames_in_flight; ++i) {
|
||||
vkUpdateDescriptorSets(
|
||||
g_dev,
|
||||
1,
|
||||
&(VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = NULL,
|
||||
.dstSet = m_descriptor_sets.data[i],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pImageInfo = NULL,
|
||||
.pBufferInfo = &(VkDescriptorBufferInfo){
|
||||
.buffer = m_uniform_buffers.data[i],
|
||||
.offset = 0,
|
||||
.range = sizeof(UniformBufferObject),
|
||||
},
|
||||
.pTexelBufferView = NULL,
|
||||
},
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
vk_update_descriptor_sets();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1515,6 +1610,11 @@ bool vk_init(GLFWwindow *window, const size_t width, const size_t height, const
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!vk_create_sampler()) {
|
||||
PTK_ERR("failed creating sampler");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!create_descriptor_set_layout()) {
|
||||
PTK_ERR("failed creating descriptor set layout");
|
||||
return false;
|
||||
|
@ -1576,6 +1676,8 @@ bool vk_init(GLFWwindow *window, const size_t width, const size_t height, const
|
|||
void vk_cleanup(void) {
|
||||
cleanup_swapchain();
|
||||
|
||||
vk_image_cleanup();
|
||||
|
||||
vkDestroyPipeline(g_dev, m_pipeline, NULL);
|
||||
vkDestroyPipelineLayout(g_dev, m_pipeline_layout, NULL);
|
||||
|
||||
|
|
|
@ -9,12 +9,17 @@
|
|||
#include <GLFW/glfw3.h>
|
||||
#include <ptk.h>
|
||||
#include <ptk_list.h>
|
||||
#include <ptk_option.h>
|
||||
|
||||
PTK_LIST_DEFINE(VkCommandBuffer);
|
||||
PTK_LIST_DEFINE(VkSemaphore);
|
||||
PTK_LIST_DEFINE(VkFence);
|
||||
PTK_OPTION_DEFINE(VkCommandBuffer);
|
||||
PTK_OPTION_DEFINE(uint32_t);
|
||||
PTK_OPTION_DEFINE(VkImageView);
|
||||
|
||||
extern VkDevice g_dev;
|
||||
extern VkPhysicalDevice g_physical_dev;
|
||||
extern VkSwapchainKHR g_swapchain;
|
||||
|
||||
extern VkQueue g_graphics_queue;
|
||||
|
@ -38,6 +43,18 @@ bool vk_recreate_swapchain(void);
|
|||
|
||||
bool vk_update_uniform_buffer(const size_t current_frame);
|
||||
|
||||
bool vk_create_buffer(const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags props, VkBuffer *buffer, VkDeviceMemory *buffer_memory);
|
||||
|
||||
PTK_OPTION(uint32_t) vk_find_memory_type(const uint32_t type_filter, const VkMemoryPropertyFlags props);
|
||||
|
||||
PTK_OPTION(VkCommandBuffer) vk_begin_single_time_commands(void);
|
||||
|
||||
bool vk_end_single_time_commands(VkCommandBuffer command_buffer);
|
||||
|
||||
PTK_OPTION(VkImageView) vk_create_image_view(VkImage image, VkFormat format);
|
||||
|
||||
void vk_update_descriptor_sets(void);
|
||||
|
||||
void vk_cleanup(void);
|
||||
|
||||
#endif // PTK_PTK_VK_INIT_H_
|
||||
|
|
Loading…
Reference in a new issue