summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-04-27 10:26:46 +1000
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-04-27 10:26:46 +1000
commit7a8d93d2b867cab853ecf8c4ec5061cdc5cab665 (patch)
tree2ff71fd92e1985e682402aaf9807ac0eb2bdbbc8
parent1a55bc92eaae3509a18e468198772b8888397492 (diff)
parentb771fc06a4339f466c0864ad896d5a96aee7e35d (diff)
Merge branch 'cleanroom-vulkan' into ral
-rw-r--r--src/maths/primitives.h24
-rw-r--r--src/renderer/backends/backend_opengl.c23
-rw-r--r--src/renderer/backends/backend_vulkan.c134
-rw-r--r--src/renderer/render.c23
-rw-r--r--src/renderer/render.h1
-rw-r--r--src/renderer/render_backend.h1
-rw-r--r--src/renderer/render_types.h3
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, &region);
+}
+
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 d8425ef..cbf9d36 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;