diff --git a/CMakeLists.txt b/CMakeLists.txt index dda56d4..0bbbc84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,24 +27,23 @@ add_compile_definitions(_POSIX_C_SOURCE=200112L) add_compile_definitions(_GNU_SOURCE) add_compile_options(-fno-trapping-math) -#add_executable(codegen_l1 src/l1/anne/codegen.c) +#add_executable(codegen_l1 src/l1/anne/codegen.c)1 #target_compile_definitions(codegen_l1 # PRIVATE PROTOTYPE1_L1_CODEGEN_BOOTSTRAP_USE_CHICKEN_VECU8) #add_executable(0_test src/l1_4/tests/t0.c) #add_executable(1_test src/l1_4/tests/t1.c) # -add_executable(l1_4_t2 src/l1_4/tests/t2.c) +#add_executable(l1_4_t2 src/l1_4/tests/t2.c) + +#add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) + +add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c) +target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng) + +add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c) +target_link_libraries(0r_tex_init_prep -lm -lpng) -add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) -# -#add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c -# src/l1/core/rb_tree_node.h) -#target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng) -# -#add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c) -#target_link_libraries(0r_tex_init_prep -lm -lpng) -# #add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c) #target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon) # @@ -58,4 +57,4 @@ add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) #target_link_libraries(0_play_test -lncurses) # -add_executable(l2t0 src/l2/tests/data_structures/t0.c) +#add_executable(l2t0 src/l2/tests/data_structures/t0.c) diff --git a/src/l1/anne/codegen.c b/src/l1/anne/codegen.c index 11b77de..d4a4c06 100644 --- a/src/l1/anne/codegen.c +++ b/src/l1/anne/codegen.c @@ -7,10 +7,11 @@ #include "some_tests.h" #include "util_temp_vulkan.h" -#include "margaret/vulkan_utils.h" +#include "margaret/margaret_misc.h" #include "marie/graphics_geom.h" #include "liza.h" #include "codegen_from_l1_5.h" +#include "margaret/png_pixel_masses.h" int main() { mkdir_nofail("l1"); @@ -21,10 +22,12 @@ int main() { generate_pixel_masses_header(); generate_headers_for_r0_r1_r2_r3(); generate_util_templ_inst_for_vulkan_headers(); - generate_margaret_eve_for_vulkan_utils(); generate_marie_headers_for_graphics_geom(); generate_liza_l1_headers(); generate_l1_headers_for_l1_5(); + mkdir_nofail("l1/margaret"); + generate_margaret_eve_for_vulkan_utils(); /* margaret misc */ + generate_margaret_png_pixel_masses_header(); finish_layer(cstr("l1")); return 0; } diff --git a/src/l1/anne/margaret/vulkan_utils.h b/src/l1/anne/margaret/margaret_misc.h similarity index 84% rename from src/l1/anne/margaret/vulkan_utils.h rename to src/l1/anne/margaret/margaret_misc.h index b42c067..b4bb8a2 100644 --- a/src/l1/anne/margaret/vulkan_utils.h +++ b/src/l1/anne/margaret/margaret_misc.h @@ -1,5 +1,5 @@ -#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_VULKAN_H -#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_VULKAN_H +#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_MARGARET_MISC_H +#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_MARGARET_MISC_H #include "../../codegen/util_template_inst.h" @@ -21,6 +21,8 @@ void generate_margaret_eve_for_vulkan_utils() { .T = cstr("PtrMargaretImageInMemoryInfo"), .t_primitive = true, .vec = true, .span = true, .mut_span = true, .collab_vec_span = true }); + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretCommandForImageCopying"), true, true); } + #endif \ No newline at end of file diff --git a/src/l1/anne/margaret/png_pixel_masses.h b/src/l1/anne/margaret/png_pixel_masses.h new file mode 100644 index 0000000..74f0b5f --- /dev/null +++ b/src/l1/anne/margaret/png_pixel_masses.h @@ -0,0 +1,302 @@ +#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_PNG_PIXEL_MASSES_H +#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_PNG_PIXEL_MASSES_H + +#include "../../codegen/util_template_inst.h" + +typedef struct { + S64 channel_count; + SpanU8 name; +} color_type_name_in_png; + +color_type_name_in_png color_types_names_in_png[] = { + {1, cstr("PNG_COLOR_TYPE_GRAY")}, + {2, cstr("PNG_COLOR_TYPE_GRAY_ALPHA")}, + {3, cstr("PNG_COLOR_TYPE_RGB")}, + {4, cstr("PNG_COLOR_TYPE_RGBA")}, +}; + +NODISCARD VecU8 generate_margaret_png_texture_data_methods(SpanU8 format_signature, S64 depth, S64 channel_count) { + if (depth != 8) + abortf("Please no\n"); + SpanU8 color_type = cstr(""); + for (size_t i = 0; i < ARRAY_SIZE(color_types_names_in_png); i++) { + if (color_types_names_in_png[i].channel_count == channel_count) + color_type = color_types_names_in_png[i].name; + } + if (color_type.len == 0) + abortf("Please don't\n"); + + U64 sizeof_pixel = (U64)depth / 8 * (U64)channel_count; + VecU8 res = VecU8_new(); + + VecU8 g_promise = VecU8_fmt("MargaretPromisedPng%s", format_signature); + SpanU8 promise = VecU8_to_span(&g_promise); + VecU8 g_tex = VecU8_fmt("TextureData%s", format_signature); + SpanU8 tex = VecU8_to_span(&g_tex); + + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD ResultVoidOrVecU8 %s_write_to_png(const %s* self, SpanU8 filename) {\n" /* tex, tex */ + SPACE "VecU8 nt_filename = VecU8_fmt(\"%%s%%c\", filename, 0);\n" + SPACE "FILE *fp = fopen((CSTR)nt_filename.buf, \"wb\");\n" + SPACE "VecU8_drop(nt_filename);\n" + SPACE "if (!fp) {\n" + SPACE SPACE "return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_fmt(\"Unable to open file %%s\", filename)};\n" + SPACE "}\n" + SPACE "png_structp pngshka = png_create_write_struct(PNG_LIBPNG_VER_STRING,\n" + SPACE SPACE "NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);\n" + SPACE "if (!pngshka)\n" + SPACE SPACE "abortf(\"png_create_write_struct\");\n" + SPACE "png_infop info = png_create_info_struct(pngshka);\n" + SPACE "if (!info)\n" + SPACE SPACE"abortf(\"png_create_info_struct\");\n" + SPACE "png_bytep* row_pointers = NULL;\n" + SPACE "if (setjmp(png_jmpbuf(pngshka))){\n" + SPACE SPACE "png_destroy_write_struct(&pngshka, &info);\n" + SPACE SPACE "fclose(fp);\n" + SPACE SPACE "free(row_pointers);\n" + SPACE SPACE "return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr(\"Some png error happened\")};\n" + SPACE "}\n" + SPACE "png_init_io(pngshka, fp);\n" + SPACE "U32 width = self->width;\n" + SPACE "U32 height = self->height;\n" + SPACE "png_set_IHDR(pngshka, info, width, height, %i, %s,\n" /* depth, color_type */ + SPACE SPACE "PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);\n" + SPACE "row_pointers = calloc(height, sizeof(row_pointers));\n" + SPACE "for (U32 y = 0; y < height; y++) {\n" + SPACE SPACE "row_pointers[height - 1 - y] = (png_bytep)((%s_at(self, 0, y)));\n" /* tex */ + SPACE "}\n" + SPACE "png_set_rows(pngshka, info, row_pointers);\n" + SPACE "png_write_png(pngshka, info, 0, NULL);\n" + SPACE "/* No more errors */\n" + SPACE "free(row_pointers);\n" + SPACE "png_destroy_write_struct(&pngshka, &info);\n" + SPACE "fclose(fp);\n" + SPACE "return (ResultVoidOrVecU8){.variant = Result_Ok};\n" + "}\n\n" + "/* Aborts on error */\n" + "void %s_write_to_png_nofail(const %s* self, SpanU8 filename) {\n" /* tex, tex*/ + SPACE "ResultVoidOrVecU8 res = %s_write_to_png(self, filename);\n" /* tex */ + SPACE "if (res.variant == Result_Err) {\n" + SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res.err), stderr);\n" + SPACE SPACE "abortf(\" %s_write_to_png\\n\");\n" /* tex */ + SPACE "}\n" + "}\n", + tex, tex, depth, color_type, tex, tex, tex, tex, tex)); + + /* Non clonable structure */ + VecU8_append_vec(&res, VecU8_fmt( + "typedef struct {\n" + SPACE "FILE* fp;\n" + SPACE "png_structp pngshka;\n" + SPACE "png_infop info;\n" + SPACE "png_infop end_info;\n" + "} %s;\n\n" + "void %s_drop(%s self) {\n" + SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n" + SPACE "fclose(self.fp);\n" + "}\n\n", + promise, promise, promise)); + + VecU8_append_vec(&res, generate_result_template_inst(promise, cstr("VecU8"), false, false)); + + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD Result%sOrVecU8 %s_begin(SpanU8 filename) {\n" /* promise, promise */ + SPACE "VecU8 nt_filename = VecU8_fmt(\"%%s%%c\", filename, 0);\n" + SPACE "FILE* fp = fopen((CSTR)nt_filename.buf, \"rb\");\n" + SPACE "VecU8_drop(nt_filename);\n" + SPACE "if (!fp) {\n" + SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err,\n" /* promise */ + SPACE SPACE SPACE ".err = VecU8_fmt(\"Unable to open file %%s\", filename)};\n" + SPACE "}\n" + SPACE "png_structp pngshka = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);\n" + SPACE "if (!pngshka)\n" + SPACE SPACE "abortf(\"png_create_read_struct\");\n" + SPACE "png_infop info = png_create_info_struct(pngshka);\n" + SPACE "if (!info)\n" + SPACE SPACE "abortf(\"png_create_info_struct\");\n" + SPACE "png_infop end_info = png_create_info_struct(pngshka);\n" + SPACE "if (!end_info)\n" + SPACE SPACE "abortf(\"png_create_info_struct\");\n" + SPACE "if (setjmp(png_jmpbuf(pngshka))) {\n" + SPACE SPACE "png_destroy_read_struct(&pngshka, &info, &end_info);\n" + SPACE SPACE "fclose(fp);\n" + SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err,\n" /* promise */ + SPACE SPACE SPACE ".err = VecU8_from_cstr(\"Some png error happened\")};\n" + SPACE "}\n" + SPACE "png_init_io(pngshka, fp);\n" + SPACE "png_read_info(pngshka, info);\n" + SPACE "U32 width, height;\n" + SPACE "int bit_depth, color_type;\n" + SPACE "check(png_get_IHDR(pngshka, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));\n", + promise, promise, promise, promise)); + + /* We are still in PROMISE_begin method, now we need to do the conversion */ + if (depth == 8) { + VecU8_append_span(&res, cstr( + SPACE "if (bit_depth == 16)\n" + SPACE SPACE "png_set_strip_16(pngshka);\n" + SPACE "else if (color_type == PNG_COLOR_TYPE_GRAY && (bit_depth == 1 || bit_depth == 2 || bit_depth == 4))\n" + SPACE SPACE "png_set_expand_gray_1_2_4_to_8(pngshka);\n" + )); + } else + assert(false); + if (channel_count == 3 || channel_count == 4) { + VecU8_append_span(&res, cstr( + SPACE "if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)\n" + SPACE SPACE "png_set_gray_to_rgb(pngshka);\n" + SPACE "else if (color_type == PNG_COLOR_TYPE_PALETTE)" + SPACE SPACE "png_set_palette_to_rgb(pngshka);\n" + )); + } else if (channel_count == 1 || channel_count == 2) { + VecU8_append_span(&res, cstr( + SPACE "if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGBA) {\n" + SPACE SPACE "png_set_rgb_to_gray_fixed(pngshka, 1, 21268, 71514);\n" + SPACE "} else if (color_type == PNG_COLOR_TYPE_PALETTE) {\n" + SPACE SPACE "png_set_palette_to_rgb(pngshka);\n" + SPACE SPACE "png_set_rgb_to_gray_fixed(pngshka, 1, 21268, 71514);\n" + SPACE "}\n" + )); + } else + assert(false); + if (channel_count == 4 || channel_count == 2) { + VecU8_append_span(&res, cstr( + SPACE "if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_PALETTE) {\n" + SPACE SPACE "if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) \n" + SPACE SPACE SPACE "png_set_tRNS_to_alpha(pngshka);\n" + SPACE SPACE "else\n" + SPACE SPACE SPACE "png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);\n" + SPACE "}\n" + )); + } else if (channel_count == 1 || channel_count == 3) { + VecU8_append_span(&res, cstr( + SPACE "if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGBA)\n" + SPACE SPACE "png_set_strip_alpha(pngshka);\n" + )); + } else + assert(false); + /* At this point we have a converted image png structure */ + + VecU8_append_vec(&res, VecU8_fmt( + SPACE "png_read_update_info(pngshka, info);\n" + SPACE "{\n" + SPACE SPACE "U32 new_width, new_height;\n" + SPACE SPACE "int new_bit_depth, new_color_type;\n" + SPACE SPACE "check(png_get_IHDR(pngshka, info, &new_width, &new_height, &new_bit_depth, &new_color_type, NULL, NULL, NULL));\n" + SPACE SPACE "assert(new_width == width && new_height == height && new_bit_depth == %i && new_color_type == %s);\n" /* depth, color_type */ + SPACE "}\n" + SPACE "return (Result%sOrVecU8){.variant = Result_Ok,\n" /* promise */ + SPACE SPACE ".ok = (%s){.fp = fp, .pngshka = pngshka, .info = info, .end_info = end_info}};\n" /* promise */ + "}\n\n", + (S64)depth, color_type, + promise, promise)); + + VecU8_append_vec(&res, VecU8_fmt( + "SizeOfRectangleU32 %s_get_extent(const %s* self) {\n" /* promise, promise */ + SPACE "U32 width, height;\n" + SPACE "int bit_depth, color_type;\n" + SPACE "check(png_get_IHDR(self->pngshka, self->info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));\n" + SPACE "return (SizeOfRectangleU32){width, height};\n" + "}\n\n", + promise, promise)); + + assert(depth == 8 || depth == 16); + assert(channel_count == 1 || channel_count == 2 || channel_count == 4 || channel_count == 3); + + VecU8_append_vec(&res, VecU8_fmt( + "size_t %s_get_needed_buffer_size(const %s* self) {\n" /* promise, promise */ + SPACE "SizeOfRectangleU32 dim = %s_get_extent(self);\n" /* promise */ + SPACE "return %u * dim.width * dim.height;\n" /* sizeof_pixel */ + "}\n\n", + promise, promise, promise, sizeof_pixel)); + + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD ResultVoidOrVecU8 %s_finish(%s self, void* buffer) {\n" /* promise, promise */ + SPACE "SizeOfRectangleU32 dim = %s_get_extent(&self);\n" /* promise */ + SPACE "png_bytep* row_pointers = NULL;\n" + SPACE "if (setjmp(png_jmpbuf(self.pngshka))) {\n" + SPACE SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n" + SPACE SPACE "fclose(self.fp);\n" + SPACE SPACE "free(row_pointers);\n" + SPACE SPACE "return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr(\"Some png error happened\")};\n" + SPACE "}\n" + SPACE "row_pointers = calloc(dim.height, sizeof(row_pointers));\n" + SPACE "for (U32 y = 0; y < dim.height; y++) {\n" + SPACE SPACE "row_pointers[dim.height - 1 - y] = ((png_bytep)buffer) + %u * dim.width * y;\n" /* sizeof_pixel */ + SPACE "}\n" + SPACE "png_read_image(self.pngshka, row_pointers);\n" + SPACE "png_read_end(self.pngshka, self.end_info);\n" + SPACE "/* No more errors */\n" + SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n" + SPACE "fclose(self.fp);\n" + SPACE "free(row_pointers);\n" + SPACE "return (ResultVoidOrVecU8){.variant = Result_Ok};\n" + "}\n\n", + promise, promise, promise, sizeof_pixel + )); + + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD Result%sOrVecU8 %s_finish_into_%s(%s self) {\n" /* tex, promise, tex, promise */ + SPACE "SizeOfRectangleU32 dim = %s_get_extent(&self);\n" /* promise */ + SPACE "if (dim.width >= UINT32_MAX / 10 || dim.height >= UINT32_MAX / 10) {\n" + SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err, .err = vcstr(\"Input image is too big\")};\n" /* tex */ + SPACE "}\n" + SPACE "%s tex = %s_new(dim.width, dim.height);\n" /* tex, tex */ + SPACE "ResultVoidOrVecU8 res = %s_finish(self, tex.pixels.buf);\n" /* promise */ + SPACE "if (res.variant == Result_Err) {\n" + SPACE SPACE "%s_drop(tex);\n" /* tex */ + SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err, .err = res.err};\n" /* tex */ + SPACE "}\n" + SPACE "return (Result%sOrVecU8){.variant = Result_Ok, .ok = tex};\n" /* tex */ + "}\n\n", + tex, promise, tex, promise, promise, tex, tex, tex, promise, tex, tex, tex + )); + + VecU8_append_vec(&res, VecU8_fmt( + + "/* aborts on error */\n" + "NODISCARD %s %s_read_from_png_nofail(SpanU8 name) {\n" /* tex, tex */ + SPACE "Result%sOrVecU8 res_1 = %s_begin(name);\n" /* promise, promise */ + SPACE "if (res_1.variant == Result_Err) {\n" + SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res_1.err), stderr);\n" + SPACE SPACE "abortf(\" MargaretPromisedPng_begin\\n\");\n" + SPACE "}\n" + SPACE "/* res_1 invalidated, we moved ownership to _finish methos */\n" + SPACE "Result%sOrVecU8 res_2 = %s_finish_into_%s(res_1.ok);\n" /* tex, promise, tex */ + SPACE "if (res_2.variant == Result_Err) {\n" + SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res_2.err), stderr);\n" + SPACE SPACE "abortf(\" MargaretPromisedPng_finish (into TextureData)\\n\");\n" + SPACE "}\n" + SPACE "return res_2.ok;\n" + "}\n\n", + tex, tex, promise, promise, tex, promise, tex + )); + + VecU8_drop(g_promise); + VecU8_drop(g_tex); + return res; +} + +void generate_margaret_png_pixel_masses_header() { + GeneratedHeader header = begin_header(cstr("l1/margaret/png_pixel_masses.h")); + + VecU8_append_span(&header.result, cstr( + "#include \"../pixel_masses.h\"\n" + "#include \"../ResultVoidOrVecU8.h\"\n" + "#include \n\n")); + + VecU8_append_span(&header.result, cstr( + "void margaret_libpng_h_error_cb(png_structp pngshka, png_const_charp err) {\n" + SPACE "printf(\"[!] %s\\n\", err);\n" + "}\n\n" + "void margaret_libpng_h_warning_cb(png_structp pngshka, png_const_charp warning) {\n" + SPACE "printf(\"[.] %s\\n\", warning);\n" + "}\n\n")); + + VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8"), 8, 1)); + VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8G8B8"), 8, 3)); + VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8G8B8A8"), 8, 4)); + + finish_header(header); +} + +#endif \ No newline at end of file diff --git a/src/l1/anne/pixel_masses.h b/src/l1/anne/pixel_masses.h index fb5d453..526ef4e 100644 --- a/src/l1/anne/pixel_masses.h +++ b/src/l1/anne/pixel_masses.h @@ -2,6 +2,7 @@ #define PROTOTYPE_SRC_L1_CODEGEN_PIXEL_MASSES_H #include "../codegen/codegen.h" +#include "../codegen/util_template_inst.h" /* Used to generate both _at() and _cat() methods */ NODISCARD VecU8 generate_texture_data_method_at(SpanU8 tex, SpanU8 pixvec, SpanU8 memb, bool const_access) { @@ -16,31 +17,26 @@ NODISCARD VecU8 generate_texture_data_method_at(SpanU8 tex, SpanU8 pixvec, SpanU /* `tex` is the type name of texture data type * `memb` is the type name of pixel data type */ -NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 memb) { +NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 memb, SpanU8 luminosity_formula) { VecU8 g_pixvec = VecU8_fmt("Vec%s", memb); SpanU8 pixvec = VecU8_to_span(&g_pixvec); - - VecU8 res = VecU8_fmt( + VecU8 res = VecU8_fmt( "typedef struct {\n" SPACE "%s pixels;\n" SPACE "size_t width;\n" + SPACE "size_t height;\n" "} %s;\n\n", pixvec, tex); /* Method _new() */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_new(U32 width, U32 height) {\n" SPACE "assert(!(SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10));\n" - SPACE "return (%s){.pixels = %s_new_zeroinit((size_t)width * height), .width = width};\n" + SPACE "return (%s){.pixels = %s_new_zeroinit((size_t)width * height), .width = width, .height = height};\n" "}\n\n", tex, tex, tex, pixvec)); /* Method _drop() */ VecU8_append_vec(&res, VecU8_fmt( "void %s_drop(%s self) {\n" SPACE "%s_drop(self.pixels);\n" "}\n\n", tex, tex, pixvec)); - /* Method _get_height() */ - VecU8_append_vec(&res, VecU8_fmt( - "size_t %s_get_height(const %s* self) {\n" - SPACE "return self->pixels.len / self->width;\n" - "}\n\n", tex, tex)); /* Methods _at and _cat */ VecU8_append_vec(&res, generate_texture_data_method_at(tex, pixvec, memb, false)); VecU8_append_vec(&res, generate_texture_data_method_at(tex, pixvec, memb, true)); @@ -76,17 +72,12 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 SPACE "write_whole_file_or_abort(path, VecU8_to_span(&data));\n" SPACE "VecU8_drop(data);\n" "}\n\n", tex, tex, tex)); - /* Result structure */ - VecU8 g_resoftex = VecU8_fmt("Result%sOrSpanU8", tex); + /* Result structure */ + VecU8 g_resoftex = get_ResultType_inst_name(tex, cstr("SpanU8")); SpanU8 resoftex = VecU8_to_span(&g_resoftex); - VecU8_append_vec(&res, VecU8_fmt( - "typedef struct {\n" - SPACE "Result_variant variant;\n" - SPACE "union {\n" - SPACE SPACE "%s ok;\n" - SPACE SPACE "SpanU8 err;\n" - SPACE "};\n" - "} %s;\n\n", tex, resoftex)); + VecU8_append_vec(&res, generate_result_template_inst(tex, cstr("SpanU8"), false, true)); + /* I also add this, because why not?? Maye I will use it in the future... */ + VecU8_append_vec(&res, generate_result_template_inst(tex, cstr("VecU8"), false, false)); /* Method _from_bitmap_text() * We assume that bytes are tightly packed in member type */ VecU8_append_vec(&res, VecU8_fmt( @@ -125,6 +116,34 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 "bool %s_is_inside(const %s* self, S32 x, S32 y) {\n" SPACE "return x >= 0 && y >= 0 && x < (S32)self->width && self->width * y + x < self->pixels.len;\n" "}\n\n", tex, tex)); + /* Method _print() */ + VecU8_append_vec(&res, VecU8_fmt( + "void %s_print(const %s* self) {\n" /* tex, tex */ + SPACE "U64 width = self->width;\n" + SPACE "U64 height = self->height;\n" + SPACE "U64 cell_width = MAX_U64(1, width / 190);\n" + SPACE "U64 cell_height = MAX_U64(1, cell_width * 14 / 8);\n" + SPACE "for (U64 CY = 0; CY < height; CY += cell_height) {\n" + SPACE SPACE "for (U64 CX = 0; CX < width; CX += cell_width) {\n" + SPACE SPACE SPACE "float lum = 0;\n" + SPACE SPACE SPACE "for (U64 j = 0; j < cell_height; j++) {\n" + SPACE SPACE SPACE SPACE "U64 y = CY + j;\n" + SPACE SPACE SPACE SPACE "if (y >= height)\n" + SPACE SPACE SPACE SPACE SPACE "continue;\n" + SPACE SPACE SPACE SPACE "for (U64 i = 0; i < cell_width; i++) {\n" + SPACE SPACE SPACE SPACE SPACE "U64 x = CX + i;\n" + SPACE SPACE SPACE SPACE SPACE "if (x >= width)\n" + SPACE SPACE SPACE SPACE SPACE SPACE "continue;\n" + SPACE SPACE SPACE SPACE SPACE "%s pix = *%s_at(self, x, y);\n" /* memb, tex */ + SPACE SPACE SPACE SPACE SPACE "lum += %s;\n" /* luminosity_formula */ + SPACE SPACE SPACE SPACE "}\n" + SPACE SPACE SPACE "}\n" + SPACE SPACE SPACE "lum /= (float)cell_width * (float)cell_height;\n" + SPACE SPACE SPACE "putc(lum > 0.95 ? '@' : (lum > 0.8 ? '#' : (lum > 0.65 ? '*' : (lum > 0.4 ? '_' : (lum > 0.2 ? '.' : ' ')))), stdout);\n" + SPACE SPACE "}\n" + SPACE SPACE "putc('\\n', stdout);\n" + SPACE "}\n" + "}\n\n", tex, tex, memb, tex, luminosity_formula)); VecU8_drop(g_resoftex); VecU8_drop(g_pixvec); @@ -137,9 +156,12 @@ void generate_pixel_masses_header() { VecU8_append_span(&res.result, cstr("#include \"../../src/l1/system/fileio.h\"\n")); VecU8_append_span(&res.result, cstr("#include \"VecAndSpan_cvec3.h\"\n")); VecU8_append_span(&res.result, cstr("#include \"VecAndSpan_cvec4.h\"\n\n")); - VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8"), cstr("U8"))); - VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8"), cstr("cvec3"))); - VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8A8"), cstr("cvec4"))); + VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8"), cstr("U8"), + cstr("(float)pix / 255"))); + VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8"), cstr("cvec3"), + cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f"))); + VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8A8"), cstr("cvec4"), + cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f"))); finish_header(res); } diff --git a/src/l1/anne/some_tests.h b/src/l1/anne/some_tests.h index f776133..22f5691 100644 --- a/src/l1/anne/some_tests.h +++ b/src/l1/anne/some_tests.h @@ -21,6 +21,9 @@ void generate_headers_for_r0_r1_r2_r3() { /* r0_scene.h */ generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("UsedGenericModelOnScene"), true, false); generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("UsedShinyModelOnScene"), true, false); + /* r0 */ + generate_eve_span_company_for_primitive(l, ns, cstr("GenericModelTopAndTexInMemoryInfo"), true, false); + generate_eve_span_company_for_primitive(l, ns, cstr("ShinyModelTopInMemoryInfo"), true, false); } mkdir_nofail("l1/eve/r2"); { /* r2 */ diff --git a/src/l1/anne/util_temp_very_base.h b/src/l1/anne/util_temp_very_base.h index 177fd31..13b4f47 100644 --- a/src/l1/anne/util_temp_very_base.h +++ b/src/l1/anne/util_temp_very_base.h @@ -3,8 +3,6 @@ #include "../codegen/util_template_inst.h" -// todo: split VecAndSpan_int_primitives into multiple files (one file per integer type) - /* These headers are guarded */ void generate_util_temp_very_base_headers() { SpanU8 l = cstr("l1"), ns = cstr(""); @@ -52,6 +50,10 @@ void generate_util_temp_very_base_headers() { } generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), cstr("CSTR"), cstr(""), true, false); + generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), + cstr(""), cstr("VecU8"), cstr("#include \"VecAndSpan_U8.h\""), true, false); + generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), + cstr(""), cstr("SpanU8"), cstr("#include \"VecAndSpan_U8.h\""), true, true); } #endif \ No newline at end of file diff --git a/src/l1/anne/util_temp_vulkan.h b/src/l1/anne/util_temp_vulkan.h index 1201086..b17e6f6 100644 --- a/src/l1/anne/util_temp_vulkan.h +++ b/src/l1/anne/util_temp_vulkan.h @@ -41,6 +41,7 @@ void generate_util_templ_inst_for_vulkan_headers() { generate_guarded_span_company_for_primitive(l, ns, cstr("VkSemaphore"), vulkan_dep, true, false); generate_guarded_span_company_for_primitive(l, ns, cstr("VkDescriptorPoolSize"), vulkan_dep, true, false); generate_guarded_span_company_for_primitive(l, ns, cstr("VkBufferCopy"), vulkan_dep, true, false); + generate_guarded_span_company_for_primitive(l, ns, cstr("VkImageMemoryBarrier"), vulkan_dep, true, false); } #endif \ No newline at end of file diff --git a/src/l1/codegen/util_template_inst.h b/src/l1/codegen/util_template_inst.h index 4f7c837..00fa61b 100644 --- a/src/l1/codegen/util_template_inst.h +++ b/src/l1/codegen/util_template_inst.h @@ -550,6 +550,94 @@ void generate_guarded_span_company_for_non_primitive_non_clonable( }); } +NODISCARD VecU8 get_ResultType_inst_name(SpanU8 OkT, SpanU8 ErrT){ + bool ok_t_void = OkT.len == 0; + bool err_t_void = ErrT.len == 0; + assert(!ok_t_void || !err_t_void); + return VecU8_fmt("Result%s%s%s", !ok_t_void ? OkT : cstr("Void"), + !err_t_void ? cstr("Or") : cstr(""), !err_t_void ? ErrT : cstr("")); +} + +/* We are talking about Result template instantiation */ +NODISCARD VecU8 generate_result_template_inst(SpanU8 OkT, SpanU8 ErrT, bool ok_t_primitive, bool err_t_primitive) { + bool ok_t_void = OkT.len == 0; + bool err_t_void = ErrT.len == 0; + assert(!ok_t_void || !err_t_void); + assert(!ok_t_void || ok_t_primitive); + assert(!err_t_void || err_t_primitive); + + VecU8 g_ResultT = get_ResultType_inst_name(OkT, ErrT); + SpanU8 ResultT = VecU8_to_span(&g_ResultT); + + VecU8 res = VecU8_new(); + + VecU8_append_span(&res, cstr( + "typedef struct {\n" + SPACE "Result_variant variant;\n")); + if (ok_t_void && !err_t_void) { + VecU8_append_vec(&res, VecU8_fmt(SPACE "%s err;\n", ErrT)); + } else if (!ok_t_void && err_t_void) { + VecU8_append_vec(&res, VecU8_fmt(SPACE "%s ok;\n", OkT)); + } else { + VecU8_append_vec(&res, VecU8_fmt( + SPACE "union {\n" + SPACE SPACE "%s ok;\n" + SPACE SPACE "%s err;\n" + SPACE "};\n", OkT, ErrT)); + } + VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", ResultT)); + + if (!ok_t_primitive || !err_t_primitive) { + VecU8_append_vec(&res, VecU8_fmt( + "void %s_drop(%s self) {\n", ResultT, ResultT)); + if (ok_t_primitive && !err_t_primitive) { + VecU8_append_vec(&res, VecU8_fmt( + SPACE "if (self.variant == Result_Err)\n" + SPACE SPACE "%s_drop(self.err);\n", ErrT)); + } else if (!ok_t_primitive && err_t_primitive) { + VecU8_append_vec(&res, VecU8_fmt( + SPACE "if (self.variant == Result_Ok)\n" + SPACE SPACE "%s_drop(self.ok);\n", OkT)); + } else { + VecU8_append_vec(&res, VecU8_fmt( + SPACE "if (self.variant == Result_Ok)\n" + SPACE SPACE "%s_drop(self.ok);\n" + SPACE "else\n" + SPACE SPACE "%s_drop(self.err);\n", OkT, ErrT)); + } + VecU8_append_span(&res, cstr("}\n\n")); + } + VecU8_drop(g_ResultT); /* ResultT variable invalidated */ + return res; +} + +void generate_eve_header_of_result_type_instantiation( + SpanU8 l, SpanU8 ns, SpanU8 OkT, SpanU8 ErrT, bool ok_t_primitive, bool err_t_primitive + ) { + VecU8 ResultT = get_ResultType_inst_name(OkT, ErrT); + VecU8 nt_filepath = VecU8_fmt("%s/eve/%s/%s.h%c", l, ns, VecU8_to_span(&ResultT), 0); + VecU8 text = generate_result_template_inst(OkT, ErrT, ok_t_primitive, err_t_primitive); + write_whole_file_or_abort((CSTR)text.buf, VecU8_to_span(&text)); + VecU8_drop(text); + VecU8_drop(nt_filepath); + VecU8_drop(ResultT); +} + +void generate_guarded_header_of_result_type_instantiation( + SpanU8 layer, SpanU8 bonus_ns, SpanU8 OkT, SpanU8 ErrT, SpanU8 dependencies, bool ok_t_primitive, bool err_t_primitive + ){ + assert(layer.len > 1); + VecU8 filename = get_ResultType_inst_name(OkT, ErrT); + VecU8 path = VecU8_fmt("%s/%s%s%s.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), VecU8_to_span(&filename)); + GeneratedHeader head = begin_header(VecU8_to_span(&path)); + VecU8_append_span(&head.result, dependencies); + VecU8_append_span(&head.result, cstr("\n\n")); + VecU8_append_vec(&head.result, generate_result_template_inst(OkT, ErrT, ok_t_primitive, err_t_primitive)); + finish_header(head); + VecU8_drop(path); + VecU8_drop(filename); +} + typedef struct{ SpanU8 T; bool t_ptr; @@ -636,6 +724,7 @@ void generate_Option_templ_inst_guarded_header( VecU8 path = VecU8_fmt("%s/%s%sOption%s.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), op.T); GeneratedHeader head = begin_header(VecU8_to_span(&path)); VecU8_drop(path); + VecU8_append_span(&head.result, cstr("#include \"../../")); int to_my_layer = get_number_of_parts_in_header_namespace(bonus_ns); for (int i = 0; i < to_my_layer; i++) diff --git a/src/l1/core/int_primitives.h b/src/l1/core/int_primitives.h index 03f48cf..fe7a667 100644 --- a/src/l1/core/int_primitives.h +++ b/src/l1/core/int_primitives.h @@ -3,6 +3,7 @@ #include #include +#include typedef uint8_t U8; typedef uint16_t U16; diff --git a/src/l1/core/uint_segments.h b/src/l1/core/uint_segments.h new file mode 100644 index 0000000..8e57260 --- /dev/null +++ b/src/l1/core/uint_segments.h @@ -0,0 +1,29 @@ +#ifndef prototype1_src_l1_core_uint_segments_h +#define prototype1_src_l1_core_uint_segments_h + +#include "int_primitives.h" + +typedef struct { + U64 start; + U64 len; +} U64Segment; + +bool U64Segment_equal_U64Segment(const U64Segment* A, const U64Segment* B){ + return A->start == B->start && A->len == B->len; +} + +bool U64Segment_equal_by_start(const U64Segment* A, const U64Segment* B){ + return A->start == B->start; +} + +bool U64Segment_less_by_start(const U64Segment* A, const U64Segment* B){ + return A->start < B->start; +} + +bool U64Segment_less_by_len_and_start(const U64Segment* A, const U64Segment* B){ + if (A->len == B->len) + return A->start < B->start; + return A->len < B->len; +} + +#endif \ No newline at end of file diff --git a/src/l1/core/util.h b/src/l1/core/util.h index dfe2826..5011224 100644 --- a/src/l1/core/util.h +++ b/src/l1/core/util.h @@ -2,7 +2,6 @@ #define PROTOTYPE1_SRC_CORE_UTIL_H #include -#include #include #include #include diff --git a/src/l1/marie/geom_alg_utils.h b/src/l1/marie/geom_alg_utils.h index 2cb162b..dd26bd2 100644 --- a/src/l1/marie/geom_alg_utils.h +++ b/src/l1/marie/geom_alg_utils.h @@ -54,6 +54,13 @@ typedef struct { vec2 v2; } MarieTriangle; +MarieTriangle MarieTriangle_mat3x2_mul_pos(MarieTriangle self, mat3x2 trop) { + return (MarieTriangle){ + .v0 = mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), + .v1 = mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), + .v2 = mat3x2_mul_vec3(trop, vec2_and_one(self.v2))}; +} + #include "../../../gen/l1/eve/marie/VecMarieTriangle.h" typedef struct { @@ -62,6 +69,14 @@ typedef struct { MariePlaneVertAttr v2; } MarieTriangleAttr; +MarieTriangleAttr MarieTriangle_goto_nat_cords_pres_par(MarieTriangle self, mat3x2 trop) { + return (MarieTriangleAttr){ + {mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), {self.v0.x, self.v0.y, 0, 0}}, + {mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), {self.v1.x, self.v1.y, 0, 0}}, + {mat3x2_mul_vec3(trop, vec2_and_one(self.v2)), {self.v2.x, self.v2.y, 0, 0}}, + }; +} + #include "../../../gen/l1/eve/marie/VecMarieTriangleAttr.h" vec2 marie_intersect_lines(vec2 A1, vec2 B1, vec2 A2, vec2 B2) { diff --git a/src/l1_5/anne/l1_5_templ_very_base.h b/src/l1_5/anne/l1_5_templ_very_base.h index 9b12e22..185371b 100644 --- a/src/l1_5/anne/l1_5_templ_very_base.h +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -4,12 +4,33 @@ #include "../codegen/rb_tree_set_map_template_inst.h" void generate_l1_5_template_instantiation_for_base_types(){ - SpanU8 l = cstr("l1_5"); - SpanU8 ns = cstr(""); + SpanU8 l = cstr("l1_5"), ns = cstr(""); generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_U64.h\""), (set_instantiation_op){.T = cstr("U64"), .t_integer = true}); generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_S64.h\""), (set_instantiation_op){.T = cstr("S64"), .t_integer = true}); + + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, + cstr("#include \"../l1/VecAndSpan_U64.h\""), + (set_instantiation_op){.T = cstr("U64"), .t_integer = true}); + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, + cstr("#include \"../l1/VecAndSpan_S64.h\""), + (set_instantiation_op){.T = cstr("S64"), .t_integer = true}); + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + (set_instantiation_op){ + .T = cstr("U64Segment"), + .t_primitive = true, + .alternative_equal = cstr("U64Segment_equal_by_start"), + .alternative_less = cstr("U64Segment_less_by_start"), + .alternative_comp_set_name_embed = cstr("Start") + }); + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + (set_instantiation_op){ + .T = cstr("U64Segment"), + .t_primitive = true, + .alternative_less = cstr("U64Segment_less_by_len_and_start"), + .alternative_comp_set_name_embed = cstr("LenAndStart") + }); } #endif diff --git a/src/l1_5/codegen/all_set_map_templ_util_inst.h b/src/l1_5/codegen/all_set_map_templ_util_inst.h index 1c0cd06..6b2b0fa 100644 --- a/src/l1_5/codegen/all_set_map_templ_util_inst.h +++ b/src/l1_5/codegen/all_set_map_templ_util_inst.h @@ -3,8 +3,6 @@ #include "../../l1/codegen/util_template_inst.h" -// todo: continue from here - /* We assume that T is trivially movable */ typedef struct { SpanU8 T; @@ -12,16 +10,26 @@ typedef struct { bool t_integer; bool t_primitive; bool t_clonable; + SpanU8 alternative_equal; + SpanU8 alternative_less; + SpanU8 alternative_comp_set_name_embed; } set_instantiation_op; void set_instantiation_op_fix(set_instantiation_op* self){ - assert(self->T.len > 0); if (self->t_ptr) self->t_integer = true; if (self->t_integer) self->t_primitive = true; if (self->t_primitive) self->t_clonable = true; + assert(self->T.len > 0); + assert(!self->t_integer || self->alternative_equal.len == 0); + assert(!self->t_integer || self->alternative_less.len == 0); + assert((self->alternative_less.len == 0 && self->alternative_equal.len == 0 + && self->alternative_comp_set_name_embed.len == 0 + )||( + self->alternative_comp_set_name_embed.len != 0 && + (self->alternative_less.len != 0 || self->alternative_equal.len != 0))); } #endif diff --git a/src/l1_5/codegen/rb_tree_set_map_template_inst.h b/src/l1_5/codegen/rb_tree_set_map_template_inst.h index cd26652..4900119 100644 --- a/src/l1_5/codegen/rb_tree_set_map_template_inst.h +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -7,6 +7,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key != self->el.buf[cur - 1]"); + if (op.alternative_equal.len != 0) + return VecU8_fmt("!%s(&key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("!%s_equal_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -14,6 +16,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiatio NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key < self->el.buf[cur - 1]"); + if (op.alternative_less.len != 0) + return VecU8_fmt("%s(&key, &self->el.buf[cur - 1])", op.alternative_less); return VecU8_fmt("%s_less_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -22,6 +26,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op NODISCARD VecU8 codegen_rb_tree_set_key_ref_NOT_EQUAL_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key != self->el.buf[cur - 1]"); + if (op.alternative_equal.len != 0) + return VecU8_fmt("!%s(key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("!%s_equal_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -29,6 +35,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_ref_NOT_EQUAL_element(set_instantiation_ NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key == self->el.buf[cur - 1]"); + if (op.alternative_equal.len != 0) + return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("%s_equal_%s(ref, &self->el.buf[cur - 1])", op.T, op.T); } @@ -36,6 +44,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op o NODISCARD VecU8 codegen_rb_tree_set_key_ref_LESS_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key < self->el.buf[cur - 1]"); + if (op.alternative_less.len != 0) + return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_less); return VecU8_fmt("%s_less_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -86,6 +96,12 @@ NODISCARD VecU8 codegen_rb_tree_set_taking_ref_t_argument(set_instantiation_op o return !op.t_integer ? VecU8_fmt("const %s*", op.T) : VecU8_from_span(op.T); } +NODISCARD VecU8 get_name_of_rb_tree_set_structure(set_instantiation_op op){ + if (op.alternative_comp_set_name_embed.len) + return VecU8_fmt("BuffRBTreeBy%s_Set%s", op.alternative_comp_set_name_embed, op.T); + return VecU8_fmt("BuffRBTree_Set%s", op.T); +} + /* Generates methods _insert() _pop_substitute() _erase_substitute() for SetT * Takes ownership of strings Tc, Fc */ void codegen_append_rb_tree_set_insert_kind_method( @@ -223,7 +239,7 @@ void codegen_append_rb_tree_set_erase_kind_method( NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op op){ set_instantiation_op_fix(&op); VecU8 res = VecU8_new(); - VecU8 g_set = VecU8_fmt("BuffRBTree_Set%s", op.T); + VecU8 g_set = get_name_of_rb_tree_set_structure(op); SpanU8 set = VecU8_to_span(&g_set); VecU8_append_vec(&res, VecU8_fmt( "typedef struct {\n" @@ -294,7 +310,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op } VecU8_append_vec(&res, VecU8_fmt( - "U64 %s_find(const %s* self, %v key) {\n" /* set, set taking_ref_t_argument */ + "U64 %s_find(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ SPACE "U64 cur = self->root;\n" SPACE "while (cur != 0 && %v) {\n" /* key reference not equal cur element */ SPACE SPACE "if (%v) {\n" /* key reference less than cue element */ @@ -379,20 +395,111 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op SPACE "return self->root != 0 ? RBTree_maximum_in_subtree(self->tree.buf, self->root) : 0;\n" "}\n\n", set, set)); - // todo: continue from here. Implement method _pop_and_substitute() + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_max_less(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_less = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE SPACE "if (cur == 0)\n" + SPACE SPACE SPACE SPACE "return last_less;\n" + SPACE SPACE SPACE "while (self->tree.buf[cur].right != 0)\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "last_less = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_less;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); - // todo: All the other methods are secondary in importance + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_max_less_or_eq(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_less = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "last_less = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_less;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); + + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_min_grtr(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_grtr = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE SPACE "if (cur == 0)\n" + SPACE SPACE SPACE SPACE "return last_grtr;\n" + SPACE SPACE SPACE "while (self->tree.buf[cur].left != 0)\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "last_grtr = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_grtr;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); + + + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_min_grtr_or_eq(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_grtr = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "last_grtr = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_grtr;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); VecU8_drop(g_set); return res; } -void generate_rb_tree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, option_template_instantiation_op op) { +void generate_rb_tree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, set_instantiation_op op) { VecU8 text = VecU8_from_cstr("/* Automatically generated file. Do not edit it.\n" " * Do not include it in more than one place */\n\n"); - VecU8_append_vec(&text, generate_OptionT_struct_and_methods(op)); - VecU8 nt_path = VecU8_fmt("%s/eve/%s/BuffRBTree_Set%s%c", layer, bonus_ns, op.T, 0); + VecU8_append_vec(&text, generate_rb_tree_Set_template_instantiation(op)); + VecU8 nt_path = VecU8_fmt("%s/eve/%s/%s.h%c", layer, bonus_ns, op.T, get_name_of_rb_tree_set_structure(op)); write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text)); VecU8_drop(nt_path); VecU8_drop(text); @@ -402,7 +509,8 @@ void generate_rb_tree_Set_templ_inst_guarded_header( SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, set_instantiation_op op ){ assert(layer.len > 1); - VecU8 path = VecU8_fmt("%s/%s%sBuffRBTree_Set%s.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), op.T); + VecU8 path = VecU8_fmt("%s/%s%s%v.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), + get_name_of_rb_tree_set_structure(op)); GeneratedHeader head = begin_header(VecU8_to_span(&path)); VecU8_drop(path); VecU8_append_span(&head.result, cstr("#include \"../../")); diff --git a/src/l1_5/codegen/trait_wrap_boil.h b/src/l1_5/codegen/trait_wrap_boil.h index 0c9dded..97b5332 100644 --- a/src/l1_5/codegen/trait_wrap_boil.h +++ b/src/l1_5/codegen/trait_wrap_boil.h @@ -42,12 +42,13 @@ NODISCARD VecU8 generate_trait_table_structure(NamedTraitDefRecordRef trait){ } typedef struct { + NamedTraitDefRecordRef trait; bool box; bool ref; bool mut_ref; } trait_wrapper_boil_options; -NODISCARD VecU8 generate_trait_wrapper_boilerplate(NamedTraitDefRecordRef trait, trait_wrapper_boil_options op) { +NODISCARD VecU8 generate_trait_wrapper_boilerplate(trait_wrapper_boil_options op) { VecU8 res = VecU8_new(); // todo: write it return res; diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index 44771f0..b01d103 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -121,7 +121,7 @@ void RBTree_steal_neighbours(RBTreeNode* tree, U64* root, U64 fr, U64 to){ /* helper function (used in _erase, _find_min methods). It is assumed that s is not null. * Guaranteed to return no-null */ -U64 RBTree_minimum_in_subtree(RBTreeNode* tree, U64 s){ +U64 RBTree_minimum_in_subtree(const RBTreeNode* tree, U64 s){ assert(s != 0); while (tree[s].left != 0) s = tree[s].left; @@ -131,7 +131,7 @@ U64 RBTree_minimum_in_subtree(RBTreeNode* tree, U64 s){ /* helper function (used in _find_max, _find_prev methods). It is assumed that s is not null. * Guaranteed to return no-null */ -U64 RBTree_maximum_in_subtree(RBTreeNode* tree, U64 s){ +U64 RBTree_maximum_in_subtree(const RBTreeNode* tree, U64 s){ assert(s != 0); while (tree[s].right != 0) s = tree[s].right; diff --git a/src/l2/margaret/png_pixel_masses.h b/src/l2/margaret/png_pixel_masses.h deleted file mode 100644 index 9fbc9c2..0000000 --- a/src/l2/margaret/png_pixel_masses.h +++ /dev/null @@ -1,254 +0,0 @@ -#ifndef PROTOTYPE1_SRC_L2_MARGARET_PNG_PIXEL_MASSES_H -#define PROTOTYPE1_SRC_L2_MARGARET_PNG_PIXEL_MASSES_H - -#include "../../../gen/l1/pixel_masses.h" -#include "../../l1/core/util.h" -#include "../../l1/core/VecU8_as_str.h" -#include - -// todo: generate all of this automaticcally - -void margaret_libpng_h_error_cb(png_structp pngshka, png_const_charp err) { - printf("[!] %s\n", err); -} - -void margaret_libpng_h_warning_cb(png_structp pngshka, png_const_charp warning) { - printf("[.] %s\n", warning); -} - -typedef struct { - Result_variant variant; - VecU8 err; -} ResultVoidOrVecU8; - -void ResultVoidOrVecU8_drop(ResultVoidOrVecU8 self) { - if (self.variant == Result_Err) - VecU8_drop(self.err); -} - -ResultVoidOrVecU8 TextureDataR8G8B8A8_write_to_png(const TextureDataR8G8B8A8* self, SpanU8 filename) { - VecU8 nt_filename = VecU8_fmt("%s%c", filename, 0); - FILE *fp = fopen((CSTR)nt_filename.buf, "wb"); - VecU8_drop(nt_filename); - if (!fp) { - return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_fmt("Unable to open file %s", filename)}; - } - png_structp pngshka = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb); - if (!pngshka) - abortf("png_create_write_struct"); - png_infop info = png_create_info_struct(pngshka); - if (!info) - abortf("png_create_info_struct"); - - png_bytep* row_pointers = NULL; - - if (setjmp(png_jmpbuf(pngshka))){ - png_destroy_write_struct(&pngshka, &info); - fclose(fp); - free(row_pointers); - return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr("Some png error happened")}; - } - png_init_io(pngshka, fp); - - U32 width = self->width; - U32 height = TextureDataR8G8B8A8_get_height(self); - - png_set_IHDR(pngshka, info, width, height, 8, PNG_COLOR_TYPE_RGBA, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - row_pointers = calloc(height, sizeof(row_pointers)); - for (U32 y = 0; y < height; y++) { - row_pointers[height - 1 - y] = (png_bytep)((TextureDataR8G8B8A8_at(self, 0, y))); - } - png_set_rows(pngshka, info, row_pointers); - png_write_png(pngshka, info, 0, NULL); - /* No more errors */ - free(row_pointers); - png_destroy_write_struct(&pngshka, &info); - fclose(fp); - return (ResultVoidOrVecU8){.variant = Result_Ok}; -} - -/* Aborts on error */ -void TextureDataR8G8B8A8_write_to_png_nofail(const TextureDataR8G8B8A8* self, SpanU8 filename) { - ResultVoidOrVecU8 res = TextureDataR8G8B8A8_write_to_png(self, filename); - if (res.variant == Result_Err) { - SpanU8_fprint(VecU8_to_span(&res.err), stderr); - abortf(" TextureDataR8G8B8A8_write_to_png\n"); - } -} - -/* This structure will be pinned */ -typedef struct { - FILE* fp; - png_structp pngshka; - png_infop info; - png_infop end_info; -} MargaretPromisedPngR8G8B8A8; - -void MargaretPromisedPngR8G8B8A8_drop(MargaretPromisedPngR8G8B8A8 self) { - png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info); - fclose(self.fp); -} - -typedef struct { - Result_variant variant; - union { - MargaretPromisedPngR8G8B8A8 ok; - VecU8 err; - }; -} ResultMargaretPromisedPngR8G8B8A8OrVecU8; - -void ResultMargaretPromisedPngR8G8B8A8OrVecU8_drop(ResultMargaretPromisedPngR8G8B8A8OrVecU8 self) { - if (self.variant == Result_Ok) - MargaretPromisedPngR8G8B8A8_drop(self.ok); - else - VecU8_drop(self.err); -} - -ResultMargaretPromisedPngR8G8B8A8OrVecU8 MargaretPromisedPngR8G8B8A8_begin(SpanU8 filename) { - VecU8 nt_filename = VecU8_fmt("%s%c", filename, 0); - FILE* fp = fopen((CSTR)nt_filename.buf, "rb"); - VecU8_drop(nt_filename); - if (!fp) { - return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Err, - .err = VecU8_fmt("Unable to open file %s", filename)}; - } - png_structp pngshka = png_create_read_struct(PNG_LIBPNG_VER_STRING, - NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb); - if (!pngshka) - abortf("png_create_read_struct"); - png_infop info = png_create_info_struct(pngshka); - if (!info) - abortf("png_create_info_struct"); - png_infop end_info = png_create_info_struct(pngshka); - if (!end_info) - abortf("png_create_info_struct"); - if (setjmp(png_jmpbuf(pngshka))) { - png_destroy_read_struct(&pngshka, &info, &end_info); - fclose(fp); - return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Err, - .err = VecU8_from_cstr("Some png error happened")}; - } - png_init_io(pngshka, fp); - png_read_info(pngshka, info); - U32 width, height; - int bit_depth, color_type; - assert(png_get_IHDR(pngshka, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL)); - - if (bit_depth == 16) { - png_set_strip_16(pngshka); - } - if (color_type == PNG_COLOR_TYPE_GRAY) { - if (bit_depth == 1 || bit_depth == 2 || bit_depth == 4) { - png_set_expand_gray_1_2_4_to_8(pngshka); - } - png_set_gray_to_rgb(pngshka); - if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(pngshka); - } else { - png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER); - } - } else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(pngshka); - } else if (color_type == PNG_COLOR_TYPE_RGB) { - if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(pngshka); - } else { - png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER); - } - } else if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(pngshka); - - if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(pngshka); - } else { - png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER); - } - } - png_read_update_info(pngshka, info); - - return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Ok, - .ok = (MargaretPromisedPngR8G8B8A8){.fp = fp, .pngshka = pngshka, .info = info, .end_info = end_info}}; -} - -SizeOfRectangleU32 MargaretPromisedPngR8G8B8A8_get_extent(const MargaretPromisedPngR8G8B8A8* self) { - U32 width, height; - int bit_depth, color_type; - assert(png_get_IHDR(self->pngshka, self->info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL)); - return (SizeOfRectangleU32){width, height}; -} - - -size_t MargaretPromisedPngR8G8B8A8_get_needed_buffer_size(const MargaretPromisedPngR8G8B8A8* self) { - SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(self); - return 4 * dim.width * dim.height; -} - -ResultVoidOrVecU8 MargaretPromisedPngR8G8B8A8_finish(MargaretPromisedPngR8G8B8A8 self, void* buffer) { - SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(&self); - - png_bytep* row_pointers = NULL; - if (setjmp(png_jmpbuf(self.pngshka))) { - png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info); - fclose(self.fp); - free(row_pointers); - return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr("Some png error happened")}; - } - - row_pointers = calloc(dim.height, sizeof(row_pointers)); - for (U32 y = 0; y < dim.height; y++) { - row_pointers[dim.height - 1 - y] = ((png_bytep)buffer) + 4 * dim.width * y; - } - png_read_image(self.pngshka, row_pointers); - png_read_end(self.pngshka, self.end_info); - /* No more errors */ - png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info); - fclose(self.fp); - free(row_pointers); - return (ResultVoidOrVecU8){.variant = Result_Ok}; -} - -// todo: move it to pixel_masses.h (and also generate result types automatically -typedef struct { - Result_variant variant; - union { - TextureDataR8G8B8A8 ok; - VecU8 err; - }; -} ResultTextureDataR8G8B8A8OrVecU8; - -void ResultTextureDataR8G8B8A8OrVecU8_drop(ResultTextureDataR8G8B8A8OrVecU8 self) { - if (self.variant == Result_Ok) - TextureDataR8G8B8A8_drop(self.ok); - else - VecU8_drop(self.err); -} - -ResultTextureDataR8G8B8A8OrVecU8 MargaretPromisedPngR8G8B8A8_finish_into_TextureDataR8G8B8A8(MargaretPromisedPngR8G8B8A8 self) { - SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(&self); - TextureDataR8G8B8A8 tex = TextureDataR8G8B8A8_new(dim.width, dim.height); - ResultVoidOrVecU8 res = MargaretPromisedPngR8G8B8A8_finish(self, tex.pixels.buf); - if (res.variant == Result_Err) - return (ResultTextureDataR8G8B8A8OrVecU8){.variant = Result_Err, .err = res.err}; - return (ResultTextureDataR8G8B8A8OrVecU8){.variant = Result_Ok, .ok = tex}; -} - -/* aborts on error */ -TextureDataR8G8B8A8 TextureDataR8G8B8A8_read_from_png_nofail(SpanU8 name) { - ResultMargaretPromisedPngR8G8B8A8OrVecU8 res_1 = MargaretPromisedPngR8G8B8A8_begin(name); - if (res_1.variant == Result_Err) { - SpanU8_fprint(VecU8_to_span(&res_1.err), stderr); - abortf(" MargaretPromisedPngR8G8B8A8_begin\n"); - } - /* res_1 invalidated, we moved ownership to _finish methos */ - ResultTextureDataR8G8B8A8OrVecU8 res_2 = MargaretPromisedPngR8G8B8A8_finish_into_TextureDataR8G8B8A8(res_1.ok); - if (res_2.variant == Result_Err) { - SpanU8_fprint(VecU8_to_span(&res_2.err), stderr); - abortf(" MargaretPromisedPngR8G8B8A8_finish (into TextureData)\n"); - } - return res_2.ok; -} - -#endif \ No newline at end of file diff --git a/src/l2/margaret/vulkan_utils.h b/src/l2/margaret/vulkan_utils.h index 277b7e2..b61c2df 100644 --- a/src/l2/margaret/vulkan_utils.h +++ b/src/l2/margaret/vulkan_utils.h @@ -1027,6 +1027,11 @@ MargaretImageInMemoryInfo margaret_prep_image_mem_info_of_gpu_texture_srgba(uint .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT }; } +MargaretImageInMemoryInfo margaret_prep_image_mem_info_of_gpu_texture_unorm_8(uint32_t w, uint32_t h){ + return (MargaretImageInMemoryInfo){ .width = w, .height = h, .format = VK_FORMAT_R8_UNORM, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT }; +} + MargaretImageInMemoryInfo margaret_prep_image_mem_info_of_gpu_texture_unorm_32(uint32_t w, uint32_t h) { return (MargaretImageInMemoryInfo){ .width = w, .height = h, .format = VK_FORMAT_R8G8B8A8_UNORM, .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT }; @@ -1103,98 +1108,107 @@ void margaret_copy_buffer_imm ( margaret_end_and_submit_and_free_command_buffer(device, command_pool, graphics_queue, cmd_buffer); } -// todo: get rid of this crap. I can do better -// For application initialization purposes only -void transition_image_layout ( - VkDevice device, VkCommandPool command_pool, VkQueue graphics_queue, - VkImage image, VkImageLayout old_layout, VkImageLayout new_layout, - VkPipelineStageFlags src_stage_mask, VkAccessFlags src_access_mask, - VkPipelineStageFlags dst_stage_mask, VkAccessFlags dst_access_mask - ) { - VkCommandBuffer cmd_buffer = margaret_alloc_and_begin_single_use_command_buffer(device, command_pool); - VkImageMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = src_access_mask, - .dstAccessMask = dst_access_mask, - .oldLayout = old_layout, - .newLayout = new_layout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange = (VkImageSubresourceRange){ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - vkCmdPipelineBarrier(cmd_buffer, src_stage_mask, dst_stage_mask, - // Flags - 0, - 0, NULL, - 0, NULL, - 1, &barrier +typedef struct { + size_t host_mem_buff_offset; + const MargaretImageInMemoryInfo* dst_image; +} MargaretCommandForImageCopying; + +#include "../../../gen/l1/eve/margaret/VecAndSpan_MargaretCommandForImageCopying.h" + +#include "../../../gen/l1/vulkan/VecVkImageMemoryBarrier.h" + +/* (destination_stage_mask, destination_access_mask) are probably + * (VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT) */ +void margaret_rerecord_cmd_buff_for_texture_init ( + VkCommandBuffer command_buffer, VkBuffer host_mem_buffer, + SpanMargaretCommandForImageCopying commands, + VkPipelineStageFlags destination_stage_mask, VkAccessFlags destination_access_mask + ){ + if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS) + abortf("vkResetCommandBuffer\n"); + VkCommandBufferBeginInfo begin_info = {.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,}; + if (vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) + abortf("vkBeginCommandBuffer\n"); + VecVkImageMemoryBarrier barriers = VecVkImageMemoryBarrier_new_reserved(commands.len); + for (size_t i = 0; i < commands.len; i++) { + MargaretCommandForImageCopying img = commands.data[i]; + VecVkImageMemoryBarrier_append(&barriers, (VkImageMemoryBarrier){ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = img.dst_image->image, + .subresourceRange = (VkImageSubresourceRange){ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }); + } + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, /* Flags */ + 0, NULL, 0, NULL, + barriers.len, barriers.buf); + barriers.len = 0; /* It's ok, VkImageMemoryBarrier is primitive */ + for (size_t i = 0; i < commands.len; i++) { + MargaretCommandForImageCopying img = commands.data[i]; + VkBufferImageCopy region = { + .bufferOffset = img.host_mem_buff_offset, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = (VkImageSubresourceLayers){ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .imageOffset = {0, 0, 0}, + .imageExtent = { + .width = img.dst_image->width, + .height = img.dst_image->height, + .depth = 1 + }, + }; + vkCmdCopyBufferToImage(command_buffer, host_mem_buffer, img.dst_image->image, + // We assume that image was already transitioned to optimal layout transition_image_layout + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } + /* filling buffers Vec again */ + for (size_t i = 0; i < commands.len; i++) { + MargaretCommandForImageCopying img = commands.data[i]; + VecVkImageMemoryBarrier_append(&barriers, (VkImageMemoryBarrier){ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = destination_access_mask, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = img.dst_image->image, + .subresourceRange = (VkImageSubresourceRange){ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }); + } + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, destination_stage_mask, + 0, /* Flags */ + 0, NULL, 0, NULL, + barriers.len, barriers.buf ); - margaret_end_and_submit_and_free_command_buffer(device, command_pool, graphics_queue, cmd_buffer); + VecVkImageMemoryBarrier_drop(barriers); + if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS) + abortf("vkEndCommandBuffer"); } -// For application initialization purposes only -void margaret_copy_buffer_to_trans_dst_optimal_image ( - VkDevice device, VkCommandPool command_pool, VkQueue graphics_queue, - const MargaretImageInMemoryInfo* dst_image, VkBuffer src_buffer - ) { - VkCommandBuffer cmd_buffer = margaret_alloc_and_begin_single_use_command_buffer(device, command_pool); - VkBufferImageCopy region = { - .bufferOffset = 0, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = (VkImageSubresourceLayers){ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .imageOffset = {0, 0, 0}, - .imageExtent = { - .width = dst_image->width, - .height = dst_image->height, - .depth = 1 - }, - }; - vkCmdCopyBufferToImage(cmd_buffer, src_buffer, dst_image->image, - // We assume that image was already transitioned to optimal layout transition_image_layout - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - - margaret_end_and_submit_and_free_command_buffer(device, command_pool, graphics_queue, cmd_buffer); -} - -// todo: AHFHDF EW WHAT IS THAT??? -// For application initialization purposes only -void margaret_copy_buffer_to_texture_for_frag_shader_imm( - VkDevice device, VkCommandPool command_pool, VkQueue graphics_queue, - const MargaretImageInMemoryInfo* dst_image, VkBuffer src_buffer - ) { - transition_image_layout(device, command_pool, graphics_queue, dst_image->image, - // previous and new layouts - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - // src stage and access - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, - // destination stage and access - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT - ); - margaret_copy_buffer_to_trans_dst_optimal_image(device, command_pool, graphics_queue, dst_image, src_buffer); - transition_image_layout(device, command_pool, graphics_queue, dst_image->image, - // previous and new layouts - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, - // src stage and access - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, - // destination stage and access - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT - ); -} - -// todo: cjafhs WHAT IS THIS?? I need to remove this. I can do better than this // For texture VkImageView margaret_create_view_for_image ( VkDevice device, const MargaretImageInMemoryInfo* image, VkImageAspectFlags aspect_flags diff --git a/src/l2/marie/rasterization.h b/src/l2/marie/rasterization.h index ca433c6..78bb141 100644 --- a/src/l2/marie/rasterization.h +++ b/src/l2/marie/rasterization.h @@ -24,7 +24,7 @@ MarieLinearFun marie_gen_scanline_borderline(vec2 a, vec2 b) { /* Utility function, that is used by rasterization function. * Don't use in your code*/ -void marie_rasterize_line_in_triangle_with_attr_sorted( +void marie_h_rasterize_only_one_line_of_triangle( vec2 v0pos, vec2 v1pos, vec2 v2pos, S32 L, S32 R, MarieVertAttr P0, MarieVertAttr P1, MarieVertAttr P2, float S, S32 my, FnMarieRasterizerCallback cb ) { @@ -44,7 +44,7 @@ void marie_rasterize_line_in_triangle_with_attr_sorted( /* Utility function, that is used by rasterization function. * Don't use in your code*/ -void marie_scan_rast_line_in_triangle_with_attr_sorted( +void marie_h_rasterize_half_of_triangle( vec2 v0pos, vec2 v1pos, vec2 v2pos, S32 below, S32 above, MarieVertAttr P0, MarieVertAttr P1, MarieVertAttr P2, MarieLinearFun left_border, MarieLinearFun right_border, FnMarieRasterizerCallback cb ) { @@ -66,7 +66,9 @@ void marie_scan_rast_line_in_triangle_with_attr_sorted( } } -void marie_rasterize_triangle_with_attr_sorted( +/* Utility function, that is used by rasterization function. + * Don't use in your code*/ +void marie_h_rasterize_triangle_with_attr_sorted( MariePlaneVertAttr v0, MariePlaneVertAttr v1, MariePlaneVertAttr v2, FnMarieRasterizerCallback cb ) { float S = marie_surface(v0.pos, v1.pos, v2.pos); @@ -89,22 +91,22 @@ void marie_rasterize_triangle_with_attr_sorted( MarieLinearFun line_12 = marie_gen_scanline_borderline(v1.pos, v2.pos); MarieLinearFun line_20 = marie_gen_scanline_borderline(v2.pos, v0.pos); - marie_rasterize_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy0, cb); + marie_h_rasterize_only_one_line_of_triangle(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy0, cb); if (sy0 + 1 < sy1) { MarieLinearFun left_border = S > 0 ? line_20 : line_01; MarieLinearFun right_border = S > 0 ? line_01 : line_20; - marie_scan_rast_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, sy0, sy1, P0, P1, P2, left_border, right_border, cb); + marie_h_rasterize_half_of_triangle(v0.pos, v1.pos, v2.pos, sy0, sy1, P0, P1, P2, left_border, right_border, cb); } if (sy1 > sy0) { - marie_rasterize_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy1, cb); + marie_h_rasterize_only_one_line_of_triangle(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy1, cb); } if (sy1 + 1 < sy2) { MarieLinearFun left_border = S > 0 ? line_20 : line_12; MarieLinearFun right_border = S > 0 ? line_12 : line_20; - marie_scan_rast_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, sy1, sy2, P0, P1, P2, left_border, right_border, cb); + marie_h_rasterize_half_of_triangle(v0.pos, v1.pos, v2.pos, sy1, sy2, P0, P1, P2, left_border, right_border, cb); } if (sy2 > sy1) { - marie_rasterize_line_in_triangle_with_attr_sorted(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy2, cb); + marie_h_rasterize_only_one_line_of_triangle(v0.pos, v1.pos, v2.pos, L, R, P0, P1, P2, S, sy2, cb); } } void marie_rasterize_triangle_with_attr( @@ -112,22 +114,22 @@ void marie_rasterize_triangle_with_attr( ) { if (a.pos.y < b.pos.y) { if (b.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(a, b, c, cb); + marie_h_rasterize_triangle_with_attr_sorted(a, b, c, cb); } else { if (a.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(a, c, b, cb); + marie_h_rasterize_triangle_with_attr_sorted(a, c, b, cb); } else { - marie_rasterize_triangle_with_attr_sorted(c, a, b, cb); + marie_h_rasterize_triangle_with_attr_sorted(c, a, b, cb); } } } else { if (a.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(b, a, c, cb); + marie_h_rasterize_triangle_with_attr_sorted(b, a, c, cb); } else { if (b.pos.y < c.pos.y) { - marie_rasterize_triangle_with_attr_sorted(b, c, a, cb); + marie_h_rasterize_triangle_with_attr_sorted(b, c, a, cb); } else { - marie_rasterize_triangle_with_attr_sorted(c, b, a, cb); + marie_h_rasterize_triangle_with_attr_sorted(c, b, a, cb); } } } diff --git a/src/l2/marie/texture_processing.h b/src/l2/marie/texture_processing.h index 26b177d..c7db612 100644 --- a/src/l2/marie/texture_processing.h +++ b/src/l2/marie/texture_processing.h @@ -2,38 +2,12 @@ #define PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H #include "../../../gen/l1/pixel_masses.h" - -void TextureDataR8G8B8A8_print(const TextureDataR8G8B8A8* self) { - U64 width = self->width; - U64 height = TextureDataR8G8B8A8_get_height(self); - U64 cell_width = MAX_U64(1, width / 350); - U64 cell_height = MAX_U64(1, cell_width * 14 / 8); - for (U64 CY = 0; CY < height; CY += cell_height) { - for (U64 CX = 0; CX < width; CX += cell_width) { - float lum = 0; - for (U64 j = 0; j < cell_height; j++) { - U64 y = cell_height * CY + j; - if (y >= height) - continue; - for (U64 i = 0; i < cell_width; i++) { - U64 x = cell_width * CX + i; - if (x >= width) - continue; - cvec4 pix = *TextureDataR8G8B8A8_at(self, x, y); - lum += (float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f; - } - } - lum /= (float)cell_width * (float)cell_height; - printf("%s", lum > 0.95 ? "@" : (lum > 0.8 ? "#" : (lum > 0.65 ? "*" : (lum > 0.4 ? "_" : (lum > 0.2 ? "." : " "))))); - } - printf("\n"); - } -} +#include "rasterization.h" /* Fixes several of my generated textures */ NODISCARD TextureDataR8G8B8A8 TextureDataR8G8B8A8_expand_nontransparent_1px(const TextureDataR8G8B8A8* self) { S32 width = (S32)self->width; - S32 height = (S32)TextureDataR8G8B8A8_get_height(self); + S32 height = (S32)self->height; TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width, height); // S32 chain[9][2] = {{0, 0}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}}; for (S32 y = 0; y < height; y++) { @@ -62,4 +36,44 @@ NODISCARD TextureDataR8G8B8A8 TextureDataR8G8B8A8_expand_nontransparent_1px(cons return res; } +vec4 marie_color_cvec4_to_vec4(cvec4 clr) { + return (vec4){(float)clr.x / 255, (float)clr.y / 255, (float)clr.z / 255, (float)clr.w / 255}; +} + +cvec4 marie_color_vec4_to_cvec4(vec4 clr) { + return (cvec4){(U8)roundf(clr.x * 255), (U8)roundf(clr.y * 255), (U8)roundf(clr.z * 255), (U8)roundf(clr.w * 255)}; +} + +vec3 marie_color_cvec3_to_vec3(cvec3 clr) { + return (vec3){(float)clr.x / 255, (float)clr.y / 255, (float)clr.z / 255}; +} + +cvec3 marie_color_vec3_to_cvec3(vec3 clr) { + return (cvec3){(U8)roundf(clr.x * 255), (U8)roundf(clr.y * 255), (U8)roundf(clr.z * 255)}; +} + +typedef struct { + TextureDataR8G8B8A8* self; + cvec4 pixel; +} TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest; + +void TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest(void* ug, S32 x, S32 y, vec4 attr) { + TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest *g = ug; + if (TextureDataR8G8B8A8_is_inside(g->self, x, y)) + *TextureDataR8G8B8A8_mat(g->self, x, y) = g->pixel; +} + +/* Given triangle is not natural : it is from parameter space */ +void TextureDataR8G8B8A8_draw_triangle_of_one_color( + TextureDataR8G8B8A8* self, vec3 color, MarieTriangle param_triang, mat3x2 trop + ) { + TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest aboba = + { self, marie_color_vec4_to_cvec4(vec3_and_one(color)) }; + MarieTriangle natural = MarieTriangle_mat3x2_mul_pos(param_triang, trop); + marie_rasterize_triangle_with_attr( + (MariePlaneVertAttr){natural.v0, {}}, (MariePlaneVertAttr){natural.v1, {}}, (MariePlaneVertAttr){natural.v2, {}}, + (FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest, + .guest = &aboba}); +} + #endif \ No newline at end of file diff --git a/src/l2/tests/r0/r0.c b/src/l2/tests/r0/r0.c index dd6c4f7..b7ddd8f 100644 --- a/src/l2/tests/r0/r0.c +++ b/src/l2/tests/r0/r0.c @@ -10,7 +10,8 @@ #include "../../../../gen/l_wl_protocols/xdg-shell-client.h" #include #include "../../../l1/system/creating_child_proc.h" -#include "../../margaret/png_pixel_masses.h" +#include "../../../../gen/l1/margaret/png_pixel_masses.h" +#include "../../../../gen/l1/VecAndSpan_U64.h" // todo: generate this structure in l2 typedef struct { @@ -269,6 +270,12 @@ PipelineHands create_graphics_pipeline_0( .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, }, + { + .binding = 3, + .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, @@ -787,12 +794,73 @@ void record_cmd_set_viewport_and_scissors(VkCommandBuffer command_buffer, VkExte vkCmdSetScissor(command_buffer, 0, 1, &scissor); } +typedef struct { + VkSemaphore in_frame_transfer_complete; + VkSemaphore image_available_semaphore; + VkSemaphore rendered_to_IT1_semaphore; + VkFence in_flight_fence; +} Jane_r0; + +NODISCARD Jane_r0 Jane_r0_create(VkDevice device) { + return (Jane_r0){ + .in_frame_transfer_complete = margaret_create_semaphore(device), + .image_available_semaphore = margaret_create_semaphore(device), + .rendered_to_IT1_semaphore = margaret_create_semaphore(device), + .in_flight_fence = margaret_create_fence(device, true) + }; +} + +void Jane_r0_destroy(VkDevice device, Jane_r0 jane) { + vkDestroyFence(device, jane.in_flight_fence, NULL); + vkDestroySemaphore(device, jane.rendered_to_IT1_semaphore, NULL); + vkDestroySemaphore(device, jane.image_available_semaphore, NULL); + vkDestroySemaphore(device, jane.in_frame_transfer_complete, NULL); +} + +// todo: handle case where presentation and graphics are from the same family +typedef struct { + VkQueue graphics_queue; + VkQueue presentation_queue; +} UsedVulkanQueues; + +typedef struct { + MargaretBufferInMemoryInfo vbo; + MargaretBufferInMemoryInfo ebo; + /* We store image in yet another meaningless buffer (will change it later) */ + TextureDataR8G8B8A8 reading_diffuse; + TextureDataR8G8B8A8 reading_normal; + TextureDataR8 reading_specular; + /* Filled during first (and the only) memory init */ + MargaretImageInMemoryInfo diffuse; + MargaretImageInMemoryInfo normal; + MargaretImageInMemoryInfo specular; + /* will be filled in later */ + VkImageView diffuse_view; + VkImageView normal_view; + VkImageView specular_view; + /* Each generic model has ti's own descriptor set + * It's because it has it's 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_0; +} GenericModelTopAndTexInMemoryInfo; + +#include "../../../../gen/l1/eve/r0/VecGenericModelTopAndTexInMemoryInfo.h" + +typedef struct { + MargaretBufferInMemoryInfo vbo; + MargaretBufferInMemoryInfo ebo; +} ShinyModelTopInMemoryInfo; + +#include "../../../../gen/l1/eve/r0/VecShinyModelTopInMemoryInfo.h" + + + void reset_and_record_command_buffer_0( VkCommandBuffer command_buffer, VkRenderPass render_pass_0, const PipelineHands* pipeline_and_layout_0a, const PipelineHands* pipeline_and_layout_0b, VkFramebuffer result_framebuffer, VkExtent2D image_extent, - const Scene* scene, - VkDescriptorSet descriptor_set_for_pipeline_0a, VkDescriptorSet descriptor_set_for_pipeline_0b, + const Scene* scene, const VecGenericModelTopAndTexInMemoryInfo* generic_models, + VkDescriptorSet descriptor_set_for_pipeline_0b, mat4 proj_cam_t, vec3 camera_pos ) { if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS) @@ -813,6 +881,7 @@ void reset_and_record_command_buffer_0( }; vkCmdBeginRenderPass(command_buffer, &renderpass_begin, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0a->pipeline); // We forgot that viewport is not built into our pipeline // We forgot that scissors are not built into out pipeline @@ -831,7 +900,7 @@ void reset_and_record_command_buffer_0( vkCmdBindIndexBuffer(command_buffer, model->model.ebo, 0, VK_INDEX_TYPE_UINT32); vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0a->pipeline_layout, 0, - 1, &descriptor_set_for_pipeline_0a, 0, NULL); + 1, &VecGenericModelTopAndTexInMemoryInfo_at(generic_models, i)->p_0a_set_0, 0, NULL); vkCmdDrawIndexed(command_buffer, model->model.indexes, model->instances.len, 0, 0, 0); } @@ -841,6 +910,9 @@ void reset_and_record_command_buffer_0( 0, sizeof(mat4), &proj_cam_t); vkCmdPushConstants(command_buffer, pipeline_and_layout_0b->pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(mat4), sizeof(vec3), &camera_pos); + vkCmdBindDescriptorSets( + command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0b->pipeline_layout, 0, + 1, &descriptor_set_for_pipeline_0b, 0, NULL); for (size_t i = 0; i < scene->shiny_models.len; i++) { const UsedShinyModelOnScene* model = VecUsedShinyModelOnScene_at(&scene->shiny_models, i); VkBuffer attached_buffers[2] = { model->model.vbo, model->model.instance_attr_buf }; @@ -849,9 +921,6 @@ void reset_and_record_command_buffer_0( assert(ARRAY_SIZE(attached_buffers) == 2 && ARRAY_SIZE(offsets_in_buffers) == 2); vkCmdBindVertexBuffers(command_buffer, 0, 2, attached_buffers, offsets_in_buffers); vkCmdBindIndexBuffer(command_buffer, model->model.ebo, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindDescriptorSets( - command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0b->pipeline_layout, 0, - 1, &descriptor_set_for_pipeline_0b, 0, NULL); vkCmdDrawIndexed(command_buffer, model->model.indexes, model->instances.len, 0, 0, 0); } @@ -990,34 +1059,7 @@ void copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer( abortf("vkEndCommandBuffer"); } -typedef struct { - VkSemaphore in_frame_transfer_complete; - VkSemaphore image_available_semaphore; - VkSemaphore rendered_to_IT1_semaphore; - VkFence in_flight_fence; -} Jane_r0; -NODISCARD Jane_r0 Jane_r0_create(VkDevice device) { - return (Jane_r0){ - .in_frame_transfer_complete = margaret_create_semaphore(device), - .image_available_semaphore = margaret_create_semaphore(device), - .rendered_to_IT1_semaphore = margaret_create_semaphore(device), - .in_flight_fence = margaret_create_fence(device, true) - }; -} - -void Jane_r0_destroy(VkDevice device, Jane_r0 jane) { - vkDestroyFence(device, jane.in_flight_fence, NULL); - vkDestroySemaphore(device, jane.rendered_to_IT1_semaphore, NULL); - vkDestroySemaphore(device, jane.image_available_semaphore, NULL); - vkDestroySemaphore(device, jane.in_frame_transfer_complete, NULL); -} - -// todo: handle case where presentation and graphics are from the same family -typedef struct { - VkQueue graphics_queue; - VkQueue presentation_queue; -} UsedVulkanQueues; typedef struct { MargaretInstanceAndItsDebug instance_and_debug; @@ -1037,20 +1079,15 @@ typedef struct { MargaretSwapchainBundle swfb; SceneTemplate scene_template; - TextureDataR8G8B8A8 cyl_1_diffuse_tex; - TextureDataR8G8B8A8 cyl_1_normal_tex; + + VecGenericModelTopAndTexInMemoryInfo device_generic_models_top_and_tex; + VecShinyModelTopInMemoryInfo device_shiny_models_top; MargaretBufferInMemoryInfo host_mem_buffer; VkDeviceMemory host_mem; - VecMargaretBufferInMemoryInfo device_ebo_buffers_for_generic_meshes; - VecMargaretBufferInMemoryInfo device_vbo_buffers_for_generic_meshes; - VecMargaretBufferInMemoryInfo device_ebo_buffers_for_shiny_meshes; - VecMargaretBufferInMemoryInfo device_vbo_buffers_for_shiny_meshes; MargaretBufferInMemoryInfo device_lighting_ubo; MargaretBufferInMemoryInfo device_instance_attrs_for_models; MargaretImageInMemoryInfo device_IT1_image; MargaretImageInMemoryInfo device_zbuffer_image; - MargaretImageInMemoryInfo device_cyl_1_diffuse_texture; - MargaretImageInMemoryInfo device_cyl_1_normal_texture; VkDeviceMemory device_mem; VkCommandPool command_pool; @@ -1065,12 +1102,12 @@ typedef struct { VkImageView zbuffer_view; VkImageView IT1_view; VkFramebuffer IT1_framebuffer; - VkImageView cyl_1_diffuse_texture_view; - VkImageView cyl_1_normal_texture_view; VkSampler linear_sampler; VkSampler nearest_sampler; VkDescriptorPool descriptor_pool; - VkDescriptorSet descriptor_set_for_pipeline_0a; + + /* Descriptor sets */ + // Descriptor sets for pipeline_0a are stored in device_generic_models_top_and_tex VkDescriptorSet descriptor_set_for_pipeline_0b; VkDescriptorSet descriptor_set_for_pipeline_1; @@ -1237,7 +1274,8 @@ void vulkano_frame_drawing(state_r0* state) { &state->vk_ctx.pipeline_hands_0a, &state->vk_ctx.pipeline_hands_0b, state->vk_ctx.IT1_framebuffer, state->vk_ctx.swfb.extent, &state->vk_ctx.scene, - state->vk_ctx.descriptor_set_for_pipeline_0a, state->vk_ctx.descriptor_set_for_pipeline_0b, + &state->vk_ctx.device_generic_models_top_and_tex, /* Needed just to get descriptor sets for generic models */ + state->vk_ctx.descriptor_set_for_pipeline_0b, t_mat, state->vk_ctx.my_cam_control_info.pos); reset_and_record_command_buffer_1(state->vk_ctx.rendering_command_buffer_1, state->vk_ctx.render_pass_1, @@ -1653,6 +1691,7 @@ int main() { state_r0 state = {0}; state.sane_image_extent_limit = (VkExtent2D){1000, 700}; + vulkan_ctx_r0 *vk_ctx = &state.vk_ctx; state.wl_display = wl_display_connect(NULL); if (!state.wl_display) @@ -1690,198 +1729,219 @@ int main() { abortf("wl_surface_frame\n"); wl_callback_add_listener(state.wl_callback, &main_h_wl_surface_frame_listener, &state); - state.vk_ctx.instance_and_debug = MargaretInstanceAndItsDebug_new(ENABLE_VALIDATION_LAYERS); - VkInstance instance = state.vk_ctx.instance_and_debug.instance; + vk_ctx->instance_and_debug = MargaretInstanceAndItsDebug_new(ENABLE_VALIDATION_LAYERS); + VkInstance instance = vk_ctx->instance_and_debug.instance; // print_instance_available_extensions(instance); // print_instance_available_layers(instance); - state.vk_ctx.surface = margaret_create_surface(instance, state.wl_display, state.wl_surface); + vk_ctx->surface = margaret_create_surface(instance, state.wl_display, state.wl_surface); - state.vk_ctx.physical_device = margaret_select_one_physical_device( - instance, state.vk_ctx.surface, GPU, bugged_GPU, sane_image_extent_limit); + vk_ctx->physical_device = margaret_select_one_physical_device( + instance, vk_ctx->surface, GPU, bugged_GPU, sane_image_extent_limit); // print_physical_device_available_extensions(physical_device); ResultMargaretChosenQueueFamiliesOrSpanU8 queue_fam_res = margaret_choose_good_queue_families( - state.vk_ctx.physical_device, state.vk_ctx.surface); + vk_ctx->physical_device, vk_ctx->surface); if (queue_fam_res.variant != Result_Ok) abortf("queue_fam_res.variant != Result_Ok"); - state.vk_ctx.queue_fam = queue_fam_res.ok; + vk_ctx->queue_fam = queue_fam_res.ok; - state.vk_ctx.device = margaret_create_logical_device(state.vk_ctx.physical_device, state.vk_ctx.queue_fam); + vk_ctx->device = margaret_create_logical_device(vk_ctx->physical_device, vk_ctx->queue_fam); - vkGetDeviceQueue(state.vk_ctx.device, state.vk_ctx.queue_fam.for_graphics, 0, &state.vk_ctx.queues.graphics_queue); - vkGetDeviceQueue(state.vk_ctx.device, state.vk_ctx.queue_fam.for_presentation, 0, &state.vk_ctx.queues.presentation_queue); + vkGetDeviceQueue(vk_ctx->device, vk_ctx->queue_fam.for_graphics, 0, &vk_ctx->queues.graphics_queue); + vkGetDeviceQueue(vk_ctx->device, vk_ctx->queue_fam.for_presentation, 0, &vk_ctx->queues.presentation_queue); ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( - state.vk_ctx.physical_device, state.vk_ctx.surface, sane_image_extent_limit); + vk_ctx->physical_device, vk_ctx->surface, sane_image_extent_limit); if (swapchain_details_res.variant != Result_Ok) abortf("swapchain_details_res.variant != Result_Ok"); - OptionVkFormat zbuffer_format = margaret_find_supported_zbuffer_format(state.vk_ctx.physical_device); + OptionVkFormat zbuffer_format = margaret_find_supported_zbuffer_format(vk_ctx->physical_device); if (zbuffer_format.variant != Option_Some) abortf("Could not find supported zbuffer format\n"); - state.vk_ctx.zbuffer_format = zbuffer_format.some; - OptionVkFormat IT1_format = margaret_find_supported_hdr_buffer_format(state.vk_ctx.physical_device); + vk_ctx->zbuffer_format = zbuffer_format.some; + OptionVkFormat IT1_format = margaret_find_supported_hdr_buffer_format(vk_ctx->physical_device); if (IT1_format.variant != Option_Some) abortf("Could not find supported hdr buffer format\n"); - state.vk_ctx.IT1_format = IT1_format.some; + vk_ctx->IT1_format = IT1_format.some; - state.vk_ctx.render_pass_0 = create_render_pass_0(state.vk_ctx.device, IT1_format.some, zbuffer_format.some); - state.vk_ctx.pipeline_hands_0a = create_graphics_pipeline_0(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0); - state.vk_ctx.pipeline_hands_0b = create_graphics_pipeline_0_b(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0); + vk_ctx->render_pass_0 = create_render_pass_0(vk_ctx->device, IT1_format.some, zbuffer_format.some); + vk_ctx->pipeline_hands_0a = create_graphics_pipeline_0(vk_ctx->device, vk_ctx->render_pass_0, 0); + vk_ctx->pipeline_hands_0b = create_graphics_pipeline_0_b(vk_ctx->device, vk_ctx->render_pass_0, 0); - state.vk_ctx.render_pass_1 = create_render_pass_1(state.vk_ctx.device, swapchain_details_res.ok.surface_format.format); - state.vk_ctx.pipeline_hands_1 = create_graphics_pipeline_1(state.vk_ctx.device, state.vk_ctx.render_pass_1, 0); + vk_ctx->render_pass_1 = create_render_pass_1(vk_ctx->device, swapchain_details_res.ok.surface_format.format); + vk_ctx->pipeline_hands_1 = create_graphics_pipeline_1(vk_ctx->device, vk_ctx->render_pass_1, 0); - state.vk_ctx.swfb = MargaretSwapchainBundle_new( - state.vk_ctx.device, state.vk_ctx.queue_fam, swapchain_details_res.ok, - state.vk_ctx.surface, state.vk_ctx.render_pass_1, NULL); + vk_ctx->swfb = MargaretSwapchainBundle_new( + vk_ctx->device, vk_ctx->queue_fam, swapchain_details_res.ok, + vk_ctx->surface, vk_ctx->render_pass_1, NULL); - state.vk_ctx.scene_template = (SceneTemplate){ + vk_ctx->scene_template = (SceneTemplate){ .generic_models = VecGenericMeshInSceneTemplate_new(), .shiny_models = VecShinyMeshInSceneTemplate_new(), .point_lights_max_count = pipeline_0_ubo_point_light_max_count, .spotlights_max_count = pipeline_0_ubo_spotlight_max_count}; - VecGenericMeshInSceneTemplate_append(&state.vk_ctx.scene_template.generic_models, - (GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(10, 2, 6), .max_instance_count = 100}); - VecGenericMeshInSceneTemplate_append(&state.vk_ctx.scene_template.generic_models, - (GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(5, 5, 10), .max_instance_count = 1}); - VecShinyMeshInSceneTemplate_append(&state.vk_ctx.scene_template.shiny_models, (ShinyMeshInSceneTemplate){ + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(10, 2, 6, 100)); + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(5, 5, 10, 1)); + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(1, 10, 4, 2)); + VecGenericMeshInSceneTemplate_append(&vk_ctx->scene_template.generic_models, + GenericMeshInSceneTemplate_for_log(2, 1, 6, 2)); + VecShinyMeshInSceneTemplate_append(&vk_ctx->scene_template.shiny_models, (ShinyMeshInSceneTemplate){ .topology = generate_shiny_rhombicuboctahedron(0.5f), .max_instance_count = 5 }); - VecShinyMeshInSceneTemplate_append(&state.vk_ctx.scene_template.shiny_models, (ShinyMeshInSceneTemplate){ + VecShinyMeshInSceneTemplate_append(&vk_ctx->scene_template.shiny_models, (ShinyMeshInSceneTemplate){ .topology = generate_shiny_cube(0.5f), .max_instance_count = 5 }); - // todo: generate more cool shiny models - // todo: learn how to use libpng - state.vk_ctx.cyl_1_diffuse_tex = TextureDataR8G8B8A8_read_from_png_nofail(cstr("textures/log_10_2_6.png")); - // todo: learn how to write texture immediately from file to mapped host memory buffer - // todo: and at the same time I need to add methods to convert between these formats - state.vk_ctx.cyl_1_normal_tex = TextureDataR8G8B8A8_read_from_png_nofail(cstr("textures/log_10_2_6_NORMAL.png")); + vk_ctx->device_generic_models_top_and_tex = VecGenericModelTopAndTexInMemoryInfo_new_reserved(vk_ctx->scene_template.generic_models.len); + for (size_t i = 0; i < vk_ctx->scene_template.generic_models.len; i++) { + const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&vk_ctx->scene_template.generic_models, i); + TextureDataR8G8B8A8 reading_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&M->diffuse_texture_path)); + TextureDataR8G8B8A8 reading_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&M->normal_texture_path)); + TextureDataR8 reading_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&M->specular_texture_path)); + VecGenericModelTopAndTexInMemoryInfo_append(&vk_ctx->device_generic_models_top_and_tex, + (GenericModelTopAndTexInMemoryInfo){ + .vbo = GenericMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len), + .ebo = margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len), + .reading_diffuse = reading_diffuse, .reading_normal = reading_normal, .reading_specular = reading_specular, + .diffuse = margaret_prep_image_mem_info_of_gpu_texture_srgba(reading_diffuse.width, reading_diffuse.height), + .normal = margaret_prep_image_mem_info_of_gpu_texture_unorm_32(reading_normal.width, reading_normal.height), + .specular = margaret_prep_image_mem_info_of_gpu_texture_unorm_8(reading_specular.width, reading_specular.height), + /* image views will be created after the images are allocated */ + /* descriptor set for each model will be allocated later */ + }); + } - // todo: kill myself (update: still WiP) + VecU64 offset_of_image_in_host_mem_buff_during_init = VecU64_new_zeroinit(vk_ctx->device_generic_models_top_and_tex.len * 3); + U64 grand_total_texture_size_in_host_mem = 0; + { + U64 offset = 0; + for (size_t i = 0; i < vk_ctx->device_generic_models_top_and_tex.len; i++) { + offset_of_image_in_host_mem_buff_during_init.buf[3 * i + 0] = offset; + offset += TextureDataR8G8B8A8_get_size_in_bytes(&vk_ctx->device_generic_models_top_and_tex.buf[i].reading_diffuse); + offset_of_image_in_host_mem_buff_during_init.buf[3 * i + 1] = offset; + offset += TextureDataR8G8B8A8_get_size_in_bytes(&vk_ctx->device_generic_models_top_and_tex.buf[i].reading_normal); + offset_of_image_in_host_mem_buff_during_init.buf[3 * i + 2] = offset; + offset += TextureDataR8_get_size_in_bytes(&vk_ctx->device_generic_models_top_and_tex.buf[i].reading_specular); + } + grand_total_texture_size_in_host_mem = offset; + } + + vk_ctx->device_shiny_models_top = VecShinyModelTopInMemoryInfo_new_reserved(vk_ctx->scene_template.shiny_models.len); + for (size_t i = 0; i < vk_ctx->scene_template.shiny_models.len; i++) { + const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&vk_ctx->scene_template.shiny_models, i); + VecShinyModelTopInMemoryInfo_append(&vk_ctx->device_shiny_models_top, + (ShinyModelTopInMemoryInfo){ + .vbo = ShinyMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len), + .ebo = margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len), + }); + } + + // todo: kill myself (update: still WiP (update: it became a growing technical debt now)) + // todo: commit suicide + // We have only one staging buffer in host memory (because we don't really need more) - state.vk_ctx.host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = - MAX_U64(SceneTemplate_get_space_for_initial_model_topology_transfer(&state.vk_ctx.scene_template), - MAX_U64(SceneTemplate_get_space_needed_for_widest_state_transfer(&state.vk_ctx.scene_template), - MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_diffuse_tex), - MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_normal_tex), 0)))) + vk_ctx->host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = + MAX_U64(SceneTemplate_get_space_for_initial_model_topology_transfer(&vk_ctx->scene_template), + MAX_U64(SceneTemplate_get_space_needed_for_widest_state_transfer(&vk_ctx->scene_template), + MAX_U64(grand_total_texture_size_in_host_mem, 0))) , .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT }; - PtrMargaretBufferInMemoryInfo host_mem_buffer_SPAN[1] = {&state.vk_ctx.host_mem_buffer}; - state.vk_ctx.host_mem = margaret_initialize_buffers_and_images(state.vk_ctx.physical_device, state.vk_ctx.device, + PtrMargaretBufferInMemoryInfo host_mem_buffer_SPAN[1] = {&vk_ctx->host_mem_buffer}; + vk_ctx->host_mem = margaret_initialize_buffers_and_images(vk_ctx->physical_device, vk_ctx->device, (MutSpanPtrMargaretBufferInMemoryInfo){.data = host_mem_buffer_SPAN, .len = 1}, (MutSpanPtrMargaretImageInMemoryInfo){ 0 }, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - // todo: split this in two (or maybe even better: merge it all into one/two buffer and use offsets - state.vk_ctx.device_ebo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); - state.vk_ctx.device_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); - for (size_t mi = 0; mi < state.vk_ctx.scene_template.generic_models.len; mi++) { - const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&state.vk_ctx.scene_template.generic_models, mi); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, - GenericMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len)); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, - margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len)); - } - state.vk_ctx.device_ebo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new(); - state.vk_ctx.device_vbo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new(); - for (size_t mi = 0; mi < state.vk_ctx.scene_template.shiny_models.len; mi++) { - const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&state.vk_ctx.scene_template.shiny_models, mi); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, - ShinyMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len)); - VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, - margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len)); - } - - state.vk_ctx.device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)); - state.vk_ctx.device_instance_attrs_for_models = (MargaretBufferInMemoryInfo){ - .sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&state.vk_ctx.scene_template), + vk_ctx->device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)); + vk_ctx->device_instance_attrs_for_models = (MargaretBufferInMemoryInfo){ + .sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&vk_ctx->scene_template), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT }; - VecPtrMargaretBufferInMemoryInfo device_mem_buffers_SPAN = VecPtrMargaretBufferInMemoryInfo_new(); - // todo: add iteration macro generation - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_generic_meshes.len; i++) { - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, i)); - } - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_generic_meshes.len; i++) { - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, i)); - } - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_shiny_meshes.len; i++) { - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, i)); - } - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_shiny_meshes.len; i++) { - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, i)); - } - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_lighting_ubo); - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_instance_attrs_for_models); + VecPtrMargaretBufferInMemoryInfo device_mem_buffers_SPAN = VecPtrMargaretBufferInMemoryInfo_new_reserved( + vk_ctx->device_generic_models_top_and_tex.len + vk_ctx->device_shiny_models_top.len); - state.vk_ctx.device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer( + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &vk_ctx->device_lighting_ubo); + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &vk_ctx->device_instance_attrs_for_models); + + vk_ctx->device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer( MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some); - state.vk_ctx.device_zbuffer_image = margaret_prep_image_mem_info_of_zbuffer( + vk_ctx->device_zbuffer_image = margaret_prep_image_mem_info_of_zbuffer( MAX_WIN_WIDTH, MAX_WIN_HEIGHT, zbuffer_format.some); - state.vk_ctx.device_cyl_1_diffuse_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba( - state.vk_ctx.cyl_1_diffuse_tex.width, TextureDataR8G8B8A8_get_height(&state.vk_ctx.cyl_1_diffuse_tex)); - state.vk_ctx.device_cyl_1_normal_texture = margaret_prep_image_mem_info_of_gpu_texture_unorm_32( - state.vk_ctx.cyl_1_normal_tex.width, TextureDataR8G8B8A8_get_height(&state.vk_ctx.cyl_1_normal_tex)); - PtrMargaretImageInMemoryInfo device_mem_images_SPAN[] = { - &state.vk_ctx.device_IT1_image, &state.vk_ctx.device_zbuffer_image, &state.vk_ctx.device_cyl_1_diffuse_texture, - &state.vk_ctx.device_cyl_1_normal_texture - }; - state.vk_ctx.device_mem = margaret_initialize_buffers_and_images(state.vk_ctx.physical_device, state.vk_ctx.device, + VecPtrMargaretImageInMemoryInfo device_mem_images_SPAN = + VecPtrMargaretImageInMemoryInfo_new_reserved(2 + 3 * vk_ctx->scene_template.generic_models.len); + VecPtrMargaretImageInMemoryInfo_append(&device_mem_images_SPAN, &vk_ctx->device_IT1_image); + VecPtrMargaretImageInMemoryInfo_append(&device_mem_images_SPAN, &vk_ctx->device_zbuffer_image); + + for (size_t i = 0; i < vk_ctx->device_generic_models_top_and_tex.len; i++) { + GenericModelTopAndTexInMemoryInfo* M = &vk_ctx->device_generic_models_top_and_tex.buf[i]; + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &M->vbo); + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &M->ebo); + VecPtrMargaretImageInMemoryInfo_append(&device_mem_images_SPAN, &M->diffuse); + VecPtrMargaretImageInMemoryInfo_append(&device_mem_images_SPAN, &M->normal); + VecPtrMargaretImageInMemoryInfo_append(&device_mem_images_SPAN, &M->specular); + } + + for (size_t i = 0; i < vk_ctx->device_shiny_models_top.len; i++) { + ShinyModelTopInMemoryInfo* M = &vk_ctx->device_shiny_models_top.buf[i]; + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &M->vbo); + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &M->ebo); + } + + vk_ctx->device_mem = margaret_initialize_buffers_and_images(vk_ctx->physical_device, vk_ctx->device, VecPtrMargaretBufferInMemoryInfo_to_mspan(&device_mem_buffers_SPAN), - (MutSpanPtrMargaretImageInMemoryInfo){ .data = device_mem_images_SPAN, .len = ARRAY_SIZE(device_mem_images_SPAN) }, + VecPtrMargaretImageInMemoryInfo_to_mspan(&device_mem_images_SPAN), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - /* device_mem_buffers_SPAN invalidated */ + + /* device_mem_buffers_SPAN, device_mem_images_SPAN invalidated */ VecPtrMargaretBufferInMemoryInfo_drop(device_mem_buffers_SPAN); + VecPtrMargaretImageInMemoryInfo_drop(device_mem_images_SPAN); - state.vk_ctx.command_pool = margaret_create_resettable_command_pool(state.vk_ctx.device, state.vk_ctx.queue_fam.for_graphics); - state.vk_ctx.rendering_command_buffer_0 = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); - state.vk_ctx.rendering_command_buffer_1 = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); - state.vk_ctx.transfer_command_buffer = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); + vk_ctx->command_pool = margaret_create_resettable_command_pool(vk_ctx->device, vk_ctx->queue_fam.for_graphics); + vk_ctx->rendering_command_buffer_0 = margaret_allocate_command_buffer(vk_ctx->device, vk_ctx->command_pool); + vk_ctx->rendering_command_buffer_1 = margaret_allocate_command_buffer(vk_ctx->device, vk_ctx->command_pool); + vk_ctx->transfer_command_buffer = margaret_allocate_command_buffer(vk_ctx->device, vk_ctx->command_pool); - state.vk_ctx.my_cam_control_info = CamControlInfo_new(); - state.vk_ctx.Buba_control_info = (vec3){0}; + vk_ctx->my_cam_control_info = CamControlInfo_new(); + vk_ctx->Buba_control_info = (vec3){0}; - state.vk_ctx.scene = Scene_new(); + vk_ctx->scene = Scene_new(); { size_t offset_in_attr_buffer = 0; - for (size_t mi = 0; mi < state.vk_ctx.scene_template.generic_models.len; mi++) { - const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&state.vk_ctx.scene_template.generic_models, mi); - VecUsedGenericModelOnScene_append(&state.vk_ctx.scene.generic_models, (UsedGenericModelOnScene){ - .model = (ModelOnSceneMem){ - .vbo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_vbo_buffers_for_generic_meshes, mi)->buffer, - .ebo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_ebo_buffers_for_generic_meshes, mi)->buffer, + for (size_t mi = 0; mi < vk_ctx->scene_template.generic_models.len; mi++) { + const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&vk_ctx->scene_template.generic_models, mi); + const GenericModelTopAndTexInMemoryInfo* MM = VecGenericModelTopAndTexInMemoryInfo_at(&vk_ctx->device_generic_models_top_and_tex, mi); + VecUsedGenericModelOnScene_append(&vk_ctx->scene.generic_models, (UsedGenericModelOnScene){ + .model = (GenericModelOnSceneMem){ + .vbo = MM->vbo.buffer, + .ebo = MM->ebo.buffer, .indexes = M->topology.indexes.len, - .instance_attr_buf = state.vk_ctx.device_instance_attrs_for_models.buffer, + .instance_attr_buf = vk_ctx->device_instance_attrs_for_models.buffer, .instance_attr_buf_offset = offset_in_attr_buffer, .limit_max_instance_count = M->max_instance_count + // todo: remove vbo, ebo from here (we don't need it here). + // as you may see, I didn't specifid images (that's becasuse I fpn need to) }, .instances = VecGenericMeshInstance_new(), }); offset_in_attr_buffer += M->max_instance_count * sizeof(GenericMeshInstance); } - for (size_t mi = 0; mi < state.vk_ctx.scene_template.shiny_models.len; mi++) { - const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&state.vk_ctx.scene_template.shiny_models, mi); - VecUsedShinyModelOnScene_append(&state.vk_ctx.scene.shiny_models, (UsedShinyModelOnScene){ - .model = (ModelOnSceneMem){ - .vbo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_vbo_buffers_for_shiny_meshes, mi)->buffer, - .ebo = VecMargaretBufferInMemoryInfo_at( - &state.vk_ctx.device_ebo_buffers_for_shiny_meshes, mi)->buffer, + for (size_t mi = 0; mi < vk_ctx->scene_template.shiny_models.len; mi++) { + const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&vk_ctx->scene_template.shiny_models, mi); + const ShinyModelTopInMemoryInfo* MM = VecShinyModelTopInMemoryInfo_at(&vk_ctx->device_shiny_models_top, mi); + VecUsedShinyModelOnScene_append(&vk_ctx->scene.shiny_models, (UsedShinyModelOnScene){ + .model = (ShinyModelOnSceneMem){ + .vbo = MM->vbo.buffer, + .ebo = MM->ebo.buffer, .indexes = M->topology.indexes.len, - .instance_attr_buf = state.vk_ctx.device_instance_attrs_for_models.buffer, + .instance_attr_buf = vk_ctx->device_instance_attrs_for_models.buffer, .instance_attr_buf_offset = offset_in_attr_buffer, .limit_max_instance_count = M->max_instance_count }, @@ -1893,149 +1953,206 @@ int main() { for (int X = 0; X < 10; X++) { for (int Z = 0; Z < 10; Z++) { - VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&state.vk_ctx.scene.generic_models, 0)->instances, + VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&vk_ctx->scene.generic_models, 0)->instances, (GenericMeshInstance){ .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}) }); } } - VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&state.vk_ctx.scene.generic_models, 1)->instances, - (GenericMeshInstance){ .model_t = marie_translation_mat4(state.vk_ctx.Buba_control_info) + VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&vk_ctx->scene.generic_models, 1)->instances, + (GenericMeshInstance){ .model_t = marie_translation_mat4(vk_ctx->Buba_control_info) }); + + VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&vk_ctx->scene.generic_models, 2)->instances, + (GenericMeshInstance){ .model_t = marie_translation_mat4((vec3){5, -7, 6})}); + VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&vk_ctx->scene.generic_models, 3)->instances, + (GenericMeshInstance){ .model_t = marie_translation_mat4((vec3){5, -7, -6})}); + + for (U64 i = 0; i < 5; i++) { - VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&state.vk_ctx.scene.shiny_models, 0)->instances, + VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&vk_ctx->scene.shiny_models, 0)->instances, (ShinyMeshInstance){ .model_t = marie_translation_mat4((vec3){ (float)((i * i * 10 + i * 4 + 1) % 13) + 2, (float)((i * i * 11 + i * 2 + 2) % 13), (float)((i * i * 9 + i * 1 + 4) % 13) + 3}), .color_off = (vec3){0.6f, 0.2f, 0.2f}}); } - VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&state.vk_ctx.scene.shiny_models, 1)->instances, + VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&vk_ctx->scene.shiny_models, 1)->instances, (ShinyMeshInstance){ .model_t = marie_translation_mat4((vec3){-5, 0, 3}), .color_off = (vec3){0.3f, 0.5f, 0.5f}}); // todo: synchronize them with my cool light sources) - if (vkMapMemory(state.vk_ctx.device, state.vk_ctx.host_mem, 0, VK_WHOLE_SIZE, 0, &state.vk_ctx.host_mem_buffer_mem) != VK_SUCCESS) + if (vkMapMemory(vk_ctx->device, vk_ctx->host_mem, 0, VK_WHOLE_SIZE, 0, &vk_ctx->host_mem_buffer_mem) != VK_SUCCESS) abortf("vkMapMemory"); - SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd( - &state.vk_ctx.scene_template, &state.vk_ctx.scene, state.vk_ctx.host_mem_buffer_mem, - state.vk_ctx.transfer_command_buffer, state.vk_ctx.host_mem_buffer.buffer); { - VkCommandBuffer command_buffers[1] = { state.vk_ctx.transfer_command_buffer }; + SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd( + &vk_ctx->scene_template, &vk_ctx->scene, vk_ctx->host_mem_buffer_mem, + vk_ctx->transfer_command_buffer, vk_ctx->host_mem_buffer.buffer); + VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = ARRAY_SIZE(command_buffers), - .pCommandBuffers = command_buffers, + .commandBufferCount = 1, .pCommandBuffers = &vk_ctx->transfer_command_buffer, }; - if (vkQueueSubmit(state.vk_ctx.queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) + if (vkQueueSubmit(vk_ctx->queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) abortf("vkQueueSubmit\n"); } - vkDeviceWaitIdle(state.vk_ctx.device); + vkDeviceWaitIdle(vk_ctx->device); + { - memcpy(state.vk_ctx.host_mem_buffer_mem, state.vk_ctx.cyl_1_diffuse_tex.pixels.buf, - TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_diffuse_tex)); - margaret_copy_buffer_to_texture_for_frag_shader_imm( - state.vk_ctx.device, state.vk_ctx.command_pool, state.vk_ctx.queues.graphics_queue, - &state.vk_ctx.device_cyl_1_diffuse_texture, state.vk_ctx.host_mem_buffer.buffer); + VecMargaretCommandForImageCopying commands = + VecMargaretCommandForImageCopying_new_reserved(vk_ctx->device_generic_models_top_and_tex.len); + for (size_t i = 0; i < vk_ctx->device_generic_models_top_and_tex.len; i++) { + const GenericModelTopAndTexInMemoryInfo* M = + VecGenericModelTopAndTexInMemoryInfo_at(&vk_ctx->device_generic_models_top_and_tex, i); + U64 diffuse_offset = *VecU64_at(&offset_of_image_in_host_mem_buff_during_init, 3 * i + 0); + U64 normal_offset = *VecU64_at(&offset_of_image_in_host_mem_buff_during_init, 3 * i + 1); + U64 specular_offset = *VecU64_at(&offset_of_image_in_host_mem_buff_during_init, 3 * i + 2); + memcpy(vk_ctx->host_mem_buffer_mem + diffuse_offset, + M->reading_diffuse.pixels.buf, TextureDataR8G8B8A8_get_size_in_bytes(&M->reading_diffuse)); + memcpy(vk_ctx->host_mem_buffer_mem + normal_offset, + M->reading_normal.pixels.buf, TextureDataR8G8B8A8_get_size_in_bytes(&M->reading_normal)); + memcpy(vk_ctx->host_mem_buffer_mem + specular_offset, + M->reading_specular.pixels.buf, TextureDataR8_get_size_in_bytes(&M->reading_specular)); + VecMargaretCommandForImageCopying_append(&commands, (MargaretCommandForImageCopying){ + .dst_image = &M->diffuse, .host_mem_buff_offset = diffuse_offset}); + VecMargaretCommandForImageCopying_append(&commands, (MargaretCommandForImageCopying){ + .dst_image = &M->normal, .host_mem_buff_offset = normal_offset}); + VecMargaretCommandForImageCopying_append(&commands, (MargaretCommandForImageCopying){ + .dst_image = &M->specular, .host_mem_buff_offset = specular_offset}); + } + margaret_rerecord_cmd_buff_for_texture_init(vk_ctx->transfer_command_buffer, vk_ctx->host_mem_buffer.buffer, + VecMargaretCommandForImageCopying_to_span(&commands), + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT); + VecMargaretCommandForImageCopying_drop(commands); + + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, .pCommandBuffers = &vk_ctx->transfer_command_buffer, + }; + if (vkQueueSubmit(vk_ctx->queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) + abortf("vkQueueSubmit\n"); } - vkDeviceWaitIdle(state.vk_ctx.device); - { - memcpy(state.vk_ctx.host_mem_buffer_mem, state.vk_ctx.cyl_1_normal_tex.pixels.buf, - TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_normal_tex)); - margaret_copy_buffer_to_texture_for_frag_shader_imm( - state.vk_ctx.device, state.vk_ctx.command_pool, state.vk_ctx.queues.graphics_queue, - &state.vk_ctx.device_cyl_1_normal_texture, state.vk_ctx.host_mem_buffer.buffer); - } - vkDeviceWaitIdle(state.vk_ctx.device); + vkDeviceWaitIdle(vk_ctx->device); // We sent everything we needed. but host_mem_buffer_mem may be used later // My zbuffer also needs a view - state.vk_ctx.zbuffer_view = margaret_create_view_for_image(state.vk_ctx.device, - &state.vk_ctx.device_zbuffer_image, VK_IMAGE_ASPECT_DEPTH_BIT); + vk_ctx->zbuffer_view = margaret_create_view_for_image(vk_ctx->device, + &vk_ctx->device_zbuffer_image, VK_IMAGE_ASPECT_DEPTH_BIT); /* Here we create an image view into a temporary IT1 texture and a framebuffer for scene rendering */ - state.vk_ctx.IT1_view = margaret_create_view_for_image(state.vk_ctx.device, - &state.vk_ctx.device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); - state.vk_ctx.IT1_framebuffer = create_IT1_framebuffer(state.vk_ctx.device, - state.vk_ctx.IT1_view, state.vk_ctx.zbuffer_view, state.vk_ctx.render_pass_0, MAX_WIN_WIDTH, MAX_WIN_HEIGHT); + vk_ctx->IT1_view = margaret_create_view_for_image(vk_ctx->device, + &vk_ctx->device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); + /* Busy creating views for all my textures */ + for (size_t i = 0; i < vk_ctx->device_generic_models_top_and_tex.len; i++) { + GenericModelTopAndTexInMemoryInfo* M = VecGenericModelTopAndTexInMemoryInfo_mat(&vk_ctx->device_generic_models_top_and_tex, i); + M->diffuse_view = margaret_create_view_for_image(vk_ctx->device, &M->diffuse, VK_IMAGE_ASPECT_COLOR_BIT); + M->normal_view = margaret_create_view_for_image(vk_ctx->device, &M->normal, VK_IMAGE_ASPECT_COLOR_BIT); + M->specular_view = margaret_create_view_for_image(vk_ctx->device, &M->specular, VK_IMAGE_ASPECT_COLOR_BIT); + } - // My cylinder 1 texture needs VkImageView - state.vk_ctx.cyl_1_diffuse_texture_view = margaret_create_view_for_image( - state.vk_ctx.device, &state.vk_ctx.device_cyl_1_diffuse_texture, VK_IMAGE_ASPECT_COLOR_BIT); - // My cylinder 1 normal texture also needs NkImageView - state.vk_ctx.cyl_1_normal_texture_view = margaret_create_view_for_image( - state.vk_ctx.device, &state.vk_ctx.device_cyl_1_normal_texture, VK_IMAGE_ASPECT_COLOR_BIT); + + vk_ctx->IT1_framebuffer = create_IT1_framebuffer(vk_ctx->device, + vk_ctx->IT1_view, vk_ctx->zbuffer_view, vk_ctx->render_pass_0, MAX_WIN_WIDTH, MAX_WIN_HEIGHT); // Right now I only have one light source - VecPipeline0PointLight_append(&state.vk_ctx.scene.point_lights, (Pipeline0PointLight){.pos = {0}, .color = {100, 100, 100}}); + VecPipeline0PointLight_append(&vk_ctx->scene.point_lights, (Pipeline0PointLight){.pos = {0}, .color = {100, 100, 100}}); // These samplers are global for a lot of my future textures - state.vk_ctx.linear_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, true); - state.vk_ctx.nearest_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, false); + vk_ctx->linear_sampler = margaret_create_sampler(vk_ctx->physical_device, vk_ctx->device, true); + vk_ctx->nearest_sampler = margaret_create_sampler(vk_ctx->physical_device, vk_ctx->device, false); - state.vk_ctx.descriptor_pool = margaret_create_descriptor_set_pool(state.vk_ctx.device, 2, 3, 3); - state.vk_ctx.descriptor_set_for_pipeline_0a = margaret_allocate_descriptor_set( - state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0a.descriptor_set_layout); - state.vk_ctx.descriptor_set_for_pipeline_0b = margaret_allocate_descriptor_set( - state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0b.descriptor_set_layout); - state.vk_ctx.descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( - state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_1.descriptor_set_layout); + vk_ctx->descriptor_pool = margaret_create_descriptor_set_pool(vk_ctx->device, + 1 + 1 * vk_ctx->device_generic_models_top_and_tex.len, + 1 + 3 * vk_ctx->device_generic_models_top_and_tex.len, + 2 + 1 * vk_ctx->device_generic_models_top_and_tex.len); + for (size_t i = 0; i < vk_ctx->device_generic_models_top_and_tex.len; i++) { + GenericModelTopAndTexInMemoryInfo* M = &vk_ctx->device_generic_models_top_and_tex.buf[i]; + M->p_0a_set_0 = margaret_allocate_descriptor_set( + vk_ctx->device, vk_ctx->descriptor_pool, vk_ctx->pipeline_hands_0a.descriptor_set_layout); + } + vk_ctx->descriptor_set_for_pipeline_0b = margaret_allocate_descriptor_set( + vk_ctx->device, vk_ctx->descriptor_pool, vk_ctx->pipeline_hands_0b.descriptor_set_layout); + vk_ctx->descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( + vk_ctx->device, vk_ctx->descriptor_pool, vk_ctx->pipeline_hands_1.descriptor_set_layout); // Configuring my descriptor sets, that I just allocated - VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0a = { - .buffer = state.vk_ctx.device_lighting_ubo.buffer, - .offset = 0, - .range = sizeof(Pipeline0UBO), - }; - VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0a = { - .sampler = state.vk_ctx.linear_sampler, - .imageView = state.vk_ctx.cyl_1_diffuse_texture_view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; - VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0a = { - .sampler = state.vk_ctx.nearest_sampler, - .imageView = state.vk_ctx.cyl_1_normal_texture_view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; + + for (size_t i = 0; i < vk_ctx->device_generic_models_top_and_tex.len; i++) { + GenericModelTopAndTexInMemoryInfo* M = &vk_ctx->device_generic_models_top_and_tex.buf[i]; + VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0a = { + .buffer = vk_ctx->device_lighting_ubo.buffer, + .offset = 0, + .range = sizeof(Pipeline0UBO), + }; + VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0a = { + .sampler = vk_ctx->linear_sampler, + .imageView = M->diffuse_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0a = { + .sampler = vk_ctx->nearest_sampler, + .imageView = M->normal_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkDescriptorImageInfo image_info_for_descriptor_3_in_set_0a = { + .sampler = vk_ctx->nearest_sampler, + .imageView = M->specular_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + // todo: add a third binding (for specular shading) + VkWriteDescriptorSet writes_in_descriptor_set[] = { + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = M->p_0a_set_0, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pBufferInfo = &buffer_info_for_descriptor_0_in_set_0a, + }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = M->p_0a_set_0, + .dstBinding = 1, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_1_in_set_0a, + }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = M->p_0a_set_0, + .dstBinding = 2, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_2_in_set_0a, + }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = M->p_0a_set_0, + .dstBinding = 3, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_3_in_set_0a, + }, + }; + vkUpdateDescriptorSets(vk_ctx->device, ARRAY_SIZE(writes_in_descriptor_set), writes_in_descriptor_set, 0, NULL); + } + + VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0b = { - .buffer = state.vk_ctx.device_lighting_ubo.buffer, + .buffer = vk_ctx->device_lighting_ubo.buffer, .offset = 0, .range = sizeof(Pipeline0UBO), }; VkDescriptorImageInfo image_info_for_descriptor_0_in_set_1 = { - .sampler = state.vk_ctx.nearest_sampler, - .imageView = state.vk_ctx.IT1_view, + .sampler = vk_ctx->nearest_sampler, + .imageView = vk_ctx->IT1_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkWriteDescriptorSet writes_in_descriptor_sets[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pBufferInfo = &buffer_info_for_descriptor_0_in_set_0a, - }, - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a, - .dstBinding = 1, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &image_info_for_descriptor_1_in_set_0a, - }, - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a, - .dstBinding = 2, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &image_info_for_descriptor_2_in_set_0a, - }, - - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0b, + .dstSet = vk_ctx->descriptor_set_for_pipeline_0b, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -2045,7 +2162,7 @@ int main() { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = state.vk_ctx.descriptor_set_for_pipeline_1, + .dstSet = vk_ctx->descriptor_set_for_pipeline_1, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -2053,90 +2170,91 @@ int main() { .pImageInfo = &image_info_for_descriptor_0_in_set_1, }, }; - vkUpdateDescriptorSets(state.vk_ctx.device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); + vkUpdateDescriptorSets(vk_ctx->device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); - state.vk_ctx.jane = Jane_r0_create(state.vk_ctx.device); + vk_ctx->jane = Jane_r0_create(vk_ctx->device); state.prev_key_frame_time = margaret_clock_gettime_monotonic_raw(); state.frame_count_since_key = 0; /* Will happen mid-frame */ - state.vk_ctx.dt_transfer_required = true; + vk_ctx->dt_transfer_required = true; while (wl_display_dispatch(state.wl_display) >= 0) { if (state.closed) break; } - vkDeviceWaitIdle(state.vk_ctx.device); + vkDeviceWaitIdle(vk_ctx->device); // The End - vkDestroyDescriptorPool(state.vk_ctx.device, state.vk_ctx.descriptor_pool, NULL); - vkDestroySampler(state.vk_ctx.device, state.vk_ctx.linear_sampler, NULL); - vkDestroySampler(state.vk_ctx.device, state.vk_ctx.nearest_sampler, NULL); + vkDestroyDescriptorPool(vk_ctx->device, vk_ctx->descriptor_pool, NULL); + vkDestroySampler(vk_ctx->device, vk_ctx->linear_sampler, NULL); + vkDestroySampler(vk_ctx->device, vk_ctx->nearest_sampler, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.cyl_1_normal_texture_view, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.cyl_1_diffuse_texture_view, NULL); - vkDestroyFramebuffer(state.vk_ctx.device, state.vk_ctx.IT1_framebuffer, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.IT1_view, NULL); - vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.zbuffer_view, NULL); + // vkDestroyImageView(vk_ctx->device, vk_ctx->cyl_1_normal_texture_view, NULL); + // vkDestroyImageView(vk_ctx->device, vk_ctx->cyl_1_diffuse_texture_view, NULL); + vkDestroyFramebuffer(vk_ctx->device, vk_ctx->IT1_framebuffer, NULL); + vkDestroyImageView(vk_ctx->device, vk_ctx->IT1_view, NULL); + vkDestroyImageView(vk_ctx->device, vk_ctx->zbuffer_view, NULL); - Scene_drop(state.vk_ctx.scene); + Scene_drop(vk_ctx->scene); - vkDestroyCommandPool(state.vk_ctx.device, state.vk_ctx.command_pool, NULL); + vkDestroyCommandPool(vk_ctx->device, vk_ctx->command_pool, NULL); - vkUnmapMemory(state.vk_ctx.device, state.vk_ctx.host_mem); - vkFreeMemory(state.vk_ctx.device, state.vk_ctx.host_mem, NULL); - vkFreeMemory(state.vk_ctx.device, state.vk_ctx.device_mem, NULL); + vkUnmapMemory(vk_ctx->device, vk_ctx->host_mem); + vkFreeMemory(vk_ctx->device, vk_ctx->host_mem, NULL); + vkFreeMemory(vk_ctx->device, vk_ctx->device_mem, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_cyl_1_diffuse_texture.image, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_cyl_1_normal_texture.image, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_IT1_image.image, NULL); - vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_zbuffer_image.image, NULL); - vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_lighting_ubo.buffer, NULL); + // todo: delete all the crap + // vkDestroyImage(vk_ctx->device, vk_ctx->device_cyl_1_diffuse_texture.image, NULL); + // vkDestroyImage(vk_ctx->device, vk_ctx->device_cyl_1_normal_texture.image, NULL); + vkDestroyImage(vk_ctx->device, vk_ctx->device_IT1_image.image, NULL); + vkDestroyImage(vk_ctx->device, vk_ctx->device_zbuffer_image.image, NULL); + vkDestroyBuffer(vk_ctx->device, vk_ctx->device_lighting_ubo.buffer, NULL); - vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_instance_attrs_for_models.buffer, NULL); + vkDestroyBuffer(vk_ctx->device, vk_ctx->device_instance_attrs_for_models.buffer, NULL); - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_generic_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, i)->buffer, - NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_buffers_for_generic_meshes); - - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_generic_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, i)->buffer, - NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_vbo_buffers_for_generic_meshes); - - for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_shiny_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, i)->buffer, - NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_buffers_for_shiny_meshes); - - for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_shiny_meshes.len; i++) - vkDestroyBuffer(state.vk_ctx.device, - VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, i)->buffer, - NULL); - VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_vbo_buffers_for_shiny_meshes); + // for (size_t i = 0; i < vk_ctx->device_ebo_buffers_for_generic_meshes.len; i++) + // vkDestroyBuffer(vk_ctx->device, + // VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_ebo_buffers_for_generic_meshes, i)->buffer, + // NULL); + // VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_ebo_buffers_for_generic_meshes); + // + // for (size_t i = 0; i < vk_ctx->device_vbo_buffers_for_generic_meshes.len; i++) + // vkDestroyBuffer(vk_ctx->device, + // VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_vbo_buffers_for_generic_meshes, i)->buffer, + // NULL); + // VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_vbo_buffers_for_generic_meshes); + // + // for (size_t i = 0; i < vk_ctx->device_ebo_buffers_for_shiny_meshes.len; i++) + // vkDestroyBuffer(vk_ctx->device, + // VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_ebo_buffers_for_shiny_meshes, i)->buffer, + // NULL); + // VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_ebo_buffers_for_shiny_meshes); + // + // for (size_t i = 0; i < vk_ctx->device_vbo_buffers_for_shiny_meshes.len; i++) + // vkDestroyBuffer(vk_ctx->device, + // VecMargaretBufferInMemoryInfo_at(&vk_ctx->device_vbo_buffers_for_shiny_meshes, i)->buffer, + // NULL); + // VecMargaretBufferInMemoryInfo_drop(vk_ctx->device_vbo_buffers_for_shiny_meshes); - vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.host_mem_buffer.buffer, NULL); + vkDestroyBuffer(vk_ctx->device, vk_ctx->host_mem_buffer.buffer, NULL); - TextureDataR8G8B8A8_drop(state.vk_ctx.cyl_1_normal_tex); - TextureDataR8G8B8A8_drop(state.vk_ctx.cyl_1_diffuse_tex); - SceneTemplate_drop(state.vk_ctx.scene_template); + // TextureDataR8G8B8A8_drop(vk_ctx->cyl_1_normal_tex); + // TextureDataR8G8B8A8_drop(vk_ctx->cyl_1_diffuse_tex); + SceneTemplate_drop(vk_ctx->scene_template); - MargaretSwapchainBundle_drop_with_device(state.vk_ctx.device, state.vk_ctx.swfb); - Jane_r0_destroy(state.vk_ctx.device, state.vk_ctx.jane); - destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_1); - vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_1, NULL); - destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0b); - destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0a); - vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_0, NULL); - vkDestroyDevice(state.vk_ctx.device, NULL); - vkDestroySurfaceKHR(instance, state.vk_ctx.surface, NULL); - MargaretInstanceAndItsDebug_drop(state.vk_ctx.instance_and_debug); + MargaretSwapchainBundle_drop_with_device(vk_ctx->device, vk_ctx->swfb); + Jane_r0_destroy(vk_ctx->device, vk_ctx->jane); + destroy_graphics_pipeline_hands(vk_ctx->device, vk_ctx->pipeline_hands_1); + vkDestroyRenderPass(vk_ctx->device, vk_ctx->render_pass_1, NULL); + destroy_graphics_pipeline_hands(vk_ctx->device, vk_ctx->pipeline_hands_0b); + destroy_graphics_pipeline_hands(vk_ctx->device, vk_ctx->pipeline_hands_0a); + vkDestroyRenderPass(vk_ctx->device, vk_ctx->render_pass_0, NULL); + vkDestroyDevice(vk_ctx->device, NULL); + vkDestroySurfaceKHR(instance, vk_ctx->surface, NULL); + MargaretInstanceAndItsDebug_drop(vk_ctx->instance_and_debug); if (state.wl_callback) wl_callback_destroy(state.wl_callback); diff --git a/src/l2/tests/r0/r0_assets.h b/src/l2/tests/r0/r0_assets.h index bdd9b21..3f5e629 100644 --- a/src/l2/tests/r0/r0_assets.h +++ b/src/l2/tests/r0/r0_assets.h @@ -8,6 +8,7 @@ #include "../../../../gen/l1/VecAndSpan_vec2.h" #include "../../../../gen/l1/pixel_masses.h" #include "../../marie/rasterization.h" +#include "../../marie/texture_processing.h" typedef struct { vec3 pos; @@ -32,10 +33,16 @@ GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) { typedef struct { GenericMeshTopology topology; U32 max_instance_count; + VecU8 diffuse_texture_path; + VecU8 normal_texture_path; + VecU8 specular_texture_path; } GenericMeshInSceneTemplate; void GenericMeshInSceneTemplate_drop(GenericMeshInSceneTemplate self) { GenericMeshTopology_drop(self.topology); + VecU8_drop(self.diffuse_texture_path); + VecU8_drop(self.normal_texture_path); + VecU8_drop(self.specular_texture_path); } GenericMeshInSceneTemplate GenericMeshInSceneTemplate_clone(const GenericMeshInSceneTemplate* self) { @@ -454,6 +461,41 @@ vec2 Bublazhuzhka_get_derivative(const Bublazhuzhka* self, vec2 v) { return sum; } +cvec3 Bublazhuzhka_get_color(const Bublazhuzhka* self, vec2 v) { + float flats = 0; + for (size_t i = 0; i < self->wimbzles.len; i++) { + Wimbzle rect = *VecWimbzle_at(&self->wimbzles, i); + vec2 B = {rect.tr.x + rect.brd, rect.tr.y + rect.brd}; + vec2 C = {rect.bl.x - rect.brd, rect.bl.y - rect.brd}; + vec2 A = {C.x, B.y}; + vec2 D = {B.x, C.y}; + vec2 F = rect.tr; + vec2 G = rect.bl; + vec2 E = {G.x, F.y}; + vec2 H = {F.x, G.y}; + float slp = rect.height / rect.brd; + if (A.x < v.x && v.x < E.x && marie_surface(E, A, v) > 0 && marie_surface(C, G, v) > 0) { + return (cvec3){100, 30, 40}; + } else if (F.x < v.x && v.x < B.x && marie_surface(B, F, v) > 0 && marie_surface(H, D, v) > 0) { + return (cvec3){70, 60, 45}; + } else if (C.y < v.y && v.y < G.y && marie_surface(G, C, v) > 0 && marie_surface(D, H, v) > 0) { + return (cvec3){10, 100, 70}; + } else if (F.y < v.y && v.y < B.y && marie_surface(A, E, v) > 0 && marie_surface(F, B, v) > 0) { + return (cvec3){25, 50, 110}; + } else if (E.x <= v.x && v.x <= F.x && G.y <= v.y && v.y <= F.y) { + flats += rect.height; + } + } + for (size_t i = 0; i < self->nibzles.len; i++) { + Nibzle sphere = *VecNibzle_at(&self->nibzles, i); + float sq_h = pow2f(sphere.rad) - pow2f(v.x - sphere.center.x) - pow2f(v.y - sphere.center.y); + if (sq_h >= 0) + return (cvec3){120, 120, 120}; + } + U8 p = (U8)roundf((1.f - expf(flats)) * 60); + return (cvec3){121 - p * 2, 30 + p, 65 - p}; +} + cvec3 compress_normal_vec_into_norm_texel(vec3 n) { return (cvec3){(U32)roundf(255 * (n.x + 1) / 2), (U32)roundf(255 * (n.y + 1) / 2), (U32)roundf(255 * (n.z + 1) / 2)}; } @@ -575,10 +617,36 @@ void draw_polygon_on_normal_texture_flat_param_surf(TextureDataR8G8B8A8* tex, ve } +typedef struct { + TextureDataR8G8B8A8* self; + const Bublazhuzhka* bublazhuzhka; +} TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_H_DrawGuest; + +void TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_h_draw_guest(void* ug, S32 x, S32 y, vec4 attr) { + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_H_DrawGuest *g = ug; + cvec3 clr = Bublazhuzhka_get_color(g->bublazhuzhka, (vec2){attr.x, attr.y}); + if (TextureDataR8G8B8A8_is_inside(g->self, x, y)) + *TextureDataR8G8B8A8_mat(g->self, x, y) = (cvec4){clr.x, clr.y, clr.z, 255}; +} + +/* Not natural coordinates. Needs translation operator to convert + * from parameter space*/ +void TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka( + TextureDataR8G8B8A8* self, const Bublazhuzhka* bublazhuzhka, MarieTriangle param_triangle, mat3x2 trop + ) { + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_H_DrawGuest aboba = + {self, bublazhuzhka}; + MarieTriangleAttr natural = MarieTriangle_goto_nat_cords_pres_par(param_triangle, trop); + // todo: continue from here + marie_rasterize_triangle_with_attr( + natural.v0, natural.v1, natural.v2, + (FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka_h_draw_guest, .guest = &aboba}); +} -TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) { + +TextureDataR8G8B8A8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) { assert(k >= 1); const float a = M_PI_2f / (float)k; const float l = 2 * r * sinf(M_PI_4f / (float)k); @@ -589,36 +657,42 @@ TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, const vec2 v1tex = {r + w, r}; const vec2 v2tex = {r, 2 * r}; const vec2 v3tex = {r + w, 2 * r}; - TextureDataR8 res = TextureDataR8_new(width_pix, height_pix); - Vecvec2 P = Vecvec2_new_reserved(6 + k * 4); - Vecvec2_append(&P, v0tex); - Vecvec2_append(&P, (vec2){r, 0}); // 4 - Vecvec2_append(&P, (vec2){r + w, 0}); // 5 - Vecvec2_append(&P, v1tex); - for (size_t i = k; i > 0; i--) { - Vecvec2_append(&P, (vec2){r + w + r * sinf(a * (float)i), r + r * cosf(a * (float)i)}); - } - Vecvec2_append(&P, v3tex); + const vec2 v4tex = {r, 0}; + const vec2 v5tex = {r + w, 0}; + TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width_pix, height_pix); + mat3x2 cord_resol_trop = (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y}; + + vec3 color_1 = (vec3){0.3f, 0.5f, 0.1f}; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_1, (MarieTriangle){v0tex, v4tex, v5tex}, cord_resol_trop); + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_1, (MarieTriangle){v0tex, v5tex, v1tex}, cord_resol_trop); + vec3 color_2 = (vec3){0.1f, 0.2f, 0.8f}; + vec3 color_3 = (vec3){0.2f, 0.3f, 0.9f}; + vec3 color_4 = (vec3){0.1f, 0.5f, 0.7f}; + vec3 color_5 = (vec3){0.7f, 0.05f, 0.2f}; for (size_t i = 1; i <= k; i++) { - Vecvec2_append(&P, (vec2){r + w, 2 * r + (float)i * l}); + vec2 A = (vec2){r - r * sinf(a * (float)i), r + r * cosf(a * (float)i)}; + vec2 B = (vec2){r - r * sinf(a * (float)(i-1)), r + r * cosf(a * (float)(i-1))}; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_2, (MarieTriangle){v0tex, B, A}, cord_resol_trop); } - for (size_t i = k; i > 0; i--) { - Vecvec2_append(&P, (vec2){r, 2 * r + (float)i * l}); - } - Vecvec2_append(&P, v2tex); for (size_t i = 1; i <= k; i++) { - Vecvec2_append(&P, (vec2){r - r * sinf(a * (float)i), r + r * cosf(a * (float)i)}); + vec2 A = (vec2){r + w + r * sinf(a * (float)i), r + r * cosf(a * (float)i)}; + vec2 B = (vec2){r + w + r * sinf(a * (float)(i-1)), r + r * cosf(a * (float)(i-1))}; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, color_3, (MarieTriangle){v1tex, A, B}, cord_resol_trop); } - for (size_t i = 0; i < P.len; i++) { - *Vecvec2_mat(&P, i) = vec2_mul_vec2(*Vecvec2_at(&P, i), cord_resol); + for (size_t i = 1; i <= k; i++) { + vec2 A = (vec2){r, 2 * r + (float)(i) * l}; + vec2 B = (vec2){r, 2 * r + (float)(i-1) * l}; + vec2 C = (vec2){r + w, 2 * r + (float)(i-1) * l}; + vec2 D = (vec2){r + w, 2 * r + (float)(i) * l}; + vec3 c = i % 2 ? color_4 : color_5; + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, c, (MarieTriangle){A, B, C}, cord_resol_trop); + TextureDataR8G8B8A8_draw_triangle_of_one_color(&res, c, (MarieTriangle){A, C, D}, cord_resol_trop); } - TextureDataR8_draw_perimeter_maxing(&res, Vecvec2_to_span(&P)); - Vecvec2_drop(P); Bublazhuzhka crap_on_back_side = fill_rectangle_with_crap(w, r); - // todo: draw bublazhuzhka pixel-by-pixel myself - Bublazhuzhka_TextureDataR8_draw_maxing(&crap_on_back_side, &res, - (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)}); + mat3x2 back_side_trop = (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)}; + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&res, &crap_on_back_side, (MarieTriangle){{0, r}, {0, 0}, {w, 0}}, back_side_trop); + TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&res, &crap_on_back_side, (MarieTriangle){{0, r}, {w, 0}, {w, r}}, back_side_trop); Bublazhuzhka_drop(crap_on_back_side); return res; } @@ -792,4 +866,13 @@ ShinyMeshTopology generate_shiny_rhombicuboctahedron(float r) { return res; } +GenericMeshInSceneTemplate GenericMeshInSceneTemplate_for_log(U32 w, U32 r, U32 k, U32 max_instance_count) { + return (GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder((float)w, (float)r, k), + .max_instance_count = max_instance_count, + .diffuse_texture_path = VecU8_format("textures/log_%u_%u_%u_diffuse.png", w, r, k), + .normal_texture_path = VecU8_format("textures/log_%u_%u_%u_NORMAL.png", w, r, k), + .specular_texture_path = VecU8_format("textures/log_%u_%u_%u_specular.png", w, r, k), + }; +} + #endif diff --git a/src/l2/tests/r0/r0_scene.h b/src/l2/tests/r0/r0_scene.h index 4eca086..b8e077e 100644 --- a/src/l2/tests/r0/r0_scene.h +++ b/src/l2/tests/r0/r0_scene.h @@ -12,12 +12,15 @@ typedef struct { VkBuffer instance_attr_buf; VkDeviceSize instance_attr_buf_offset; U32 limit_max_instance_count; -} ModelOnSceneMem; + VkImage diffuse_texture; + VkImage normal_texture; + VkImage specular_texture; +} GenericModelOnSceneMem; /* Contains both data for model instances attributes and buffer (+offset) where it is stored */ /* Also, I made it non-clonable. Thus */ typedef struct { - ModelOnSceneMem model; + GenericModelOnSceneMem model; VecGenericMeshInstance instances; } UsedGenericModelOnScene; @@ -28,7 +31,16 @@ void UsedGenericModelOnScene_drop(UsedGenericModelOnScene self) { #include "../../../../gen/l1/eve/r0/VecUsedGenericModelOnScene.h" typedef struct { - ModelOnSceneMem model; + VkBuffer vbo; + VkBuffer ebo; + size_t indexes; + VkBuffer instance_attr_buf; + VkDeviceSize instance_attr_buf_offset; + U32 limit_max_instance_count; +} ShinyModelOnSceneMem; + +typedef struct { + ShinyModelOnSceneMem model; VecShinyMeshInstance instances; } UsedShinyModelOnScene; @@ -134,7 +146,7 @@ void SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd( // todo: ot use one buffer per all the data for (size_t mi = 0; mi < scene_template->generic_models.len; mi++) { const GenericMeshInSceneTemplate* mt = VecGenericMeshInSceneTemplate_at(&scene_template->generic_models, mi); - const ModelOnSceneMem *m_buf = &VecUsedGenericModelOnScene_at(&scene->generic_models, mi)->model; + const GenericModelOnSceneMem *m_buf = &VecUsedGenericModelOnScene_at(&scene->generic_models, mi)->model; size_t vbo_len = mt->topology.vertices.len * sizeof(GenericMeshVertex); memcpy(host_mem_buffer_mem + offset, mt->topology.vertices.buf, vbo_len); VkBufferCopy ra = {.srcOffset = offset, .dstOffset = 0, .size = vbo_len}; @@ -148,7 +160,7 @@ void SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd( } for (size_t mi = 0; mi < scene_template->shiny_models.len; mi++) { const ShinyMeshInSceneTemplate* mt = VecShinyMeshInSceneTemplate_at(&scene_template->shiny_models, mi); - const ModelOnSceneMem *m_buf = &VecUsedShinyModelOnScene_at(&scene->shiny_models, mi)->model; + const ShinyModelOnSceneMem *m_buf = &VecUsedShinyModelOnScene_at(&scene->shiny_models, mi)->model; size_t vbo_len = mt->topology.vertices.len * sizeof(ShinyMeshVertex); memcpy(host_mem_buffer_mem + offset, mt->topology.vertices.buf, vbo_len); VkBufferCopy ra = {.srcOffset = offset, .dstOffset = 0, .size = vbo_len}; diff --git a/src/l2/tests/r0/r0_tex_init_prep.c b/src/l2/tests/r0/r0_tex_init_prep.c index d96de16..37bd066 100644 --- a/src/l2/tests/r0/r0_tex_init_prep.c +++ b/src/l2/tests/r0/r0_tex_init_prep.c @@ -1,30 +1,46 @@ #include "r0_assets.h" #include "../../marie/rasterization.h" -#include "../../margaret/png_pixel_masses.h" +// #include "../../margaret/png_pixel_masses.h" // todo: delete this file +#include "../../../../gen/l1/margaret/png_pixel_masses.h" #include "../../marie/texture_processing.h" -void model_1_template() { - TextureDataR8 tex = generate_tex_template_for_one_fourth_of_a_cylinder(120, 10, 2, 6); - TextureDataR8G8B8A8 tex_1_big = TextureDataR8G8B8A8_new(tex.width, TextureDataR8_get_height(&tex)); - for (size_t i = 0; i < tex.pixels.len; i++) { - U8 g = *VecU8_at(&tex.pixels, i); - *Veccvec4_mat(&tex_1_big.pixels, i) = (cvec4){g, g, g, 255}; +void for_log(U32 w, U32 r, U32 k) { + { + TextureDataR8G8B8A8 tex = generate_tex_template_for_one_fourth_of_a_cylinder(120, (float)w, (float)r, k); + TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex); + VecU8 name = VecU8_format("textures/log_%u_%u_%u_TEMPLATE.png", w, r, k); + TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, VecU8_to_span(&name)); + VecU8_drop(name); + TextureDataR8G8B8A8_drop(fixed_tex); + TextureDataR8G8B8A8_drop(tex); + } + { + TextureDataR8G8B8A8 tex = generate_normal_tex_for_one_fourth_of_a_cylinder(120, (float)w, (float)r, k); + TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex); + VecU8 name = VecU8_format("textures/log_%u_%u_%u_NORMAL.png", w, r, k); + TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, VecU8_to_span(&name)); + VecU8_drop(name); + TextureDataR8G8B8A8_drop(fixed_tex); + TextureDataR8G8B8A8_drop(tex); } - TextureDataR8G8B8A8_write_to_png_nofail(&tex_1_big, cstr("textures/log_10_2_6_TEMPLATE.png")); - TextureDataR8G8B8A8_drop(tex_1_big); - TextureDataR8_drop(tex); -} - -void model_1_normal() { - TextureDataR8G8B8A8 tex = generate_normal_tex_for_one_fourth_of_a_cylinder(120, 10, 2, 6); - TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex); - TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, cstr("textures/log_10_2_6_NORMAL.png")); - TextureDataR8G8B8A8_drop(fixed_tex); - TextureDataR8G8B8A8_drop(tex); } int main() { - model_1_template(); - model_1_normal(); + // TextureDataR8G8B8A8 tex = TextureDataR8G8B8A8_read_from_png_nofail(cstr("/home/gregory/test/basn3p04.png")); + // TextureDataR8G8B8A8_print(&tex); + // TextureDataR8G8B8A8_drop(tex); + // + // TextureDataR8G8B8 TEX = TextureDataR8G8B8_read_from_png_nofail(cstr("/home/gregory/test/basn3p04.png")); + // TextureDataR8G8B8_print(&TEX); + // TextureDataR8G8B8_drop(TEX); + + // TextureDataR8 tex = TextureDataR8_read_from_png_nofail(cstr("textures/log_5_5_10_TEMPLATE.png")); + // TextureDataR8_print(&tex); + // TextureDataR8_drop(tex); + + for_log(10, 2, 6); + for_log(5, 5, 10); + for_log(1, 10, 4); + for_log(2, 1, 6); return 0; } diff --git a/src/l2/tests/r0/shaders/glsl/0/0.frag b/src/l2/tests/r0/shaders/glsl/0/0.frag index 8f41989..512d843 100644 --- a/src/l2/tests/r0/shaders/glsl/0/0.frag +++ b/src/l2/tests/r0/shaders/glsl/0/0.frag @@ -3,11 +3,12 @@ layout(location = 0) in vec2 fsin_tex; layout(location = 1) in vec3 fsin_pos; +/* Righ now all in set 0 */ layout(location = 0) out vec4 fin_color; - +/* Yes, even these guys */ layout(binding = 1) uniform sampler2D color_tex; - layout(binding = 2) uniform sampler2D normal_map; +layout(binding = 3) uniform sampler2D specular_map; layout(push_constant, std430) uniform pc { layout(offset = 64) vec3 camera_pos; @@ -57,7 +58,8 @@ void main(){ Pipeline0Spotlight lamp = spotlight_arr[i]; } vec3 natural_color = texture(color_tex, fsin_tex).xyz; - // todo: add specular map texture - vec3 color = natural_color * diffuse_illumination + 0.5 * specular_illumination; + float specular_c = texture(specular_map, fsin_tex).x; + vec3 color = natural_color * diffuse_illumination + specular_c * specular_illumination; fin_color = vec4(color, 1); + // fin_color = vec4(specular_c, 0, 0, 1); } diff --git a/src/l2/tests/r0/textures/log_10_2_6.png b/src/l2/tests/r0/textures/log_10_2_6_diffuse.png similarity index 100% rename from src/l2/tests/r0/textures/log_10_2_6.png rename to src/l2/tests/r0/textures/log_10_2_6_diffuse.png diff --git a/src/l2/tests/r0/textures/log_10_2_6_specular.png b/src/l2/tests/r0/textures/log_10_2_6_specular.png new file mode 100644 index 0000000..c815435 Binary files /dev/null and b/src/l2/tests/r0/textures/log_10_2_6_specular.png differ diff --git a/src/l2/tests/r0/textures/log_1_10_4_diffuse.png b/src/l2/tests/r0/textures/log_1_10_4_diffuse.png new file mode 100644 index 0000000..11bf115 Binary files /dev/null and b/src/l2/tests/r0/textures/log_1_10_4_diffuse.png differ diff --git a/src/l2/tests/r0/textures/log_1_10_4_specular.png b/src/l2/tests/r0/textures/log_1_10_4_specular.png new file mode 100644 index 0000000..11bf115 Binary files /dev/null and b/src/l2/tests/r0/textures/log_1_10_4_specular.png differ diff --git a/src/l2/tests/r0/textures/log_2_1_6_diffuse.png b/src/l2/tests/r0/textures/log_2_1_6_diffuse.png new file mode 100644 index 0000000..06a0575 Binary files /dev/null and b/src/l2/tests/r0/textures/log_2_1_6_diffuse.png differ diff --git a/src/l2/tests/r0/textures/log_2_1_6_specular.png b/src/l2/tests/r0/textures/log_2_1_6_specular.png new file mode 100644 index 0000000..06a0575 Binary files /dev/null and b/src/l2/tests/r0/textures/log_2_1_6_specular.png differ diff --git a/src/l2/tests/r0/textures/log_5_5_10_diffuse.png b/src/l2/tests/r0/textures/log_5_5_10_diffuse.png new file mode 100644 index 0000000..b7de520 Binary files /dev/null and b/src/l2/tests/r0/textures/log_5_5_10_diffuse.png differ diff --git a/src/l2/tests/r0/textures/log_5_5_10_specular.png b/src/l2/tests/r0/textures/log_5_5_10_specular.png new file mode 100644 index 0000000..b7de520 Binary files /dev/null and b/src/l2/tests/r0/textures/log_5_5_10_specular.png differ diff --git a/src/l2/tests/tv0/tv0.c b/src/l2/tests/tv0/tv0.c new file mode 100644 index 0000000..e69de29