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:
parent
2367ce1e9d
commit
15089cf7b5
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user