Add textures

Textures supported
This commit is contained in:
Piotr Krygier committed 2023-10-03 09:00:02 +02:00
1 parent 4fcda01ba2
commit 548ed57969
11 files changed
+183 -76

No files matched your search

+4 -2
View File
@@ -1,12 +1,14 @@
#version 450
layout(binding = 1) uniform sampler2D texSampler;
/* Each time texture count is changed this value also need to change. I have to fix it somehow. */
layout(binding = 1) uniform sampler2D texSampler[1];
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
layout(location = 2) in flat uint instanceTextureId;
layout(location = 0) out vec4 outColor;
void main() {
outColor = texture(texSampler, fragTexCoord);
outColor = vec4(fragColor * texture(texSampler[instanceTextureId], fragTexCoord).rgb, 1.0);
}
+4
View File
@@ -13,9 +13,12 @@ layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in vec3 instancePosition;
layout(location = 4) in vec3 instanceRotation;
layout(location = 5) in float instanceScale;
layout(location = 6) in uint instanceTextureId;
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
layout(location = 2) out uint outInstanceTextureId;
void main()
{
@@ -62,4 +65,5 @@ void main()
fragColor = inColor;
fragTexCoord = inTexCoord;
outInstanceTextureId = instanceTextureId;
}
+14 -4
View File
@@ -38,11 +38,14 @@ void rse_graphics_deinit()
uint8_t rse_graphics_run(void)
{
int8_t tex_id_2 = 0;
window_init();
if (0 != init_vulkan())
if (0 != preinit_vulkan())
return -1;
tex_id_2 = rse_load_texture("../../test_image.png");
// FIXME: Temporary array of vertices, for testing purposes
struct rse_vertex_t vertices[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
@@ -60,22 +63,29 @@ uint8_t rse_graphics_run(void)
create_mesh_instance(mesh_id, (struct rse_instance_data_t){
{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, rse_math_deg_to_radians(45.0f)},
1.0f
1.0f,
tex_id_2
});
create_mesh_instance(mesh_id, (struct rse_instance_data_t){
{-1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f},
1.0f
1.0f,
tex_id_2
});
mesh_id = create_mesh(vertices2, indices, 8, 6);
create_mesh_instance(mesh_id, (struct rse_instance_data_t){
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, rse_math_deg_to_radians(0.0f)},
1.0f
1.0f,
tex_id_2
});
if (0 != init_vulkan())
return -1;
window_loop();
deinit_vulkan();
+31 -9
View File
@@ -90,7 +90,7 @@ static VkDeviceSize format_to_pixel_size(VkFormat format)
}
static uint8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat format, unsigned char* pixels)
static int8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat format, unsigned char* pixels)
{
struct rse_vulkan_buffer_t staging_buffer = {0};
VkDeviceSize staging_buffer_size = 0U;
@@ -116,7 +116,7 @@ static uint8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat for
/* Check if we found free image handle */
if (free_texture_image == NULL) {
LOGE("Failed to find free texture image handle");
return 1;
return -1;
}
staging_buffer_size = width * height * format_to_pixel_size(format);
@@ -157,7 +157,7 @@ static uint8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat for
&free_texture_image->allocation,
&free_texture_image->allocation_info)) {
LOGF("Failed to create image");
return 1;
return -1;
}
/* Put image into correct layout to copy pixels from buffer to image memory */
@@ -199,7 +199,7 @@ static uint8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat for
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
&staging_buffer)) {
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
return -1;
}
memcpy(staging_buffer.allocation_info.pMappedData, pixels, staging_buffer_size);
@@ -264,11 +264,11 @@ static uint8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat for
NULL,
&free_texture_image->image_view)) {
LOGF("Failed to create image view");
return 1;
return -1;
}
free_texture_image->id_taken = IMAGE_TAKEN;
return VULKAN_ERROR_NO_ERROR;
return i;
}
uint8_t init_vulkan_images()
@@ -282,29 +282,33 @@ uint8_t init_vulkan_images()
return status;
}
void rse_load_texture(const char* file_path)
int8_t rse_load_texture(const char* file_path)
{
int width = 0;
int height = 0;
int channels = 0;
stbi_uc* pixel_buffer = NULL;
int8_t ret;
pixel_buffer = stbi_load(file_path, &width, &height, &channels, STBI_rgb_alpha);
if (pixel_buffer == NULL) {
LOGE("Failed to load texture from file: %s", file_path);
return;
return -1;
}
/* Create actual Vulkan Image */
create_vulkan_image(width,
ret = create_vulkan_image(width,
height,
VK_FORMAT_R8G8B8A8_SRGB,
pixel_buffer);
stbi_image_free(pixel_buffer);
return ret;
}
void rse_destroy_textures()
@@ -321,6 +325,10 @@ void rse_destroy_textures()
}
}
int8_t image_exists(uint8_t image_id) {
return g_texture_images[image_id].id_taken == IMAGE_TAKEN;
}
VkImageView rse_get_image_view(size_t image_id)
{
return g_texture_images[image_id].image_view;
@@ -329,4 +337,18 @@ VkImageView rse_get_image_view(size_t image_id)
VkSampler rse_get_texture_sampler()
{
return g_sampler;
}
size_t get_textures_count()
{
size_t count = 0U;
size_t i = 0U;
for (i = 0U; i < RSE_MAX_IMAGE_COUNT; ++i) {
if(g_texture_images[i].id_taken == IMAGE_TAKEN) {
count++;
}
}
return count;
}
+46 -1
View File
@@ -18,16 +18,61 @@
#include <stdint.h>
/**
* @brief Maximum number of textures that can be loaded
*
*/
#define RSE_MAX_IMAGE_COUNT 256
/**
* @brief Initialize vulkan with image views and stuff
*
* @return uint8_t VULKAN_ERROR_NO_ERROR on success
*/
uint8_t init_vulkan_images(void);
void rse_load_texture(const char* path);
/**
* @brief Loads image from file, for later to be uysed as a texture
*
* @param path Path to texture file
* @return int8_t -1 on error. Texture ID on success
*/
int8_t rse_load_texture(const char* path);
/**
* @brief Destroy all loaded textures. Usefull for closing application or just clearing.
*
*/
void rse_destroy_textures(void);
/**
* @brief Returns image view for provided image id
*
* @param image_id image id
* @return VkImageView Found image view.
*/
VkImageView rse_get_image_view(size_t image_id);
/**
* @brief Returns sampler
*
* @return VkSampler Sampler object
*/
VkSampler rse_get_texture_sampler();
/**
* @brief Checks if image exists for provided image ID.
*
* @param image_id Image ID
* @return int8_t 1 on success, 0 on failure
*/
int8_t image_exists(uint8_t image_id);
/**
* @brief Returns number of loaded texture
*
* @return size_t Texture count
*/
size_t get_textures_count();
#endif /* RSE_TEXTURE_H */
+9 -13
View File
@@ -550,7 +550,7 @@ uint8_t create_sync_objects()
}
uint8_t init_vulkan()
uint8_t preinit_vulkan()
{
uint8_t status = VULKAN_ERROR_NO_ERROR;
@@ -563,25 +563,21 @@ uint8_t init_vulkan()
STATUS_CHECK(pick_physical_device());
STATUS_CHECK(create_device());
STATUS_CHECK(create_memory_allocator());
STATUS_CHECK(create_pipeline());
STATUS_CHECK(init_commands());
STATUS_CHECK(create_buffers());
STATUS_CHECK(init_vulkan_images());
//FIXME: Images have to be add after vulkan initialization but before creating descriptors.
// I have to fix it somehow to be able to add textures from anywhere in the code in some initialization step
// at the beginnning.
rse_load_texture("../../miotacz_piorunów.png");
return status;
}
uint8_t init_vulkan()
{
uint8_t status = VULKAN_ERROR_NO_ERROR;
STATUS_CHECK(create_pipeline());
STATUS_CHECK(create_descriptors());
STATUS_CHECK(create_sync_objects());
rse_init_time();
return status;
}
+9 -1
View File
@@ -19,7 +19,15 @@
#include "vulkan_commons.h"
/**
* @brief Initialize Vulkan backend
* @brief Initialize Vulkan backend for buffers and stuff
*
* @param state
* @return uint8_t 0 on success. Status code on failure
*/
uint8_t preinit_vulkan();
/**
* @brief Initialize Vulkan backend with descriptors
*
* @param state
* @return uint8_t 0 on success. Status code on failure
+1
View File
@@ -78,6 +78,7 @@ struct rse_instance_data_t {
struct vec3_t pos;
struct vec3_t rot;
float scale;
uint8_t texture_id;
};
void rse_init_time();
+15 -8
View File
@@ -27,8 +27,8 @@ uint8_t create_descriptor_pool()
pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
pool_sizes[0].descriptorCount = (uint32_t)(SWAP_BUFFER_COUNT);
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
pool_sizes[1].descriptorCount = (uint32_t)(SWAP_BUFFER_COUNT);
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
pool_sizes[1].descriptorCount = (uint32_t)(SWAP_BUFFER_COUNT*get_textures_count());
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.poolSizeCount = 2;
@@ -69,15 +69,22 @@ uint8_t create_descriptor_sets()
for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) {
VkDescriptorBufferInfo buffer_info = {};
VkWriteDescriptorSet descriptor_writes[2] = {};
VkDescriptorImageInfo image_info = {};
VkDescriptorImageInfo image_infos[RSE_MAX_IMAGE_COUNT] = {};
size_t image_iterator = 0U;
size_t image_info_iterator = 0U;
buffer_info.buffer = g_vulkan_state.uniform_buffers[i].buffer;
buffer_info.offset = 0;
buffer_info.range = sizeof(struct rse_uniform_buffer_object_t);
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
image_info.imageView = rse_get_image_view(0);
image_info.sampler = rse_get_texture_sampler();
for (image_iterator = 0U; image_iterator < RSE_MAX_IMAGE_COUNT; ++image_iterator) {
if (image_exists(image_iterator)) {
image_infos[image_info_iterator].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
image_infos[image_info_iterator].imageView = rse_get_image_view(image_iterator);
image_infos[image_info_iterator].sampler = rse_get_texture_sampler();
image_info_iterator++;
}
}
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_writes[0].dstSet = g_vulkan_state.descriptor_sets[i];
@@ -92,8 +99,8 @@ uint8_t create_descriptor_sets()
descriptor_writes[1].dstBinding = 1;
descriptor_writes[1].dstArrayElement = 0;
descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptor_writes[1].descriptorCount = 1;
descriptor_writes[1].pImageInfo = &image_info;
descriptor_writes[1].descriptorCount = image_info_iterator;
descriptor_writes[1].pImageInfo = image_infos;
vkUpdateDescriptorSets(g_vulkan_state.device, 2, descriptor_writes, 0, NULL);
}
+50 -38
View File
@@ -5,6 +5,7 @@
#include "utilities/logger.h"
#include "vulkan_errors.h"
#include "mesh_controller.h"
#include "rse_vulkan_image.h"
#include "vulkan/vulkan.h"
@@ -72,24 +73,24 @@ static VkVertexInputBindingDescription get_binding_description()
static VkVertexInputAttributeDescription* get_attribute_descriptions()
{
static VkVertexInputAttributeDescription attributeDescriptions[3];
static VkVertexInputAttributeDescription attribute_descriptions[3];
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0; /* inPosition in shader.vert */
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(struct rse_vertex_t, pos);
attribute_descriptions[0].binding = 0;
attribute_descriptions[0].location = 0; /* inPosition in shader.vert */
attribute_descriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attribute_descriptions[0].offset = offsetof(struct rse_vertex_t, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1; /* inColor in shader.vert */
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(struct rse_vertex_t, color);
attribute_descriptions[1].binding = 0;
attribute_descriptions[1].location = 1; /* inColor in shader.vert */
attribute_descriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attribute_descriptions[1].offset = offsetof(struct rse_vertex_t, color);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2; /* inTexCoords in shader.vert */
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(struct rse_vertex_t, tex_coords);
attribute_descriptions[2].binding = 0;
attribute_descriptions[2].location = 2; /* inTexCoords in shader.vert */
attribute_descriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attribute_descriptions[2].offset = offsetof(struct rse_vertex_t, tex_coords);
return attributeDescriptions;
return attribute_descriptions;
}
/**
@@ -266,6 +267,7 @@ uint8_t create_descriptor_set_layout()
VkDescriptorSetLayoutBinding bindings[2];
VkDescriptorSetLayoutBinding ubo_layout_binding = {};
VkDescriptorSetLayoutBinding sampler_layout_binding = {};
// VkDescriptorSetLayoutBinding textures_layout_binding = {};
ubo_layout_binding.binding = 0;
ubo_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@@ -275,12 +277,13 @@ uint8_t create_descriptor_set_layout()
sampler_layout_binding.binding = 1;
sampler_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
sampler_layout_binding.descriptorCount = 1;
sampler_layout_binding.descriptorCount = get_textures_count();
sampler_layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
sampler_layout_binding.pImmutableSamplers = NULL;
bindings[0] = ubo_layout_binding;
bindings[1] = sampler_layout_binding;
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layout_info.pNext = NULL;
layout_info.flags = 0U;
@@ -549,45 +552,54 @@ void free_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_
*/
void fill_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_info)
{
const size_t binding_descriptions_count = 2;
const size_t attribute_descriptions_count = 7;
/* This is clusterfuck with some magic numbers here and there and unneeded malloc and memcpy stuff. Change,
* so you won't feel ashamed. */
VkVertexInputBindingDescription vertex_binding_description = get_binding_description();
VkVertexInputAttributeDescription* vertex_attribute_descriptions = get_attribute_descriptions();
VkVertexInputBindingDescription* bindingDescriptions = malloc(sizeof(VkVertexInputBindingDescription) * 2);
VkVertexInputAttributeDescription* attributeDescriptions = malloc(sizeof(VkVertexInputAttributeDescription) * 6);
VkVertexInputBindingDescription* binding_descriptions = malloc(sizeof(VkVertexInputBindingDescription)
* binding_descriptions_count);
VkVertexInputAttributeDescription* attribute_descriptions = malloc(sizeof(VkVertexInputAttributeDescription)
* attribute_descriptions_count);
bindingDescriptions[0] = vertex_binding_description;
binding_descriptions[0] = vertex_binding_description;
bindingDescriptions[1].binding = 1;
bindingDescriptions[1].stride = sizeof(struct rse_instance_data_t); //TODO: change
bindingDescriptions[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
binding_descriptions[1].binding = 1;
binding_descriptions[1].stride = sizeof(struct rse_instance_data_t); //TODO: change
binding_descriptions[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
memcpy(attributeDescriptions, vertex_attribute_descriptions, sizeof(VkVertexInputAttributeDescription) * 3);
memcpy(attribute_descriptions, vertex_attribute_descriptions, sizeof(VkVertexInputAttributeDescription) * 3);
attributeDescriptions[3].binding = 1;
attributeDescriptions[3].location = 3;
attributeDescriptions[3].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[3].offset = offsetof(struct rse_instance_data_t, pos);
attribute_descriptions[3].binding = 1;
attribute_descriptions[3].location = 3;
attribute_descriptions[3].format = VK_FORMAT_R32G32B32_SFLOAT;
attribute_descriptions[3].offset = offsetof(struct rse_instance_data_t, pos);
attributeDescriptions[4].binding = 1;
attributeDescriptions[4].location = 4;
attributeDescriptions[4].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[4].offset = offsetof(struct rse_instance_data_t, rot);
attribute_descriptions[4].binding = 1;
attribute_descriptions[4].location = 4;
attribute_descriptions[4].format = VK_FORMAT_R32G32B32_SFLOAT;
attribute_descriptions[4].offset = offsetof(struct rse_instance_data_t, rot);
attributeDescriptions[5].binding = 1;
attributeDescriptions[5].location = 5;
attributeDescriptions[5].format = VK_FORMAT_R32_SFLOAT;
attributeDescriptions[5].offset = offsetof(struct rse_instance_data_t, scale);
attribute_descriptions[5].binding = 1;
attribute_descriptions[5].location = 5;
attribute_descriptions[5].format = VK_FORMAT_R32_SFLOAT;
attribute_descriptions[5].offset = offsetof(struct rse_instance_data_t, scale);
attribute_descriptions[6].binding = 1;
attribute_descriptions[6].location = 6;
attribute_descriptions[6].format = VK_FORMAT_R8_UINT;
attribute_descriptions[6].offset = offsetof(struct rse_instance_data_t, texture_id);
// ************************
vertex_input_info->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_input_info->pNext = NULL;
vertex_input_info->flags = 0U;
vertex_input_info->vertexBindingDescriptionCount = 2U;
vertex_input_info->pVertexBindingDescriptions = bindingDescriptions;
vertex_input_info->vertexAttributeDescriptionCount = 6U;
vertex_input_info->pVertexAttributeDescriptions = attributeDescriptions;
vertex_input_info->vertexBindingDescriptionCount = binding_descriptions_count;
vertex_input_info->pVertexBindingDescriptions = binding_descriptions;
vertex_input_info->vertexAttributeDescriptionCount = attribute_descriptions_count;
vertex_input_info->pVertexAttributeDescriptions = attribute_descriptions;
}
/**