From 9a870d7101c79d8fdb2066efcd91b2d269915f66 Mon Sep 17 00:00:00 2001 From: Andreev Gregory Date: Mon, 21 Jul 2025 11:07:36 +0300 Subject: [PATCH] Added kernel filter to r0. Wrote a lot of gl matrix method generation --- .gitignore | 3 +- src/l1/core/VecU8_format.h | 34 ++ src/l1/main.c | 556 ++++++++++++++++++++++-- src/l2/margaret/graphics_geom.h | 8 + src/l2/margaret/margaret.h | 22 + src/l2/tests/r0.c | 426 +++++++++++++++--- src/l2/tests/test_shader_compile.sh | 11 +- src/l2/tests/test_shaders/glsl/0/0.frag | 14 +- src/l2/tests/test_shaders/glsl/0/0.vert | 9 +- src/l2/tests/test_shaders/glsl/1/1.frag | 15 + src/l2/tests/test_shaders/glsl/1/1.vert | 20 + 11 files changed, 1022 insertions(+), 96 deletions(-) create mode 100644 src/l1/core/VecU8_format.h create mode 100644 src/l2/margaret/graphics_geom.h create mode 100644 src/l2/tests/test_shaders/glsl/1/1.frag create mode 100644 src/l2/tests/test_shaders/glsl/1/1.vert diff --git a/.gitignore b/.gitignore index 9985800..9b8c381 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ cmake-build-debug/ .idea/ vgcore.* -gen/ \ No newline at end of file +gen/ +*.pdf \ No newline at end of file diff --git a/src/l1/core/VecU8_format.h b/src/l1/core/VecU8_format.h new file mode 100644 index 0000000..6a51160 --- /dev/null +++ b/src/l1/core/VecU8_format.h @@ -0,0 +1,34 @@ +#ifndef PROTOTYPE1_SRC_L1_CORE_VECU8_PRINT_H +#define PROTOTYPE1_SRC_L1_CORE_VECU8_PRINT_H + +#include +#include "./VecSpan_int_primitives.h" + +VecU8 VecU8_format(const char *fmt, ...) +{ + if (!fmt) + abortf("NULL passed as format\n"); + + /* first pass: figure out required length */ + va_list ap; + va_start(ap, fmt); + va_list ap_copy; + va_copy(ap_copy, ap); + + /* bytes *without* NUL */ + const int needed = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + if (needed < 0) + abortf("Formatting error\n"); + const size_t len = (size_t)needed; + /* allocate buffer (+1 so vsnprintf can add its NUL) */ + U8 *buf = safe_malloc(len + 1); + /* second pass: actually format */ + vsnprintf((char *)buf, len + 1, fmt, ap_copy); + va_end(ap_copy); + + return (VecU8){ .buf = buf, .len = len, .capacity = len + 1 }; +} + + +#endif diff --git a/src/l1/main.c b/src/l1/main.c index 7768002..2dbcb7b 100644 --- a/src/l1/main.c +++ b/src/l1/main.c @@ -1,6 +1,7 @@ #include #include "system/fileio.h" +#include "core/VecU8_format.h" NODISCARD VecU8 begin_header(ConstSpanU8 guard) { VecU8 res = VecU8_new(); @@ -8,7 +9,8 @@ NODISCARD VecU8 begin_header(ConstSpanU8 guard) { VecU8_append_span(&res, guard); VecU8_append_span(&res, cstr("\n#define ")); VecU8_append_span(&res, guard); - VecU8_append_span(&res, cstr("\n/* Automatically generated file. Do not edit it. */\n")); + VecU8_append_span(&res, cstr("\n/* Automatically generated file. Do not edit it. */\n\n" + "#include \"../src/l1/core/int_primitives.h\"\n\n")); return res; } @@ -18,9 +20,17 @@ void finish_header(VecU8 text_before_endif) { VecU8_drop(text_before_endif); } -void string_append_spaces(VecU8* str, int sc) { - for (int i = 0; i < sc; i++) - VecU8_append(str, ' '); +#define SPACE4 " " + +void string_append_vec_field_name(VecU8* str, int ci) { + assert(0 <= ci && ci < 4); + + VecU8_append(str, ci == 3 ? 'w' : 'x' + ci); +} + +void string_append_xvecy(VecU8* str, ConstSpanU8 xvec, int cc) { + VecU8_append_span(str, xvec); + VecU8_append(str, '0' + cc); } NODISCARD VecU8 generate_xvecy_struct_definition(ConstSpanU8 xvec, ConstSpanU8 member, int cc) { @@ -28,46 +38,532 @@ NODISCARD VecU8 generate_xvecy_struct_definition(ConstSpanU8 xvec, ConstSpanU8 m VecU8 res = VecU8_new(); VecU8_append_span(&res, cstr("typedef struct {\n")); - string_append_spaces(&res, 4); - VecU8_append_span(&res, member); - VecU8_append_span(&res, cstr(" x;\n")); - - string_append_spaces(&res, 4); - VecU8_append_span(&res, member); - VecU8_append_span(&res, cstr(" y;\n")); - - if (cc >= 3) { - string_append_spaces(&res, 4); + for (int ci = 0; ci < cc; ci++) { + VecU8_append_span(&res, cstr(SPACE4)); VecU8_append_span(&res, member); - VecU8_append_span(&res, cstr(" z;\n")); - } - if (cc >= 4) { - string_append_spaces(&res, 4); - VecU8_append_span(&res, member); - VecU8_append_span(&res, cstr(" w;\n")); + VecU8_append(&res, ' '); + string_append_vec_field_name(&res, ci); + VecU8_append_span(&res, cstr(";\n")); } VecU8_append_span(&res, cstr("} ")); - VecU8_append_span(&res, xvec); - VecU8_append(&res, '0' + cc); + string_append_xvecy(&res, xvec, cc); VecU8_append_span(&res, cstr(";\n\n")); return res; } -NODISCARD VecU8 generate_xvec234_struct_definition(ConstSpanU8 xvec, ConstSpanU8 member) { +// todo: replace all these number operations with function forms +NODISCARD VecU8 generate_xvecy_method_add_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int cc) { VecU8 res = VecU8_new(); - VecU8_append_vec(&res, generate_xvecy_struct_definition(xvec, member, 2)); - VecU8_append_vec(&res, generate_xvecy_struct_definition(xvec, member, 3)); - VecU8_append_vec(&res, generate_xvecy_struct_definition(xvec, member, 4)); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("_add_")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("(")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("){ ")); + for (int ci = 0; ci < cc; ci++) { + if (ci) + VecU8_append_span(&res, cstr(", ")); + VecU8_append_span(&res, cstr("A.")); + string_append_vec_field_name(&res, ci); + VecU8_append_span(&res, cstr(" + B.")); + string_append_vec_field_name(&res, ci); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xvecy_method_minus_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int cc) { + VecU8 res = VecU8_new(); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("_minus_")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("(")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("){ ")); + for (int ci = 0; ci < cc; ci++) { + if (ci) + VecU8_append_span(&res, cstr(", ")); + VecU8_append_span(&res, cstr("A.")); + string_append_vec_field_name(&res, ci); + VecU8_append_span(&res, cstr(" - B.")); + string_append_vec_field_name(&res, ci); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + + +NODISCARD VecU8 generate_xvecy_method_minus(ConstSpanU8 xvec, ConstSpanU8 member, int cc) { + VecU8 res = VecU8_new(); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("_minus(")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return(")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("){ ")); + for (int ci = 0; ci < cc; ci++) { + if (ci) + VecU8_append_span(&res, cstr(", ")); + VecU8_append_span(&res, cstr("-A.")); + string_append_vec_field_name(&res, ci); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xvecy_method_mul_scal(ConstSpanU8 xvec, ConstSpanU8 member, int cc) { + VecU8 res = VecU8_new(); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("_mul_scal(")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" A, ")); + VecU8_append_span(&res, member); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("){ ")); + for (int ci = 0; ci < cc; ci++) { + if (ci) + VecU8_append_span(&res, cstr(", ")); + VecU8_append_span(&res, cstr("A.")); + string_append_vec_field_name(&res, ci); + VecU8_append_span(&res, cstr(" * B")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xvecy_method_div_by_scal(ConstSpanU8 xvec, ConstSpanU8 member, int cc) { + VecU8 res = VecU8_new(); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("_div_by_scal(")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr(" A, ")); + VecU8_append_span(&res, member); + VecU8_append_span(&res, cstr(" B){\n" SPACE4 "return ")); + string_append_xvecy(&res, xvec, cc); + VecU8_append_span(&res, cstr("_mul_scal(A, 1/B);\n}\n\n")); + return res; +} + +void string_append_xmatnm(VecU8* str, ConstSpanU8 xmat, int cols, int rows) { + VecU8_append_span(str, xmat); + VecU8_append(str, '0' + cols); + if (rows != cols) { + VecU8_append(str, 'x'); + VecU8_append(str, '0' + rows); + } +} + +/* With columns padded to 16 bytes (for std140, std140 is our everything) */ +NODISCARD VecU8 generate_xmatnm_structure_definition(ConstSpanU8 xmat, ConstSpanU8 xvec, int cols, int rows, int sizeof_member) { + int sv = (rows * sizeof_member) % 16; + VecU8 res = VecU8_from_cstr("typedef struct {\n"); + for (int x = 0; x < cols; x++) { + VecU8_append_span(&res, cstr(SPACE4)); + string_append_xvecy(&res, xvec, rows); + VecU8_append_span(&res, cstr(" ")); + string_append_vec_field_name(&res, x); + VecU8_append_span(&res, cstr(";\n")); + if (sv) { + VecU8_append_vec(&res, VecU8_format(SPACE4 "char _padding_%d[%d];\n", x, 16 - sv)); + } + } + VecU8_append_span(&res, cstr("} ")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(";\n\n")); + return res; +} + +void string_append_mat_col_definition(VecU8* str, int ci) { + VecU8_append(str, '.'); + string_append_vec_field_name(str, ci); + VecU8_append_span(str, cstr(" = ")); +} + +void string_append_mat_el_access(VecU8* str, int x, int y) { + VecU8_append(str, '.'); + string_append_vec_field_name(str, x); + VecU8_append(str, '.'); + string_append_vec_field_name(str, y); +} + +NODISCARD VecU8 generate_xmatnm_method_new(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("_new(")); + for (int y = 0; y < rows; y++) { + for (int x = 0; x < cols; x++) { + if (x > 0 || y > 0) + VecU8_append_span(&res, cstr(", ")); + VecU8_append_span(&res, member); + VecU8_append(&res, ' '); + string_append_vec_field_name(&res, x); + string_append_vec_field_name(&res, y); + } + } + VecU8_append_span(&res, cstr(") {\n" SPACE4 "return (")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("){ ")); + for (int x = 0; x < cols; x++) { + if (x) + VecU8_append_span(&res, cstr(", ")); + string_append_mat_col_definition(&res, x); + VecU8_append_span(&res, cstr("{ ")); + for (int y = 0; y < rows; y++) { + if (y) + VecU8_append_span(&res, cstr(", ")); + string_append_vec_field_name(&res, x); + string_append_vec_field_name(&res, y); + } + VecU8_append_span(&res, cstr(" }")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_square_xmatnn_E_definition(ConstSpanU8 xmat, int n) { + VecU8 res = VecU8_from_cstr("const "); + string_append_xmatnm(&res, xmat, n, n); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, n, n); + VecU8_append_span(&res, cstr("_E = { ")); + for (int x = 0; x < n; x++) { + if (x) + VecU8_append_span(&res, cstr(", ")); + string_append_mat_col_definition(&res, x); + VecU8_append_span(&res, cstr("{ ")); + for (int y = 0; y < n; y++) { + if (y) + VecU8_append_span(&res, cstr(", ")); + VecU8_append(&res, '0' + (x == y)); + } + VecU8_append_span(&res, cstr(" }")); + } + VecU8_append_span(&res, cstr(" };\n\n")); + return res; +} + +NODISCARD VecU8 generate_xmatnm_method_add_xmatnm(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("_add_")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("(")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("){ ")); + for (int x = 0; x < cols; x++) { + if (x) + VecU8_append_span(&res, cstr(", ")); + string_append_mat_col_definition(&res, x); + string_append_xvecy(&res, xvec, rows); + VecU8_append_span(&res, cstr("_add_")); + string_append_xvecy(&res, xvec, rows); + VecU8_append_span(&res, cstr("(A.")); + string_append_vec_field_name(&res, x); + VecU8_append_span(&res, cstr(", B.")); + string_append_vec_field_name(&res, x); + VecU8_append_span(&res, cstr(")")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xmatnm_method_minus_xmatnm(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("_minus_")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("(")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("){ ")); + for (int x = 0; x < cols; x++) { + if (x) + VecU8_append_span(&res, cstr(", ")); + string_append_mat_col_definition(&res, x); + string_append_xvecy(&res, xvec, rows); + VecU8_append_span(&res, cstr("_minus_")); + string_append_xvecy(&res, xvec, rows); + VecU8_append_span(&res, cstr("(A.")); + string_append_vec_field_name(&res, x); + VecU8_append_span(&res, cstr(", B.")); + string_append_vec_field_name(&res, x); + VecU8_append_span(&res, cstr(")")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xmatnm_method_minus(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("_minus(")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return (")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("){ ")); + for (int x = 0; x < cols; x++) { + if (x) + VecU8_append_span(&res, cstr(", ")); + string_append_mat_col_definition(&res, x); + string_append_xvecy(&res, xvec, rows); + VecU8_append_span(&res, cstr("_minus(A.")); + string_append_vec_field_name(&res, x); + VecU8_append_span(&res, cstr(")")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xmatnm_method_mul_scal(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("_mul_scal(")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(" A, ")); + VecU8_append_span(&res, member); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("){ ")); + for (int x = 0; x < cols; x++) { + if (x) + VecU8_append_span(&res, cstr(", ")); + string_append_mat_col_definition(&res, x); + string_append_xvecy(&res, xvec, rows); + VecU8_append_span(&res, cstr("_mul_scal(A.")); + string_append_vec_field_name(&res, x); + VecU8_append_span(&res, cstr(", B)")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xmatnm_method_div_by_scal(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("_div_by_scal(")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr(" A, ")); + VecU8_append_span(&res, member); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ")); + string_append_xmatnm(&res, xmat, cols, rows); + VecU8_append_span(&res, cstr("_mul_scal(A, 1/B);\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xvecn_method_dot_xvecn(ConstSpanU8 xvec, ConstSpanU8 member, int n) { + VecU8 res = VecU8_from_span(member); + VecU8_append(&res, ' '); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr("_dot_")); + string_append_xvecy(&res, xvec, n); + VecU8_append(&res, '('); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ")); + for (int i = 0; i < n; i++) { + if (i) + VecU8_append_span(&res, cstr(" + ")); + VecU8_append_span(&res, cstr("A.")); + string_append_vec_field_name(&res, i); + VecU8_append_span(&res, cstr(" * B.")); + string_append_vec_field_name(&res, i); + } + VecU8_append_span(&res, cstr(";\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xmatnm_method_mul_xvecn(ConstSpanU8 xmat, ConstSpanU8 xvec, int n, int m) { + VecU8 res = VecU8_new(); + string_append_xvecy(&res, xvec, m); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, n, m); + VecU8_append_span(&res, cstr("_mul_")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr("(")); + string_append_xmatnm(&res, xmat, n, m); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xvecy(&res, xvec, n); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xvecy(&res, xvec, m); + VecU8_append_span(&res, cstr("){")); + for (int ci = 0; ci < m; ci++) { + if (ci) + VecU8_append(&res, ','); + VecU8_append_span(&res, cstr("\n" SPACE4 SPACE4)); + for (int x = 0; x < n; x++) { + if (x) + VecU8_append_span(&res, cstr(" + ")); + VecU8_append_span(&res, cstr("A")); + string_append_mat_el_access(&res, x, ci); + VecU8_append_span(&res, cstr(" * B.")); + string_append_vec_field_name(&res, x); + } + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xmatnm_method_mul_xmatkn(ConstSpanU8 xmat, int n, int m, int k) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, k, m); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, n, m); + VecU8_append_span(&res, cstr("_mul_")); + string_append_xmatnm(&res, xmat, k, n); + VecU8_append_span(&res, cstr("(")); + string_append_xmatnm(&res, xmat, n, m); + VecU8_append_span(&res, cstr(" A, ")); + string_append_xmatnm(&res, xmat, k, n); + VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return (")); + string_append_xmatnm(&res, xmat, k, m); + VecU8_append_span(&res, cstr("){")); + for (int x = 0; x < k; x++) { + if (x) + VecU8_append_span(&res, cstr(",")); + VecU8_append_span(&res, cstr("\n" SPACE4 SPACE4)); + string_append_mat_col_definition(&res, x); + VecU8_append_span(&res, cstr("{ ")); + for (int y = 0; y < m; y++) { + if (y) + VecU8_append_span(&res, cstr(", ")); + for (int z = 0; z < n; z++) { + if (z) + VecU8_append_span(&res, cstr(" + ")); + VecU8_append_span(&res, cstr("A")); + string_append_mat_el_access(&res, z, y); + VecU8_append_span(&res, cstr(" * B")); + string_append_mat_el_access(&res, x, z); + } + } + VecU8_append_span(&res, cstr(" }")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +VecU8 generate_xmatnm_method_transpose(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int n, int m) { + VecU8 res = VecU8_new(); + string_append_xmatnm(&res, xmat, m, n); + VecU8_append(&res, ' '); + string_append_xmatnm(&res, xmat, n, m); + VecU8_append_span(&res, cstr("_transpose(")); + string_append_xmatnm(&res, xmat, n, m); + VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return (")); + string_append_xmatnm(&res, xmat, m, n); + VecU8_append_span(&res, cstr("){ ")); + for (int bx = 0; bx < m; bx++) { + if (bx) + VecU8_append_span(&res, cstr(", ")); + string_append_mat_col_definition(&res, bx); + VecU8_append_span(&res, cstr("{ ")); + for (int by = 0; by < n; by++) { + if (by) + VecU8_append_span(&res, cstr(", ")); + VecU8_append_span(&res, cstr("A")); + string_append_mat_el_access(&res, by, bx); + } + VecU8_append_span(&res, cstr(" }")); + } + VecU8_append_span(&res, cstr(" };\n}\n\n")); + return res; +} + +NODISCARD VecU8 generate_xvec234_structs_and_methods(ConstSpanU8 xvec, ConstSpanU8 member) { + VecU8 res = VecU8_new(); + for (int cc = 2; cc <= 4; cc++) { + VecU8_append_vec(&res, generate_xvecy_struct_definition(xvec, member, cc)); + VecU8_append_vec(&res, generate_xvecy_method_add_xvecy(xvec, member, cc)); + VecU8_append_vec(&res, generate_xvecy_method_minus_xvecy(xvec, member, cc)); + VecU8_append_vec(&res, generate_xvecy_method_minus(xvec, member, cc)); + VecU8_append_vec(&res, generate_xvecy_method_mul_scal(xvec, member, cc)); + VecU8_append_vec(&res, generate_xvecy_method_div_by_scal(xvec, member, cc)); + } + return res; +} + +NODISCARD VecU8 generate_xmat234x234_structs_and_methods(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int sizeof_member) { + VecU8 res = VecU8_new(); + for (int cols = 2; cols <= 4; cols++) { + for (int rows = 2; rows <= 4; rows++) { + VecU8_append_vec(&res, generate_xmatnm_structure_definition(xmat, xvec, cols, rows, sizeof_member)); + } + } + for (int cols = 2; cols <= 4; cols++) { + for (int rows = 2; rows <= 4; rows++) { + VecU8_append_vec(&res, generate_xmatnm_method_new(xmat, xvec, member, cols, rows)); + VecU8_append_vec(&res, generate_xmatnm_method_add_xmatnm(xmat, xvec, member, cols, rows)); + VecU8_append_vec(&res, generate_xmatnm_method_minus_xmatnm(xmat, xvec, member, cols, rows)); + VecU8_append_vec(&res, generate_xmatnm_method_minus(xmat, xvec, member, cols, rows)); + VecU8_append_vec(&res, generate_xmatnm_method_mul_scal(xmat, xvec, member, cols, rows)); + VecU8_append_vec(&res, generate_xmatnm_method_div_by_scal(xmat, xvec, member, cols, rows)); + VecU8_append_vec(&res, generate_xmatnm_method_transpose(xmat, xvec, member, cols, rows)); + } + } + for (int n = 2; n <= 4; n++) { + VecU8_append_vec(&res, generate_square_xmatnn_E_definition(xmat, n)); + } + for (int n = 2; n <= 4; n++) { + for (int m = 2; m <= 4; m++) { + VecU8_append_vec(&res, generate_xmatnm_method_mul_xvecn(xmat, xvec, n, m)); + } + } + for (int n = 2; n <= 4; n++) { + for (int m = 2; m <= 4; m++) { + for (int k = 2; k <= 4; k++) { + VecU8_append_vec(&res, generate_xmatnm_method_mul_xmatkn(xmat, n, m, k)); + } + } + } return res; } void generate_geometry_header() { VecU8 res = begin_header(cstr("PROTOTYPE1_GEN_GEOM")); - VecU8_append_vec(&res, generate_xvec234_struct_definition(cstr("ivec"), cstr("int32_t"))); - VecU8_append_vec(&res, generate_xvec234_struct_definition(cstr("uvec"), cstr("uint32_t"))); - VecU8_append_vec(&res, generate_xvec234_struct_definition(cstr("vec"), cstr("float"))); - VecU8_append_vec(&res, generate_xvec234_struct_definition(cstr("dvec"), cstr("double"))); + VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("ivec"), cstr("S32"))); + VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("vec"), cstr("float"))); + VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("dvec"), cstr("double"))); + VecU8_append_vec(&res, generate_xmat234x234_structs_and_methods(cstr("mat"), cstr("vec"), cstr("float"), sizeof(float))); + VecU8_append_vec(&res, generate_xmat234x234_structs_and_methods(cstr("dmat"), cstr("dvec"), cstr("double"), sizeof(double))); finish_header(res); } diff --git a/src/l2/margaret/graphics_geom.h b/src/l2/margaret/graphics_geom.h new file mode 100644 index 0000000..0d76da2 --- /dev/null +++ b/src/l2/margaret/graphics_geom.h @@ -0,0 +1,8 @@ +#ifndef PROTOTYPE1_SRC_L2_MARGARET_GRAPHICS_GEOM_H +#define PROTOTYPE1_SRC_L2_MARGARET_GRAPHICS_GEOM_H + +#include "../../../gen/geom.h" + + + +#endif diff --git a/src/l2/margaret/margaret.h b/src/l2/margaret/margaret.h index 0f71857..dcf102c 100644 --- a/src/l2/margaret/margaret.h +++ b/src/l2/margaret/margaret.h @@ -736,6 +736,7 @@ VkFence margaret_create_fence(VkDevice device, bool create_signaled) { return res; } +//todo: strip synchronization lines out of here, pls PLS DO IT ADGASDHH HDJHFHFDKKF DFKDKDK THIS IS SO STUPID typedef struct { VkSwapchainKHR swapchain; VecVkImageView image_views; @@ -744,6 +745,7 @@ typedef struct { VkSemaphore in_frame_transfer_complete; VkSemaphore image_available_semaphore; + VkSemaphore rendered_to_IT1_semaphore; VkSemaphore render_finished_semaphore; VkFence in_flight_fence; } MargaretSwapchainBundle; @@ -759,6 +761,7 @@ MargaretSwapchainBundle MargaretSwapchainBundle_new( .framebuffers = framebuffers, .extent = swapchain_details.image_extent, .in_frame_transfer_complete = margaret_create_semaphore(device), .image_available_semaphore = margaret_create_semaphore(device), + .rendered_to_IT1_semaphore = margaret_create_semaphore(device), .render_finished_semaphore = margaret_create_semaphore(device), .in_flight_fence = margaret_create_fence(device, true), }; @@ -773,6 +776,7 @@ VkSwapchainKHR MargaretSwapchainBundle_pop_swapchain_drop_rest(VkDevice device, } vkDestroyFence(device, swfb.in_flight_fence, NULL); vkDestroySemaphore(device, swfb.render_finished_semaphore, NULL); + vkDestroySemaphore(device, swfb.rendered_to_IT1_semaphore, NULL); vkDestroySemaphore(device, swfb.image_available_semaphore, NULL); vkDestroySemaphore(device, swfb.in_frame_transfer_complete, NULL); // Old swapchain bundle is 83% dropped @@ -1058,6 +1062,12 @@ MargaretImageInMemoryInfo margaret_prep_image_mem_info_of_zbuffer(uint32_t max_w .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT }; } +/* Used both for sampling and as a color attachment */ +MargaretImageInMemoryInfo margaret_prep_image_mem_info_of_colorbuffer(U32 width, U32 height, VkFormat format) { + return (MargaretImageInMemoryInfo){.width = width, .height = height, .format = format, + .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT}; +} + MargaretBufferInMemoryInfo margaret_prep_buffer_mem_info_of_gpu_ubo(size_t struct_sz) { return (MargaretBufferInMemoryInfo){ .sz = struct_sz, .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT }; @@ -1345,5 +1355,17 @@ void margaret_record_buf_copying_command_buf( abortf("vkEndCommandBuffer"); } +VkDescriptorSet margaret_allocate_descriptor_set(VkDevice device, VkDescriptorPool descriptor_pool, VkDescriptorSetLayout layout) { + VkDescriptorSetAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = descriptor_pool, + .descriptorSetCount = 1, + .pSetLayouts = &layout, + }; + VkDescriptorSet descriptor_set; + if (vkAllocateDescriptorSets(device, &alloc_info, &descriptor_set) != VK_SUCCESS) + abortf("vkAllocateDescriptorSets"); + return descriptor_set; +} #endif diff --git a/src/l2/tests/r0.c b/src/l2/tests/r0.c index 859b800..c02aeb7 100644 --- a/src/l2/tests/r0.c +++ b/src/l2/tests/r0.c @@ -36,7 +36,59 @@ typedef struct { } Scene; // todo: generate this function in l2 -VkRenderPass create_render_pass(VkDevice logical_device, VkFormat image_format) { +VkRenderPass create_render_pass_1(VkDevice logical_device, VkFormat image_format) { + // Color attachments array for our render pass + VkAttachmentDescription all_attachments[1] = { (VkAttachmentDescription){ + .format = image_format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + } }; + + // For our one single render subpass + VkAttachmentReference color_attachment_refs[1] = { (VkAttachmentReference){ + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + } }; + + VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){ + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .colorAttachmentCount = ARRAY_SIZE(color_attachment_refs), + .pColorAttachments = color_attachment_refs, + } }; + + VkSubpassDependency subpass_dependencies[1] = { + // subpass_0_external + (VkSubpassDependency) { + .srcSubpass = VK_SUBPASS_EXTERNAL, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = 0, + .dstSubpass = 0, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }}; + + VkRenderPassCreateInfo render_pass_crinfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = ARRAY_SIZE(all_attachments), + .pAttachments = all_attachments, + .subpassCount = ARRAY_SIZE(subpasses_descr), + .pSubpasses = subpasses_descr, + .dependencyCount = ARRAY_SIZE(subpass_dependencies), + .pDependencies = subpass_dependencies, + }; + VkRenderPass render_pass; + if (vkCreateRenderPass(logical_device, &render_pass_crinfo, NULL, &render_pass) != VK_SUCCESS) + abortf("vkCreateRenderPass"); + return render_pass; +} + +// todo: generate this function in l2 +VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat image_format) { // Color attachments array for our render pass VkAttachmentDescription all_attachments[1] = { (VkAttachmentDescription){ .format = image_format, @@ -59,7 +111,6 @@ VkRenderPass create_render_pass(VkDevice logical_device, VkFormat image_format) .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, .colorAttachmentCount = ARRAY_SIZE(color_attachment_refs), .pColorAttachments = color_attachment_refs, - } }; VkSubpassDependency subpass_dependencies[1] = { @@ -102,7 +153,150 @@ void destroy_graphics_pipeline_hands(VkDevice device, PipelineHands hands) { } // todo: generate this function in l2 -PipelineHands create_graphics_pipeline( +PipelineHands create_graphics_pipeline_1( + VkDevice device, VkRenderPass render_pass, uint32_t subpass + ) { + VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/1/vert.spv"); + VecU8 frag_bin_code = read_whole_file_or_abort("test_shaders/spv/1/frag.spv"); + VkShaderModule vert_module = margaret_VkShaderModule_new(device, vert_bin_code); + VkShaderModule frag_module = margaret_VkShaderModule_new(device, frag_bin_code); + VecU8_drop(vert_bin_code); + VecU8_drop(frag_bin_code); + + VkPipelineShaderStageCreateInfo shader_stages_crinfo[2] = { + margaret_shader_stage_vertex_crinfo(vert_module), + margaret_shader_stage_fragment_crinfo(frag_module) + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = 0, + .pVertexBindingDescriptions = NULL, + .vertexAttributeDescriptionCount = 0, + .pVertexAttributeDescriptions = NULL, + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkPipelineViewportStateCreateInfo viewport_state = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + // We are using dynamic viewport and scissors, that is why we do not attach viewport/scissor values + // when creating a rendering pipeline. We will do that later + .viewportCount = 1, + .scissorCount = 1, + }; + + VkPipelineRasterizationStateCreateInfo rasterizer_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .depthClampEnable = VK_FALSE, + .polygonMode = VK_POLYGON_MODE_FILL, + .cullMode = VK_CULL_MODE_BACK_BIT, + .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, + .depthBiasEnable = VK_FALSE, + .depthBiasConstantFactor = 0.0f, + .depthBiasClamp = 0.0f, + .depthBiasSlopeFactor = 0.0f, + .lineWidth = 1.0f, + }; + + VkPipelineMultisampleStateCreateInfo multisampling_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .sampleShadingEnable = VK_FALSE, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + .minSampleShading = 1.0f, + .pSampleMask = NULL, + .alphaToCoverageEnable = VK_FALSE, + .alphaToOneEnable = VK_FALSE, + }; + + // For one framebuffer + VkPipelineColorBlendAttachmentState color_blend_attachments[1] = {(VkPipelineColorBlendAttachmentState){ + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + .blendEnable = VK_FALSE, + }}; + + // For the entire pipeline + VkPipelineColorBlendStateCreateInfo color_blending_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_COPY, + .attachmentCount = ARRAY_SIZE(color_blend_attachments), + .pAttachments = color_blend_attachments, + // Blend constants specified heres + }; + + VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; + VkPipelineDynamicStateCreateInfo dynamic_state_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = ARRAY_SIZE(dynamic_states), + .pDynamicStates = dynamic_states, + }; + + VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + }; + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_crinfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout), + .pBindings = bindings_for_my_descr_set_layout, + }; + VkDescriptorSetLayout my_descriptor_set_layout; + if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS) + abortf("vkCreateDescriptorSetLayout"); + + VkPushConstantRange used_region_sz_push_const = { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, .size = sizeof(vec2) + }; + + VkPipelineLayoutCreateInfo layout_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &my_descriptor_set_layout, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &used_region_sz_push_const, + }; + VkPipelineLayout pipeline_layout; + if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS) + abortf("vkCreatePipelineLayout"); + // todo: kill myself (update: still todo (update: still not done )) update: work in progress + VkGraphicsPipelineCreateInfo pipeline_crinfo = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .stageCount = ARRAY_SIZE(shader_stages_crinfo), + .pStages = shader_stages_crinfo, + .pVertexInputState = &vertex_input_crinfo, + .pInputAssemblyState = &input_assembly_crinfo, + .pViewportState = &viewport_state, + .pRasterizationState = &rasterizer_crinfo, + .pMultisampleState = &multisampling_crinfo, + .pDepthStencilState = NULL, + .pColorBlendState = &color_blending_crinfo, + .pDynamicState = &dynamic_state_crinfo, + .layout = pipeline_layout, + .renderPass = render_pass, + .subpass = subpass, + .basePipelineHandle = VK_NULL_HANDLE, + }; + + VkPipeline pipeline; + if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_crinfo, NULL, &pipeline) != VK_SUCCESS) + abortf("vkCreateGraphicsPipelines"); + + vkDestroyShaderModule(device, frag_module, NULL); + vkDestroyShaderModule(device, vert_module, NULL); + return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; +} + +PipelineHands create_graphics_pipeline_0( VkDevice device, VkRenderPass render_pass, uint32_t subpass ) { VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/0/vert.spv"); @@ -240,7 +434,6 @@ PipelineHands create_graphics_pipeline( VkPipelineLayout pipeline_layout; if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS) abortf("vkCreatePipelineLayout"); - // todo: kill myself (update: still todo (update: still not done )) update: work in progress VkGraphicsPipelineCreateInfo pipeline_crinfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .stageCount = ARRAY_SIZE(shader_stages_crinfo), @@ -259,6 +452,8 @@ PipelineHands create_graphics_pipeline( .basePipelineHandle = VK_NULL_HANDLE, }; + // todo: actually use this function + VkPipeline pipeline; if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_crinfo, NULL, &pipeline) != VK_SUCCESS) abortf("vkCreateGraphicsPipelines"); @@ -268,8 +463,26 @@ PipelineHands create_graphics_pipeline( return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; } -void reset_and_record_command_buffer( - VkCommandBuffer command_buffer, VkRenderPass render_pass, + +VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkRenderPass render_pass_0, VkExtent2D MAX_WIN_SIZE) { + VkImageView attachments[1] = {IT1_view}; + VkFramebufferCreateInfo framebuffer_crinfo = { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = render_pass_0, + .attachmentCount = ARRAY_SIZE(attachments), + .pAttachments = attachments, + .width = MAX_WIN_SIZE.width, + .height = MAX_WIN_SIZE.height, + .layers = 1 + }; + VkFramebuffer framebuffer; + if (vkCreateFramebuffer(device, &framebuffer_crinfo, NULL, &framebuffer) != VK_SUCCESS) + abortf("vkCreateFramebuffer"); + return framebuffer; +} + +void reset_and_record_command_buffer_0( + VkCommandBuffer command_buffer, VkRenderPass render_pass_0, const PipelineHands* pipeline_and_layout, VkFramebuffer swapchain_image_framebuffer, VkExtent2D image_extent, const Scene* scene, VkDescriptorSet my_descriptor_set @@ -283,7 +496,7 @@ void reset_and_record_command_buffer( VkClearValue clear_color[1] = {{.color = scene->color}}; VkRenderPassBeginInfo renderpass_begin = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = render_pass, + .renderPass = render_pass_0, .framebuffer = swapchain_image_framebuffer, .renderArea.offset = (VkOffset2D){0, 0}, .renderArea.extent = image_extent, @@ -328,6 +541,63 @@ void reset_and_record_command_buffer( abortf("vkEndCommandBuffer"); } +void reset_and_record_command_buffer_1( + VkCommandBuffer command_buffer, VkRenderPass render_pass_1, + const PipelineHands* pipeline_and_layout_1, + VkFramebuffer swapchain_image_framebuffer, VkExtent2D image_extent, + VkExtent2D max_win_size, + VkDescriptorSet descriptor_set_for_pipeline_1 + ) { + if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS) + abortf("vkResetCommandBuffer"); + VkCommandBufferBeginInfo info_begin = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS) + abortf("vkBeginCommandBuffer"); + + // VkClearValue clear_color[1] = {{.color = scene->color}}; + VkRenderPassBeginInfo renderpass_begin = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = render_pass_1, + .framebuffer = swapchain_image_framebuffer, + .renderArea.offset = (VkOffset2D){0, 0}, + .renderArea.extent = image_extent, + .clearValueCount = 0, + .pClearValues = NULL, + }; + + vkCmdBeginRenderPass(command_buffer, &renderpass_begin, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_1->pipeline); + + VkViewport viewport = { + .x = 0.0f, + .y = 0.0f, + .width = (float)(image_extent.width), + .height = (float)(image_extent.height), + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + vkCmdSetViewport(command_buffer, 0, 1, &viewport); + VkRect2D scissor = { + .offset = (VkOffset2D){0, 0}, + .extent = image_extent, + }; + vkCmdSetScissor(command_buffer, 0, 1, &scissor); + vkCmdBindDescriptorSets( + command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_1->pipeline_layout, 0, + 1, &descriptor_set_for_pipeline_1, 0, NULL); + + vec2 region_tex_scale = {(float)image_extent.width / (float)max_win_size.width, + (float)image_extent.height / (float)max_win_size.height}; + vkCmdPushConstants(command_buffer, pipeline_and_layout_1->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vec2), ®ion_tex_scale); + + vkCmdDraw(command_buffer, 3, 1, 0, 0); + + vkCmdEndRenderPass(command_buffer); + if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS) + abortf("vkEndCommandBuffer"); +} + + void recreate_swapchain( VkPhysicalDevice physical_device, VkDevice device, MargaretChosenQueueFamilies queue_fam, VkSurfaceKHR surface, VkRenderPass render_pass, MargaretSwapchainBundle* swfb) { @@ -369,10 +639,8 @@ int main() { ConstSpanU8 GPU = cstr("amd"); ConstSpanU8 bugged_GPU = cstr("nvidia"); bool ENABLE_VALIDATION_LAYERS = true; - // U32 MAX_WIN_WIDTH = 1900; - // U32 MAX_WIN_HEIGHT = 800; - - // int MAX_FRAMES_IN_FLIGHT = 2; + U32 MAX_WIN_WIDTH = 1920; + U32 MAX_WIN_HEIGHT = 1080; MargaretSingleWindowSetup x = MargaretSingleWindowSetup_new(); Margaret_WEP wep = Margaret_WEP_new(x.dpy, x.win); @@ -410,17 +678,20 @@ int main() { // We hope that the image format won't be changed even when window gets resized // VkSurfaceFormatKHR image_format = choose_surface_format_i_want(swap_chain_support).value(); - VkRenderPass render_pass = create_render_pass(device, swapchain_details.surface_format.format); - PipelineHands pipeline_hands = create_graphics_pipeline(device, render_pass, 0); + VkRenderPass render_pass_0 = create_render_pass_0(device, swapchain_details.surface_format.format); + PipelineHands pipeline_hands_0 = create_graphics_pipeline_0(device, render_pass_0, 0); - MargaretSwapchainBundle swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details, surface, render_pass, NULL); + VkRenderPass render_pass_1 = create_render_pass_1(device, swapchain_details.surface_format.format); + PipelineHands pipeline_hands_1 = create_graphics_pipeline_1(device, render_pass_1, 0); + + MargaretSwapchainBundle swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details, surface, render_pass_1, NULL); // Filling scene info const OA_Vertex obj1_vertexes[] = { - (OA_Vertex){ .pos = {-1, -1, 0}, .tex = {0, 1} }, - (OA_Vertex){ .pos = {1, -1, 0}, .tex = {1, 1} }, - (OA_Vertex){ .pos = {1, 1, 0}, .tex = {1, 0} }, - (OA_Vertex){ .pos = {-1, 1, 0}, .tex = {0, 0} }, + (OA_Vertex){ .pos = {-1, -0.5f, 0}, .tex = {0, 1} }, + (OA_Vertex){ .pos = {0.3f, -0.5f, 0}, .tex = {1, 1} }, + (OA_Vertex){ .pos = {-3.f, 3.f, 0}, .tex = {1, 0} }, + (OA_Vertex){ .pos = {-0.5f, .4f, 0}, .tex = {0, 0} }, }; const uint32_t obj1_indices[] = { 0, 2, 1, 0, 3, 2 }; const OA_Vertex obj2_vertexes[] = { @@ -447,6 +718,11 @@ int main() { wood_texture_data[y][col + 3] = (color8rgba){125, 20, 20, 255}; } } + for (U32 y = 0; y < 10; y++) { + for (U32 col = 0; col < 10; col++) { + wood_texture_data[13 + y][4 + col] = (color8rgba){140, 50, 20, 255}; + } + } // We have only one staging buffer in host memory (because we don't really need more) MargaretBufferInMemoryInfo host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = @@ -469,7 +745,8 @@ int main() { margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(MyUbo)), }; MargaretImageInMemoryInfo device_mem_images[] = { - margaret_prep_image_mem_info_of_gpu_texture_rgba(wood_texture_width, wood_texture_height) + margaret_prep_image_mem_info_of_gpu_texture_rgba(wood_texture_width, wood_texture_height), + margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, swapchain_details.surface_format.format), }; VkDeviceMemory device_mem = margaret_initialize_buffers_and_images(physical_device, device, (SpanMargaretBufferInMemoryInfo){ .data = device_mem_buffers, .len = ARRAY_SIZE(device_mem_buffers)}, @@ -481,9 +758,11 @@ int main() { MargaretBufferInMemoryInfo device_ebo_2_buffer = device_mem_buffers[3]; MargaretBufferInMemoryInfo device_ubo_my_buffer = device_mem_buffers[4]; MargaretImageInMemoryInfo device_wood_texture = device_mem_images[0]; + MargaretImageInMemoryInfo device_IT1_image = device_mem_images[1]; // todo: use it in my shenanigans VkCommandPool command_pool = margaret_create_resettable_command_pool(device, queue_fam.for_graphics); - VkCommandBuffer rendering_command_buffer = margaret_allocate_command_buffer(device, command_pool); + VkCommandBuffer rendering_command_buffer_0 = margaret_allocate_command_buffer(device, command_pool); + VkCommandBuffer rendering_command_buffer_1 = margaret_allocate_command_buffer(device, command_pool); VkCommandBuffer uniform_transfer_command_buffer = margaret_allocate_command_buffer(device, command_pool); margaret_record_buf_copying_command_buf(device, uniform_transfer_command_buffer, @@ -513,6 +792,12 @@ int main() { // My wood texture needs VkImageView VkImageView wood_texture_view = margaret_create_view_for_image(device, &device_wood_texture, VK_IMAGE_ASPECT_COLOR_BIT); + /* Here we create an image view into a temporary IT1 texture and a framebuffer for scene rendering */ + VkImageView IT1_view = margaret_create_view_for_image(device, &device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); + // todo: I will get back here soon + VkFramebuffer IT1_framebuffer = create_IT1_framebuffer(device, IT1_view, render_pass_0, + (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}); + Scene scene; scene.oa_objects = VecOA_ObjectOnScene_new_zeroinit(2); *VecOA_ObjectOnScene_at(&scene.oa_objects, 0) = (OA_ObjectOnScene){ @@ -523,48 +808,59 @@ int main() { // Sampler is global for a lot of my future textures VkSampler my_texture_sampler = margaret_create_sampler(physical_device, device); - VkDescriptorPool descriptor_pool = margaret_create_descriptor_set_pool(device, 1, 1, 2); - VkDescriptorSetAllocateInfo descriptor_sets_alloc_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .descriptorPool = descriptor_pool, - .descriptorSetCount = 1, - .pSetLayouts = &pipeline_hands.descriptor_set_layout, - }; - VkDescriptorSet my_descriptor_set; - if (vkAllocateDescriptorSets(device, &descriptor_sets_alloc_info, &my_descriptor_set) != VK_SUCCESS) - abortf("vkAllocateDescriptorSets"); - // Configuring my descriptor set, that I just allocated - VkDescriptorBufferInfo buffer_info_for_descriptor_0 = { + VkDescriptorPool descriptor_pool = margaret_create_descriptor_set_pool(device, 1, 2, 2); + + VkDescriptorSet descriptor_set_for_pipeline_0 = margaret_allocate_descriptor_set(device, descriptor_pool, pipeline_hands_0.descriptor_set_layout); + VkDescriptorSet descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set(device, descriptor_pool, pipeline_hands_1.descriptor_set_layout); + + // Configuring my descriptor sets, that I just allocated + VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0 = { .buffer = device_ubo_my_buffer.buffer, .offset = 0, .range = sizeof(MyUbo), }; - VkDescriptorImageInfo image_info_for_descriptor_1 = { + VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0 = { .sampler = my_texture_sampler, .imageView = wood_texture_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; - VkWriteDescriptorSet descriptor_writes[] = { + VkDescriptorImageInfo image_info_for_descriptor_0_in_set_1 = { + .sampler = my_texture_sampler, + .imageView = IT1_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet writes_in_descriptor_sets[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = my_descriptor_set, + .dstSet = descriptor_set_for_pipeline_0, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pBufferInfo = &buffer_info_for_descriptor_0, + .pBufferInfo = &buffer_info_for_descriptor_0_in_set_0, }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = my_descriptor_set, + .dstSet = descriptor_set_for_pipeline_0, .dstBinding = 1, .dstArrayElement = 0, .descriptorCount = 1, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &image_info_for_descriptor_1, + .pImageInfo = &image_info_for_descriptor_1_in_set_0, + }, + + + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptor_set_for_pipeline_1, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_0_in_set_1, }, }; - vkUpdateDescriptorSets(device, ARRAY_SIZE(descriptor_writes), descriptor_writes, 0, NULL); + vkUpdateDescriptorSets(device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); // Mainloop margaret_ns_time start = margaret_clock_gettime_monotonic_raw(); @@ -587,11 +883,11 @@ int main() { ); if (aq_ret == VK_ERROR_OUT_OF_DATE_KHR) { fprintf(stderr, "vkAcquireNextImageKHR: VK_ERROR_OUT_OF_DATE_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass, &swfb); + recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb); continue; } else if (aq_ret == VK_SUBOPTIMAL_KHR) { fprintf(stderr, "vkAcquireNextImageKHR: VK_SUBOPTIMAL_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass, &swfb); + recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb); continue; } else if (aq_ret != VK_SUCCESS) { abortf("vkAcquireNextImageKHR"); @@ -617,8 +913,12 @@ int main() { vkQueueSubmit(graphics_queue, 1, &ubo_copying_cmd_buffer_submit, NULL); } - reset_and_record_command_buffer(rendering_command_buffer, render_pass, &pipeline_hands, - *VecVkFramebuffer_cat(&swfb.framebuffers, ij), swfb.extent, &scene, my_descriptor_set); + reset_and_record_command_buffer_0(rendering_command_buffer_0, render_pass_0, &pipeline_hands_0, + IT1_framebuffer, swfb.extent, &scene, descriptor_set_for_pipeline_0); + + reset_and_record_command_buffer_1(rendering_command_buffer_1, render_pass_1, &pipeline_hands_1, + *VecVkFramebuffer_cat(&swfb.framebuffers, ij), + swfb.extent, (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}, descriptor_set_for_pipeline_1); { VkSemaphore waiting_for_semaphores[2] = { @@ -630,8 +930,8 @@ int main() { }; assert(ARRAY_SIZE(waiting_for_semaphores) == ARRAY_SIZE(waiting_stages)); // VkCommandBuffer command_buffers[1] = {*VecVkCommandBuffer_cat(&rendering_command_buffers, ij)}; - VkCommandBuffer command_buffers[1] = {rendering_command_buffer}; - VkSemaphore signaling_semaphores[1] = { swfb.render_finished_semaphore }; + VkCommandBuffer command_buffers[1] = {rendering_command_buffer_0}; + VkSemaphore signaling_semaphores[1] = { swfb.rendered_to_IT1_semaphore }; VkSubmitInfo cmd_submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, @@ -648,6 +948,30 @@ int main() { .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), .pSignalSemaphores = signaling_semaphores, }; + if (vkQueueSubmit(graphics_queue, 1, &cmd_submit_info, NULL) != VK_SUCCESS) + abortf("vkQueueSubmit"); + } + + { + VkSemaphore waiting_for_semaphores[1] = { swfb.rendered_to_IT1_semaphore }; + VkPipelineStageFlags waiting_stages[1] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + assert(ARRAY_SIZE(waiting_for_semaphores) == ARRAY_SIZE(waiting_stages)); + VkCommandBuffer command_buffers[1] = { rendering_command_buffer_1 }; + VkSemaphore signaling_semaphores[1] = { swfb.render_finished_semaphore }; + VkSubmitInfo cmd_submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + + .waitSemaphoreCount = ARRAY_SIZE(waiting_for_semaphores), + .pWaitSemaphores = waiting_for_semaphores, + .pWaitDstStageMask = waiting_stages, + + .commandBufferCount = ARRAY_SIZE(command_buffers), + .pCommandBuffers = command_buffers, + + .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), + .pSignalSemaphores = signaling_semaphores, + }; + if (vkQueueSubmit(graphics_queue, 1, &cmd_submit_info, swfb.in_flight_fence) != VK_SUCCESS) abortf("vkQueueSubmit"); } @@ -670,13 +994,14 @@ int main() { }; VkResult pres_ret = vkQueuePresentKHR(presentation_queue, &present_info); + // todo: ponder more over this if (pres_ret == VK_ERROR_OUT_OF_DATE_KHR) { fprintf(stderr, "vkQueuePresentKHR: VK_ERROR_OUT_OF_DATE_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass, &swfb); + recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb); continue; } else if (pres_ret == VK_SUBOPTIMAL_KHR) { fprintf(stderr, "vkQueuePresentKHR: VK_SUBOPTIMAL_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass, &swfb); + recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb); continue; } else if (pres_ret != VK_SUCCESS) { abortf("vkQueuePresentKHR"); @@ -712,6 +1037,7 @@ int main() { vkDestroyBuffer(device, device_ebo_2_buffer.buffer, NULL); vkDestroyBuffer(device, device_ubo_my_buffer.buffer, NULL); vkDestroyImage(device, device_wood_texture.image, NULL); + vkDestroyImage(device, device_IT1_image.image, NULL); vkDestroyBuffer(device, host_mem_buffer.buffer, NULL); vkFreeMemory(device, device_mem, NULL); @@ -719,8 +1045,10 @@ int main() { vkFreeMemory(device, host_mem, NULL); vkDestroyCommandPool(device, command_pool, NULL); MargaretSwapchainBundle_drop_with_device(device, swfb); - destroy_graphics_pipeline_hands(device, pipeline_hands); - vkDestroyRenderPass(device, render_pass, NULL); + destroy_graphics_pipeline_hands(device, pipeline_hands_1); + vkDestroyRenderPass(device, render_pass_1, NULL); + destroy_graphics_pipeline_hands(device, pipeline_hands_0); + vkDestroyRenderPass(device, render_pass_0, NULL); vkDestroyDevice(device, NULL); vkDestroySurfaceKHR(instance, surface, NULL); MargaretInstanceAndItsDebug_drop(inst_hands); diff --git a/src/l2/tests/test_shader_compile.sh b/src/l2/tests/test_shader_compile.sh index a8ef12a..916e835 100755 --- a/src/l2/tests/test_shader_compile.sh +++ b/src/l2/tests/test_shader_compile.sh @@ -1,4 +1,11 @@ #!/usr/bin/env bash cd test_shaders -glslc -o spv/0/vert.spv glsl/0/0.vert -glslc -o spv/0/frag.spv glsl/0/0.frag + +function compile(){ + mkdir -p "spv/$1" + glslc -o "spv/$1/vert.spv" "glsl/$1/$1.vert" + glslc -o "spv/$1/frag.spv" "glsl/$1/$1.frag" +} + +compile 0 +compile 1 diff --git a/src/l2/tests/test_shaders/glsl/0/0.frag b/src/l2/tests/test_shaders/glsl/0/0.frag index f6e2c38..a1dbad1 100644 --- a/src/l2/tests/test_shaders/glsl/0/0.frag +++ b/src/l2/tests/test_shaders/glsl/0/0.frag @@ -4,14 +4,6 @@ layout(location = 0) in vec2 fsin_tex; layout(location = 0) out vec4 fin_color; -layout(binding = 0) uniform my_ubo { - vec3 s; // 0 + 12 + 4 -}; - -layout(binding = 1) uniform sampler2D wood_texture; - -void main() { - vec2 tex_offset = 1.0 / textureSize(wood_texture, 0); - - fin_color = texture(wood_texture, gl_FragCoord.xy * tex_offset); -} +void main(){ + fin_color = vec4(fsin_tex, 0, 1); +} \ No newline at end of file diff --git a/src/l2/tests/test_shaders/glsl/0/0.vert b/src/l2/tests/test_shaders/glsl/0/0.vert index b3968cd..d77ba17 100644 --- a/src/l2/tests/test_shaders/glsl/0/0.vert +++ b/src/l2/tests/test_shaders/glsl/0/0.vert @@ -5,7 +5,10 @@ layout(location = 1) in vec2 tex; layout(location = 0) out vec2 vsout_tex; -void main() { - gl_Position = vec4(pos, 1.0); + +// todo: add my ubo (location = 0) into the mix +// todo: add my woiod_texture (location = 1) into the mix +void main(){ vsout_tex = tex; -} + gl_Position = vec4(pos, 1); +} \ No newline at end of file diff --git a/src/l2/tests/test_shaders/glsl/1/1.frag b/src/l2/tests/test_shaders/glsl/1/1.frag new file mode 100644 index 0000000..a6749a9 --- /dev/null +++ b/src/l2/tests/test_shaders/glsl/1/1.frag @@ -0,0 +1,15 @@ +#version 450 + +layout(location = 0) in vec2 fsin_tex; +layout(location = 0) out vec4 fin_color; + +layout(binding = 0) uniform sampler2D prev; + +void main() { + vec2 tex_offset = 1.0 / textureSize(prev, 0); +// fin_color = texture(wood_texture, gl_FragCoord.xy * tex_offset); + + fin_color = (texture(prev, fsin_tex + tex_offset * vec2(1, 0)) + texture(prev, fsin_tex + tex_offset * vec2(-1, 0)) + + texture(prev, fsin_tex + tex_offset * vec2(0, 1)) + texture(prev, fsin_tex + tex_offset * vec2(0, -1)) - 4 * + texture(prev, fsin_tex + tex_offset * vec2(0, 0))) / 8; +} diff --git a/src/l2/tests/test_shaders/glsl/1/1.vert b/src/l2/tests/test_shaders/glsl/1/1.vert new file mode 100644 index 0000000..e88a00e --- /dev/null +++ b/src/l2/tests/test_shaders/glsl/1/1.vert @@ -0,0 +1,20 @@ +#version 450 + +vec2 big_triangle_pos[3] = vec2[]( + vec2(-1, -1), vec2(-1, 3), vec2(3, -1) +); + +vec2 big_triangle_tex[3] = vec2[]( + vec2(0, 1), vec2(0, -1), vec2(2, 1) +); + +layout(location = 0) out vec2 vsout_tex; + +layout(push_constant, std430) uniform pc { + vec2 region_tex_scale; +}; + +void main() { + vsout_tex = big_triangle_tex[gl_VertexIndex] * region_tex_scale; + gl_Position = vec4(big_triangle_pos[gl_VertexIndex], 0, 1); +}