diff options
author | Omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-03-31 22:08:05 +1100 |
---|---|---|
committer | Omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-03-31 22:08:05 +1100 |
commit | b771fc06a4339f466c0864ad896d5a96aee7e35d (patch) | |
tree | f667213fe01155e1ed56bc606a02e0f7c546fab5 | |
parent | 1b4c27d514423c9e27a93742b8c8e9eb9f588e27 (diff) |
adding image creation for textures
-rw-r--r-- | src/maths/primitives.h | 24 | ||||
-rw-r--r-- | src/renderer/backends/backend_opengl.c | 23 | ||||
-rw-r--r-- | src/renderer/backends/backend_vulkan.c | 134 | ||||
-rw-r--r-- | src/renderer/render.c | 23 | ||||
-rw-r--r-- | src/renderer/render.h | 1 | ||||
-rw-r--r-- | src/renderer/render_backend.h | 1 | ||||
-rw-r--r-- | src/renderer/render_types.h | 3 |
7 files changed, 159 insertions, 50 deletions
diff --git a/src/maths/primitives.h b/src/maths/primitives.h index 77dbbae..4fb6b4d 100644 --- a/src/maths/primitives.h +++ b/src/maths/primitives.h @@ -22,36 +22,36 @@ static mesh prim_cube_mesh_create() { // back faces vertex_darray_push( cube.vertices, - (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); vertex_darray_push( cube.vertices, - (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 0 } }); vertex_darray_push( cube.vertices, - (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); vertex_darray_push( cube.vertices, - (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); vertex_darray_push( cube.vertices, - (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1,1 } }); vertex_darray_push( cube.vertices, - (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); // front faces vertex_darray_push(cube.vertices, - (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1} }); vertex_darray_push(cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); vertex_darray_push(cube.vertices, - (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 0} }); vertex_darray_push(cube.vertices, - (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } }); vertex_darray_push(cube.vertices, - (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 1 } }); vertex_darray_push(cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 0 } }); + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); // top faces vertex_darray_push(cube.vertices, diff --git a/src/renderer/backends/backend_opengl.c b/src/renderer/backends/backend_opengl.c index ea6cb00..a9f7482 100644 --- a/src/renderer/backends/backend_opengl.c +++ b/src/renderer/backends/backend_opengl.c @@ -60,6 +60,29 @@ void clear_screen(vec3 colour) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } +void texture_data_upload(texture* tex) { + printf("Texture name %s\n", tex->name); + TRACE("Upload texture data"); + u32 texture_id; + glGenTextures(1, &texture_id); + glBindTexture(GL_TEXTURE_2D, texture_id); + tex->texture_id = texture_id; + + // set the texture wrapping parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex->width, tex->height, 0, tex->channel_type, + GL_UNSIGNED_BYTE, tex->image_data); + glGenerateMipmap(GL_TEXTURE_2D); + DEBUG("Freeing texture image data after uploading to GPU"); + // stbi_image_free(tex->image_data); // data is on gpu now so we dont need it around +} + void bind_texture(shader s, texture *tex, u32 slot) { // printf("bind texture slot %d with texture id %d \n", slot, tex->texture_id); glActiveTexture(GL_TEXTURE0 + slot); diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index d149e15..9d0ef51 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -6,7 +6,6 @@ // ^ Temporary #include <assert.h> -#include <stdatomic.h> #include <stdbool.h> #include <stdint.h> #include <string.h> @@ -64,6 +63,11 @@ typedef struct vulkan_image { u32 height; } vulkan_image; +typedef struct vulkan_texture_data { + vulkan_image image; + VkSampler sampler; +} vulkan_texture_data; + typedef enum vulkan_renderpass_state { READY, RECORDING, @@ -863,6 +867,67 @@ void vulkan_image_view_create(vulkan_context* context, VkFormat format, vulkan_i &image->view); } +void vulkan_image_transition_layout( + vulkan_context* context, + vulkan_command_buffer* command_buffer, + vulkan_image* image, + VkFormat format, + VkImageLayout old_layout, + VkImageLayout new_layout +) { + VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER}; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = context->device.graphics_queue_index; + barrier.dstQueueFamilyIndex = context->device.graphics_queue_index; + barrier.image = image->handle; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.srcAccessMask = 0; + barrier.dstAccessMask = 0; + + VkPipelineStageFlags source_stage; + VkPipelineStageFlags dest_stage; + + if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dest_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + } else if (old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dest_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } else { + FATAL("Unsupported image layout transition"); + return; + } + + vkCmdPipelineBarrier(command_buffer->handle, source_stage, dest_stage, 0, 0, 0, 0, 0, 1, &barrier); +} + +void vulkan_image_copy_from_buffer( + vulkan_image* image, + VkBuffer buffer, + vulkan_command_buffer* command_buffer +) { + VkBufferImageCopy region; + region.bufferOffset = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = image->width; + region.imageExtent.height = image->height; + region.imageExtent.depth = 1; + + vkCmdCopyBufferToImage(command_buffer->handle, buffer, image->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); +} + void vulkan_image_create(vulkan_context* context, VkImageType image_type, u32 width, u32 height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags memory_flags, bool create_view, @@ -1584,8 +1649,6 @@ bool gfx_backend_init(renderer* ren) { mesh cube = prim_cube_mesh_create(); - // const u32 vert_count = 36; - vertex_pos* verts = malloc(sizeof(vertex_pos) * cube.vertices->len); f32 scale = 3.0; @@ -1620,6 +1683,8 @@ bool gfx_backend_init(renderer* ren) { upload_data_range(&context, context.device.gfx_command_pool, 0, context.device.graphics_queue, &context.object_index_buffer, 0, sizeof(u32) * cube.indices_len, cube.indices); TRACE("Uploaded index data"); + vertex_darray_free(cube.vertices); + free(cube.indices); // --- End test code INFO("Vulkan renderer initialisation succeeded"); @@ -1679,21 +1744,64 @@ void backend_begin_frame(renderer* ren, f32 delta_time) { vulkan_renderpass_begin(command_buffer, &context.main_renderpass, context.swapchain.framebuffers->data[context.image_index].handle); +} - // TODO: temp test code - // vulkan_object_shader_use(&context, &context.object_shader); - - // VkDeviceSize offsets[1] = { 0 }; - // vkCmdBindVertexBuffers(command_buffer->handle, 0, 1, &context.object_vertex_buffer.handle, - // (VkDeviceSize*)offsets); +void texture_data_upload(texture* tex) { + printf("Texture name %s\n", tex->name); + tex->backend_data = malloc(sizeof(vulkan_texture_data)); + vulkan_texture_data* data = (vulkan_texture_data*)tex->backend_data; + VkDeviceSize image_size = tex->width * tex->height * tex->channel_count; - // vkCmdBindIndexBuffer(command_buffer->handle, context.object_index_buffer.handle, 0, - // VK_INDEX_TYPE_UINT32); + VkFormat image_format = VK_FORMAT_R8G8B8A8_SNORM; - // vkCmdDrawIndexed(command_buffer->handle, 6, 1, 0, 0, 0); - // --- End temp test code + VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + VkMemoryPropertyFlags memory_prop_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + vulkan_buffer staging; + vulkan_buffer_create(&context, image_size, usage, memory_prop_flags, true, &staging); + vulkan_buffer_load_data(&context, &staging, 0, image_size, 0, tex->image_data); + + vulkan_image_create(&context, VK_IMAGE_TYPE_2D, tex->width, tex->height, image_format, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true, VK_IMAGE_ASPECT_COLOR_BIT, &data->image); + + vulkan_command_buffer temp_buffer; + vulkan_command_buffer_allocate_and_begin_oneshot(&context, context.device.gfx_command_pool, &temp_buffer); + + vulkan_image_transition_layout(&context, &temp_buffer, &data->image, image_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vulkan_image_copy_from_buffer(&data->image, staging.handle, &temp_buffer); + + vulkan_image_transition_layout(&context, &temp_buffer, &data->image, image_format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + vulkan_command_buffer_end_oneshot(&context, context.device.gfx_command_pool, &temp_buffer, context.device.graphics_queue); + + VkSamplerCreateInfo sampler_info = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; + sampler_info.magFilter = VK_FILTER_LINEAR; + sampler_info.minFilter = VK_FILTER_LINEAR; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.anisotropyEnable = VK_TRUE; + sampler_info.maxAnisotropy = 16; + sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + sampler_info.unnormalizedCoordinates = VK_FALSE; + sampler_info.compareEnable = VK_FALSE; + sampler_info.compareOp = VK_COMPARE_OP_ALWAYS; + sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + sampler_info.mipLodBias = 0.0; + sampler_info.minLod = 0.0; + sampler_info.maxLod = 0.0; + + VkResult res = vkCreateSampler(context.device.logical_device, &sampler_info, context.allocator, &data->sampler); + if (res != VK_SUCCESS) { + ERROR("Error creating texture sampler for image %s", tex->name); + return; + } + } +// TODO: destroy texture + void backend_end_frame(renderer* ren, f32 delta_time) { vulkan_command_buffer* command_buffer = &context.gfx_command_buffers->data[context.image_index]; diff --git a/src/renderer/render.c b/src/renderer/render.c index 54b63b6..9dc47c2 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -247,29 +247,6 @@ texture texture_data_load(const char* path, bool invert_y) { .image_data = data }; } -void texture_data_upload(texture* tex) { - printf("Texture name %s\n", tex->name); - TRACE("Upload texture data"); - u32 texture_id; - glGenTextures(1, &texture_id); - glBindTexture(GL_TEXTURE_2D, texture_id); - tex->texture_id = texture_id; - - // set the texture wrapping parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - // set texture filtering parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex->width, tex->height, 0, tex->channel_type, - GL_UNSIGNED_BYTE, tex->image_data); - glGenerateMipmap(GL_TEXTURE_2D); - DEBUG("Freeing texture image data after uploading to GPU"); - // stbi_image_free(tex->image_data); // data is on gpu now so we dont need it around -} - void dir_light_upload_uniforms(shader shader, directional_light* light) { uniform_vec3f(shader.program_id, "dirLight.direction", &light->direction); uniform_vec3f(shader.program_id, "dirLight.ambient", &light->ambient); diff --git a/src/renderer/render.h b/src/renderer/render.h index 6cd9701..b6dad00 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -37,4 +37,3 @@ void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* vie // --- texture texture_data_load(const char* path, bool invert_y); // #frontend -void texture_data_upload(texture* tex); // #backend diff --git a/src/renderer/render_backend.h b/src/renderer/render_backend.h index ea84b27..af62f9f 100644 --- a/src/renderer/render_backend.h +++ b/src/renderer/render_backend.h @@ -19,6 +19,7 @@ void gfx_backend_update_global_state(mat4 projection, mat4 view, vec3 view_pos, void clear_screen(vec3 colour); +void texture_data_upload(texture* tex); void bind_texture(shader s, texture* tex, u32 slot); void bind_mesh_vertex_buffer(void* backend, mesh* mesh); void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count); diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 2cc321c..80e1372 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -52,7 +52,8 @@ typedef struct renderer { typedef struct texture { u32 texture_id; char name[MAX_TEXTURE_NAME_LEN]; - void *image_data; + void* image_data; + void* backend_data; u32 width; u32 height; u8 channel_count; |