I did the thing, I moved all textures into one big descriptor array. Now each frame looks up a texture in an array. But this has absolutely destroyed performance

This commit is contained in:
Андреев Григорий 2026-02-14 22:35:47 +03:00
parent 2367ce1e9d
commit 15089cf7b5
5 changed files with 346 additions and 351 deletions

View File

@ -16,7 +16,6 @@ void generate_code_for_alice_on_l1(){
generate_eve_span_company_for_primitive(l, ns, cstr("RefAliceTextureUplOnce"), true, false);
/* Engine stuff */
// todo: yes, maybe right now it is not primitive but I surely will make it primitive someday. Right now I don't care
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){
.T = cstr("AliceGenericMeshHand"), .t_primitive = true}, true);
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){
@ -28,4 +27,6 @@ void generate_code_for_alice_on_l1(){
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("GenericMeshTopology")
});
generate_eve_span_company_for_primitive(l, ns, cstr("AliceTextureSlot"), true, false);
}

View File

@ -34,7 +34,6 @@ GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) {
/* non-primitive */
typedef struct {
VecU8 diffuse_texture_path;
VecU8 normal_texture_path;
VecU8 specular_texture_path;
} AliceGenericMeshTexturePaths;

View File

@ -6,31 +6,15 @@
#include "transfer_in_mainloop.h"
#include "../lucy/glyph_render.h"
typedef struct {
/* Each generic model has its own descriptor set
* It's because it has its own textures. But it also has copies of references to light UBO
* Because I am to lazy to create two set layouts for generic model pipeline */
VkDescriptorSet p_0a_set_1;
} AliceGenericMeshMemDependantVkObj;
typedef struct {
size_t indexes;
// todo: replace TextureDataXXX with MargaretPngPromises
TextureDataR8G8B8A8 pixels_diffuse;
TextureDataR8G8B8A8 pixels_normal;
TextureDataR8 pixels_specular;
MargaretSubbuf vbo;
MargaretSubbuf ebo;
MargaretTexture diffuse_texture;
MargaretTexture normal_texture;
MargaretTexture specular_texture;
PatriciaBuf instance_attr;
AliceGenericMeshMemDependantVkObj mem_dependant_vk_obj;
U32 diffuse_tex_slot, normal_tex_slot, specular_tex_slot;
} AliceGenericMeshHand;
#include "../../../gen/l1/eve/alice/ListAliceGenericMeshHand.h"
@ -174,6 +158,9 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_
return render_pass;
}
#define ALICE_MAX_TEXTURES_COUNT 600
VkDescriptorSetLayout alice_create_pipline0_desc_set0_layout(VkDevice device) {
VkDescriptorSetLayout pipeline0_desc_set0_layout;
check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){
@ -196,50 +183,43 @@ VkDescriptorSetLayout alice_create_pipline0_desc_set0_layout(VkDevice device) {
return pipeline0_desc_set0_layout;
}
VkDescriptorSetLayout alice_create_pipeline0_desc_set1_layout(VkDevice device, U32 max_textures_cnt) {
VkDescriptorSetLayout pipeline0_desc_set0_layout;
check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = &(VkDescriptorSetLayoutBindingFlagsCreateInfo){
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
.bindingCount = 1,
.pBindingFlags = (VkDescriptorBindingFlags[]){ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT }
},
.bindingCount = 1,
.pBindings = (VkDescriptorSetLayoutBinding[]){
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = max_textures_cnt,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
}
},
}, NULL, &pipeline0_desc_set0_layout) == VK_SUCCESS);
return pipeline0_desc_set0_layout;
}
typedef struct {
VkPipelineLayout pipeline_layout;
VkPipeline pipeline;
VkDescriptorSetLayout desc_set_0b1_layout;
} AlicePipeline0a;
void AlicePipeline0a_destroy(VkDevice device, AlicePipeline0a hands) {
vkDestroyPipeline(device, hands.pipeline, NULL);
vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL);
vkDestroyDescriptorSetLayout(device, hands.desc_set_0b1_layout, NULL);
}
AlicePipeline0a create_graphics_pipeline_0a(
VkDevice device, SpanU8 root_dir, VkDescriptorSetLayout pipline0_desc_set0_layout,
VkDevice device, SpanU8 root_dir,
VkDescriptorSetLayout pipline0_desc_set0_layout, VkDescriptorSetLayout pipeline0_desc_set1_layout,
VkRenderPass render_pass, uint32_t subpass
) {
VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = {
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
},
{
.binding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
},
{
.binding = 2,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
},
};
VkDescriptorSetLayoutCreateInfo descriptor_set_layout_crinfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout),
.pBindings = bindings_for_my_descr_set_layout,
};
VkDescriptorSetLayout my_descriptor_set_layout;
check(vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) == VK_SUCCESS);
VkPushConstantRange pc_ranges[] = {
{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
@ -247,13 +227,16 @@ AlicePipeline0a create_graphics_pipeline_0a(
}, {
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = sizeof(mat4), .size = sizeof(vec3)
},
}, {
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = sizeof(mat4) + sizeof(vec3), .size = sizeof(U32) * 3
}
};
VkPipelineLayoutCreateInfo layout_crinfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 2,
.pSetLayouts = (VkDescriptorSetLayout[]){pipline0_desc_set0_layout, my_descriptor_set_layout},
.pSetLayouts = (VkDescriptorSetLayout[]){pipline0_desc_set0_layout, pipeline0_desc_set1_layout},
.pushConstantRangeCount = ARRAY_SIZE(pc_ranges),
.pPushConstantRanges = pc_ranges,
};
@ -338,8 +321,7 @@ AlicePipeline0a create_graphics_pipeline_0a(
.vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), vertex_attributes,
.depthTestEnable = true, .depthWriteEnable = true, .blendEnable = false
});
return (AlicePipeline0a){.pipeline_layout = pipeline_layout, .pipeline = pipeline,
.desc_set_0b1_layout = my_descriptor_set_layout};
return (AlicePipeline0a){.pipeline_layout = pipeline_layout, .pipeline = pipeline};
}
typedef struct {
@ -696,7 +678,7 @@ float AliceWaylandApp_get_elapsed_time(const AliceWaylandApp* self){
}
/* They are actually MutRef, but who cares lol, we won't have such distinction here anytime soon, so we shorten
* it to Ref (whil keeping in kind that it is actually MutRef)
* it to Ref (while keeping in kind that it is actually MutRef). Also, these lines do nothing useful
*/
typedef struct ListNodeAliceGenericMeshHand* RefListNodeAliceGenericMeshHand;
#include "../../../gen/l1/eve/alice/VecRefListNodeAliceGenericMeshHand.h"
@ -704,6 +686,12 @@ typedef struct ListNodeAliceGenericMeshHand* RefListNodeAliceGenericMeshHand;
typedef struct ListNodeAliceShinyMeshHand* RefListNodeAliceShinyMeshHand;
#include "../../../gen/l1/eve/alice/VecRefListNodeAliceShinyMeshHand.h"
typedef struct {
bool is_some;
MargaretTexture tex;
} AliceTextureSlot;
#include "../../../gen/l1/eve/alice/VecAliceTextureSlot.h"
struct Alice {
AliceCallbacks callbacks;
@ -721,6 +709,8 @@ struct Alice {
VkRenderPass render_pass_0;
// One descriptor set found in all shaders of pipeline0
VkDescriptorSetLayout pipeline0_desc_set0_layout;
// This one contains textures
VkDescriptorSetLayout pipeline0_desc_set1_layout;
// Features it's own descriptor set layout + built on top of pipeline0_desc_set0_layout
AlicePipeline0a pipeline_hands_0a;
// No personal descriptor set layouts (though it borrows pipeline0_desc_set0_layout)
@ -747,6 +737,8 @@ struct Alice {
Abigail abigail;
AlicePipline0LightConf pipeline0_light_conf;
VecAliceTextureSlot texture_slots;
ListAliceGenericMeshHand generic_models;
ListAliceShinyMeshHand shiny_models;
AliceCamVerticalControl cam_info;
@ -764,7 +756,8 @@ struct Alice {
VkImageView zbuffer_view;
VkImageView IT1_view;
VkFramebuffer IT1_framebuffer;
VkDescriptorSet descriptor_set_for_pipeline_0;
VkDescriptorSet descriptor_set0_for_pipeline_0;
VkDescriptorSet descriptor_set1_for_pipeline_0;
VkDescriptorSet descriptor_set_for_pipeline_1;
/* You see, there are two places when user can write to transfer_command_buffer: When Alice is initialized, but
@ -775,274 +768,6 @@ struct Alice {
bool transfer_command_buf_already_reset;
};
ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const GenericMeshTopology* topology,
AliceGenericMeshTexturePaths t_paths
){
ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand));
AliceGenericMeshHand* mm = &mm_node->el;
mm->indexes = topology->indexes.len;
mm->instance_attr.count = 0;
mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 200);
mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 200);
// todo: change this, I don't like this at all :(
mm->pixels_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&t_paths.diffuse_texture_path));
mm->pixels_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&t_paths.normal_texture_path));
mm->pixels_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&t_paths.specular_texture_path));
VecU8_drop(t_paths.diffuse_texture_path);
VecU8_drop(t_paths.normal_texture_path);
VecU8_drop(t_paths.specular_texture_path);
GenericMeshVertex* staging_vbo;
mm->vbo = Abigail_register_new_buffer(&alice->abigail,
topology->vertices.len * sizeof(GenericMeshVertex),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_vbo /* We return values here */);
U32* staging_ebo;
mm->ebo = Abigail_register_new_buffer(&alice->abigail,
topology->indexes.len * sizeof(U32),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_ebo /* We return values here */);
void* diffuse_tex_staging;
mm->diffuse_texture = Abigail_register_new_texture(&alice->abigail,
mm->pixels_diffuse.width, mm->pixels_diffuse.height,
sizeof(cvec4), VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images,
&diffuse_tex_staging);
void *normal_tex_staging;
mm->normal_texture = Abigail_register_new_texture(&alice->abigail,
mm->pixels_normal.width, mm->pixels_normal.height,
sizeof(cvec4), VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images,
&normal_tex_staging);
void* specular_tex_staging;
mm->specular_texture = Abigail_register_new_texture(&alice->abigail,
mm->pixels_specular.width, mm->pixels_specular.height,
sizeof(U8), VK_FORMAT_R8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images,
&specular_tex_staging);
assert(mm->vbo.len >= topology->vertices.len * sizeof(GenericMeshVertex));
/* We allocated enough memory, but now it's time to actually fill staging buffers */
/* Filling staging VBO */
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
assert(topology->indexes.len % 3 == 0);
for (size_t ti = 0; ti * 3 < topology->indexes.len; ti++) {
U32 v0 = topology->indexes.buf[ti * 3 + 0];
U32 v1 = topology->indexes.buf[ti * 3 + 1];
U32 v2 = topology->indexes.buf[ti * 3 + 2];
const GenericMeshVertexInc* A0 = VecGenericMeshVertexInc_at(&topology->vertices, v0);
const GenericMeshVertexInc* A1 = VecGenericMeshVertexInc_at(&topology->vertices, v1);
const GenericMeshVertexInc* A2 = VecGenericMeshVertexInc_at(&topology->vertices, v2);
vec3 dp1 = vec3_minus_vec3(A1->pos, A0->pos);
vec3 dp2 = vec3_minus_vec3(A2->pos, A0->pos);
float du1 = A1->tex.x - A0->tex.x;
float dv1 = A1->tex.y - A0->tex.y;
float du2 = A2->tex.x - A0->tex.x;
float dv2 = A2->tex.y - A0->tex.y;
vec3 norm = vec3_normalize(vec3_cross(dp1, dp2));
mat2x3 tang_U_V = mat3x2_transpose(mat2_mul_mat3x2(
mat2_inverse(mat2_new(du1, dv1, du2, dv2)),
mat2x3_transpose((mat2x3){.x = dp1, .y = dp2})
));
staging_vbo[v0].norm = staging_vbo[v1].norm = staging_vbo[v2].norm = norm;
staging_vbo[v0].tang_U = staging_vbo[v1].tang_U = staging_vbo[v2].tang_U = tang_U_V.x;
staging_vbo[v0].tang_V = staging_vbo[v1].tang_V = staging_vbo[v2].tang_V = tang_U_V.y;
}
/* Filling EBO is easy */
assert(topology->indexes.len == mm->indexes);
size_t ebo_len = topology->indexes.len * sizeof(U32);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
/* Filling staging textures from memory pixel data */
/* todo: do it immediately ON THE READ */
memcpy(diffuse_tex_staging, mm->pixels_diffuse.pixels.buf,
TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_diffuse));
memcpy(normal_tex_staging, mm->pixels_normal.pixels.buf,
TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_normal));
memcpy(specular_tex_staging, mm->pixels_specular.pixels.buf,
TextureDataR8_get_size_in_bytes(&mm->pixels_specular));
// todo: that is about time when we can delete mm->pixels_* buffers. They are still wasting space out there
// todo: BUt I won't do it, because I chose inplace texture reading (from png)
/* But now we are filling AliceGenericMeshMemDependantVkObj. If we ever gonna do defragmentation,
* this step would have to be repeated */
VkDescriptorSet P = margaret_allocate_descriptor_set(alice->device,
alice->descriptor_pool, alice->pipeline_hands_0a.desc_set_0b1_layout);
mm->mem_dependant_vk_obj.p_0a_set_1 = P;
VkWriteDescriptorSet writes_in_descriptor_set[] = {
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &(VkDescriptorImageInfo){
.sampler = alice->linear_sampler, .imageView = mm->diffuse_texture.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
},
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &(VkDescriptorImageInfo){
.sampler = alice->nearest_sampler, .imageView = mm->normal_texture.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
},
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P,
.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &(VkDescriptorImageInfo){
.sampler = alice->nearest_sampler, .imageView = mm->specular_texture.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
},
},
};
vkUpdateDescriptorSets(alice->device, ARRAY_SIZE(writes_in_descriptor_set), writes_in_descriptor_set, 0, NULL);
ListAliceGenericMeshHand_insert_node(&alice->generic_models, mm_node);
return mm_node;
}
ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTopology* topology){
ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand));
AliceShinyMeshHand* mm = &mm_node->el;
mm->indexes = topology->indexes.len;
mm->instance_attr.count = 0;
mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 128);
mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 128);
ShinyMeshVertex* staging_vbo;
mm->vbo = Abigail_register_new_buffer(&alice->abigail,
topology->vertices.len * sizeof(ShinyMeshVertex),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_vbo);
U32* staging_ebo;
mm->ebo = Abigail_register_new_buffer(&alice->abigail,
topology->indexes.len * sizeof(U32),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_ebo);
assert(mm->vbo.len >= topology->vertices.len * sizeof(ShinyMeshVertex));
/* We allocated enough memory, now it's time to actually fill staging buffers */
/* And we start by filling staging VBO */
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
assert(topology->indexes.len % 3 == 0);
for (size_t ti = 0; ti * 3 < topology->indexes.len; ti++) {
U32 v0 = topology->indexes.buf[ti * 3 + 0];
U32 v1 = topology->indexes.buf[ti * 3 + 1];
U32 v2 = topology->indexes.buf[ti * 3 + 2];
vec3 p0 = VecShinyMeshVertexInc_at(&topology->vertices, v0)->pos;
vec3 p1 = VecShinyMeshVertexInc_at(&topology->vertices, v1)->pos;
vec3 p2 = VecShinyMeshVertexInc_at(&topology->vertices, v2)->pos;
vec3 norm = vec3_normalize(vec3_cross(vec3_minus_vec3(p1, p0), vec3_minus_vec3(p2, p0)));
staging_vbo[v0].normal = staging_vbo[v1].normal = staging_vbo[v2].normal = norm;
}
/* Filling staging EBO is super-duper easy */
assert(topology->indexes.len == mm->indexes);
size_t ebo_len = topology->indexes.len * sizeof(U32);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
ListAliceShinyMeshHand_insert_node(&alice->shiny_models, mm_node);
return mm_node;
}
// todo: write deletion after I separate textures from Meshes
void Alice_delete_generic_mesh(Alice* alice, ListNodeAliceGenericMeshHand* hand) {
AliceGenericMeshHand* mm = &hand->el;
MargaretBufAllocator_free(alice->dev_local_buffers, mm->vbo);
MargaretBufAllocator_free(alice->dev_local_buffers, mm->ebo);
MargaretImgAllocator_free(alice->dev_local_images, mm->diffuse_texture.img.a);
MargaretImgAllocator_free(alice->dev_local_images, mm->normal_texture.img.a);
MargaretImgAllocator_free(alice->dev_local_images, mm->specular_texture.img.a);
MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging);
MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local);
// todo: the problem is, here we don't free some memory stored in AliceGenericMeshHand to store texture.
// todo: but the truth is: I am gonna get rid of pixels_{,,} fields very soon, so AliceGenericMeshHand would
// todo: be primitive again, without stupid crap
ListAliceGenericMeshHand_erase_by_it(&alice->generic_models, hand);
}
/* Be careful to only delete meshes when you actually allowed to do so */
void Alice_delete_shiny_mesh(Alice* alice, ListNodeAliceShinyMeshHand* hand) {
AliceShinyMeshHand* mm = &hand->el;
MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.vbo);
MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.ebo);
MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging);
MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local);
ListAliceShinyMeshHand_erase_by_it(&alice->shiny_models, hand);
}
void AliceGenericMeshHand_resize_instance_arr(Alice* alice, AliceGenericMeshHand* self, U64 new_count){
U64 needed_length = new_count * sizeof(GenericMeshInstance);
if (self->instance_attr.staging.len < needed_length) {
printf("Alice generic model instance staging Buffer: Gotta replace %lu with %lu\n",
self->instance_attr.staging.len, needed_length);
MargaretBufAllocator_expand_or_move_old_host_visible(
alice->staging_buffers, &self->instance_attr.staging, needed_length);
}
self->instance_attr.count = new_count;
}
void AliceShinyMeshHand_resize_instance_arr(Alice* alice, AliceShinyMeshHand* self, U64 new_count){
U64 needed_length = new_count * sizeof(ShinyMeshInstance);
if (self->instance_attr.staging.len < needed_length) {
MargaretBufAllocator_expand_or_move_old_host_visible(
alice->staging_buffers, &self->instance_attr.staging, needed_length);
}
self->instance_attr.count = new_count;
}
void AliceGenericMeshHand_set_inst(AliceGenericMeshHand* self, size_t instance, GenericMeshInstanceInc uncomp){
assert(instance < self->instance_attr.count);
GenericMeshInstance* staging = (GenericMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging);
staging[instance].base = uncomp;
mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t));
staging[instance].normal_t = mat3_new(
tr_inv.x.x, tr_inv.y.x, tr_inv.z.x,
tr_inv.x.y, tr_inv.y.y, tr_inv.z.y,
tr_inv.x.z, tr_inv.y.z, tr_inv.z.z );
}
void AliceShinyMeshHand_set_inst(AliceShinyMeshHand* self, size_t instance, ShinyMeshInstanceInc uncomp){
assert(instance < self->instance_attr.count);
ShinyMeshInstance* staging = (ShinyMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging);
staging[instance].base = uncomp;
mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t));
staging[instance].normal_t = mat3_new(
tr_inv.x.x, tr_inv.y.x, tr_inv.z.x,
tr_inv.x.y, tr_inv.y.y, tr_inv.z.y,
tr_inv.x.z, tr_inv.y.z, tr_inv.z.z );
}
/* No buffer rerecording, no buffer beginning, no buffer ending,
* 1) It copies initial generic model and shiny model topology. Textures of generic models included
* 2) For all models and for all light sources it copies EVERYTHING.
@ -1132,17 +857,17 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) {
vkCmdBindPipeline(alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline);
record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_0, image_extent);
vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof(mat4), &proj_cam_t);
0, sizeof(mat4), &proj_cam_t);
vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT,
sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos);
vkCmdBindDescriptorSets(
alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout,
0, 1, &alice->descriptor_set_for_pipeline_0, 0, NULL);
alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout,
0, 2,
(VkDescriptorSet[]){alice->descriptor_set0_for_pipeline_0, alice->descriptor_set1_for_pipeline_0},
0, NULL);
for (ListNodeAliceGenericMeshHand* mm_node = alice->generic_models.first; mm_node; mm_node = mm_node->next) {
AliceGenericMeshHand* model = &mm_node->el;
VkDescriptorSet descriptor_set1_for_textures = model->mem_dependant_vk_obj.p_0a_set_1;
const MargaretSubbuf* dev_local_inst_attr = &model->instance_attr.device_local;
vkCmdBindVertexBuffers(alice->rendering_command_buf_0, 0,
@ -1152,9 +877,9 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) {
}, (VkDeviceSize[]){ model->vbo.start, dev_local_inst_attr->start });
vkCmdBindIndexBuffer(alice->rendering_command_buf_0,
MargaretSubbuf_get_buffer(&model->ebo), model->ebo.start, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(
alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout,
1, 1, &descriptor_set1_for_textures, 0, NULL);
vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout,
VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(mat4) + sizeof(vec3), sizeof(U32) * 3,
(U32[]){model->diffuse_tex_slot, model->normal_tex_slot, model->specular_tex_slot});
vkCmdDrawIndexed(alice->rendering_command_buf_0, model->indexes, model->instance_attr.count, 0, 0, 0);
}
@ -1166,7 +891,7 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) {
sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos);
vkCmdBindDescriptorSets(
alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0b.pipeline_layout,
0, 1, &alice->descriptor_set_for_pipeline_0, 0, NULL);
0, 1, &alice->descriptor_set0_for_pipeline_0, 0, NULL);
for (ListNodeAliceShinyMeshHand* mm_node = alice->shiny_models.first; mm_node; mm_node = mm_node->next) {
const AliceShinyMeshHand* model = &mm_node->el;
@ -1252,7 +977,7 @@ void recreate_swapchain(Alice *alice) {
void alice_update_pipe0_set0_descr1(Alice* alice) {
vkUpdateDescriptorSets(alice->device, 1, &(VkWriteDescriptorSet){
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = alice->descriptor_set_for_pipeline_0,
.dstSet = alice->descriptor_set0_for_pipeline_0,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -1277,15 +1002,17 @@ void alice_create_mem_dependant_vk_obj(Alice* alice){
alice->IT1_view, alice->zbuffer_view, alice->render_pass_0,
alice->wl.sane_image_extent_limit.width, alice->wl.sane_image_extent_limit.height);
alice->descriptor_set_for_pipeline_0 = margaret_allocate_descriptor_set(
alice->descriptor_set0_for_pipeline_0 = margaret_allocate_descriptor_set(
alice->device, alice->descriptor_pool, alice->pipeline0_desc_set0_layout);
alice->descriptor_set1_for_pipeline_0 = margaret_allocate_descriptor_set(
alice->device, alice->descriptor_pool, alice->pipeline0_desc_set1_layout);
alice->descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set(
alice->device, alice->descriptor_pool, alice->pipeline_hands_1.descriptor_set_layout);
VkWriteDescriptorSet writes_in_descriptor_sets[] = {
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = alice->descriptor_set_for_pipeline_0,
.dstSet = alice->descriptor_set0_for_pipeline_0,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -1782,7 +1509,9 @@ Alice* Alice_new(){
alice->render_pass_0 = create_render_pass_0(alice->device, alice->IT1_format, alice->zbuffer_format);
alice->pipeline0_desc_set0_layout = alice_create_pipline0_desc_set0_layout(alice->device);
alice->pipeline_hands_0a = create_graphics_pipeline_0a(alice->device, root_dir, alice->pipeline0_desc_set0_layout,
alice->pipeline0_desc_set1_layout = alice_create_pipeline0_desc_set1_layout(alice->device, ALICE_MAX_TEXTURES_COUNT);
alice->pipeline_hands_0a = create_graphics_pipeline_0a(alice->device, root_dir,
alice->pipeline0_desc_set0_layout, alice->pipeline0_desc_set1_layout,
alice->render_pass_0, 0);
alice->pipeline_hands_0b = create_graphics_pipeline_0b(alice->device, root_dir, alice->pipeline0_desc_set0_layout,
alice->render_pass_0, 0);
@ -1866,6 +1595,8 @@ Alice* Alice_new(){
alice->pipeline0_light_conf.point_lights.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 1000);
alice->pipeline0_light_conf.point_lights.device_local = MargaretBufAllocator_alloc(alice->storage_buffer, 1000);
alice->texture_slots = VecAliceTextureSlot_new_zeroinit(ALICE_MAX_TEXTURES_COUNT);
alice->cam_info = AliceCamVerticalControl_new();
alice->rendering_config = AliceRenderConfig_new();
@ -1902,6 +1633,259 @@ Alice* Alice_new(){
return alice;
}
/* Helper function. Automatically aquires the slot */
U32 Alice__find_free_texture_slot(Alice* alice) {
for (U32 i = 0; i < alice->texture_slots.len; i++) {
if (!alice->texture_slots.buf[i].is_some) {
return i;
}
}
abortf("Alice textures descriptor array binding ran out of descriptors.\n"
"You should either set this limit to a higher number, or wait till I implement resize\n");
}
void Alice__put_img_and_view_into_tex_slot(Alice* alice, U32 slot_id, MargaretTexture tex) {
assert(slot_id < alice->texture_slots.len);
assert(!alice->texture_slots.buf[slot_id].is_some);
alice->texture_slots.buf[slot_id].is_some = true;
vkUpdateDescriptorSets(alice->device, 1, &(VkWriteDescriptorSet){
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = alice->descriptor_set1_for_pipeline_0,
.dstBinding = 0,
.dstArrayElement = slot_id,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &(VkDescriptorImageInfo){
.sampler = alice->linear_sampler, .imageView = tex.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
},
}, 0, NULL);
alice->texture_slots.buf[slot_id].tex = tex;
}
U32 Alice_load_r8g8b8a8_texture(Alice* alice, VecU8 texture_path) {
U32 slot_id = Alice__find_free_texture_slot(alice);
TextureDataR8G8B8A8 pixels = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&texture_path));
VecU8_drop(texture_path);
void* tex_staging;
MargaretTexture tex = Abigail_register_new_texture(&alice->abigail,
pixels.width, pixels.height,
sizeof(cvec4), VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images,
&tex_staging);
memcpy(tex_staging, pixels.pixels.buf, TextureDataR8G8B8A8_get_size_in_bytes(&pixels));
TextureDataR8G8B8A8_drop(pixels);
Alice__put_img_and_view_into_tex_slot(alice, slot_id, tex);
return slot_id;
}
U32 Alice_load_r8_texture(Alice* alice, VecU8 texture_path) {
U32 slot_id = Alice__find_free_texture_slot(alice);
TextureDataR8 pixels = TextureDataR8_read_from_png_nofail(VecU8_to_span(&texture_path));
VecU8_drop(texture_path);
void* tex_staging;
MargaretTexture tex = Abigail_register_new_texture(&alice->abigail,
pixels.width, pixels.height,
sizeof(U8), VK_FORMAT_R8_SRGB,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images,
&tex_staging);
memcpy(tex_staging, pixels.pixels.buf, TextureDataR8_get_size_in_bytes(&pixels));
TextureDataR8_drop(pixels);
Alice__put_img_and_view_into_tex_slot(alice, slot_id, tex);
return slot_id;
}
void Alice_delete_texture_from_slot(Alice* alice, U32 slot_id) {
assert(slot_id < alice->texture_slots.len);
assert(!alice->texture_slots.buf[slot_id].is_some);
alice->texture_slots.buf[slot_id].is_some = false;
}
ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const GenericMeshTopology* topology,
U32 diffuse_tex_slot, U32 normal_tex_slot, U32 specular_tex_slot
){
ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand));
AliceGenericMeshHand* mm = &mm_node->el;
mm->indexes = topology->indexes.len;
mm->instance_attr.count = 0;
mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 200);
mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 200);
GenericMeshVertex* staging_vbo;
mm->vbo = Abigail_register_new_buffer(&alice->abigail,
topology->vertices.len * sizeof(GenericMeshVertex),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_vbo /* We return values here */);
U32* staging_ebo;
mm->ebo = Abigail_register_new_buffer(&alice->abigail,
topology->indexes.len * sizeof(U32),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_ebo /* We return values here */);
assert(mm->vbo.len >= topology->vertices.len * sizeof(GenericMeshVertex));
/* We allocated enough memory, but now it's time to actually fill staging buffers */
/* Filling staging VBO */
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
assert(topology->indexes.len % 3 == 0);
for (size_t ti = 0; ti * 3 < topology->indexes.len; ti++) {
U32 v0 = topology->indexes.buf[ti * 3 + 0];
U32 v1 = topology->indexes.buf[ti * 3 + 1];
U32 v2 = topology->indexes.buf[ti * 3 + 2];
const GenericMeshVertexInc* A0 = VecGenericMeshVertexInc_at(&topology->vertices, v0);
const GenericMeshVertexInc* A1 = VecGenericMeshVertexInc_at(&topology->vertices, v1);
const GenericMeshVertexInc* A2 = VecGenericMeshVertexInc_at(&topology->vertices, v2);
vec3 dp1 = vec3_minus_vec3(A1->pos, A0->pos);
vec3 dp2 = vec3_minus_vec3(A2->pos, A0->pos);
float du1 = A1->tex.x - A0->tex.x;
float dv1 = A1->tex.y - A0->tex.y;
float du2 = A2->tex.x - A0->tex.x;
float dv2 = A2->tex.y - A0->tex.y;
vec3 norm = vec3_normalize(vec3_cross(dp1, dp2));
mat2x3 tang_U_V = mat3x2_transpose(mat2_mul_mat3x2(
mat2_inverse(mat2_new(du1, dv1, du2, dv2)),
mat2x3_transpose((mat2x3){.x = dp1, .y = dp2})
));
staging_vbo[v0].norm = staging_vbo[v1].norm = staging_vbo[v2].norm = norm;
staging_vbo[v0].tang_U = staging_vbo[v1].tang_U = staging_vbo[v2].tang_U = tang_U_V.x;
staging_vbo[v0].tang_V = staging_vbo[v1].tang_V = staging_vbo[v2].tang_V = tang_U_V.y;
}
/* Filling EBO is easy */
assert(topology->indexes.len == mm->indexes);
size_t ebo_len = topology->indexes.len * sizeof(U32);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
mm->diffuse_tex_slot = diffuse_tex_slot;
mm->normal_tex_slot = normal_tex_slot;
mm->specular_tex_slot = specular_tex_slot;
ListAliceGenericMeshHand_insert_node(&alice->generic_models, mm_node);
return mm_node;
}
ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTopology* topology){
ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand));
AliceShinyMeshHand* mm = &mm_node->el;
mm->indexes = topology->indexes.len;
mm->instance_attr.count = 0;
mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 128);
mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 128);
ShinyMeshVertex* staging_vbo;
mm->vbo = Abigail_register_new_buffer(&alice->abigail,
topology->vertices.len * sizeof(ShinyMeshVertex),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_vbo);
U32* staging_ebo;
mm->ebo = Abigail_register_new_buffer(&alice->abigail,
topology->indexes.len * sizeof(U32),
alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers,
(void**)&staging_ebo);
assert(mm->vbo.len >= topology->vertices.len * sizeof(ShinyMeshVertex));
/* We allocated enough memory, now it's time to actually fill staging buffers */
/* And we start by filling staging VBO */
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
assert(topology->indexes.len % 3 == 0);
for (size_t ti = 0; ti * 3 < topology->indexes.len; ti++) {
U32 v0 = topology->indexes.buf[ti * 3 + 0];
U32 v1 = topology->indexes.buf[ti * 3 + 1];
U32 v2 = topology->indexes.buf[ti * 3 + 2];
vec3 p0 = VecShinyMeshVertexInc_at(&topology->vertices, v0)->pos;
vec3 p1 = VecShinyMeshVertexInc_at(&topology->vertices, v1)->pos;
vec3 p2 = VecShinyMeshVertexInc_at(&topology->vertices, v2)->pos;
vec3 norm = vec3_normalize(vec3_cross(vec3_minus_vec3(p1, p0), vec3_minus_vec3(p2, p0)));
staging_vbo[v0].normal = staging_vbo[v1].normal = staging_vbo[v2].normal = norm;
}
/* Filling staging EBO is super-duper easy */
assert(topology->indexes.len == mm->indexes);
size_t ebo_len = topology->indexes.len * sizeof(U32);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
ListAliceShinyMeshHand_insert_node(&alice->shiny_models, mm_node);
return mm_node;
}
// todo: write deletion after I separate textures from Meshes
void Alice_delete_generic_mesh(Alice* alice, ListNodeAliceGenericMeshHand* hand) {
AliceGenericMeshHand* mm = &hand->el;
MargaretBufAllocator_free(alice->dev_local_buffers, mm->vbo);
MargaretBufAllocator_free(alice->dev_local_buffers, mm->ebo);
MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging);
MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local);
// todo: the problem is, here we don't free some memory stored in AliceGenericMeshHand to store texture.
// todo: but the truth is: I am gonna get rid of pixels_{,,} fields very soon, so AliceGenericMeshHand would
// todo: be primitive again, without stupid crap
ListAliceGenericMeshHand_erase_by_it(&alice->generic_models, hand);
}
/* Be careful to only delete meshes when you actually allowed to do so */
void Alice_delete_shiny_mesh(Alice* alice, ListNodeAliceShinyMeshHand* hand) {
AliceShinyMeshHand* mm = &hand->el;
MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.vbo);
MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.ebo);
MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging);
MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local);
ListAliceShinyMeshHand_erase_by_it(&alice->shiny_models, hand);
}
void AliceGenericMeshHand_resize_instance_arr(Alice* alice, AliceGenericMeshHand* self, U64 new_count){
U64 needed_length = new_count * sizeof(GenericMeshInstance);
if (self->instance_attr.staging.len < needed_length) {
printf("Alice generic model instance staging Buffer: Gotta replace %lu with %lu\n",
self->instance_attr.staging.len, needed_length);
MargaretBufAllocator_expand_or_move_old_host_visible(
alice->staging_buffers, &self->instance_attr.staging, needed_length);
}
self->instance_attr.count = new_count;
}
void AliceShinyMeshHand_resize_instance_arr(Alice* alice, AliceShinyMeshHand* self, U64 new_count){
U64 needed_length = new_count * sizeof(ShinyMeshInstance);
if (self->instance_attr.staging.len < needed_length) {
MargaretBufAllocator_expand_or_move_old_host_visible(
alice->staging_buffers, &self->instance_attr.staging, needed_length);
}
self->instance_attr.count = new_count;
}
void AliceGenericMeshHand_set_inst(AliceGenericMeshHand* self, size_t instance, GenericMeshInstanceInc uncomp){
assert(instance < self->instance_attr.count);
GenericMeshInstance* staging = (GenericMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging);
staging[instance].base = uncomp;
mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t));
staging[instance].normal_t = mat3_new(
tr_inv.x.x, tr_inv.y.x, tr_inv.z.x,
tr_inv.x.y, tr_inv.y.y, tr_inv.z.y,
tr_inv.x.z, tr_inv.y.z, tr_inv.z.z );
}
void AliceShinyMeshHand_set_inst(AliceShinyMeshHand* self, size_t instance, ShinyMeshInstanceInc uncomp){
assert(instance < self->instance_attr.count);
ShinyMeshInstance* staging = (ShinyMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging);
staging[instance].base = uncomp;
mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t));
staging[instance].normal_t = mat3_new(
tr_inv.x.x, tr_inv.y.x, tr_inv.z.x,
tr_inv.x.y, tr_inv.y.y, tr_inv.z.y,
tr_inv.x.z, tr_inv.y.z, tr_inv.z.z );
}
void Alice_set_point_light_count(Alice* alice, U32 new_count){
check(new_count < 1000000);
Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_light_conf.num_ubo_staging);
@ -1922,6 +1906,8 @@ void Alice_set_point_light(Alice* alice, U32 index, Pipeline0PointLight data){
arr[index] = data;
}
/* This function actually consumes alice handler. Alice must not be used after */
void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) {
alice->callbacks.on_wl_pointer_button = callbacks->on_wl_pointer_button,

View File

@ -85,6 +85,10 @@ typedef struct{
RBTreeNodeLucyFaceFixedSize* font_face_of_size_40;
vec3 hero_pos;
U32 ROA_diffuse_tex_slot;
U32 ROA_normal_tex_slot;
U32 ROA_specular_tex_slot;
ListNodeAliceGenericMeshHand* ROA_mesh;
GenericMeshTopology ROA_topology;
RigidBodyState ROA_state;
@ -335,12 +339,13 @@ void run_app(){
VecU8 ROA_mesh_path = vcstr("./gen/l2/models/log_10_2_6.AliceGenericMesh");
st.ROA_topology = alice_expect_read_generic_mesh_from_file(ROA_mesh_path);
st.ROA_diffuse_tex_slot = Alice_load_r8g8b8a8_texture(alice, vcstr("./src/l3/textures/log_10_2_6_diffuse.png"));
st.ROA_normal_tex_slot = Alice_load_r8g8b8a8_texture(alice, vcstr("./gen/l2/textures/log_10_2_6_NORMAL.png"));
st.ROA_specular_tex_slot = Alice_load_r8_texture(alice, vcstr("./src/l3/textures/log_10_2_6_specular.png"));
st.ROA_mesh = Alice_add_generic_mesh(st.alice, &st.ROA_topology,
(AliceGenericMeshTexturePaths){
.diffuse_texture_path = vcstr("./src/l3/textures/log_10_2_6_diffuse.png"),
.normal_texture_path = vcstr("./gen/l2/textures/log_10_2_6_NORMAL.png"),
.specular_texture_path = vcstr("./src/l3/textures/log_10_2_6_specular.png")
});
st.ROA_diffuse_tex_slot, st.ROA_normal_tex_slot, st.ROA_specular_tex_slot);
AliceGenericMeshHand_resize_instance_arr(st.alice, &st.ROA_mesh->el, 1);
const float gamma_l_c = 4.f / 3 / M_PIf;
st.ROA_state = (RigidBodyState){

View File

@ -1,4 +1,6 @@
#version 450
#version 460
#extension GL_EXT_nonuniform_qualifier : require
layout(location = 0) in vec3 tang_norm;
layout(location = 1) in vec3 tang_U;
@ -6,15 +8,15 @@ layout(location = 2) in vec3 tang_V;
layout(location = 3) in vec2 tex;
layout(location = 4) in vec3 pos;
/* Right now all in set 0 */
layout(location = 0) out vec4 fin_color;
/* Yes, even these guys */
layout(set = 1, binding = 0) uniform sampler2D color_tex;
layout(set = 1, binding = 1) uniform sampler2D normal_map;
layout(set = 1, binding = 2) uniform sampler2D specular_map;
layout(set = 1, binding = 0) uniform sampler2D textures[];
layout(push_constant, std430) uniform pc {
layout(offset = 64) vec3 camera_pos;
uint diffuse_tex_slot;
uint normal_tex_slot;
uint specular_tex_slot;
};
struct PointLight {
@ -43,7 +45,10 @@ float get_intensity(float dist){
}
void main(){
vec3 compressed_normal = texture(normal_map, tex).xyz;
vec3 compressed_normal = texture(textures[nonuniformEXT(normal_tex_slot)], tex).xyz;
vec3 natural_color = texture(textures[nonuniformEXT(diffuse_tex_slot)], tex).xyz;
float specular_c = texture(textures[nonuniformEXT(specular_tex_slot)], tex).x;
vec3 correct_norm_on_tang = compressed_normal * 2 - 1;
vec3 norm = normalize(mat3(tang_U, tang_norm, tang_V) * correct_norm_on_tang);
vec3 diffuse_illumination = vec3(0);
@ -63,8 +68,7 @@ void main(){
//for (int i = 0; i < spotlight_count; i++) {
// Pipeline0Spotlight lamp = spotlight_arr[i];
//}
vec3 natural_color = texture(color_tex, tex).xyz;
float specular_c = texture(specular_map, tex).x;
vec3 color = natural_color * diffuse_illumination + specular_c * specular_illumination;
fin_color = vec4(color, 1);
}