summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cool/LICENSE39
-rw-r--r--Cool/README.md44
-rw-r--r--Cool/compile.py153
-rw-r--r--Cool/cool.h249
-rw-r--r--Cool/demos/cool.html56
-rwxr-xr-xCool/demos/doc_generatorbin0 -> 28016 bytes
-rw-r--r--Cool/demos/doc_generator.c80
-rw-r--r--Cool/demos/view.cool9
-rw-r--r--Cool/demos/view.cool.c10
-rw-r--r--README.md13
-rw-r--r--Rend/rend.c125
-rw-r--r--Rend/rend.h3
-rw-r--r--Rend/rend_internal.h29
-rw-r--r--Rend/rend_vk.c3187
-rw-r--r--Rend/rend_vk_allocator.c118
-rw-r--r--Rend/rend_vk_arena.c264
-rw-r--r--Rend/rend_vk_device.c377
-rw-r--r--Rend/rend_vk_image.c125
-rw-r--r--Rend/rend_vk_internal.c1014
-rw-r--r--Rend/rend_vk_internal.h177
-rw-r--r--build.c33
-rw-r--r--demos/compute/rend_compute.c (renamed from demos/rend_compute.c)15
-rw-r--r--demos/compute/rend_compute.slang (renamed from demos/rend_compute.slang)0
-rwxr-xr-xdemos/compute/rend_compute_demobin446416 -> 434248 bytes
-rwxr-xr-xdemos/compute/rend_compute_fastbin474256 -> 0 bytes
-rwxr-xr-xdemos/multiplatform/demo (renamed from demos/demo)bin60352 -> 60392 bytes
-rw-r--r--demos/multiplatform/demo.c (renamed from demos/demo.c)2
-rw-r--r--demos/multiplatform/demo.html (renamed from demos/demo.html)0
-rw-r--r--demos/multiplatform/demo.js (renamed from demos/demo.js)0
-rwxr-xr-xdemos/multiplatform/demo.wasm (renamed from demos/demo.wasm)bin31763 -> 31779 bytes
-rwxr-xr-xdemos/multiplatform/demo_run (renamed from demos/demo_run)bin60592 -> 60640 bytes
-rw-r--r--demos/multiplatform/demo_run.c (renamed from demos/demo_run.c)2
-rwxr-xr-xdemos/teapot/rend_teapotbin849944 -> 845880 bytes
-rw-r--r--demos/teapot/rend_teapot.c (renamed from demos/rend_teapot.c)0
-rw-r--r--demos/teapot/teapot.h (renamed from demos/teapot.h)0
35 files changed, 3241 insertions, 2883 deletions
diff --git a/Cool/LICENSE b/Cool/LICENSE
new file mode 100644
index 0000000..1910a7a
--- /dev/null
+++ b/Cool/LICENSE
@@ -0,0 +1,39 @@
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2026 Vasco Alves
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
diff --git a/Cool/README.md b/Cool/README.md
new file mode 100644
index 0000000..3c9f770
--- /dev/null
+++ b/Cool/README.md
@@ -0,0 +1,44 @@
+# Cool
+
+Build server-side components with C! Use the single-header library as a standalone HTML formatter
+or use the transpiler to convert `.cool` files into `.c` files that you can include directly!
+
+## Example
+
+Write something like so:
+
+```code
+COOL void Api(char *name, char *func, char *desc) {
+ <div class="api-card">
+ <h3 class="api-name">{ name }</h3>
+ <code class="language-c">{ func } </code>
+ <div class="api-description">
+ { desc }
+ </div>
+ </div>
+}
+```
+
+Call `compiler.py` to get `view.cool.c` and include it into your code.
+
+```c
+#include "views.cool.c" // include server side components directly
+
+int main() {
+ char func_name[256];
+ char func_decl[256];
+ char *comment_text = NULL;
+ /* ... */
+ /* call you view directly! */
+ if (feel_like_it) {
+ Api(func_name, func_decl, comment_text);
+ }
+ return 0;
+}
+
+```
+
+## Contributing
+
+This is one of the few open source projects where I'm very open to contribution.
+Web is not my area of expertise. And this idea deserves fome fleshing out.
diff --git a/Cool/compile.py b/Cool/compile.py
new file mode 100644
index 0000000..9c19403
--- /dev/null
+++ b/Cool/compile.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+import sys
+import re
+import argparse
+
+TYPE_SPECIFIERS = {
+ 'int': '%d',
+ 'int32_t': '%d',
+ 'short': '%d',
+ 'long': '%ld',
+ 'unsigned': '%u',
+ 'unsigned int': '%u',
+ 'uint32_t': '%u',
+ 'size_t': '%zu',
+ 'float': '%f',
+ 'double': '%f',
+ 'char': '%c',
+ 'char*': '%s',
+ 'const char*': '%s',
+ 'char *': '%s',
+ 'const char *': '%s',
+}
+
+def parse_parameters(args_str: str) -> dict:
+ param_map = {}
+ if not args_str or args_str == 'void':
+ return param_map
+
+ params = args_str.split(',')
+ for param in params:
+ param = param.strip()
+ if not param:
+ continue
+
+ match = re.match(r'^(.*?)\b([A-Za-z0-9_]+)$', param)
+ if match:
+ type_part = match.group(1).strip()
+ var_name = match.group(2).strip()
+
+ type_clean = re.sub(r'\s*\*\s*', '*', type_part)
+ specifier = TYPE_SPECIFIERS.get(type_clean, '%d')
+ param_map[var_name] = (type_clean, specifier)
+
+ return param_map
+
+def escape_c_string(text: str) -> str:
+ return (text.replace('\\', '\\\\')
+ .replace('"', '\\"')
+ .replace('\r', '')
+ .replace('\n', '\\n'))
+
+def transpile_cool(cool_code: str, filename: str = "<stdin>") -> str:
+ lines = cool_code.splitlines(keepends=True)
+ c_output = []
+
+ cool_func_re = re.compile(r'^\s*COOL\s+void\s+([A-Za-z0-9_]+)\s*\((.*?)\)\s*\{\s*$')
+
+ in_cool_func = False
+ current_func = ""
+ raw_buffer = []
+ local_scope = {}
+
+ def flush_raw_buffer():
+ nonlocal raw_buffer
+ if raw_buffer:
+ combined = "".join(raw_buffer)
+ if combined:
+ escaped = escape_c_string(combined)
+ c_output.append(f' cool_html_raw(COOL_SV("{escaped}"));\n')
+ raw_buffer = []
+
+ for line_num, line in enumerate(lines, start=1):
+ match = cool_func_re.match(line)
+
+ if match and not in_cool_func:
+ in_cool_func = True
+ current_func, args = match.groups()
+ args_str = args.strip() if args.strip() else "void"
+
+ local_scope = parse_parameters(args_str)
+ c_output.append(f"void {current_func}({args_str}) {{\n")
+ continue
+
+ if in_cool_func:
+ if line.strip() == "}":
+ flush_raw_buffer()
+ c_output.append("}\n\n")
+ in_cool_func = False
+ current_func = ""
+ local_scope = {}
+ continue
+
+ # Tokenize line into @Component(), { expression }, and plain HTML
+ tokens = re.split(r'(@[A-Za-z0-9_]+\s*\([^)]*\)|\{[^{}]+\})', line)
+
+ for token in tokens:
+ if not token:
+ continue
+
+ # @Component()
+ if token.startswith('@') and '(' in token:
+ flush_raw_buffer()
+ call_code = token[1:].strip()
+ c_output.append(f" {call_code};\n")
+
+ # { expression }
+ elif token.startswith('{') and token.endswith('}'):
+ flush_raw_buffer()
+ expr = token[1:-1].strip()
+
+ if expr in local_scope:
+ type_clean, specifier = local_scope[expr]
+
+ if 'char*' in type_clean:
+ c_output.append(f" cool_html_txt({expr}, strlen({expr}));\n")
+ else:
+ c_output.append(f' cool_htmlf_raw("{specifier}", {expr});\n')
+ else:
+ available = ", ".join(f"'{p}'" for p in local_scope.keys()) if local_scope else "none"
+ sys.stderr.write(
+ f"\n[Transpiler Error] {filename}:{line_num}: "
+ f"Expression '{{{expr}}}' in function '{current_func}' does not match any parameter.\n"
+ f" -> Available parameter(s): {available}\n\n"
+ )
+ sys.exit(1)
+
+ # Raw HTML text
+ else:
+ raw_buffer.append(token)
+ else:
+ c_output.append(line)
+
+ return "".join(c_output)
+
+def main():
+ parser = argparse.ArgumentParser(description="Transpiles .cool template files to C source code.")
+ parser.add_argument("input", help="Input .cool file")
+ parser.add_argument("-o", "--output", help="Output .c file")
+ args = parser.parse_args()
+
+ with open(args.input, "r", encoding="utf-8") as f:
+ cool_code = f.read()
+
+ transpiled_c = transpile_cool(cool_code, filename=args.input)
+
+ if args.output:
+ with open(args.output, "w", encoding="utf-8") as f:
+ f.write(transpiled_c)
+ else:
+ sys.stdout.write(transpiled_c)
+
+if __name__ == "__main__":
+ main()
diff --git a/Cool/cool.h b/Cool/cool.h
new file mode 100644
index 0000000..f26024b
--- /dev/null
+++ b/Cool/cool.h
@@ -0,0 +1,249 @@
+/* ===========================================================================
+ * Cool - Server-side Components in C - Copyright (c) 2026 Vasco Alves
+ *
+ * _.-\ _.-\
+ * __.-'' \ __.-'' \
+ * -----------------------------------'
+ * \ X X / \ X X /
+ * \ X X / \ X X /
+ * \ X X / \ X X /
+ * \---------/ \---------/
+ *
+ * "Hasta la vista, baby."
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * PREFIX: COOL (macros) Cool_ (types) cool (function)
+ *
+ * USAGE:
+ * Can be used directly for very simple applications or through a transpiler
+ * that converts a separate "higher level" template language directly into
+ * C functions!
+ *
+ * --- view.cool ---
+ * COOL void GenDocs(char *name, char *func, char *desc) {
+ * <div class="api-card">
+ * <h3 class="api-name">{ name }</h3>
+ * <code class="language-c">{ func } </code>
+ * <div class="api-description">
+ * { desc }
+ * </div>
+ * </div>
+ * }
+ *
+ * --- main.c ---
+ * #include "view.cool.c"
+ * int main(int argc, char **argv) {
+ *
+ * if (argc < 2) {
+ * puts("Usage: doc_generator [FILE]");
+ * return 1;
+ * }
+ *
+ * FILE *header_file = fopen(argv[1], "r");
+ *
+ * char *line_buf = malloc(256);
+ * size_t len = 0;
+ * while (getline(&line_buf, &len, header_file) > 0) {
+ * char func_name[256];
+ * char func_decl[256];
+ * char *comment_text = NULL;
+ *
+ * if (parse_header_line(line_buf, func_name, func_decl, &comment_text)) {
+ * GenDocs(func_name, func_decl, comment_text);
+ * }
+ * }
+ *
+ * free(line_buf);
+ *
+ * return 0;
+ * }
+ *
+ * =========================================================================== */
+
+#ifndef _COOL_H_
+#define _COOL_H_
+
+#define COOL_MAJOR 0 // breaking API changes
+#define COOL_MINOR 0 // non-breaking features
+#define COOL_PATCH 0 // non-breaking patches and bug fixes
+
+/* CHANGE LOG
+ * 0.0.0 - @vasco - server-side HTML from C functions
+ */
+
+#define COOLDEF static inline
+#define COOL_OUTPUT stdout
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <assert.h>
+
+typedef struct {
+ char *cstr; // original cstring
+ size_t len; // len
+} Cool_StrView;
+
+/* Macro to wrap string literal in a string view. Since we will be dealing with a lot of */
+#define COOL_SV(literal) ((Cool_StrView){ .cstr = (literal), .len = sizeof(literal) - 1 })
+COOLDEF void cool_sv_write(Cool_StrView sv); // Write string view to output.
+COOLDEF void cool_html(Cool_StrView sv); // SAFELY write HTML to a buffer. Handles escaping malicious sequences.
+COOLDEF void cool_html_raw(Cool_StrView sv); // Writes HTML to buffer without escaping sequences. Vulnerable to XSS. Use with caution.
+COOLDEF void cool_html_raw_cstr(const char *str, size_t len); // Writes unsafe HTML using C strings.
+COOLDEF void cool_html_txt(const char *str, size_t len); // Meant for inner text. Escapes '<', '>' and '&'.
+COOLDEF void cool_htmlf(const char *fmt, ...); // SAFELY write formatted string to buffer.
+COOLDEF void cool_htmlf_raw(const char *fmt, ...); // Writes formatting HTML string to buffer without escaping sequences. Vulnerable to XSS. Use with caution.
+
+#endif
+
+#define COOL_IMPLEMENTATION
+#ifdef COOL_IMPLEMENTATION
+#undef COOL_IMPLEMENTATION
+
+static const char* cool_url_escape_table[256] = {
+ "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
+ "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f",
+ "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
+ "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f",
+ "%20", NULL, "%22", "%23", NULL, "%25", "%26", "%27",
+ NULL, NULL, NULL, "%2b", NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, "%3c", "%3d", "%3e", "%3f",
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, "%5c", NULL, "%5e", NULL,
+ "%60", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "%7b", "%7c", "%7d", NULL, "%7f",
+ "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
+ "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f",
+ "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
+ "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
+ "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af",
+ "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7",
+ "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf",
+ "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
+ "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf",
+ "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
+ "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df",
+ "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7",
+ "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef",
+ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
+ "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff"
+};
+
+COOLDEF void
+cool_sv_write(Cool_StrView sv)
+{
+ fwrite(sv.cstr, sizeof *sv.cstr, sv.len, COOL_OUTPUT);
+}
+
+COOLDEF void
+cool_html(Cool_StrView sv)
+{
+ assert(0 && "TODO");
+}
+
+COOLDEF void
+cool_html_raw(Cool_StrView sv)
+{
+ fwrite(sv.cstr, sizeof *sv.cstr, sv.len, COOL_OUTPUT);
+}
+
+COOLDEF void
+cool_html_raw_cstr(const char *str, size_t len)
+{
+ fwrite(str, sizeof *str, len, COOL_OUTPUT);
+}
+
+COOLDEF void
+cool_html_txt(const char *str, size_t len)
+{
+ const char *s = str;
+ while (s && *s && len--) {
+ int c = *str;
+ if (c == '<' || c == '>' || c == '&') {
+ cool_html_raw_cstr(str, s - str);
+ switch (c) {
+ case '>':
+ cool_html_raw(COOL_SV("&gt;"));
+ break;
+ case '<':
+ cool_html_raw(COOL_SV("&lt;"));
+ break;
+ case '&':
+ cool_html_raw(COOL_SV("&amp;"));
+ break;
+ }
+ str = s + 1;
+ }
+ s++;
+ }
+
+ if (s != str) cool_html_raw_cstr(str, s - str);
+}
+
+COOLDEF void
+cool_htmlf(const char *fmt, ...)
+{
+ assert(0 && "TODO");
+}
+
+COOLDEF void
+cool_htmlf_raw(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(COOL_OUTPUT, fmt, args);
+ va_end(args);
+}
+
+#endif
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2026 Vasco Alves
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
+
diff --git a/Cool/demos/cool.html b/Cool/demos/cool.html
new file mode 100644
index 0000000..b75c841
--- /dev/null
+++ b/Cool/demos/cool.html
@@ -0,0 +1,56 @@
+ <div class="api-card">
+ <h3 class="api-name">cool_sv_write</h3>
+ <code class="language-c">COOLDEF void cool_sv_write(Cool_StrView sv) </code>
+ <div class="api-description">
+ Write string view to output.
+
+ </div>
+ </div>
+ <div class="api-card">
+ <h3 class="api-name">cool_html</h3>
+ <code class="language-c">COOLDEF void cool_html(Cool_StrView sv) </code>
+ <div class="api-description">
+ SAFELY write HTML to a buffer. Handles escaping malicious sequences.
+
+ </div>
+ </div>
+ <div class="api-card">
+ <h3 class="api-name">cool_html_raw</h3>
+ <code class="language-c">COOLDEF void cool_html_raw(Cool_StrView sv) </code>
+ <div class="api-description">
+ Writes HTML to buffer without escaping sequences. Vulnerable to XSS. Use with caution.
+
+ </div>
+ </div>
+ <div class="api-card">
+ <h3 class="api-name">cool_html_raw_cstr</h3>
+ <code class="language-c">COOLDEF void cool_html_raw_cstr(const char *str, size_t len) </code>
+ <div class="api-description">
+ Writes unsafe HTML using C strings.
+
+ </div>
+ </div>
+ <div class="api-card">
+ <h3 class="api-name">cool_html_txt</h3>
+ <code class="language-c">COOLDEF void cool_html_txt(const char *str, size_t len) </code>
+ <div class="api-description">
+ Meant for inner text. Escapes '<', '>' and '&'.
+
+ </div>
+ </div>
+ <div class="api-card">
+ <h3 class="api-name">cool_htmlf</h3>
+ <code class="language-c">COOLDEF void cool_htmlf(const char *fmt, ...) </code>
+ <div class="api-description">
+ SAFELY write formatted string to buffer.
+
+ </div>
+ </div>
+ <div class="api-card">
+ <h3 class="api-name">cool_htmlf_raw</h3>
+ <code class="language-c">COOLDEF void cool_htmlf_raw(const char *fmt, ...) </code>
+ <div class="api-description">
+ Writes formatting HTML string to buffer without escaping sequences. Vulnerable to XSS. Use with caution.
+
+ </div>
+ </div>
diff --git a/Cool/demos/doc_generator b/Cool/demos/doc_generator
new file mode 100755
index 0000000..a41a10c
--- /dev/null
+++ b/Cool/demos/doc_generator
Binary files differ
diff --git a/Cool/demos/doc_generator.c b/Cool/demos/doc_generator.c
new file mode 100644
index 0000000..5074cf6
--- /dev/null
+++ b/Cool/demos/doc_generator.c
@@ -0,0 +1,80 @@
+/*
+ * This simple demo illustrates how I use this library to generate my documentation.
+ * Could be used either statically or live because it's as simple as executing doc_generator
+ * with the given header file and reading from stdout.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#define COOL_IMPLEMENTATION
+#include "../cool.h"
+
+#include "view.cool.c"
+
+int parse_header_line(const char *line, char *func_name, char *func_decl, char **comment_out);
+
+int main(int argc, char **argv) {
+
+ if (argc < 2) {
+ puts("Usage: doc_generator [FILE]");
+ return 1;
+ }
+
+ FILE *header_file = fopen(argv[1], "r");
+
+ char *line_buf = malloc(256);
+ size_t len = 0;
+ while (getline(&line_buf, &len, header_file) > 0) {
+ char func_name[256];
+ char func_decl[256];
+ char *comment_text = NULL;
+
+ if (parse_header_line(line_buf, func_name, func_decl, &comment_text)) {
+ Api(func_name, func_decl, comment_text);
+ }
+ }
+
+ free(line_buf);
+
+ return 0;
+}
+
+int parse_header_line(const char *line, char *func_name, char *func_decl, char **comment_out) {
+ char *comment_ptr = strstr(line, "//");
+ if (!comment_ptr) return 0;
+
+ *comment_out = comment_ptr + 2;
+ while (**comment_out == ' ' || **comment_out == '\t') {
+ (*comment_out)++;
+ }
+
+ size_t decl_len = comment_ptr - line;
+ if (decl_len >= 256) decl_len = 255;
+ strncpy(func_decl, line, decl_len);
+ func_decl[decl_len] = '\0';
+
+ while (decl_len > 0 && (isspace((unsigned char)func_decl[decl_len - 1]) || func_decl[decl_len - 1] == ';')) {
+ func_decl[--decl_len] = '\0';
+ }
+
+ char *open_paren = strchr(func_decl, '(');
+ if (!open_paren) return 0;
+
+ char *end_name = open_paren - 1;
+ while (end_name > func_decl && isspace((unsigned char)*end_name)) {
+ end_name--;
+ }
+
+ char *start_name = end_name;
+ while (start_name > func_decl && (isalnum((unsigned char)start_name[-1]) || start_name[-1] == '_')) {
+ start_name--;
+ }
+
+ size_t name_len = (end_name - start_name) + 1;
+ if (name_len >= 256) name_len = 255;
+ strncpy(func_name, start_name, name_len);
+ func_name[name_len] = '\0';
+
+ return 1;
+}
diff --git a/Cool/demos/view.cool b/Cool/demos/view.cool
new file mode 100644
index 0000000..238cfaf
--- /dev/null
+++ b/Cool/demos/view.cool
@@ -0,0 +1,9 @@
+COOL void Api(char *name, char *func, char *desc) {
+ <div class="api-card">
+ <h3 class="api-name">{ name }</h3>
+ <code class="language-c">{ func } </code>
+ <div class="api-description">
+ { desc }
+ </div>
+ </div>
+}
diff --git a/Cool/demos/view.cool.c b/Cool/demos/view.cool.c
new file mode 100644
index 0000000..458072e
--- /dev/null
+++ b/Cool/demos/view.cool.c
@@ -0,0 +1,10 @@
+void Api(char *name, char *func, char *desc) {
+ cool_html_raw(COOL_SV(" <div class=\"api-card\">\n <h3 class=\"api-name\">"));
+ cool_html_txt(name, strlen(name));
+ cool_html_raw(COOL_SV("</h3>\n <code class=\"language-c\">"));
+ cool_html_txt(func, strlen(func));
+ cool_html_raw(COOL_SV(" </code>\n <div class=\"api-description\">\n "));
+ cool_html_txt(desc, strlen(desc));
+ cool_html_raw(COOL_SV("\n </div>\n </div>\n"));
+}
+
diff --git a/README.md b/README.md
index 5a69cdf..d10f06d 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,8 @@
```
Collection of modular and minimal libraries used by our games. These libraries are designed to be
-"vendored in" aka. copy-and-pasted into a project's folder. Some libraries may depend on each other.
-Each library should contain a license in the header.
+"vendored in" aka. copy-and-pasted into a project's folder. Some libraries may depend on each other,
+but most can be used in isolation. Each library should contain a license in the header.
Use at your own risk.
@@ -21,11 +21,12 @@ Use at your own risk.
| Rend | Modern graphics API layer. |
| Cool | Render HTML by calling functions. |
-## Maturity
+## Maturity & Versioning
-Rend and Peak are the most mature. Some libraries are still in development. Check the version
-included in each header file. Be encouraged and not discouraged if a library "isn't updated," it's probably
-because it works.
+Most libraries include a version and a change log at the top of the file.
+This is helpful if you decide to update one of the libraries you are using in a project.
+Libraries that have reached or surpassed the 1.0.0 landmark are generally considered
+to be "completed."
## Documentation
diff --git a/Rend/rend.c b/Rend/rend.c
index 4d85745..f390de2 100644
--- a/Rend/rend.c
+++ b/Rend/rend.c
@@ -8,12 +8,10 @@
#include "rend.h"
#include "rend_internal.h"
#include "rend_vk.c"
-#include "rend_vk_internal.h"
/* clean up functions */
-static void rend__renderer_destroy_recursive(RendRenderer renderer);
-static void rend__pipeline_destroy_recursive(RendPipeline pipeline);
+static void rend__pipeline_free_list(RendPipeline pipeline);
static bool rend__renderer_init_recursive(RendRenderer renderer, RendBackendType backend, bool auto_pick);
static RendRenderer rend_renderers_head = NULL;
@@ -65,40 +63,44 @@ RendVTable rend_vtables[] = {
extern void
rend_quit()
{
- rend__renderer_destroy_recursive(rend_renderers_head);
+ while (rend_renderers_head)
+ rend_renderer_destroy(rend_renderers_head);
if (rend_backend_vk_initialized) {
rend_vk_quit();
rend_backend_vk_initialized = false;
}
-
}
extern RendRenderer
rend_renderer_create(PeakWindow *target, RendBackendType backend, void* device, bool vsync, RendBindingInfo *bind_info)
{
-
RendRenderer rend = rmalloc(sizeof *rend);
- rend->next = rend_renderers_head;
- rend->prev = NULL;
- rend_renderers_head = rend;
- if(rend->next) {
- rend->next->prev = rend;
- }
+ if (!rend) return NULL;
+ memset(rend, 0, sizeof *rend);
- rend__renderer_init_recursive(rend, backend, false);
+ if (!rend__renderer_init_recursive(rend, backend, false)) {
+ rfree(rend);
+ return NULL;
+ }
rend->vsync = vsync;
rend->bind_info = *bind_info;
rend->window = target;
- rend->pipeline_head = 0;
rend->context = rend_vtables[rend->backend].renderer_create(target, bind_info);
- if (rend->context) {
- return rend;
+ if (!rend->context) {
+ rfree(rend);
+ return NULL;
}
- return NULL;
+ rend->next = rend_renderers_head;
+ rend->prev = NULL;
+ rend_renderers_head = rend;
+ if (rend->next)
+ rend->next->prev = rend;
+
+ return rend;
}
extern void
@@ -107,10 +109,12 @@ rend_renderer_destroy(RendRenderer renderer)
RASSERT(renderer && renderer->context, "Invalid renderer.");
if (!renderer) return;
- rend__pipeline_destroy_recursive(renderer->pipeline_head);
+ rend__pipeline_free_list(renderer->pipeline_head);
+ renderer->pipeline_head = NULL;
- if (renderer->backend != 0) {
+ if (renderer->backend != 0 && renderer->context) {
rend_vtables[renderer->backend].renderer_destroy(renderer->context);
+ renderer->context = NULL;
}
if (renderer->prev) renderer->prev->next = renderer->next;
@@ -118,6 +122,8 @@ rend_renderer_destroy(RendRenderer renderer)
if (renderer->next) renderer->next->prev = renderer->prev;
+ renderer->next = NULL;
+ renderer->prev = NULL;
rfree(renderer);
}
@@ -153,21 +159,21 @@ extern void
rend_renderer_render_pass_begin(RendRenderer renderer, float r, float g ,float b, float a)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin(renderer, r, g, b, a);
+ rend_vtables[renderer->backend].renderer_render_pass_begin(renderer->context, r, g, b, a);
}
extern void
rend_renderer_render_pass_begin_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer->context, texture);
}
extern void
rend_renderer_render_pass_end_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer->context, texture);
}
@@ -175,25 +181,25 @@ extern void
rend_renderer_render_pass_end(RendRenderer renderer)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end(renderer);
+ rend_vtables[renderer->backend].renderer_render_pass_end(renderer->context);
}
extern void
rend_descriptor_write_ubo(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot)
{
- rend_vtables[renderer->backend].descriptor_write_buffer(renderer, ubo, binding, slot, 0, ubo.size, true);
+ rend_vtables[renderer->backend].descriptor_write_buffer(renderer->context, ubo, binding, slot, 0, ubo.size, true);
}
extern void
rend_descriptor_write_ssbo(RendRenderer renderer, RendBuffer ssbo, uint32_t binding, uint32_t slot)
{
- rend_vtables[renderer->backend].descriptor_write_buffer(renderer, ssbo, binding, slot, 0, ssbo.size, false);
+ rend_vtables[renderer->backend].descriptor_write_buffer(renderer->context, ssbo, binding, slot, 0, ssbo.size, false);
}
extern RendBuffer
rend_buffer_create(RendRenderer renderer, size_t size, RendBufferType type, bool gpu) {
- RendBuffer buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer, size, type, gpu, REND_LIFETIME_PERMANENT);
+ RendBuffer buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer->context, size, type, gpu, REND_LIFETIME_PERMANENT);
buffer.backend = renderer->backend;
return buffer;
}
@@ -211,9 +217,9 @@ rend_buffer_write(RendRenderer renderer, RendBuffer *buffer, const void *data, s
memcpy(ptr + offset, data, size);
} else {
/* if the memory is bound to the device we must create and deallocate a transfer buffer */
- RendBuffer transfer_buffer = rend_vtables[buffer->backend].buffer_create_lifetime(renderer, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
+ RendBuffer transfer_buffer = rend_vtables[buffer->backend].buffer_create_lifetime(renderer->context, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
memcpy(transfer_buffer.mapped_memory, data, size);
- rend_vtables[buffer->backend].buffer_copy(renderer, buffer, offset, &transfer_buffer, 0, size);
+ rend_vtables[buffer->backend].buffer_copy(renderer->context, buffer, offset, &transfer_buffer, 0, size);
rend_vtables[buffer->backend].buffer_destroy(&transfer_buffer);
}
}
@@ -221,7 +227,7 @@ rend_buffer_write(RendRenderer renderer, RendBuffer *buffer, const void *data, s
extern void
rend_buffer_copy(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes)
{
- rend_vtables[renderer->backend].buffer_copy(renderer, dest, dest_offset, src, src_offset, bytes);
+ rend_vtables[renderer->backend].buffer_copy(renderer->context, dest, dest_offset, src, src_offset, bytes);
}
extern uint64_t
@@ -234,7 +240,7 @@ rend_buffer_address(RendBuffer *buffer)
extern RendTexture
rend_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format)
{
- RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer, width, height, depth, mip_levels, layers, format);
+ RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer->context, width, height, depth, mip_levels, layers, format);
tex.backend = renderer->backend;
return tex;
}
@@ -242,14 +248,14 @@ rend_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint
extern RendTexture
rend_texture_create_from_data(RendRenderer renderer, const void *data, uint32_t width, uint32_t height, RendFormat format)
{
- RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer, width, height, 1, 1, 1, format);
+ RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer->context, width, height, 1, 1, 1, format);
tex.backend = renderer->backend;
uint32_t size = width * height * rend_format_size[format];
- RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
+ RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer->context, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
memcpy(staging_buffer.mapped_memory, data, size);
- rend_vtables[renderer->backend].texture_copy_buffer(renderer, &tex, &staging_buffer);
+ rend_vtables[renderer->backend].texture_copy_buffer(renderer->context, &tex, &staging_buffer);
rend_vtables[renderer->backend].buffer_destroy(&staging_buffer);
return tex;
}
@@ -257,9 +263,9 @@ rend_texture_create_from_data(RendRenderer renderer, const void *data, uint32_t
extern void
rend_texture_copy_data(RendRenderer renderer, RendTexture *texture, const void *data, size_t size)
{
- RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
+ RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer->context, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
memcpy(staging_buffer.mapped_memory, data, size);
- rend_vtables[renderer->backend].texture_copy_buffer(renderer, texture, &staging_buffer);
+ rend_vtables[renderer->backend].texture_copy_buffer(renderer->context, texture, &staging_buffer);
rend_vtables[renderer->backend].buffer_destroy(&staging_buffer);
}
@@ -267,13 +273,13 @@ rend_texture_copy_data(RendRenderer renderer, RendTexture *texture, const void *
extern void
rend_texture_copy_buffer(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer)
{
- rend_vtables[renderer->backend].texture_copy_buffer(renderer, texture, buffer);
+ rend_vtables[renderer->backend].texture_copy_buffer(renderer->context, texture, buffer);
}
extern void
rend_texture_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h)
{
- rend_vtables[renderer->backend].texture_blit(renderer, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
+ rend_vtables[renderer->backend].texture_blit(renderer->context, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
}
extern uint64_t
@@ -285,7 +291,7 @@ rend_texture_id(RendTexture *texture)
extern void
rend_texture_destroy(RendRenderer renderer, RendTexture *tex)
{
- rend_vtables[renderer->backend].texture_destroy(renderer, tex);
+ rend_vtables[renderer->backend].texture_destroy(renderer->context, tex);
}
extern void
@@ -341,7 +347,7 @@ rend_pipeline_create_graphics_spirv(RendRenderer renderer, uint8_t *vertex_bytes
.color_format = color_format,
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->next = renderer->pipeline_head;
@@ -378,7 +384,7 @@ rend_pipeline_create_graphics_bindless_spirv(RendRenderer renderer, uint8_t *ver
.color_format = color_format,
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->next = renderer->pipeline_head;
@@ -404,7 +410,7 @@ rend_pipeline_create_compute_spirv(RendRenderer renderer, const uint8_t *compute
.push_constant_count = push_constant_count,
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_COMPUTE, compute_bytes, compute_size, NULL, 0, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_COMPUTE, compute_bytes, compute_size, NULL, 0, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->type = REND__PIPELINE_COMPUTE;
@@ -432,7 +438,7 @@ rend_pipeline_create_meshlet_spirv(RendRenderer renderer, uint8_t *meshlet_bytes
.cull_mode = cull_mode,
.depth_test_enable = depth_test_enable
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_MESH, meshlet_bytes, meshlet_size, frag_bytes, frag_size, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_MESH, meshlet_bytes, meshlet_size, frag_bytes, frag_size, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->type = REND__PIPELINE_MESH;
@@ -483,28 +489,28 @@ extern void
rend_cmd_render_begin(RendRenderer renderer, float r, float g, float b, float a)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin(renderer, r, g, b, a);
+ rend_vtables[renderer->backend].renderer_render_pass_begin(renderer->context, r, g, b, a);
}
extern void
rend_cmd_render_begin_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer->context, texture);
}
extern void
rend_cmd_render_end(RendRenderer renderer)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end(renderer);
+ rend_vtables[renderer->backend].renderer_render_pass_end(renderer->context);
}
extern void
rend_cmd_render_end_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer->context, texture);
}
extern void
@@ -557,7 +563,7 @@ rend_cmd_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_
RASSERT(renderer->in_frame && "Must be called while rendering a frame!");
RASSERT(!renderer->in_pass && "Must be called outside a render pass!");
renderer->in_pass = true;
- rend_vtables[renderer->backend].texture_blit(renderer, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
+ rend_vtables[renderer->backend].texture_blit(renderer->context, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
}
static bool
@@ -597,24 +603,13 @@ rend__renderer_init_recursive(RendRenderer renderer, RendBackendType backend, bo
}
static void
-rend__renderer_destroy_recursive(RendRenderer renderer)
+rend__pipeline_free_list(RendPipeline pipeline)
{
- if (renderer == NULL) return;
-
- rend__renderer_destroy_recursive(renderer->next);
-
- if (renderer->backend != 0) {
- rend_vtables[renderer->backend].renderer_destroy(renderer);
+ while (pipeline) {
+ RendPipeline next = pipeline->next;
+ pipeline->next = NULL;
+ pipeline->prev = NULL;
+ rfree(pipeline);
+ pipeline = next;
}
-
- rend__pipeline_destroy_recursive(renderer->pipeline_head);
- rfree(renderer);
-}
-
-static void
-rend__pipeline_destroy_recursive(RendPipeline pipeline)
-{
- if (pipeline == NULL) return;
- rend__pipeline_destroy_recursive(pipeline->next);
- rfree(pipeline);
}
diff --git a/Rend/rend.h b/Rend/rend.h
index c4ba1d4..489686a 100644
--- a/Rend/rend.h
+++ b/Rend/rend.h
@@ -15,7 +15,7 @@
#define REND_MAJOR 1 // breaking API changes
#define REND_MINOR 0 // non-breaking features
-#define REND_PATCH 3 // non-breaking patches and bug fixes
+#define REND_PATCH 4 // non-breaking patches and bug fixes
#ifndef PEAK_VULKAN
#define PEAK_VULKAN
@@ -284,6 +284,7 @@ enum RendBufferType_t {
* 1.0.1 - @vasco - render pass that targets textures
* 1.0.2 - @vasco - Peak instead of Podium
* 1.0.3 - @vasco - frame_begin no longer sticks in_frame or burns timeline on OUT_OF_DATE
+ * 1.0.4 - @vasco - vulkan backend collapsed; renderer create fails cleanly
*
* 1.0.0 finished API release
*
diff --git a/Rend/rend_internal.h b/Rend/rend_internal.h
index 4993d92..78275cc 100644
--- a/Rend/rend_internal.h
+++ b/Rend/rend_internal.h
@@ -1,9 +1,6 @@
#ifndef REND_INTERNAL_H
#define REND_INTERNAL_H
-#include "rend_vk_internal.h"
-
-
#if defined(REND_DEBUG)
#ifndef P_LOG_DEBUG_ENABLED
#define P_LOG_DEBUG_ENABLED 1
@@ -78,19 +75,19 @@ typedef struct {
bool (*renderer_frame_begin)(RendContextHandle);
void (*renderer_frame_end)(RendContextHandle, float *delta);
- void (*descriptor_write_buffer)(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo);
- void (*descriptor_write_texture)(void *ctx, RendTexture *texture, uint32_t binding, uint32_t slot);
+ void (*descriptor_write_buffer)(RendContextHandle handle, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo);
+ void (*descriptor_write_texture)(RendContextHandle handle, RendTexture *texture, uint32_t binding, uint32_t slot);
- RendBuffer (*buffer_create_lifetime)(RendRenderer renderer, size_t size, RendBufferType type, bool gpu, int lifetime);
+ RendBuffer (*buffer_create_lifetime)(RendContextHandle handle, size_t size, RendBufferType type, bool gpu, int lifetime);
void (*buffer_destroy)(RendBuffer *buffer);
- void (*buffer_copy)(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes);
+ void (*buffer_copy)(RendContextHandle handle, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes);
- RendTexture (*texture_create)(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format);
- void (*texture_destroy)(RendRenderer renderer, RendTexture *tex);
- void (*texture_copy_buffer)(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer);
- void (*texture_blit)(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h);
+ RendTexture (*texture_create)(RendContextHandle handle, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format);
+ void (*texture_destroy)(RendContextHandle handle, RendTexture *tex);
+ void (*texture_copy_buffer)(RendContextHandle handle, RendTexture *texture, RendBuffer *buffer);
+ void (*texture_blit)(RendContextHandle handle, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h);
- bool (*pipeline_create)(RendRenderer, RendPipeline, Rend__PipelineConfig, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3);
+ bool (*pipeline_create)(RendContextHandle, RendPipeline, Rend__PipelineConfig, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3);
void (*pipeline_bind)(RendPipeline);
void (*pipeline_push_constants)(RendPipeline pipeline, void *push_data, size_t size);
@@ -102,10 +99,10 @@ typedef struct {
void (*pipeline_draw_indexed)(RendPipeline pipeline, uint32_t index_count, uint32_t first_index, int32_t vertex_offset, uint32_t instance_count);
void (*pipeline_set_blend)(RendPipeline, bool);
- void (*renderer_render_pass_begin)(RendRenderer renderer, float r, float g, float b, float a);
- void (*renderer_render_pass_begin_texture)(RendRenderer, RendTexture*);
- void (*renderer_render_pass_end)(RendRenderer renderer);
- void (*renderer_render_pass_end_texture)(RendRenderer renderer, RendTexture*);
+ void (*renderer_render_pass_begin)(RendContextHandle handle, float r, float g, float b, float a);
+ void (*renderer_render_pass_begin_texture)(RendContextHandle, RendTexture*);
+ void (*renderer_render_pass_end)(RendContextHandle handle);
+ void (*renderer_render_pass_end_texture)(RendContextHandle handle, RendTexture*);
} RendVTable;
diff --git a/Rend/rend_vk.c b/Rend/rend_vk.c
index 8fac97b..cfce9d4 100644
--- a/Rend/rend_vk.c
+++ b/Rend/rend_vk.c
@@ -1,53 +1,46 @@
-#pragma once
-#include "rend.h"
-#include "rend_internal.h"
+/*
+ * Vulkan 1.4 backend. Per-renderer context is RendVk14Context.
+ * Instance, allocator, and device are process-global (see rend_vk_internal.c).
+ *
+ * * 1.0.3 - @vasco - backend functions take RendContextHandle
+ */
+
#include <stdint.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
-#include "rend_vk_internal.h"
-#include "rend_vk_allocator.c"
-#include "rend_vk_device.c"
-#include "rend_vk_arena.c"
-#include "rend_vk_image.c"
+#include "rend.h"
+#include "rend_internal.h"
+#include "rend_vk_internal.c"
-#define REND_MIN_FRAMES_IN_FLIGHT 2 // double buffering!
-#define REND_MAX_FRAMES_IN_FLIGHT 4 // quadruple buffering!
+#define REND_MIN_FRAMES_IN_FLIGHT 2 /* double buffering! */
+#define REND_MAX_FRAMES_IN_FLIGHT 4 /* quadruple buffering! */
#define REND_VK_MAX_PIPELINES 100
typedef struct {
- VkSwapchainKHR handle;
- VkSurfaceFormatKHR format;
- VkExtent2D extent;
+ VkSwapchainKHR handle;
+ VkSurfaceFormatKHR format;
+ VkExtent2D extent;
- uint32_t image_count;
- VkImage *images;
- VkImageView *views;
+ uint32_t image_count;
+ VkImage *images;
+ VkImageView *views;
- RendVkImage depth_attachment;
+ RendVkImage depth_attachment;
} RendVkSwapchain;
typedef struct {
- VkCommandPool command_pool;
- VkCommandBuffer command_buffer;
- VkSemaphore image_acquired_semaphore;
+ VkCommandPool command_pool;
+ VkCommandBuffer command_buffer;
+ VkSemaphore image_acquired_semaphore;
} RendVkFrameResources;
-typedef struct {
- uint8_t push_data[128];
- uint32_t size;
-} RendVkResourceSet;
-
typedef struct RendVkPipeline {
- void *ctx;
- VkPipeline handle;
- VkPipelineLayout layout;
- uint32_t vertex_count;
- uint32_t vertex_stride;
- uint32_t push_constants_range;
-
- bool blend_enable;
+ VkPipeline handle;
+ VkPipelineLayout layout;
+ uint32_t push_constants_range;
+ bool blend_enable;
} RendVkPipeline;
@@ -56,1851 +49,1627 @@ typedef struct RendVkPipeline {
* such as the instance, the allocator, the devices etc...
*/
typedef struct RendVk14Context {
+ PeakWindow *window;
+ VkSurfaceKHR surface;
+ RendVkPipeline pipelines[REND_VK_MAX_PIPELINES];
+ RendVkFrameResources frame_resources[REND_MAX_FRAMES_IN_FLIGHT];
+ RendVkSwapchain swapchain;
+ VkSemaphore timeline_semaphore;
+ VkSemaphore render_complete_semaphores[REND_MAX_FRAMES_IN_FLIGHT];
- RendVkDevice device; // SPEC: All objects created or allocated from a VkDevice are private to that device, and must not be used on other devices.
-
- PeakWindow *window;
- VkSurfaceKHR surface;
- RendVkPipeline pipelines[REND_VK_MAX_PIPELINES];
- RendVkFrameResources frame_resources[REND_MAX_FRAMES_IN_FLIGHT];
- RendVkSwapchain swapchain;
- VkSemaphore timeline_semaphore;
- VkSemaphore render_complete_semaphores[REND_MAX_FRAMES_IN_FLIGHT];
-
- VkCommandPool upload_command_pool;
- VkCommandPool graphics_command_pool;
+ VkCommandPool upload_command_pool;
+ VkCommandPool graphics_command_pool;
- RendVkArenaAllocator arena_persistent; // magical arena allocator for every type of memory
- RendVkArenaAllocator arena_frame;
+ RendVkArenaAllocator arena_persistent; /* magical arena allocator for every type of memory */
+ RendVkArenaAllocator arena_frame;
- uint64_t frame;
- uint64_t frame_index;
- uint64_t signal_value;
- uint64_t next_signal_value;
- uint64_t max_frames_in_flight;
- uint32_t pipeline_count;
- uint32_t image_index;
+ uint64_t frame;
+ uint64_t frame_index;
+ uint64_t signal_value;
+ uint64_t next_signal_value;
+ uint64_t max_frames_in_flight;
+ uint32_t pipeline_count;
+ uint32_t image_index;
- bool require_swapchain_recreation;
+ bool require_swapchain_recreation;
- bool vsync;
- bool in_frame;
+ bool vsync;
+ bool in_frame;
- VkDescriptorPool descriptor_pool;
- VkDescriptorSet desc_set;
- VkDescriptorSetLayout desc_layout;
+ VkDescriptorPool descriptor_pool;
+ VkDescriptorSet desc_set;
+ VkDescriptorSetLayout desc_layout;
} RendVk14Context;
-/* function declarations */
-extern bool rend_vk_init();
-extern void rend_vk_quit();
-
-extern RendContextHandle rend_vk_renderer_create(PeakWindow *window, RendBindingInfo *bind_info);
-extern void rend_vk_renderer_destroy(RendContextHandle handle);
-extern bool rend_vk_renderer_frame_begin(RendContextHandle handle);
-extern void rend_vk_renderer_frame_end(RendContextHandle handle, float *delta);
-
-static inline void rend_vk__renderer_render_pass_begin_internal(RendRenderer renderer, float r, float g, float b, float a, uint64_t view_handle, uint64_t depth_attachment_view_handle, uint32_t offset_x, uint32_t offset_y, uint32_t width, uint32_t height);
-
-extern void rend_vk_renderer_render_pass_begin(RendRenderer renderer, float r, float g, float b, float a);
-extern void rend_vk_renderer_render_pass_begin_texture(RendRenderer renderer, RendTexture *texture);
-extern void rend_vk_renderer_render_pass_end(RendRenderer renderer);
-extern void rend_vk_renderer_render_pass_end_texture(RendRenderer renderer, RendTexture *texture);
-
-extern void rend_vk_descriptor_write_buffer(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo);
-extern void rend_vk_descriptor_write_texture(void *ctx, RendTexture *texture, uint32_t binding, uint32_t slot);
-
-extern RendBuffer rend_vk_buffer_create_lifetime(RendRenderer renderer, size_t size, RendBufferType type, bool gpu, int lifetime);
-extern void rend_vk_buffer_destroy(RendBuffer *buffer);
-extern void rend_vk_buffer_copy(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes);
-
-extern RendTexture rend_vk_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format);
-extern void rend_vk_texture_destroy(RendRenderer renderer, RendTexture *tex);
-extern void rend_vk_texture_transition_layout(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout);
-extern void rend_vk_texture_transfer_ownership_release(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout);
-extern void rend_vk_texture_transfer_ownership_acquire(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout);
-extern void rend_vk_texture_copy_buffer(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer);
-extern void rend_vk_texture_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h);
-
+static void rend_vk_texture_transition_layout(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout);
static VkCommandBuffer rend_vk_cmdbuffer_single_use_begin(VkCommandPool pool);
static void rend_vk_cmdbuffer_single_use_end(VkCommandPool pool, VkCommandBuffer cmd, VkQueue q);
-
-extern bool rend_vk_pipeline_create(RendRenderer renderer, RendPipeline pipeline, Rend__PipelineConfig config, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3);
-extern void rend_vk_pipeline_bind(RendPipeline);
-extern void rend_vk_pipeline_push_constants(RendPipeline pipeline, void *push_data, size_t size);
-
-extern void rend_vk_pipeline_bind_vertex_buffer(RendPipeline pipeline, uint32_t binding, RendBuffer buffer, size_t offset);
-extern void rend_vk_pipeline_bind_index_buffer(RendPipeline pipeline, RendBuffer buffer, size_t offset, RendIndexType index_type);
-
-extern void rend_vk_pipeline_dispatch(RendPipeline pipeline, uint32_t x, uint32_t y, uint32_t z);
-extern void rend_vk_pipeline_draw(RendPipeline, size_t count, uint32_t instance_count);
-extern void rend_vk_pipeline_draw_indexed(RendPipeline pipeline, uint32_t index_count, uint32_t first_index, int32_t vertex_offset, uint32_t instance_count);
-extern void rend_vk_pipeline_set_blend(RendPipeline, bool);
-
-VKAPI_ATTR VkBool32 VKAPI_CALL rend_vk_debug_func( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data);
static void rend_vk_pipeline_destroy(RendVkPipeline *pipeline);
static void rend_vk_swapchain_create(RendVk14Context *ctx, RendVkSwapchain *swapchain);
static void rend_vk_swapchain_destroy(RendVk14Context *ctx, RendVkSwapchain *swapchain);
-
static VkShaderModule rend_vk_shader_module_create(const void *data, size_t size);
static uint32_t rend_vk_get_heap_index(uint32_t memory_type_bits, uint32_t preferred_index);
+VKAPI_ATTR VkBool32 VKAPI_CALL rend_vk_debug_func(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data);
-extern bool
-rend_vk_init()
+bool
+rend_vk_init(void)
{
- RASSERT(sizeof(void*) == 8 && sizeof(int64_t) == 8 && sizeof(double) == 8, "SPEC: Host device 64-bit integer and floating-point types.");
+ RASSERT(sizeof(void*) == 8 && sizeof(int64_t) == 8 && sizeof(double) == 8, "SPEC: Host device 64-bit integer and floating-point types.");
- /* trying to init another renderer with the same backend */
- if (vk_instance) {
- return true;
- }
+ /* trying to init another renderer with the same backend */
+ if (vk_instance) {
+ return true;
+ }
- /* create instance if does not exist */
- VkApplicationInfo vk_app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
- vk_app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- vk_app_info.pApplicationName = "REND";
- vk_app_info.applicationVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
- vk_app_info.apiVersion = VK_API_VERSION_1_4;
- vk_app_info.pEngineName = "REND Renderer";
- vk_app_info.engineVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
+ /* create instance if does not exist */
+ VkApplicationInfo vk_app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
+ vk_app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ vk_app_info.pApplicationName = "REND";
+ vk_app_info.applicationVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
+ vk_app_info.apiVersion = VK_API_VERSION_1_4;
+ vk_app_info.pEngineName = "REND Renderer";
+ vk_app_info.engineVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
- uint32_t peak_ext_count = 0;
- const char **peak_exts = peak_vulkan_get_extensions(&peak_ext_count);
- const char *extensions[8];
- uint32_t ext_count = 0;
- uint32_t ei;
- for (ei = 0; ei < peak_ext_count && ext_count < 8; ei++)
- extensions[ext_count++] = peak_exts[ei];
+ uint32_t peak_ext_count = 0;
+ const char **peak_exts = peak_vulkan_get_extensions(&peak_ext_count);
+ const char *extensions[8];
+ uint32_t ext_count = 0;
+ uint32_t ei;
+ for (ei = 0; ei < peak_ext_count && ext_count < 8; ei++)
+ extensions[ext_count++] = peak_exts[ei];
#ifdef REND_DEBUG
- if (ext_count < 8)
- extensions[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
- PDEBUG("Vulkan Extensions: ");
- for (ei = 0; ei < ext_count; ei++)
- PDEBUG("%s", extensions[ei]);
+ if (ext_count < 8)
+ extensions[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
+ PDEBUG("Vulkan Extensions: ");
+ for (ei = 0; ei < ext_count; ei++)
+ PDEBUG("%s", extensions[ei]);
#endif
#ifdef REND_DEBUG
- const char *required_validation_layers[] = { "VK_LAYER_KHRONOS_validation" };
- uint32_t layer_count = 1;
-
- PDEBUG("Required Validation Layers: ");
- for (ei = 0; ei < layer_count; ei++) {
- PDEBUG(" - %s", required_validation_layers[ei]);
- }
+ const char *required_validation_layers[] = { "VK_LAYER_KHRONOS_validation" };
+ uint32_t layer_count = 1;
- VkValidationFeatureEnableEXT enabled_validation_features[] = {
- // VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
- // VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
- };
+ PDEBUG("Required Validation Layers: ");
+ for (ei = 0; ei < layer_count; ei++) {
+ PDEBUG(" - %s", required_validation_layers[ei]);
+ }
- VkValidationFeaturesEXT validation_features = {
- .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
- .pNext = NULL,
- // .enabledValidationFeatureCount = sizeof(enabled_validation_features) / sizeof(enabled_validation_features[0]),
- // .pEnabledValidationFeatures = enabled_validation_features,
- };
+ VkValidationFeaturesEXT validation_features = {
+ .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
+ .pNext = NULL,
+ /* GPU-assisted validation: VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT */
+ };
#endif
- VkInstanceCreateInfo vk_create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
- vk_create_info.pApplicationInfo = &vk_app_info;
- vk_create_info.ppEnabledExtensionNames = extensions;
- vk_create_info.enabledExtensionCount = ext_count;
- vk_create_info.pApplicationInfo = &vk_app_info;
+ VkInstanceCreateInfo vk_create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
+ vk_create_info.pApplicationInfo = &vk_app_info;
+ vk_create_info.ppEnabledExtensionNames = extensions;
+ vk_create_info.enabledExtensionCount = ext_count;
+ vk_create_info.pApplicationInfo = &vk_app_info;
#ifdef REND_DEBUG
- vk_create_info.enabledLayerCount = layer_count;
- vk_create_info.ppEnabledLayerNames = required_validation_layers;
- vk_create_info.pNext = &validation_features;
+ vk_create_info.enabledLayerCount = layer_count;
+ vk_create_info.ppEnabledLayerNames = required_validation_layers;
+ vk_create_info.pNext = &validation_features;
#else
- vk_create_info.enabledLayerCount = 0;
- vk_create_info.ppEnabledLayerNames = NULL;
+ vk_create_info.enabledLayerCount = 0;
+ vk_create_info.ppEnabledLayerNames = NULL;
#endif
- VkResult res = vkCreateInstance(&vk_create_info, vk_allocator, &vk_instance);
- CHECK_VK_RESULT(res);
+ VkResult res = vkCreateInstance(&vk_create_info, vk_allocator, &vk_instance);
+ CHECK_VK_RESULT(res);
- PDEBUG("Vulkan instance created!");
+ PDEBUG("Vulkan instance created!");
#ifdef REND_DEBUG
- uint32_t log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
- VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
- debug_create_info.messageSeverity = log_severity;
- debug_create_info.messageType =
- VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
- debug_create_info.pfnUserCallback = rend_vk_debug_func;
+ uint32_t log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
+ debug_create_info.messageSeverity = log_severity;
+ debug_create_info.messageType =
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ debug_create_info.pfnUserCallback = rend_vk_debug_func;
- PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( vk_instance, "vkCreateDebugUtilsMessengerEXT");
- if (!func) {
- PDEBUG("Failed to create vulkan debug messenger!");
- return false;
- }
- func(vk_instance, &debug_create_info, vk_allocator, &vk_debug_messenger);
+ PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk_instance, "vkCreateDebugUtilsMessengerEXT");
+ if (!func) {
+ PDEBUG("Failed to create vulkan debug messenger!");
+ return false;
+ }
+ func(vk_instance, &debug_create_info, vk_allocator, &vk_debug_messenger);
#endif
- return true;
+ return true;
}
-extern void
-rend_vk_quit()
+void
+rend_vk_quit(void)
{
- PDEBUG("[REND_VK14] Destroying device.");
+ PDEBUG("[REND_VK14] Destroying device.");
- /* we destroy the device on quit */
- if (vk_device.logical_device != 0) {
- rend_vk_device_destroy(&vk_device);
- }
+ /* we destroy the device on quit */
+ if (vk_device.logical_device != 0) {
+ rend_vk_device_destroy(&vk_device);
+ }
- if (vk_debug_messenger) {
- PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( vk_instance, "vkDestroyDebugUtilsMessengerEXT");
- func(vk_instance, vk_debug_messenger, vk_allocator);
- vk_debug_messenger = 0;
- }
+ if (vk_debug_messenger) {
+ PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk_instance, "vkDestroyDebugUtilsMessengerEXT");
+ func(vk_instance, vk_debug_messenger, vk_allocator);
+ vk_debug_messenger = 0;
+ }
- vkDestroyInstance(vk_instance, vk_allocator);
- vk_instance = 0;
+ vkDestroyInstance(vk_instance, vk_allocator);
+ vk_instance = 0;
}
-extern RendContextHandle
+RendContextHandle
rend_vk_renderer_create(PeakWindow *window, RendBindingInfo *bind_info)
{
- RendVk14Context *ctx = rmalloc(sizeof(*ctx));
- if (!ctx) {
- PERROR("Failed to allocate internal vulkan context.");
- return NULL;
- }
+ uint32_t u;
+ uint32_t i;
+ RendVk14Context *ctx = rmalloc(sizeof(*ctx));
+ if (!ctx) {
+ PERROR("Failed to allocate internal vulkan context.");
+ return NULL;
+ }
- memset(ctx, 0, sizeof *ctx);
- ctx->window = window;
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->window = window;
- /* get surface from window */
- if (!peak_vulkan_create_surface(window, vk_instance, vk_allocator, &ctx->surface)) {
- PERROR("Failed to create vulkan surface!");
- rfree(ctx);
- return NULL;
- }
+ /* get surface from window */
+ if (!peak_vulkan_create_surface(window, vk_instance, vk_allocator, &ctx->surface)) {
+ PERROR("Failed to create vulkan surface!");
+ rfree(ctx);
+ return NULL;
+ }
- RendSpecs specs = {
- .sampler_anisotropy = true,
- .graphics = true,
- .transfer = true,
- .discrete_gpu = false, // even though its not a requirement, I expect discrete gpu to be picked
- };
+ RendSpecs specs = {
+ .sampler_anisotropy = true,
+ .graphics = true,
+ .transfer = true,
+ .discrete_gpu = false, /* even though its not a requirement, I expect discrete gpu to be picked */
+ };
- /* we lazily create the logical device only after creating the first renderer
- * because we need the surface first */
- if (vk_device.logical_device == 0) {
- rend_vk_device_create(ctx->surface, specs, &vk_device, rend_vk_device_score_default);
- }
+ /* we lazily create the logical device only after creating the first renderer
+ * because we need the surface first */
+ if (vk_device.logical_device == 0) {
+ rend_vk_device_create(ctx->surface, specs, &vk_device);
+ }
- /* we must create arena before swapchain */
- ctx->arena_persistent = rend_vk_arena_create(
- vk_device.logical_device,
- vk_device.physical_device,
- vk_device.properties.limits,
- vk_allocator);
+ /* we must create arena before swapchain */
+ ctx->arena_persistent = rend_vk_arena_create(
+ vk_device.logical_device,
+ vk_device.physical_device,
+ vk_device.properties.limits,
+ vk_allocator);
- ctx->arena_frame = rend_vk_arena_create(
- vk_device.logical_device,
- vk_device.physical_device,
- vk_device.properties.limits,
- vk_allocator);
+ ctx->arena_frame = rend_vk_arena_create(
+ vk_device.logical_device,
+ vk_device.physical_device,
+ vk_device.properties.limits,
+ vk_allocator);
- /* create swapchain */
- rend_vk_swapchain_create(ctx, &ctx->swapchain);
+ /* create swapchain */
+ rend_vk_swapchain_create(ctx, &ctx->swapchain);
- /* timeline semaphore */
- VkSemaphoreTypeCreateInfo timeline_type_info = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO};
- timeline_type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
- timeline_type_info.initialValue = ctx->max_frames_in_flight;
+ /* timeline semaphore */
+ VkSemaphoreTypeCreateInfo timeline_type_info = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO};
+ timeline_type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
+ timeline_type_info.initialValue = ctx->max_frames_in_flight;
- VkSemaphoreCreateInfo timeline_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
- timeline_semaphore_info.pNext = &timeline_type_info;
+ VkSemaphoreCreateInfo timeline_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
+ timeline_semaphore_info.pNext = &timeline_type_info;
- if (vkCreateSemaphore(vk_device.logical_device, &timeline_semaphore_info, vk_allocator, &ctx->timeline_semaphore) != VK_SUCCESS) {
- PERROR("Unable to create the timeline semaphore for the renderer!");
- rfree(ctx);
- return NULL;
- }
+ if (vkCreateSemaphore(vk_device.logical_device, &timeline_semaphore_info, vk_allocator, &ctx->timeline_semaphore) != VK_SUCCESS) {
+ PERROR("Unable to create the timeline semaphore for the renderer!");
+ rfree(ctx);
+ return NULL;
+ }
- /* create per frame semaphores */
- VkSemaphoreCreateInfo frame_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
- for (uint32_t u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
- if (vkCreateSemaphore(
- vk_device.logical_device,
- &frame_semaphore_info,
- vk_allocator,
- &ctx->frame_resources[u].image_acquired_semaphore) != VK_SUCCESS) {
- PERROR("Unable to create semaphore for frame #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ /* create per frame semaphores */
+ VkSemaphoreCreateInfo frame_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
+ for (u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
+ if (vkCreateSemaphore(
+ vk_device.logical_device,
+ &frame_semaphore_info,
+ vk_allocator,
+ &ctx->frame_resources[u].image_acquired_semaphore) != VK_SUCCESS) {
+ PERROR("Unable to create semaphore for frame #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- if (vkCreateSemaphore(
- vk_device.logical_device,
- &frame_semaphore_info,
- vk_allocator,
- &ctx->render_complete_semaphores[u]) != VK_SUCCESS) {
- PERROR("Unable to create render complete semaphore #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ if (vkCreateSemaphore(
+ vk_device.logical_device,
+ &frame_semaphore_info,
+ vk_allocator,
+ &ctx->render_complete_semaphores[u]) != VK_SUCCESS) {
+ PERROR("Unable to create render complete semaphore #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
- pool_info.queueFamilyIndex = vk_device.graphics_family_index;
- if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->frame_resources[u].command_pool) != VK_SUCCESS) {
- PERROR("Unable to create command pool for frame #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
+ pool_info.queueFamilyIndex = vk_device.graphics_family_index;
+ if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->frame_resources[u].command_pool) != VK_SUCCESS) {
+ PERROR("Unable to create command pool for frame #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- VkCommandBufferAllocateInfo cmdbuf_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
- cmdbuf_info.commandPool = ctx->frame_resources[u].command_pool;
- cmdbuf_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- cmdbuf_info.commandBufferCount = 1;
- if (vkAllocateCommandBuffers(vk_device.logical_device, &cmdbuf_info, &ctx->frame_resources[u].command_buffer) != VK_SUCCESS) {
- PERROR("Unable to create command buffer for frame #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ VkCommandBufferAllocateInfo cmdbuf_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
+ cmdbuf_info.commandPool = ctx->frame_resources[u].command_pool;
+ cmdbuf_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ cmdbuf_info.commandBufferCount = 1;
+ if (vkAllocateCommandBuffers(vk_device.logical_device, &cmdbuf_info, &ctx->frame_resources[u].command_buffer) != VK_SUCCESS) {
+ PERROR("Unable to create command buffer for frame #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- }
+ }
- VkCommandPoolCreateInfo pool_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
- .queueFamilyIndex = vk_device.transfer_family_index,
- .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
- };
+ VkCommandPoolCreateInfo pool_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .queueFamilyIndex = vk_device.transfer_family_index,
+ .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
+ };
- if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->upload_command_pool) != VK_SUCCESS) {
- PERROR("Unable to create upload command pool!");
- rfree(ctx);
- return NULL;
- }
+ if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->upload_command_pool) != VK_SUCCESS) {
+ PERROR("Unable to create upload command pool!");
+ rfree(ctx);
+ return NULL;
+ }
- pool_info.queueFamilyIndex = vk_device.graphics_family_index;
- if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->graphics_command_pool) != VK_SUCCESS) {
- PERROR("Unable to create graphics command pool!");
- rfree(ctx);
- return NULL;
- }
+ pool_info.queueFamilyIndex = vk_device.graphics_family_index;
+ if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->graphics_command_pool) != VK_SUCCESS) {
+ PERROR("Unable to create graphics command pool!");
+ rfree(ctx);
+ return NULL;
+ }
- ctx->frame = 0;
- ctx->frame_index = 0;
- ctx->next_signal_value = ctx->max_frames_in_flight + 1; /* start at frame zero */
+ ctx->frame = 0;
+ ctx->frame_index = 0;
+ ctx->next_signal_value = ctx->max_frames_in_flight + 1; /* start at frame zero */
- /*
- * Descriptor Pool
- */
- {
- RendBindingInfo bind_info_local = {0};
- if (bind_info) bind_info_local = *bind_info;
- RendBindingInfo bind_info = bind_info_local;
+ /*
+ * Descriptor Pool
+ */
+ {
+ RendBindingInfo bind_info_local = {0};
+ if (bind_info) bind_info_local = *bind_info;
+ RendBindingInfo bind_info = bind_info_local;
- uint32_t total_ubos = 0;
- for (uint32_t i = 0; i < bind_info.ubo_binding_count; ++i) {
- total_ubos += bind_info.ubo_array_sizes[i];
- }
+ uint32_t total_ubos = 0;
+ for (i = 0; i < bind_info.ubo_binding_count; ++i) {
+ total_ubos += bind_info.ubo_array_sizes[i];
+ }
- uint32_t total_ssbos = 0;
- for (uint32_t i = 0; i < bind_info.ssbo_binding_count; ++i) {
- total_ssbos += bind_info.ssbo_array_sizes[i];
- }
+ uint32_t total_ssbos = 0;
+ for (i = 0; i < bind_info.ssbo_binding_count; ++i) {
+ total_ssbos += bind_info.ssbo_array_sizes[i];
+ }
- uint32_t total_textures = 0;
- for (uint32_t i = 0; i < bind_info.texture_binding_count; ++i) {
- total_textures += bind_info.texture_array_sizes[i];
- }
+ uint32_t total_textures = 0;
+ for (i = 0; i < bind_info.texture_binding_count; ++i) {
+ total_textures += bind_info.texture_array_sizes[i];
+ }
- const uint32_t pool_count = 3;
- VkDescriptorPoolSize pool_sizes[3] = {
- { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = (total_ubos > 0) ? total_ubos : 1 },
- { .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = (total_ssbos > 0) ? total_ssbos : 1 },
- { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = (total_textures > 0) ? total_textures : 1 }
- };
+ const uint32_t pool_count = 3;
+ VkDescriptorPoolSize pool_sizes[3] = {
+ { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = (total_ubos > 0) ? total_ubos : 1 },
+ { .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = (total_ssbos > 0) ? total_ssbos : 1 },
+ { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = (total_textures > 0) ? total_textures : 1 }
+ };
- VkDescriptorPoolCreateInfo pool_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
- .flags = 0,
- .maxSets = 1,
- .poolSizeCount = pool_count,
- .pPoolSizes = pool_sizes,
- .pNext = NULL,
- };
+ VkDescriptorPoolCreateInfo pool_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ .flags = 0,
+ .maxSets = 1,
+ .poolSizeCount = pool_count,
+ .pPoolSizes = pool_sizes,
+ .pNext = NULL,
+ };
- VkResult result = vkCreateDescriptorPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->descriptor_pool);
- if (result != VK_SUCCESS) {
- rfree(ctx);
- return NULL;
- }
+ VkResult result = vkCreateDescriptorPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->descriptor_pool);
+ if (result != VK_SUCCESS) {
+ rfree(ctx);
+ return NULL;
+ }
- /*
- * Descriptor Sets!!!!!!
- */
+ /*
+ * Descriptor Sets!!!!!!
+ */
- const uint32_t binding_count = bind_info.ubo_binding_count + bind_info.ssbo_binding_count + bind_info.texture_binding_count;
- VkDescriptorSetLayoutBinding binding_array[binding_count];
+ const uint32_t binding_count = bind_info.ubo_binding_count + bind_info.ssbo_binding_count + bind_info.texture_binding_count;
+ VkDescriptorSetLayoutBinding binding_array[binding_count];
- for (uint32_t i = 0; i < bind_info.ubo_binding_count; ++i) {
- binding_array[i] = (VkDescriptorSetLayoutBinding) {
- .binding = bind_info.ubo_bindings[i],
- .descriptorCount = bind_info.ubo_array_sizes[i],
- .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- .stageFlags = VK_SHADER_STAGE_ALL,
- .pImmutableSamplers = 0,
- };
- };
+ for (i = 0; i < bind_info.ubo_binding_count; ++i) {
+ binding_array[i] = (VkDescriptorSetLayoutBinding) {
+ .binding = bind_info.ubo_bindings[i],
+ .descriptorCount = bind_info.ubo_array_sizes[i],
+ .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ .pImmutableSamplers = 0,
+ };
+ };
- uint32_t offset = bind_info.ubo_binding_count;
- for (uint32_t i = 0; i < bind_info.ssbo_binding_count; ++i) {
- binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
- .binding = bind_info.ssbo_bindings[i],
- .descriptorCount = bind_info.ssbo_array_sizes[i],
- .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
- .stageFlags = VK_SHADER_STAGE_ALL,
- .pImmutableSamplers = 0,
- };
- };
+ uint32_t offset = bind_info.ubo_binding_count;
+ for (i = 0; i < bind_info.ssbo_binding_count; ++i) {
+ binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
+ .binding = bind_info.ssbo_bindings[i],
+ .descriptorCount = bind_info.ssbo_array_sizes[i],
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ .pImmutableSamplers = 0,
+ };
+ };
- offset += bind_info.ssbo_binding_count;
- for (uint32_t i = 0; i < bind_info.texture_binding_count; ++i) {
- binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
- .binding = bind_info.texture_bindings[i],
- .descriptorCount = bind_info.texture_array_sizes[i],
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .stageFlags = VK_SHADER_STAGE_ALL,
- .pImmutableSamplers = 0,
- };
- };
+ offset += bind_info.ssbo_binding_count;
+ for (i = 0; i < bind_info.texture_binding_count; ++i) {
+ binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
+ .binding = bind_info.texture_bindings[i],
+ .descriptorCount = bind_info.texture_array_sizes[i],
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ .pImmutableSamplers = 0,
+ };
+ };
- VkDescriptorBindingFlags binding_flags[binding_count];
- for (uint32_t u = 0; u < binding_count; ++u) {
- binding_flags[u] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
- }
+ VkDescriptorBindingFlags binding_flags[binding_count];
+ for (u = 0; u < binding_count; ++u) {
+ binding_flags[u] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
+ }
- VkDescriptorSetLayoutBindingFlagsCreateInfo desc_flags_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
- .bindingCount = binding_count,
- .pBindingFlags = binding_flags
- };
+ VkDescriptorSetLayoutBindingFlagsCreateInfo desc_flags_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
+ .bindingCount = binding_count,
+ .pBindingFlags = binding_flags
+ };
- VkDescriptorSetLayoutCreateInfo desc_layout_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .flags = 0,
- .bindingCount = binding_count,
- .pBindings = binding_array,
- .pNext = &desc_flags_info,
- };
+ VkDescriptorSetLayoutCreateInfo desc_layout_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .flags = 0,
+ .bindingCount = binding_count,
+ .pBindings = binding_array,
+ .pNext = &desc_flags_info,
+ };
- result = vkCreateDescriptorSetLayout(vk_device.logical_device, &desc_layout_info, vk_allocator, &ctx->desc_layout);
- if (result != VK_SUCCESS) {
- PERROR("Failed to create descriptor set layout!");
- rfree(ctx);
- return NULL;
- }
+ result = vkCreateDescriptorSetLayout(vk_device.logical_device, &desc_layout_info, vk_allocator, &ctx->desc_layout);
+ if (result != VK_SUCCESS) {
+ PERROR("Failed to create descriptor set layout!");
+ rfree(ctx);
+ return NULL;
+ }
- VkDescriptorSetAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
- .descriptorPool = ctx->descriptor_pool,
- .descriptorSetCount = 1, // ONLY ONE DESCRIPTOR SET
- .pSetLayouts = &ctx->desc_layout,
- .pNext = NULL,
- };
+ VkDescriptorSetAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ .descriptorPool = ctx->descriptor_pool,
+ .descriptorSetCount = 1, /* ONLY ONE DESCRIPTOR SET */
+ .pSetLayouts = &ctx->desc_layout,
+ .pNext = NULL,
+ };
- result = vkAllocateDescriptorSets(vk_device.logical_device, &alloc_info, &ctx->desc_set);
- if (result != VK_SUCCESS) {
- PERROR("Failed to allocate descriptors!!!");
- rfree(ctx);
- return NULL;
- }
- }
+ result = vkAllocateDescriptorSets(vk_device.logical_device, &alloc_info, &ctx->desc_set);
+ if (result != VK_SUCCESS) {
+ PERROR("Failed to allocate descriptors!!!");
+ rfree(ctx);
+ return NULL;
+ }
+ }
- return ctx;
+ return ctx;
}
-extern void
+void
rend_vk_renderer_destroy(RendContextHandle handle)
{
- RASSERT(handle, "Invalid context handle.");
+ uint32_t u;
+ RASSERT(handle, "Invalid context handle.");
- RendVk14Context *ctx = (RendVk14Context *)handle;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- VkDevice dev = vk_device.logical_device;
+ VkDevice dev = vk_device.logical_device;
- PDEBUG("[REND] Waiting for device...");
- vkDeviceWaitIdle(dev);
+ PDEBUG("[REND] Waiting for device...");
+ vkDeviceWaitIdle(dev);
- PDEBUG("[REND] Destroying renderer...");
- vkDestroySemaphore(dev, ctx->timeline_semaphore, vk_allocator);
+ PDEBUG("[REND] Destroying renderer...");
+ vkDestroySemaphore(dev, ctx->timeline_semaphore, vk_allocator);
- /* destroy per frame semaphores */
- for (uint32_t u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
- vkDestroySemaphore(dev, ctx->frame_resources[u].image_acquired_semaphore, vk_allocator);
- vkDestroySemaphore(dev, ctx->render_complete_semaphores[u], vk_allocator);
- vkDestroyCommandPool(dev, ctx->frame_resources[u].command_pool, vk_allocator);
- ctx->frame_resources[u].image_acquired_semaphore = 0;
- ctx->frame_resources[u].command_pool = 0;
- ctx->frame_resources[u].command_buffer = 0;
- }
+ /* destroy per frame semaphores */
+ for (u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
+ vkDestroySemaphore(dev, ctx->frame_resources[u].image_acquired_semaphore, vk_allocator);
+ vkDestroySemaphore(dev, ctx->render_complete_semaphores[u], vk_allocator);
+ vkDestroyCommandPool(dev, ctx->frame_resources[u].command_pool, vk_allocator);
+ ctx->frame_resources[u].image_acquired_semaphore = 0;
+ ctx->frame_resources[u].command_pool = 0;
+ ctx->frame_resources[u].command_buffer = 0;
+ }
- vkDestroyCommandPool(vk_device.logical_device, ctx->upload_command_pool, vk_allocator);
- vkDestroyCommandPool(vk_device.logical_device, ctx->graphics_command_pool, vk_allocator);
+ vkDestroyCommandPool(vk_device.logical_device, ctx->upload_command_pool, vk_allocator);
+ vkDestroyCommandPool(vk_device.logical_device, ctx->graphics_command_pool, vk_allocator);
- rend_vk_arena_destroy(&ctx->arena_persistent);
- rend_vk_arena_destroy(&ctx->arena_frame);
+ rend_vk_arena_destroy(&ctx->arena_persistent);
+ rend_vk_arena_destroy(&ctx->arena_frame);
- vkDestroyDescriptorSetLayout(dev, ctx->desc_layout, vk_allocator);
- vkDestroyDescriptorPool(dev, ctx->descriptor_pool, vk_allocator);
+ vkDestroyDescriptorSetLayout(dev, ctx->desc_layout, vk_allocator);
+ vkDestroyDescriptorPool(dev, ctx->descriptor_pool, vk_allocator);
- PDEBUG("[REND] Destroying pipelines...");
- for (uint32_t u = 0; u < ctx->pipeline_count; ++u) {
- rend_vk_pipeline_destroy(&ctx->pipelines[u]);
- }
+ PDEBUG("[REND] Destroying pipelines...");
+ for (u = 0; u < ctx->pipeline_count; ++u) {
+ rend_vk_pipeline_destroy(&ctx->pipelines[u]);
+ }
- PDEBUG("[REND] Destroying swapchain...");
- rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
- ctx->swapchain.handle = 0;
+ PDEBUG("[REND] Destroying swapchain...");
+ rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
+ ctx->swapchain.handle = 0;
- PDEBUG("[REND] Destroying surface...");
- RASSERT(vk_instance);
- vkDestroySurfaceKHR(vk_instance, ctx->surface, vk_allocator);
- ctx->surface = 0;
+ PDEBUG("[REND] Destroying surface...");
+ RASSERT(vk_instance);
+ vkDestroySurfaceKHR(vk_instance, ctx->surface, vk_allocator);
+ ctx->surface = 0;
- /* handle is guarranteed to be allocated */
- rfree(handle);
+ /* handle is guarranteed to be allocated */
+ rfree(handle);
}
-extern bool
+bool
rend_vk_renderer_frame_begin(RendContextHandle handle)
{
- RendVk14Context *ctx;
- VkDevice dev;
- uint32_t retries;
+ RendVk14Context *ctx;
+ VkDevice dev;
+ uint32_t retries;
- RASSERT(handle, "Invalid handle.");
+ RASSERT(handle, "Invalid handle.");
- ctx = (RendVk14Context *) handle;
- dev = vk_device.logical_device;
+ ctx = (RendVk14Context *)handle;
+ dev = vk_device.logical_device;
- for (retries = 0; retries < 4; retries++) {
- uint64_t frame_res_index;
- uint64_t wait_value;
- VkResult acquire_image;
- RendVkFrameResources frame_resource;
- VkSemaphoreWaitInfo timeline_wait_info;
+ for (retries = 0; retries < 4; retries++) {
+ uint64_t frame_res_index;
+ uint64_t wait_value;
+ VkResult acquire_image;
+ RendVkFrameResources frame_resource;
+ VkSemaphoreWaitInfo timeline_wait_info;
- if (ctx->require_swapchain_recreation) {
- if (ctx->window && (ctx->window->width == 0 || ctx->window->height == 0))
- return false;
- PDEBUG("[REND] Awaiting device...");
- vkDeviceWaitIdle(vk_device.logical_device);
- PDEBUG("[REND] Recreating swapchain...");
- rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
- rend_vk_swapchain_create(ctx, &ctx->swapchain);
- ctx->require_swapchain_recreation = false;
- }
+ if (ctx->require_swapchain_recreation) {
+ if (ctx->window && (ctx->window->width == 0 || ctx->window->height == 0))
+ return false;
+ PDEBUG("[REND] Awaiting device...");
+ vkDeviceWaitIdle(vk_device.logical_device);
+ PDEBUG("[REND] Recreating swapchain...");
+ rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
+ rend_vk_swapchain_create(ctx, &ctx->swapchain);
+ ctx->require_swapchain_recreation = false;
+ }
- if (ctx->max_frames_in_flight == 0)
- return false;
+ if (ctx->max_frames_in_flight == 0)
+ return false;
- /* wait on timeline semaphore */
- frame_res_index = ctx->frame % ctx->max_frames_in_flight;
- ctx->frame_index = frame_res_index;
+ /* wait on timeline semaphore */
+ frame_res_index = ctx->frame % ctx->max_frames_in_flight;
+ ctx->frame_index = frame_res_index;
- wait_value = ctx->next_signal_value - ctx->max_frames_in_flight;
+ wait_value = ctx->next_signal_value - ctx->max_frames_in_flight;
- timeline_wait_info = (VkSemaphoreWaitInfo) {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
- .semaphoreCount = 1,
- .pSemaphores = &ctx->timeline_semaphore,
- .pValues = &wait_value
- };
+ timeline_wait_info = (VkSemaphoreWaitInfo) {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+ .semaphoreCount = 1,
+ .pSemaphores = &ctx->timeline_semaphore,
+ .pValues = &wait_value
+ };
- vkWaitSemaphores(vk_device.logical_device, &timeline_wait_info, UINT64_MAX);
+ vkWaitSemaphores(vk_device.logical_device, &timeline_wait_info, UINT64_MAX);
- frame_resource = ctx->frame_resources[frame_res_index];
- vkResetCommandPool(dev, frame_resource.command_pool, 0);
+ frame_resource = ctx->frame_resources[frame_res_index];
+ vkResetCommandPool(dev, frame_resource.command_pool, 0);
- /* acquire next image */
- acquire_image = vkAcquireNextImageKHR(
- vk_device.logical_device,
- ctx->swapchain.handle,
- UINT64_MAX,
- frame_resource.image_acquired_semaphore,
- VK_NULL_HANDLE,
- &ctx->image_index);
+ /* acquire next image */
+ acquire_image = vkAcquireNextImageKHR(
+ vk_device.logical_device,
+ ctx->swapchain.handle,
+ UINT64_MAX,
+ frame_resource.image_acquired_semaphore,
+ VK_NULL_HANDLE,
+ &ctx->image_index);
- if (acquire_image == VK_ERROR_OUT_OF_DATE_KHR) {
- ctx->require_swapchain_recreation = true;
- continue;
- }
- if (acquire_image == VK_SUBOPTIMAL_KHR) {
- ctx->require_swapchain_recreation = true;
- } else if (acquire_image != VK_SUCCESS) {
- return false;
- }
+ if (acquire_image == VK_ERROR_OUT_OF_DATE_KHR) {
+ ctx->require_swapchain_recreation = true;
+ continue;
+ }
+ if (acquire_image == VK_SUBOPTIMAL_KHR) {
+ ctx->require_swapchain_recreation = true;
+ } else if (acquire_image != VK_SUCCESS) {
+ return false;
+ }
- ctx->signal_value = ctx->next_signal_value++;
+ ctx->signal_value = ctx->next_signal_value++;
- {
- VkCommandBufferBeginInfo cmd_begin_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
- };
+ {
+ VkCommandBufferBeginInfo cmd_begin_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
+ };
- vkBeginCommandBuffer(frame_resource.command_buffer, &cmd_begin_info);
+ vkBeginCommandBuffer(frame_resource.command_buffer, &cmd_begin_info);
- static const size_t NUM_LAYOUT_BARRIERS = 2;
- VkImageMemoryBarrier2 layout_barriers[NUM_LAYOUT_BARRIERS];
- layout_barriers[0] = (VkImageMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ static const size_t NUM_LAYOUT_BARRIERS = 2;
+ VkImageMemoryBarrier2 layout_barriers[NUM_LAYOUT_BARRIERS];
+ layout_barriers[0] = (VkImageMemoryBarrier2) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
- .srcAccessMask = 0,
+ .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .srcAccessMask = 0,
- .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
- .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR,
+ .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR,
- .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .image = ctx->swapchain.images[ctx->image_index],
+ .image = ctx->swapchain.images[ctx->image_index],
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1
- },
+ .subresourceRange = (VkImageSubresourceRange) {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ },
- // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- };
- layout_barriers[1] = (VkImageMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ /* .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, */
+ /* .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, */
+ };
+ layout_barriers[1] = (VkImageMemoryBarrier2) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
- .srcAccessMask = 0,
+ .srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
+ .srcAccessMask = 0,
- .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
- .dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
+ .dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
- .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .newLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
+ .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .newLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
- .image = ctx->swapchain.depth_attachment.handle,
+ .image = ctx->swapchain.depth_attachment.handle,
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1
- },
- };
+ .subresourceRange = (VkImageSubresourceRange) {
+ .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ },
+ };
- VkMemoryBarrier2 memory_barrier = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
- .srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT,
- .dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT,
- .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
- };
+ VkMemoryBarrier2 memory_barrier = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
+ .srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
+ .srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT,
+ .dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT,
+ .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
+ };
- VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
- dep_info.memoryBarrierCount = 1;
- dep_info.pMemoryBarriers = &memory_barrier;
- dep_info.imageMemoryBarrierCount = (uint32_t) NUM_LAYOUT_BARRIERS;
- dep_info.pImageMemoryBarriers = layout_barriers;
+ VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
+ dep_info.memoryBarrierCount = 1;
+ dep_info.pMemoryBarriers = &memory_barrier;
+ dep_info.imageMemoryBarrierCount = (uint32_t) NUM_LAYOUT_BARRIERS;
+ dep_info.pImageMemoryBarriers = layout_barriers;
- vkCmdPipelineBarrier2(frame_resource.command_buffer, &dep_info);
- }
+ vkCmdPipelineBarrier2(frame_resource.command_buffer, &dep_info);
+ }
- ctx->in_frame = true;
- return true;
- }
+ ctx->in_frame = true;
+ return true;
+ }
- return false;
+ return false;
}
-extern void
+void
rend_vk_renderer_frame_end(RendContextHandle handle, float *delta)
{
- RendVk14Context *ctx = (RendVk14Context *)handle;
- RASSERT(ctx, "Uninitialized renderer.");
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ RASSERT(ctx, "Uninitialized renderer.");
- RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
+ RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
- VkImageMemoryBarrier2 present_barrier;
- present_barrier = (VkImageMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ VkImageMemoryBarrier2 present_barrier;
+ present_barrier = (VkImageMemoryBarrier2) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
- .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
+ .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
- .dstStageMask = VK_PIPELINE_STAGE_2_NONE,
- .dstAccessMask = 0,
+ .dstStageMask = VK_PIPELINE_STAGE_2_NONE,
+ .dstAccessMask = 0,
- .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
- .image = ctx->swapchain.images[ctx->image_index],
+ .image = ctx->swapchain.images[ctx->image_index],
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1
- }
+ .subresourceRange = (VkImageSubresourceRange) {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ }
- };
+ };
- VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
- dep_info.imageMemoryBarrierCount = 1;
- dep_info.pImageMemoryBarriers = &present_barrier;
+ VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
+ dep_info.imageMemoryBarrierCount = 1;
+ dep_info.pImageMemoryBarriers = &present_barrier;
- vkCmdPipelineBarrier2(res.command_buffer, &dep_info);
- vkEndCommandBuffer(res.command_buffer);
+ vkCmdPipelineBarrier2(res.command_buffer, &dep_info);
+ vkEndCommandBuffer(res.command_buffer);
- /* ensure swapchain image is available */
- VkSemaphoreSubmitInfo image_acquire_await_info = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = res.image_acquired_semaphore,
- .stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
- };
+ /* ensure swapchain image is available */
+ VkSemaphoreSubmitInfo image_acquire_await_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = res.image_acquired_semaphore,
+ .stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
+ };
- /* signal that the image is presented */
- VkSemaphoreSubmitInfo semaphore_signals[2] = {
- [0] = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = ctx->render_complete_semaphores[ctx->image_index],
- .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
- },
- [1] = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = ctx->timeline_semaphore,
- .value = ctx->signal_value,
- .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
- },
- };
+ /* signal that the image is presented */
+ VkSemaphoreSubmitInfo semaphore_signals[2] = {
+ [0] = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = ctx->render_complete_semaphores[ctx->image_index],
+ .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
+ },
+ [1] = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = ctx->timeline_semaphore,
+ .value = ctx->signal_value,
+ .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
+ },
+ };
- VkCommandBufferSubmitInfo cmd_submit_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
- .commandBuffer = res.command_buffer,
- };
+ VkCommandBufferSubmitInfo cmd_submit_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
+ .commandBuffer = res.command_buffer,
+ };
- VkSubmitInfo2 submit_info = {
- .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
- .waitSemaphoreInfoCount = 1,
- .pWaitSemaphoreInfos = &image_acquire_await_info,
- .commandBufferInfoCount = 1,
- .pCommandBufferInfos = &cmd_submit_info,
- .signalSemaphoreInfoCount = 2,
- .pSignalSemaphoreInfos = semaphore_signals
- };
+ VkSubmitInfo2 submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
+ .waitSemaphoreInfoCount = 1,
+ .pWaitSemaphoreInfos = &image_acquire_await_info,
+ .commandBufferInfoCount = 1,
+ .pCommandBufferInfos = &cmd_submit_info,
+ .signalSemaphoreInfoCount = 2,
+ .pSignalSemaphoreInfos = semaphore_signals
+ };
- vkQueueSubmit2(vk_device.graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
+ vkQueueSubmit2(vk_device.graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
- VkPresentInfoKHR present_info = {
- .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
- .waitSemaphoreCount = 1,
- .pWaitSemaphores = &ctx->render_complete_semaphores[ctx->image_index],
- .swapchainCount = 1,
- .pSwapchains = &ctx->swapchain.handle,
- .pImageIndices = &ctx->image_index,
- .pResults = NULL,
- };
+ VkPresentInfoKHR present_info = {
+ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &ctx->render_complete_semaphores[ctx->image_index],
+ .swapchainCount = 1,
+ .pSwapchains = &ctx->swapchain.handle,
+ .pImageIndices = &ctx->image_index,
+ .pResults = NULL,
+ };
- vkQueuePresentKHR(vk_device.graphics_queue, &present_info);
+ vkQueuePresentKHR(vk_device.graphics_queue, &present_info);
- ctx->frame++;
- ctx->in_frame = false;
- uint64_t f = ctx->frame_index;
+ ctx->frame++;
+ ctx->in_frame = false;
- /* clear host mapped memory */
- rend_vk_arena_clear_all(&ctx->arena_frame);
- rend_vk_arena_clear(&ctx->arena_persistent, vk_device.host_index);
+ /* clear host mapped memory */
+ rend_vk_arena_clear_all(&ctx->arena_frame);
+ rend_vk_arena_clear(&ctx->arena_persistent, vk_device.host_index);
}
static inline void
-rend_vk__renderer_render_pass_begin_internal(RendRenderer renderer, float r, float g, float b, float a, uint64_t view_handle, uint64_t depth_attachment_view_handle, uint32_t offset_x, uint32_t offset_y, uint32_t width, uint32_t height)
+rend_vk__renderer_render_pass_begin_internal(RendContextHandle handle, float r, float g, float b, float a, uint64_t view_handle, uint64_t depth_attachment_view_handle, uint32_t offset_x, uint32_t offset_y, uint32_t width, uint32_t height, VkAttachmentLoadOp color_load)
{
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- RASSERT(ctx->in_frame && "must begin render pass inside a frame");
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ RASSERT(ctx->in_frame && "must begin render pass inside a frame");
- RendVkFrameResources frame_resource = ctx->frame_resources[ctx->frame_index];
+ RendVkFrameResources frame_resource = ctx->frame_resources[ctx->frame_index];
- VkRenderingAttachmentInfo color_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) view_handle,
- .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, // clear image
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE, // store for presentation
- .clearValue = (VkClearValue) {
- .color = {r, g, b, a},
- }
- };
-
- VkRenderingAttachmentInfo depth_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) depth_attachment_view_handle,
- .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, // clear depth data
- .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // don't care after rendering
- .clearValue = (VkClearValue) {
- .depthStencil = (VkClearDepthStencilValue) {1.0f, 0},
- },
- };
+ VkRenderingAttachmentInfo color_attachment = {
+ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+ .imageView = (VkImageView)view_handle,
+ .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .loadOp = color_load,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .clearValue = {
+ .color = {{r, g, b, a}},
+ }
+ };
- VkRenderingInfo rendering_info = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
- .renderArea.offset = (VkOffset2D) {offset_x, offset_y},
- .renderArea.extent = (VkExtent2D) {width, height},
- .layerCount = 1,
- .colorAttachmentCount = 1,
- .pColorAttachments = &color_attachment,
- .pDepthAttachment = &depth_attachment,
- };
+ VkRenderingAttachmentInfo depth_attachment = {
+ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+ .imageView = (VkImageView)depth_attachment_view_handle,
+ .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, /* clear depth data */
+ .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, /* don't care after rendering */
+ .clearValue = (VkClearValue) {
+ .depthStencil = (VkClearDepthStencilValue) {1.0f, 0},
+ },
+ };
- vkCmdBeginRendering(frame_resource.command_buffer, &rendering_info);
+ VkRenderingInfo rendering_info = {
+ .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
+ .renderArea.offset = (VkOffset2D) {offset_x, offset_y},
+ .renderArea.extent = (VkExtent2D) {width, height},
+ .layerCount = 1,
+ .colorAttachmentCount = 1,
+ .pColorAttachments = &color_attachment,
+ .pDepthAttachment = &depth_attachment,
+ };
- VkViewport viewport = {
- .x = offset_x,
- .y = offset_y,
- .width = width,
- .height = height,
- .minDepth = 0.0f,
- .maxDepth = 1.0f
- };
+ vkCmdBeginRendering(frame_resource.command_buffer, &rendering_info);
- vkCmdSetViewport(frame_resource.command_buffer, 0, 1, &viewport);
+ VkViewport viewport = {
+ .x = offset_x,
+ .y = offset_y,
+ .width = width,
+ .height = height,
+ .minDepth = 0.0f,
+ .maxDepth = 1.0f
+ };
- VkRect2D scissor = {{offset_x, offset_y}, {width, height}};
- vkCmdSetScissor(frame_resource.command_buffer, 0, 1, &scissor);
+ vkCmdSetViewport(frame_resource.command_buffer, 0, 1, &viewport);
+
+ VkRect2D scissor = {{offset_x, offset_y}, {width, height}};
+ vkCmdSetScissor(frame_resource.command_buffer, 0, 1, &scissor);
}
-extern void
-rend_vk_renderer_render_pass_begin(RendRenderer renderer, float r, float g, float b, float a)
+void
+rend_vk_renderer_render_pass_begin(RendContextHandle handle, float r, float g, float b, float a)
{
-
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- rend_vk__renderer_render_pass_begin_internal(
- renderer,
- r, g, b, a,
- (uint64_t) ctx->swapchain.views[ctx->image_index],
- (uint64_t) ctx->swapchain.depth_attachment.view,
- 0, 0,
- ctx->swapchain.extent.width, ctx->swapchain.extent.height
- );
+ rend_vk__renderer_render_pass_begin_internal(
+ handle,
+ r, g, b, a,
+ (uint64_t) ctx->swapchain.views[ctx->image_index],
+ (uint64_t) ctx->swapchain.depth_attachment.view,
+ 0, 0,
+ ctx->swapchain.extent.width, ctx->swapchain.extent.height,
+ VK_ATTACHMENT_LOAD_OP_CLEAR
+ );
}
-extern void
-rend_vk_renderer_render_pass_begin_texture(RendRenderer renderer, RendTexture *texture)
+void
+rend_vk_renderer_render_pass_begin_texture(RendContextHandle handle, RendTexture *texture)
{
-
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
-
- RendVkFrameResources frame_resource = ctx->frame_resources[ctx->frame_index];
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- rend_vk_texture_transition_layout(renderer, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- VkRenderingAttachmentInfo color_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) texture->view,
- .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, // load image instead of clearing
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE, // store for presentation
- };
-
- VkRenderingAttachmentInfo depth_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) ctx->swapchain.depth_attachment.view,
- .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, // clear depth data
- .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // don't care after rendering
- .clearValue = (VkClearValue) {
- .depthStencil = (VkClearDepthStencilValue) {1.0f, 0},
- },
- };
-
- VkRenderingInfo rendering_info = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
- .renderArea.offset = (VkOffset2D) {0, 0},
- .renderArea.extent = (VkExtent2D) {texture->width, texture->height},
- .layerCount = 1,
- .colorAttachmentCount = 1,
- .pColorAttachments = &color_attachment,
- .pDepthAttachment = &depth_attachment,
- };
-
- vkCmdBeginRendering(frame_resource.command_buffer, &rendering_info);
-
- VkViewport viewport = {
- .x = 0,
- .y = 0,
- .width = texture->width,
- .height = texture->height,
- .minDepth = 0.0f,
- .maxDepth = 1.0f
- };
-
- vkCmdSetViewport(frame_resource.command_buffer, 0, 1, &viewport);
-
- VkRect2D scissor = {{0, 0}, {texture->width, texture->height}};
- vkCmdSetScissor(frame_resource.command_buffer, 0, 1, &scissor);
+ rend_vk_texture_transition_layout(handle, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ rend_vk__renderer_render_pass_begin_internal(
+ handle,
+ 0, 0, 0, 0,
+ (uint64_t)texture->view,
+ (uint64_t)ctx->swapchain.depth_attachment.view,
+ 0, 0,
+ texture->width, texture->height,
+ VK_ATTACHMENT_LOAD_OP_LOAD
+ );
}
-extern void
-rend_vk_renderer_render_pass_end_texture(RendRenderer renderer, RendTexture *texture)
+void
+rend_vk_renderer_render_pass_end(RendContextHandle handle)
{
-
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- rend_vk_texture_transition_layout(renderer, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
- rend_vk_renderer_render_pass_end(renderer);
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ RASSERT(ctx->in_frame && "must end render pass inside a frame");
+ RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
+ vkCmdEndRendering(res.command_buffer);
}
-
-extern void
-rend_vk_renderer_render_pass_end(RendRenderer renderer)
+void
+rend_vk_renderer_render_pass_end_texture(RendContextHandle handle, RendTexture *texture)
{
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- RASSERT(ctx->in_frame && "must end render pass inside a frame");
- RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
- vkCmdEndRendering(res.command_buffer);
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ rend_vk_texture_transition_layout(handle, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
+ rend_vk_renderer_render_pass_end(handle);
}
-extern void
-rend_vk_descriptor_write_buffer(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo)
+void
+rend_vk_descriptor_write_buffer(RendContextHandle handle, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo)
{
- RendVk14Context *ctx = renderer->context;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- VkDescriptorBufferInfo buffer_info = {
- .buffer = (VkBuffer) ubo.handle,
- .offset = offset,
- .range = size,
- };
+ VkDescriptorBufferInfo buffer_info = {
+ .buffer = (VkBuffer)ubo.handle,
+ .offset = offset,
+ .range = size,
+ };
- VkWriteDescriptorSet descriptor_write = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = ctx->desc_set,
- .dstBinding = binding,
- .dstArrayElement = slot, // write texture to slot
- .descriptorCount = 1,
- .descriptorType = (is_ubo) ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
- .pBufferInfo = &buffer_info,
- };
+ VkWriteDescriptorSet descriptor_write = {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = ctx->desc_set,
+ .dstBinding = binding,
+ .dstArrayElement = slot, /* write texture to slot */
+ .descriptorCount = 1,
+ .descriptorType = (is_ubo) ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ .pBufferInfo = &buffer_info,
+ };
- vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
+ vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
}
-extern RendBuffer
-rend_vk_buffer_create_lifetime(RendRenderer renderer, size_t size, RendBufferType type, bool gpu, int lifetime)
+RendBuffer
+rend_vk_buffer_create_lifetime(RendContextHandle handle, size_t size, RendBufferType type, bool gpu, int lifetime)
{
- RendVk14Context *ctx = (RendVk14Context *)renderer->context;
- int32_t index = (gpu) ? vk_device.device_index : vk_device.host_index;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ int32_t index = (gpu) ? vk_device.device_index : vk_device.host_index;
- VkBufferUsageFlags vk_usage = 0;
- switch (type) {
- case REND_BUFFER_VERTEX:
- vk_usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- case REND_BUFFER_INDEX:
- vk_usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- case REND_BUFFER_UNIFORM:
- vk_usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- case REND_BUFFER_STORAGE:
- vk_usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- break;
- case REND_BUFFER_TRANSFER:
- vk_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- default:
- REND__CRASH("Invalid buffer type!");
- break;
- }
+ if (type >= REND_BUFFER_COUNT || !vk_buffer_usage[type]) {
+ REND__CRASH("Invalid buffer type!");
+ }
+ VkBufferUsageFlags vk_usage = vk_buffer_usage[type];
- RendBuffer buffer = {0};
- buffer.usage = vk_usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
+ RendBuffer buffer = {0};
+ buffer.usage = vk_usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
- bool is_concurrent = (gpu && (vk_device.graphics_family_index != vk_device.transfer_family_index));
- int32_t family[] = { vk_device.graphics_family_index, vk_device.transfer_family_index };
+ bool is_concurrent = (gpu && (vk_device.graphics_family_index != vk_device.transfer_family_index));
+ uint32_t family[] = { vk_device.graphics_family_index, vk_device.transfer_family_index };
- VkBufferCreateInfo buffer_info = {
- .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
- .size = size,
- .usage = buffer.usage,
- .sharingMode = is_concurrent ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE,
- .queueFamilyIndexCount = is_concurrent ? 2 : 1,
- .pQueueFamilyIndices = is_concurrent ? family : NULL,
- };
+ VkBufferCreateInfo buffer_info = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ .size = size,
+ .usage = buffer.usage,
+ .sharingMode = is_concurrent ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE,
+ .queueFamilyIndexCount = is_concurrent ? 2 : 1,
+ .pQueueFamilyIndices = is_concurrent ? family : NULL,
+ };
- if (vkCreateBuffer(vk_device.logical_device, &buffer_info, vk_allocator, (VkBuffer*) &buffer.handle) != VK_SUCCESS) {
- REND__CRASH("Failed to create VkBuffer!");
- }
+ if (vkCreateBuffer(vk_device.logical_device, &buffer_info, vk_allocator, (VkBuffer *) &buffer.handle) != VK_SUCCESS) {
+ REND__CRASH("Failed to create VkBuffer!");
+ }
- VkMemoryRequirements mem_reqs;
- vkGetBufferMemoryRequirements(vk_device.logical_device, (VkBuffer) buffer.handle, &mem_reqs);
+ VkMemoryRequirements mem_reqs;
+ vkGetBufferMemoryRequirements(vk_device.logical_device, (VkBuffer)buffer.handle, &mem_reqs);
- RASSERT((mem_reqs.memoryTypeBits & (1u << index)) && "Buffer incompatible with chosen memory type!");
+ RASSERT((mem_reqs.memoryTypeBits & (1u << index)) && "Buffer incompatible with chosen memory type!");
- RendVkArenaAllocator *arena = (lifetime == REND_LIFETIME_FRAME) ? &ctx->arena_frame : &ctx->arena_persistent;
- RendMemory vk_memory = rend_vk_arena_alloc(arena, mem_reqs.size, index);
+ RendVkArenaAllocator *arena = (lifetime == REND_LIFETIME_FRAME) ? &ctx->arena_frame : &ctx->arena_persistent;
+ RendMemory vk_memory = rend_vk_arena_alloc(arena, mem_reqs.size, index);
- if (vkBindBufferMemory(vk_device.logical_device, (VkBuffer) buffer.handle, (VkDeviceMemory) vk_memory.device_memory, vk_memory.offset) != VK_SUCCESS) {
- REND__CRASH("Failed to bind VkBuffer memory!");
- }
+ if (vkBindBufferMemory(vk_device.logical_device, (VkBuffer)buffer.handle, (VkDeviceMemory)vk_memory.device_memory, vk_memory.offset) != VK_SUCCESS) {
+ REND__CRASH("Failed to bind VkBuffer memory!");
+ }
- buffer.memory = vk_memory;
+ buffer.memory = vk_memory;
- VkBufferDeviceAddressInfo address_info = {
- .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
- .buffer = (VkBuffer) buffer.handle,
- };
+ VkBufferDeviceAddressInfo address_info = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
+ .buffer = (VkBuffer)buffer.handle,
+ };
- if (!gpu && vk_memory.host_mapped_memory) {
- buffer.mapped_memory = vk_memory.host_mapped_memory;
- } else {
- buffer.mapped_memory = NULL;
- }
+ if (!gpu && vk_memory.host_mapped_memory) {
+ buffer.mapped_memory = vk_memory.host_mapped_memory;
+ } else {
+ buffer.mapped_memory = NULL;
+ }
- buffer.gpu_address = vkGetBufferDeviceAddress(vk_device.logical_device, &address_info);
- buffer.size = size;
- return buffer;
+ buffer.gpu_address = vkGetBufferDeviceAddress(vk_device.logical_device, &address_info);
+ buffer.size = size;
+ return buffer;
}
-extern void
+void
rend_vk_buffer_destroy(RendBuffer *buffer)
{
- // NOTE: this function is meant to be called by the user
- // when freeing his buffers mid frame, there may be a better
- // way using fences perhaps? or by checking the timeline semaphore?
- vkDeviceWaitIdle(vk_device.logical_device);
- vkDestroyBuffer(vk_device.logical_device, (VkBuffer) buffer->handle, vk_allocator);
- memset(buffer, 0xC0FFEE, sizeof *buffer); // fill buffer with coffee
+ /* NOTE: this function is meant to be called by the user */
+ /* when freeing his buffers mid frame, there may be a better */
+ /* way using fences perhaps? or by checking the timeline semaphore? */
+ vkDeviceWaitIdle(vk_device.logical_device);
+ vkDestroyBuffer(vk_device.logical_device, (VkBuffer)buffer->handle, vk_allocator);
+ memset(buffer, 0xC0FFEE, sizeof(*buffer)); /* fill buffer with coffee */
}
-extern void
-rend_vk_buffer_copy(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes)
+void
+rend_vk_buffer_copy(RendContextHandle handle, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes)
{
- RASSERT(src && dest); // check that im not sending null pointers
- RASSERT(src->usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT); // source buffer must be marked as transfer src
- RASSERT(dest->usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT); // dest buffer must be marked as transfer dest
+ RASSERT(src && dest); /* check that im not sending null pointers */
+ RASSERT(src->usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT); /* source buffer must be marked as transfer src */
+ RASSERT(dest->usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT); /* dest buffer must be marked as transfer dest */
+
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ VkBuffer src_vk = (VkBuffer)(uintptr_t)src->handle;
+ VkBuffer dest_vk = (VkBuffer)(uintptr_t)dest->handle;
- RendVk14Context *ctx = (RendVk14Context *)renderer->context;
- VkBuffer src_vk = (VkBuffer)(uintptr_t)src->handle;
- VkBuffer dest_vk = (VkBuffer)(uintptr_t)dest->handle;
+ VkCommandBuffer transfer_cmd = VK_NULL_HANDLE;
- VkCommandBuffer transfer_cmd = VK_NULL_HANDLE;
+ VkCommandBufferAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .commandBufferCount = 1,
+ .commandPool = ctx->upload_command_pool,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .pNext = NULL,
+ };
- VkCommandBufferAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .commandBufferCount = 1,
- .commandPool = ctx->upload_command_pool,
- .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- .pNext = NULL,
- };
+ if (vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &transfer_cmd) != VK_SUCCESS) {
+ REND__CRASH("Failed to allocate transfer command buffer!");
+ }
- if (vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &transfer_cmd) != VK_SUCCESS) {
- REND__CRASH("Failed to allocate transfer command buffer!");
- }
+ VkCommandBufferBeginInfo begin_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ };
+ vkBeginCommandBuffer(transfer_cmd, &begin_info);
- VkCommandBufferBeginInfo begin_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
- };
- vkBeginCommandBuffer(transfer_cmd, &begin_info);
+ VkBufferCopy buffer_copy = {
+ .srcOffset = (VkDeviceSize)src_offset,
+ .dstOffset = (VkDeviceSize)dest_offset,
+ .size = (VkDeviceSize)bytes,
+ };
- VkBufferCopy buffer_copy = {
- .srcOffset = (VkDeviceSize)src_offset,
- .dstOffset = (VkDeviceSize)dest_offset,
- .size = (VkDeviceSize)bytes,
- };
+ vkCmdCopyBuffer(transfer_cmd, src_vk, dest_vk, 1, &buffer_copy);
+ vkEndCommandBuffer(transfer_cmd);
- vkCmdCopyBuffer(transfer_cmd, src_vk, dest_vk, 1, &buffer_copy);
- vkEndCommandBuffer(transfer_cmd);
+ VkCommandBufferSubmitInfo cmd_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
+ .commandBuffer = transfer_cmd,
+ .deviceMask = 0,
+ };
- VkCommandBufferSubmitInfo cmd_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
- .commandBuffer = transfer_cmd,
- .deviceMask = 0,
- };
+ VkSubmitInfo2 submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
+ .commandBufferInfoCount = 1,
+ .pCommandBufferInfos = &cmd_info,
+ };
- VkSubmitInfo2 submit_info = {
- .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
- .commandBufferInfoCount = 1,
- .pCommandBufferInfos = &cmd_info,
- };
+ vkQueueSubmit2(vk_device.transfer_queue, 1, &submit_info, VK_NULL_HANDLE);
- vkQueueSubmit2(vk_device.transfer_queue, 1, &submit_info, VK_NULL_HANDLE);
-
- vkQueueWaitIdle(vk_device.transfer_queue);
- vkFreeCommandBuffers(vk_device.logical_device, ctx->upload_command_pool, 1, &transfer_cmd);
+ vkQueueWaitIdle(vk_device.transfer_queue);
+ vkFreeCommandBuffers(vk_device.logical_device, ctx->upload_command_pool, 1, &transfer_cmd);
}
-extern RendTexture
-rend_vk_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format)
+RendTexture
+rend_vk_texture_create(RendContextHandle handle, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format)
{
- RASSERT(format < REND_FORMAT_COUNT && "Invalid format!");
+ RASSERT(format < REND_FORMAT_COUNT && "Invalid format!");
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- VkFormat vk_format = vk_format_from_rend_format[format];
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ VkFormat vk_format = vk_format_from_rend_format[format];
- uint32_t safe_depth = (depth > 0) ? depth : 1;
- uint32_t safe_mips = (mip_levels > 0) ? mip_levels : 1;
- uint32_t safe_layers = (layers > 0) ? layers : 1;
+ uint32_t safe_depth = (depth > 0) ? depth : 1;
+ uint32_t safe_mips = (mip_levels > 0) ? mip_levels : 1;
+ uint32_t safe_layers = (layers > 0) ? layers : 1;
- RendTexture tex = {
- .handle = 0,
- .width = width,
- .height = height,
- .depth = safe_depth,
- .mip_levels = safe_mips,
- .layers = safe_layers,
- .format = vk_format,
- .layout = VK_IMAGE_LAYOUT_UNDEFINED,
- };
+ RendTexture tex = {
+ .handle = 0,
+ .width = width,
+ .height = height,
+ .depth = safe_depth,
+ .mip_levels = safe_mips,
+ .layers = safe_layers,
+ .format = vk_format,
+ .layout = VK_IMAGE_LAYOUT_UNDEFINED,
+ };
- VkImageCreateInfo image_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = (safe_depth > 1) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
- .extent = { .width = width, .height = height, .depth = safe_depth },
- .mipLevels = tex.mip_levels,
- .arrayLayers = tex.layers,
- .format = vk_format,
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
- .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
- .samples = VK_SAMPLE_COUNT_1_BIT,
- .flags = 0,
- };
+ VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = (safe_depth > 1) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
+ .extent = { .width = width, .height = height, .depth = safe_depth },
+ .mipLevels = tex.mip_levels,
+ .arrayLayers = tex.layers,
+ .format = vk_format,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .flags = 0,
+ };
- if (vkCreateImage(vk_device.logical_device, &image_info, vk_allocator, (VkImage*)&tex.handle) != VK_SUCCESS) {
- REND__CRASH("failed to create image!");
- return tex;
- }
+ if (vkCreateImage(vk_device.logical_device, &image_info, vk_allocator, (VkImage *)&tex.handle) != VK_SUCCESS) {
+ REND__CRASH("failed to create image!");
+ return tex;
+ }
- VkMemoryRequirements mem_requirements;
- vkGetImageMemoryRequirements(vk_device.logical_device, (VkImage)tex.handle, &mem_requirements);
+ VkMemoryRequirements mem_requirements;
+ vkGetImageMemoryRequirements(vk_device.logical_device, (VkImage)tex.handle, &mem_requirements);
- uint32_t index = rend_vk_get_heap_index(mem_requirements.memoryTypeBits, vk_device.device_index);
- tex.memory = rend_vk_arena_alloc(&ctx->arena_persistent, mem_requirements.size, index);
+ uint32_t index = rend_vk_get_heap_index(mem_requirements.memoryTypeBits, vk_device.device_index);
+ tex.memory = rend_vk_arena_alloc(&ctx->arena_persistent, mem_requirements.size, index);
- vkBindImageMemory(vk_device.logical_device, (VkImage)tex.handle, (VkDeviceMemory)tex.memory.device_memory, (VkDeviceSize)tex.memory.offset);
+ vkBindImageMemory(vk_device.logical_device, (VkImage)tex.handle, (VkDeviceMemory)tex.memory.device_memory, (VkDeviceSize)tex.memory.offset);
- // Correct ImageView creation using strict VkImageViewType and derived format
- VkImageViewCreateInfo view_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = (VkImage)tex.handle,
- .viewType = (safe_depth > 1) ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D,
- .format = vk_format,
- .subresourceRange = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = tex.mip_levels,
- .baseArrayLayer = 0,
- .layerCount = tex.layers,
- },
- };
+ /* Correct ImageView creation using strict VkImageViewType and derived format */
+ VkImageViewCreateInfo view_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = (VkImage)tex.handle,
+ .viewType = (safe_depth > 1) ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D,
+ .format = vk_format,
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = tex.mip_levels,
+ .baseArrayLayer = 0,
+ .layerCount = tex.layers,
+ },
+ };
- if (vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, (VkImageView*)&tex.view) != VK_SUCCESS) {
- REND__CRASH("failed to create image view!");
- return tex;
- }
+ if (vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, (VkImageView *)&tex.view) != VK_SUCCESS) {
+ REND__CRASH("failed to create image view!");
+ return tex;
+ }
- /* per-texture sampler */
- VkSamplerCreateInfo sampler_info = {
- .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
- .magFilter = VK_FILTER_LINEAR, // force sharp upscaling
- .minFilter = VK_FILTER_LINEAR, // TODO: add filter setting to texture
- .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
- .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
- .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ /* per-texture sampler */
+ VkSamplerCreateInfo sampler_info = {
+ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+ .magFilter = VK_FILTER_LINEAR, /* force sharp upscaling */
+ .minFilter = VK_FILTER_LINEAR, /* TODO: add filter setting to texture */
+ .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
- .mipmapMode = (tex.mip_levels > 1) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST,
- .minLod = 0.0f,
- .maxLod = (tex.mip_levels > 1) ? (float)tex.mip_levels : 0.0f,
+ .mipmapMode = (tex.mip_levels > 1) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ .minLod = 0.0f,
+ .maxLod = (tex.mip_levels > 1) ? (float)tex.mip_levels : 0.0f,
- .anisotropyEnable = (tex.mip_levels > 1 && vk_device.features.samplerAnisotropy) ? VK_TRUE : VK_FALSE,
- .maxAnisotropy = 8.0f,
- };
+ .anisotropyEnable = (tex.mip_levels > 1 && vk_device.features.samplerAnisotropy) ? VK_TRUE : VK_FALSE,
+ .maxAnisotropy = 8.0f,
+ };
- if (vkCreateSampler(vk_device.logical_device, &sampler_info, vk_allocator, (VkSampler*)&tex.sampler) != VK_SUCCESS) {
- REND__CRASH("failed to create sampler!");
- }
+ if (vkCreateSampler(vk_device.logical_device, &sampler_info, vk_allocator, (VkSampler *)&tex.sampler) != VK_SUCCESS) {
+ REND__CRASH("failed to create sampler!");
+ }
- return tex;
+ return tex;
}
-extern void
-rend_vk_texture_destroy(RendRenderer renderer, RendTexture *tex)
+void
+rend_vk_texture_destroy(RendContextHandle handle, RendTexture *tex)
{
- RASSERT(renderer && tex);
- RendVk14Context *ctx = (RendVk14Context*)renderer->context;
+ RASSERT(handle && tex);
- if (tex->handle) {
- vkDestroyImage(vk_device.logical_device, (VkImage) tex->handle, vk_allocator);
- tex->handle = 0;
- }
+ if (tex->handle) {
+ vkDestroyImage(vk_device.logical_device, (VkImage)tex->handle, vk_allocator);
+ tex->handle = 0;
+ }
- if (tex->view) {
- vkDestroyImageView(vk_device.logical_device, (VkImageView) tex->view, vk_allocator);
- tex->view = 0;
- }
+ if (tex->view) {
+ vkDestroyImageView(vk_device.logical_device, (VkImageView)tex->view, vk_allocator);
+ tex->view = 0;
+ }
- if (tex->sampler) {
- vkDestroySampler(vk_device.logical_device, (VkSampler)tex->sampler, vk_allocator);
- tex->sampler = 0;
- }
+ if (tex->sampler) {
+ vkDestroySampler(vk_device.logical_device, (VkSampler)tex->sampler, vk_allocator);
+ tex->sampler = 0;
+ }
- // memset(tex, 0xBABE, sizeof *tex);
+ /* memset(tex, 0xBABE, sizeof(*tex)); */
}
-extern void
-rend_vk_texture_transition_layout(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout)
+static void
+rend_vk_texture_barrier(VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout, uint32_t src_family, uint32_t dst_family, VkAccessFlags2 src_access, VkAccessFlags2 dst_access, VkPipelineStageFlags2 src_stage, VkPipelineStageFlags2 dst_stage)
{
- RendVk14Context *ctx = renderer->context;
- VkCommandPool pool = ctx->upload_command_pool;
-
- VkImageMemoryBarrier2 barrier = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .oldLayout = texture->layout,
- .newLayout = new_layout,
-
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-
- .image = (VkImage) texture->handle,
-
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = texture->mip_levels,
- .baseArrayLayer = 0,
- .layerCount = texture->layers,
- },
-
- .srcAccessMask = 0, // TODO
- .dstAccessMask = 0, // TODO
-
- };
-
- if (texture->layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- } else if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
- barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
- } else {
- barrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- }
-
- VkDependencyInfo dep = {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pImageMemoryBarriers = &barrier,
- .imageMemoryBarrierCount = 1,
- };
-
- texture->layout = new_layout;
- vkCmdPipelineBarrier2(cmd, &dep);
+ VkImageMemoryBarrier2 barrier = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ .oldLayout = texture->layout,
+ .newLayout = new_layout,
+ .srcQueueFamilyIndex = src_family,
+ .dstQueueFamilyIndex = dst_family,
+ .image = (VkImage)texture->handle,
+ .srcAccessMask = src_access,
+ .dstAccessMask = dst_access,
+ .srcStageMask = src_stage,
+ .dstStageMask = dst_stage,
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = texture->mip_levels,
+ .baseArrayLayer = 0,
+ .layerCount = texture->layers,
+ },
+ };
+ VkDependencyInfo dep = {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+ .pImageMemoryBarriers = &barrier,
+ .imageMemoryBarrierCount = 1,
+ };
+ texture->layout = new_layout;
+ vkCmdPipelineBarrier2(cmd, &dep);
}
-extern void
-rend_vk_texture_transfer_ownership_release(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
+void
+rend_vk_texture_transition_layout(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout)
{
- RendVk14Context *ctx = renderer->context;
- (void) ctx; // reserved in case you need it for stage/access lookups later
-
- VkImageMemoryBarrier2 barrier = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .oldLayout = texture->layout,
- .newLayout = new_layout,
- .srcQueueFamilyIndex = src_family,
- .dstQueueFamilyIndex = dst_family,
- .image = (VkImage) texture->handle,
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = texture->mip_levels,
- .baseArrayLayer = 0,
- .layerCount = texture->layers,
- },
- };
-
- if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
- barrier.dstAccessMask = 0;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
- } else {
- barrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.dstAccessMask = 0;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
- }
-
- VkDependencyInfo dep = {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pImageMemoryBarriers = &barrier,
- .imageMemoryBarrierCount = 1,
- };
-
- texture->layout = new_layout;
- vkCmdPipelineBarrier2(cmd, &dep);
+ (void)handle;
+ if (texture->layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
+ 0, VK_ACCESS_2_TRANSFER_WRITE_BIT,
+ VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_TRANSFER_BIT);
+ } else if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
+ VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT,
+ VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT);
+ } else {
+ rend_vk_texture_barrier(cmd, texture, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
+ VK_ACCESS_2_MEMORY_WRITE_BIT, VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
+ }
}
-extern void
-rend_vk_texture_transfer_ownership_acquire(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
+void
+rend_vk_texture_transfer_ownership_release(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
{
- RendVk14Context *ctx = renderer->context;
- (void) ctx;
-
- VkImageMemoryBarrier2 barrier = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .oldLayout = texture->layout,
- .newLayout = new_layout,
- .srcQueueFamilyIndex = src_family,
- .dstQueueFamilyIndex = dst_family,
- .image = (VkImage) texture->handle,
-
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = texture->mip_levels,
- .baseArrayLayer = 0,
- .layerCount = texture->layers,
- },
- };
-
- if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
- } else {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- }
-
- VkDependencyInfo dep = {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pImageMemoryBarriers = &barrier,
- .imageMemoryBarrierCount = 1,
- };
+ (void)handle;
+ if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ VK_ACCESS_2_TRANSFER_WRITE_BIT, 0,
+ VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
+ } else {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ VK_ACCESS_2_MEMORY_WRITE_BIT, 0,
+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
+ }
+}
- texture->layout = new_layout;
- vkCmdPipelineBarrier2(cmd, &dep);
+void
+rend_vk_texture_transfer_ownership_acquire(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
+{
+ (void)handle;
+ if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ 0, VK_ACCESS_2_SHADER_READ_BIT,
+ VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT);
+ } else {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ 0, VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
+ VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
+ }
}
-extern void
-rend_vk_texture_copy_buffer(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer)
+void
+rend_vk_texture_copy_buffer(RendContextHandle handle, RendTexture *texture, RendBuffer *buffer)
{
- RendVk14Context *ctx = renderer->context;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- VkCommandBuffer cmd_transfer = rend_vk_cmdbuffer_single_use_begin(ctx->upload_command_pool); {
- rend_vk_texture_transition_layout(renderer, cmd_transfer, texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- VkBufferImageCopy region = {
- .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .imageSubresource.layerCount = texture->layers,
- .imageExtent = (VkExtent3D) { texture->width, texture->height, texture->depth },
- };
+ VkCommandBuffer cmd_transfer = rend_vk_cmdbuffer_single_use_begin(ctx->upload_command_pool); {
+ rend_vk_texture_transition_layout(handle, cmd_transfer, texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ VkBufferImageCopy region = {
+ .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .imageSubresource.layerCount = texture->layers,
+ .imageExtent = (VkExtent3D) { texture->width, texture->height, texture->depth },
+ };
- vkCmdCopyBufferToImage(cmd_transfer, (VkBuffer) buffer->handle, (VkImage) texture->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
- rend_vk_texture_transfer_ownership_release(renderer, cmd_transfer, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- } rend_vk_cmdbuffer_single_use_end(ctx->upload_command_pool, cmd_transfer, vk_device.transfer_queue);
+ vkCmdCopyBufferToImage(cmd_transfer, (VkBuffer)buffer->handle, (VkImage)texture->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+ rend_vk_texture_transfer_ownership_release(handle, cmd_transfer, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ } rend_vk_cmdbuffer_single_use_end(ctx->upload_command_pool, cmd_transfer, vk_device.transfer_queue);
- VkCommandBuffer cmd_graphics = rend_vk_cmdbuffer_single_use_begin(ctx->graphics_command_pool); {
- rend_vk_texture_transfer_ownership_acquire(renderer, cmd_graphics, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- } rend_vk_cmdbuffer_single_use_end(ctx->graphics_command_pool, cmd_graphics, vk_device.graphics_queue);
+ VkCommandBuffer cmd_graphics = rend_vk_cmdbuffer_single_use_begin(ctx->graphics_command_pool); {
+ rend_vk_texture_transfer_ownership_acquire(handle, cmd_graphics, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ } rend_vk_cmdbuffer_single_use_end(ctx->graphics_command_pool, cmd_graphics, vk_device.graphics_queue);
}
-extern void
-rend_vk_texture_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h)
+void
+rend_vk_texture_blit(RendContextHandle handle, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h)
{
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
-
- rend_vk_texture_transition_layout(renderer, cmd, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
- rend_vk_texture_transition_layout(renderer, cmd, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ rend_vk_texture_transition_layout(handle, cmd, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+ rend_vk_texture_transition_layout(handle, cmd, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- VkImageBlit2 blit_region = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
- .srcSubresource = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .mipLevel = 0,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
- .srcOffsets = {
- { src_x, src_y, 0 },
- { src_x + src_w, src_y + src_h, 1 }
- },
- .dstSubresource = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .mipLevel = 0,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
- .dstOffsets = {
- { dst_x, dst_y, 0 },
- { dst_x + dst_w, dst_y + dst_h, 1 }
- }
- };
+ VkImageBlit2 blit_region = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
+ .srcSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ .srcOffsets = {
+ { src_x, src_y, 0 },
+ { src_x + src_w, src_y + src_h, 1 }
+ },
+ .dstSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ .dstOffsets = {
+ { dst_x, dst_y, 0 },
+ { dst_x + dst_w, dst_y + dst_h, 1 }
+ }
+ };
- VkBlitImageInfo2 blit_info = {
- .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
- .srcImage = (VkImage) src->handle,
- .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- .dstImage = (VkImage) dst->handle,
- .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- .regionCount = 1,
- .pRegions = &blit_region,
+ VkBlitImageInfo2 blit_info = {
+ .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
+ .srcImage = (VkImage)src->handle,
+ .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ .dstImage = (VkImage)dst->handle,
+ .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ .regionCount = 1,
+ .pRegions = &blit_region,
- .filter = VK_FILTER_NEAREST // crispy
- };
+ .filter = VK_FILTER_NEAREST /* crispy */
+ };
- vkCmdBlitImage2(cmd, &blit_info);
+ vkCmdBlitImage2(cmd, &blit_info);
}
static VkCommandBuffer
rend_vk_cmdbuffer_single_use_begin(VkCommandPool pool)
{
- VkCommandBufferAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- .commandPool = pool,
- .commandBufferCount = 1,
- };
+ VkCommandBufferAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandPool = pool,
+ .commandBufferCount = 1,
+ };
- VkCommandBuffer cmd;
- vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &cmd);
+ VkCommandBuffer cmd;
+ vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &cmd);
- VkCommandBufferBeginInfo begin = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
- };
+ VkCommandBufferBeginInfo begin = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ };
- vkBeginCommandBuffer(cmd, &begin);
+ vkBeginCommandBuffer(cmd, &begin);
- return cmd;
+ return cmd;
}
static void
rend_vk_cmdbuffer_single_use_end(VkCommandPool pool, VkCommandBuffer cmd, VkQueue q)
{
- vkEndCommandBuffer(cmd);
+ vkEndCommandBuffer(cmd);
- VkSubmitInfo submit_info = {
- .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
- .commandBufferCount = 1,
- .pCommandBuffers = &cmd,
- };
+ VkSubmitInfo submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .commandBufferCount = 1,
+ .pCommandBuffers = &cmd,
+ };
- vkQueueSubmit(q, 1, &submit_info, VK_NULL_HANDLE);
- vkQueueWaitIdle(q);
+ vkQueueSubmit(q, 1, &submit_info, VK_NULL_HANDLE);
+ vkQueueWaitIdle(q);
- vkFreeCommandBuffers(vk_device.logical_device, pool, 1, &cmd);
+ vkFreeCommandBuffers(vk_device.logical_device, pool, 1, &cmd);
}
-extern bool
-rend_vk_pipeline_create(RendRenderer renderer, RendPipeline pipeline, Rend__PipelineConfig config, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3)
+bool
+rend_vk_pipeline_create(RendContextHandle handle, RendPipeline pipeline, Rend__PipelineConfig config, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3)
{
+ uint32_t u;
+ uint32_t i;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ pipeline->idx = ctx->pipeline_count++;
+ pipeline->backend_ctx = ctx; /* useful for when we only have RendPipeline as an argument */
- RendVk14Context *ctx = (RendVk14Context *)renderer->context;
- pipeline->idx = ctx->pipeline_count++;
- pipeline->backend_ctx = ctx; // useful for when we only have RendPipeline as an argument
-
- RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
- vk_pipeline->blend_enable = false;
-
- /*
- * set color and depth format
- */
- VkFormat color_format = (config.color_format != REND_FORMAT_UNDEFINED)
- ? vk_format_from_rend_format[config.color_format]
- : ctx->swapchain.format.format;
-
- VkFormat depth_format = (config.depth_format != REND_FORMAT_UNDEFINED)
- ? vk_format_from_rend_format[config.depth_format]
- : vk_device.depth_format;
-
- /*
- * Pipeline Layout
- */
-
- vk_pipeline->push_constants_range = 0;
- uint32_t total_size = 0;
- for (uint32_t u = 0; u < config.push_constant_count; ++u) {
- total_size += config.push_constants[u].size;
- }
-
- vk_pipeline->push_constants_range = total_size;
-
- VkPushConstantRange pc_range = {
- .offset = 0,
- .size = total_size,
- .stageFlags = VK_SHADER_STAGE_ALL,
- };
+ RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
+ vk_pipeline->blend_enable = false;
- VkPipelineLayoutCreateInfo layout_info = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .pSetLayouts = &ctx->desc_layout,
- .setLayoutCount = 1,
- .pPushConstantRanges = (total_size > 0) ? &pc_range : NULL,
- .pushConstantRangeCount = (total_size > 0) ? 1 : 0,
- };
+ /*
+ * set color and depth format
+ */
+ VkFormat color_format = (config.color_format != REND_FORMAT_UNDEFINED)
+ ? vk_format_from_rend_format[config.color_format]
+ : ctx->swapchain.format.format;
- CHECK_VK_RESULT(vkCreatePipelineLayout(vk_device.logical_device, &layout_info, vk_allocator, &vk_pipeline->layout));
+ VkFormat depth_format = (config.depth_format != REND_FORMAT_UNDEFINED)
+ ? vk_format_from_rend_format[config.depth_format]
+ : vk_device.depth_format;
- /*
- * Setup shaders based on pipeline type
- */
- VkPipelineShaderStageCreateInfo shader_stages[3] = {0};
- VkShaderModule shader_modules[3] = {0};
- uint32_t shader_count = 0;
+ /*
+ * Pipeline Layout
+ */
- if (type == REND__PIPELINE_GRAPHICS) {
- shader_count = 2;
- shader_modules[0] = rend_vk_shader_module_create(shader1, bytes1);
- shader_modules[1] = rend_vk_shader_module_create(shader2, bytes2);
+ uint32_t total_size = 0;
+ for (u = 0; u < config.push_constant_count; ++u) {
+ total_size += config.push_constants[u].size;
+ }
+ vk_pipeline->push_constants_range = total_size;
- shader_stages[0] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_VERTEX_BIT,
- .module = shader_modules[0],
- .pName = "main"
- };
+ VkPushConstantRange pc_range = {
+ .offset = 0,
+ .size = total_size,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ };
- shader_stages[1] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
- .module = shader_modules[1],
- .pName = "main",
- };
+ VkPipelineLayoutCreateInfo layout_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pSetLayouts = &ctx->desc_layout,
+ .setLayoutCount = 1,
+ .pPushConstantRanges = (total_size > 0) ? &pc_range : NULL,
+ .pushConstantRangeCount = (total_size > 0) ? 1 : 0,
+ };
- } else if (type == REND__PIPELINE_MESH) {
- shader_count = 2;
- shader_modules[0] = rend_vk_shader_module_create(shader1, bytes1);
- shader_modules[1] = rend_vk_shader_module_create(shader2, bytes2);
+ CHECK_VK_RESULT(vkCreatePipelineLayout(vk_device.logical_device, &layout_info, vk_allocator, &vk_pipeline->layout));
- shader_stages[0] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_MESH_BIT_EXT,
- .module = shader_modules[0],
- .pName = "main"
- };
+ VkPipelineShaderStageCreateInfo shader_stages[3] = {0};
+ VkShaderModule shader_modules[3] = {0};
+ const uint8_t *shader_bytes[3] = { shader1, shader2, shader3 };
+ size_t shader_sizes[3] = { bytes1, bytes2, bytes3 };
+ uint32_t shader_count = 0;
- shader_stages[1] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
- .module = shader_modules[1],
- .pName = "main",
- };
+ if (type != REND__PIPELINE_GRAPHICS && type != REND__PIPELINE_MESH && type != REND__PIPELINE_COMPUTE) {
+ REND__CRASH("Invalid pipeline type");
+ }
+ for (i = 0; i < 3 && vk_pipeline_stages[type][i]; ++i) {
+ shader_modules[i] = rend_vk_shader_module_create(shader_bytes[i], shader_sizes[i]);
+ shader_stages[i] = (VkPipelineShaderStageCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = vk_pipeline_stages[type][i],
+ .module = shader_modules[i],
+ .pName = "main"
+ };
+ shader_count++;
+ }
- } else if (type == REND__PIPELINE_COMPUTE) {
- shader_count = 1;
- shader_modules[0] = rend_vk_shader_module_create(shader1, bytes1);
+ /*
+ * Compute Pipeline Branch
+ */
+ if (type == REND__PIPELINE_COMPUTE) {
+ VkComputePipelineCreateInfo compute_pipeline_info = {
+ .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ .stage = shader_stages[0],
+ .layout = vk_pipeline->layout,
+ .basePipelineHandle = VK_NULL_HANDLE,
+ .basePipelineIndex = -1,
+ };
- shader_stages[0] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_COMPUTE_BIT,
- .module = shader_modules[0],
- .pName = "main"
- };
- } else {
- REND__CRASH("Invalid pipeline type");
- }
+ CHECK_VK_RESULT(vkCreateComputePipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &compute_pipeline_info, vk_allocator, &vk_pipeline->handle));
- /*
- * Compute Pipeline Branch
- */
- if (type == REND__PIPELINE_COMPUTE) {
- VkComputePipelineCreateInfo compute_pipeline_info = {
- .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
- .stage = shader_stages[0],
- .layout = vk_pipeline->layout,
- .basePipelineHandle = VK_NULL_HANDLE,
- .basePipelineIndex = -1,
- };
+ PINFO("Successfully created compute pipeline!");
+ }
+ /*
+ * Graphics / Mesh Pipeline Branch
+ */
+ else {
+ VkPipelineRenderingCreateInfo rendering_info = {VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO};
+ rendering_info.colorAttachmentCount = 1;
+ rendering_info.pColorAttachmentFormats = &color_format;
+ rendering_info.depthAttachmentFormat = depth_format;
- CHECK_VK_RESULT(vkCreateComputePipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &compute_pipeline_info, vk_allocator, &vk_pipeline->handle));
+ VkPipelineViewportStateCreateInfo viewport_state = {VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
+ viewport_state.viewportCount = 1;
+ viewport_state.scissorCount = 1;
- PINFO("Successfully created compute pipeline!");
- }
- /*
- * Graphics / Mesh Pipeline Branch
- */
- else {
- VkPipelineRenderingCreateInfo rendering_info = {VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO};
- rendering_info.colorAttachmentCount = 1;
- rendering_info.pColorAttachmentFormats = &color_format;
- rendering_info.depthAttachmentFormat = depth_format;
+ VkPipelineRasterizationStateCreateInfo rasterizer = {VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO};
+ rasterizer.depthClampEnable = VK_FALSE;
+ rasterizer.rasterizerDiscardEnable = VK_FALSE;
+ rasterizer.polygonMode = vk_polymode[config.polygon_mode];
+ rasterizer.lineWidth = 1.0f;
+ rasterizer.cullMode = vk_cullflags[config.cull_mode];
+ rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rasterizer.depthBiasEnable = VK_FALSE;
- VkPipelineViewportStateCreateInfo viewport_state = {VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
- viewport_state.viewportCount = 1;
- viewport_state.scissorCount = 1;
+ VkPipelineMultisampleStateCreateInfo multisampling = {VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
+ multisampling.sampleShadingEnable = VK_FALSE;
+ multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
- VkPipelineRasterizationStateCreateInfo rasterizer = {VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO};
- rasterizer.depthClampEnable = VK_FALSE;
- rasterizer.rasterizerDiscardEnable = VK_FALSE;
- rasterizer.polygonMode = vk_polymode[config.polygon_mode];
- rasterizer.lineWidth = 1.0f;
- rasterizer.cullMode = vk_cullflags[config.cull_mode];
- rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
- rasterizer.depthBiasEnable = VK_FALSE;
+ VkPipelineColorBlendAttachmentState color_blend_attachment = {0};
+ color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+ color_blend_attachment.blendEnable = VK_FALSE;
- VkPipelineMultisampleStateCreateInfo multisampling = {VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
- multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ VkPipelineColorBlendStateCreateInfo color_blending = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
+ color_blending.logicOpEnable = VK_FALSE;
+ color_blending.logicOp = VK_LOGIC_OP_COPY;
+ color_blending.attachmentCount = 1;
+ color_blending.pAttachments = &color_blend_attachment;
- VkPipelineColorBlendAttachmentState color_blend_attachment = {0};
- color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
- color_blend_attachment.blendEnable = VK_FALSE;
+ VkPipelineDepthStencilStateCreateInfo depth_stencil = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
+ depth_stencil.depthTestEnable = config.depth_test_enable;
+ depth_stencil.depthWriteEnable = VK_TRUE;
+ depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
+ depth_stencil.depthBoundsTestEnable = VK_FALSE;
+ depth_stencil.stencilTestEnable = VK_FALSE;
- VkPipelineColorBlendStateCreateInfo color_blending = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
- color_blending.logicOpEnable = VK_FALSE;
- color_blending.logicOp = VK_LOGIC_OP_COPY;
- color_blending.attachmentCount = 1;
- color_blending.pAttachments = &color_blend_attachment;
+ VkDynamicState dynamic_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
+ VkPipelineDynamicStateCreateInfo dynamic_state = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO};
+ dynamic_state.dynamicStateCount = 2;
+ dynamic_state.pDynamicStates = dynamic_states;
- VkPipelineDepthStencilStateCreateInfo depth_stencil = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
- depth_stencil.depthTestEnable = config.depth_test_enable;
- depth_stencil.depthWriteEnable = VK_TRUE;
- depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
- depth_stencil.depthBoundsTestEnable = VK_FALSE;
- depth_stencil.stencilTestEnable = VK_FALSE;
+ VkPipelineVertexInputStateCreateInfo vertex_input_info = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO};
+ VkPipelineInputAssemblyStateCreateInfo input_assembly = {VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
+ VkVertexInputBindingDescription* vk_bindings = NULL;
+ VkVertexInputAttributeDescription* vk_attributes = NULL;
- VkDynamicState dynamic_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
- VkPipelineDynamicStateCreateInfo dynamic_state = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO};
- dynamic_state.dynamicStateCount = 2;
- dynamic_state.pDynamicStates = dynamic_states;
+ if (type == REND__PIPELINE_GRAPHICS) {
+ uint32_t binding_count = config.vertex_binding_count;
+ uint32_t attribute_count = config.vertex_attribute_count;
- VkPipelineVertexInputStateCreateInfo vertex_input_info = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO};
- VkPipelineInputAssemblyStateCreateInfo input_assembly = {VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
- VkVertexInputBindingDescription* vk_bindings = NULL;
- VkVertexInputAttributeDescription* vk_attributes = NULL;
+ /*
+ * Bind Vertex Attributes
+ */
+ if (binding_count > 0) {
+ vk_bindings = rmalloc(sizeof(VkVertexInputBindingDescription) * binding_count);
+ for (i = 0; i < binding_count; i++) {
+ RendVertexBinding rb = config.vertex_bindings[i];
+ vk_bindings[i].binding = rb.binding;
+ vk_bindings[i].stride = rb.stride;
+ vk_bindings[i].inputRate = (rb.input_rate == REND_INPUT_RATE_INSTANCE) ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
+ }
+ }
- if (type == REND__PIPELINE_GRAPHICS) {
- uint32_t binding_count = config.vertex_binding_count;
- uint32_t attribute_count = config.vertex_attribute_count;
+ if (attribute_count > 0) {
+ vk_attributes = rmalloc(sizeof(VkVertexInputAttributeDescription) * attribute_count);
+ for (i = 0; i < attribute_count; i++) {
+ RendVertexAttributes ra = config.vertex_attributes[i];
+ vk_attributes[i].binding = ra.binding;
+ vk_attributes[i].location = ra.location;
+ vk_attributes[i].offset = ra.offset;
+ vk_attributes[i].format = vk_format_from_rend_format[ra.format];
+ }
+ }
- /*
- * Bind Vertex Attributes
- */
- if (binding_count > 0) {
- vk_bindings = rmalloc(sizeof(VkVertexInputBindingDescription) * binding_count);
- for (uint32_t i = 0; i < binding_count; i++) {
- RendVertexBinding rb = config.vertex_bindings[i];
- vk_bindings[i].binding = rb.binding;
- vk_bindings[i].stride = rb.stride;
- vk_bindings[i].inputRate = (rb.input_rate == REND_INPUT_RATE_INSTANCE) ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
- }
- }
+ vertex_input_info.vertexBindingDescriptionCount = binding_count;
+ vertex_input_info.pVertexBindingDescriptions = vk_bindings;
+ vertex_input_info.vertexAttributeDescriptionCount = attribute_count;
+ vertex_input_info.pVertexAttributeDescriptions = vk_attributes;
- if (attribute_count > 0) {
- vk_attributes = rmalloc(sizeof(VkVertexInputAttributeDescription) * attribute_count);
- for (uint32_t i = 0; i < attribute_count; i++) {
- RendVertexAttributes ra = config.vertex_attributes[i];
- vk_attributes[i].binding = ra.binding;
- vk_attributes[i].location = ra.location;
- vk_attributes[i].offset = ra.offset;
- vk_attributes[i].format = vk_format_from_rend_format[ra.format];
- }
- }
+ input_assembly.topology = vk_topology[config.topology];
+ input_assembly.primitiveRestartEnable = VK_FALSE;
+ }
- vertex_input_info.vertexBindingDescriptionCount = binding_count;
- vertex_input_info.pVertexBindingDescriptions = vk_bindings;
- vertex_input_info.vertexAttributeDescriptionCount = attribute_count;
- vertex_input_info.pVertexAttributeDescriptions = vk_attributes;
+ VkGraphicsPipelineCreateInfo pipeline_info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
+ pipeline_info.pNext = &rendering_info;
+ pipeline_info.stageCount = shader_count;
+ pipeline_info.pStages = shader_stages;
+ pipeline_info.pVertexInputState = &vertex_input_info;
+ pipeline_info.pInputAssemblyState = &input_assembly;
+ pipeline_info.pViewportState = &viewport_state;
+ pipeline_info.pRasterizationState = &rasterizer;
+ pipeline_info.pMultisampleState = &multisampling;
+ pipeline_info.pColorBlendState = &color_blending;
+ pipeline_info.pDepthStencilState = &depth_stencil;
+ pipeline_info.pDynamicState = &dynamic_state;
+ pipeline_info.layout = vk_pipeline->layout;
+ pipeline_info.renderPass = VK_NULL_HANDLE;
- input_assembly.topology = vk_topology[config.topology];
- input_assembly.primitiveRestartEnable = VK_FALSE;
- }
+ CHECK_VK_RESULT(vkCreateGraphicsPipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &pipeline_info, vk_allocator, &vk_pipeline->handle));
- VkGraphicsPipelineCreateInfo pipeline_info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
- pipeline_info.pNext = &rendering_info;
- pipeline_info.stageCount = shader_count;
- pipeline_info.pStages = shader_stages;
- pipeline_info.pVertexInputState = &vertex_input_info;
- pipeline_info.pInputAssemblyState = &input_assembly;
- pipeline_info.pViewportState = &viewport_state;
- pipeline_info.pRasterizationState = &rasterizer;
- pipeline_info.pMultisampleState = &multisampling;
- pipeline_info.pColorBlendState = &color_blending;
- pipeline_info.pDepthStencilState = &depth_stencil;
- pipeline_info.pDynamicState = &dynamic_state;
- pipeline_info.layout = vk_pipeline->layout;
- pipeline_info.renderPass = VK_NULL_HANDLE;
+ if (vk_bindings) rfree(vk_bindings);
+ if (vk_attributes) rfree(vk_attributes);
- CHECK_VK_RESULT(vkCreateGraphicsPipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &pipeline_info, vk_allocator, &vk_pipeline->handle));
+ }
- if (vk_bindings) rfree(vk_bindings);
- if (vk_attributes) rfree(vk_attributes);
+ /* destroy shader modules */
+ for (i = 0; i < shader_count; ++i) {
+ if (shader_modules[i] != VK_NULL_HANDLE) {
+ vkDestroyShaderModule(vk_device.logical_device, shader_modules[i], vk_allocator);
+ }
+ }
- }
-
- /* destroy shader modules */
- for (uint32_t i = 0; i < shader_count; ++i) {
- if (shader_modules[i] != VK_NULL_HANDLE) {
- vkDestroyShaderModule(vk_device.logical_device, shader_modules[i], vk_allocator);
- }
- }
-
- return true;
+ return true;
}
-extern void
+void
rend_vk_pipeline_bind(RendPipeline pipeline)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- RendVkPipeline vk_pipeline = ctx->pipelines[pipeline->idx];
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- VkPipelineBindPoint bind_point = (pipeline->type == REND__PIPELINE_COMPUTE) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
- vkCmdBindPipeline(cmd, bind_point, vk_pipeline.handle);
- vkCmdBindDescriptorSets(cmd, bind_point, vk_pipeline.layout, 0, 1, &ctx->desc_set, 0, NULL);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ RendVkPipeline vk_pipeline = ctx->pipelines[pipeline->idx];
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ VkPipelineBindPoint bind_point = (pipeline->type == REND__PIPELINE_COMPUTE) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
+ vkCmdBindPipeline(cmd, bind_point, vk_pipeline.handle);
+ vkCmdBindDescriptorSets(cmd, bind_point, vk_pipeline.layout, 0, 1, &ctx->desc_set, 0, NULL);
}
-extern void
+void
rend_vk_pipeline_push_constants(RendPipeline pipeline, void *push_data, size_t size)
{
- RASSERT(pipeline && push_data);
+ RASSERT(pipeline && push_data);
- RendVk14Context *ctx = pipeline->backend_ctx;
- RendVkPipeline p = ctx->pipelines[pipeline->idx];
- RASSERT(size <= p.push_constants_range && "Size exceeds bound push constant range!");
- vkCmdPushConstants(ctx->frame_resources[ctx->frame_index].command_buffer, p.layout, VK_SHADER_STAGE_ALL, 0, size, push_data);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ RendVkPipeline p = ctx->pipelines[pipeline->idx];
+ RASSERT(size <= p.push_constants_range && "Size exceeds bound push constant range!");
+ vkCmdPushConstants(ctx->frame_resources[ctx->frame_index].command_buffer, p.layout, VK_SHADER_STAGE_ALL, 0, size, push_data);
}
-extern void
+void
rend_vk_pipeline_bind_vertex_buffer(RendPipeline pipeline, uint32_t binding, RendBuffer buffer, size_t offset)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
-
- VkDeviceSize vk_offset = (VkDeviceSize)offset;
- vkCmdBindVertexBuffers(cmd, binding, 1, &buf, &vk_offset);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+
+ VkDeviceSize vk_offset = (VkDeviceSize)offset;
+ vkCmdBindVertexBuffers(cmd, binding, 1, &buf, &vk_offset);
}
-extern void
+void
rend_vk_pipeline_bind_index_buffer(RendPipeline pipeline, RendBuffer buffer, size_t offset, RendIndexType index_type)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
-
- VkIndexType vk_index_type = (index_type == REND_INDEX_UINT16) ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
-
- vkCmdBindIndexBuffer(cmd, buf, (VkDeviceSize)offset, vk_index_type);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+
+ VkIndexType vk_index_type = (index_type == REND_INDEX_UINT16) ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
+
+ vkCmdBindIndexBuffer(cmd, buf, (VkDeviceSize)offset, vk_index_type);
}
-extern void
-rend_vk_descriptor_write_texture(void *ctx, RendTexture *texture, uint32_t binding, uint32_t slot)
+void
+rend_vk_descriptor_write_texture(RendContextHandle handle, RendTexture *texture, uint32_t binding, uint32_t slot)
{
- RendVk14Context *vk_ctx = (RendVk14Context*) ctx;
+ RendVk14Context *vk_ctx = (RendVk14Context *)handle;
- VkDescriptorImageInfo image_info = {
- .sampler = (VkSampler) texture->sampler,
- .imageView = (VkImageView) texture->view,
- .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- };
+ VkDescriptorImageInfo image_info = {
+ .sampler = (VkSampler)texture->sampler,
+ .imageView = (VkImageView)texture->view,
+ .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ };
- VkWriteDescriptorSet descriptor_write = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = vk_ctx->desc_set,
- .dstBinding = binding,
- .dstArrayElement = slot, // write texture to slot
- .descriptorCount = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .pImageInfo = &image_info,
- };
+ VkWriteDescriptorSet descriptor_write = {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = vk_ctx->desc_set,
+ .dstBinding = binding,
+ .dstArrayElement = slot, /* write texture to slot */
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &image_info,
+ };
- vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
+ vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
}
-extern void
+void
rend_vk_pipeline_dispatch(RendPipeline pipeline, uint32_t x, uint32_t y, uint32_t z)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDispatch(cmd, x, y, z);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ vkCmdDispatch(cmd, x, y, z);
}
-extern void
+void
rend_vk_pipeline_draw(RendPipeline pipeline, size_t count, uint32_t instance_count)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDraw(cmd, count, instance_count, 0, 0);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ vkCmdDraw(cmd, count, instance_count, 0, 0);
}
-extern void
+void
rend_vk_pipeline_draw_indexed(RendPipeline pipeline, uint32_t index_count, uint32_t first_index, int32_t vertex_offset, uint32_t instance_count)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, 0);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, 0);
}
-extern void
+void
rend_vk_pipeline_set_blend(RendPipeline pipeline, bool blend)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
- vk_pipeline->blend_enable = blend;
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
+ vk_pipeline->blend_enable = blend;
}
-extern void
-rend_vk_pipeline_draw_instanced(RendPipeline pipeline, uint32_t index_count, uint32_t instance_count)
-{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDraw(cmd, index_count, instance_count, 0, 0);
-}
-
-extern VKAPI_ATTR VkBool32 VKAPI_CALL
+VKAPI_ATTR VkBool32 VKAPI_CALL
rend_vk_debug_func(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data)
{
- switch (message_severity) {
- default:
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
- PERROR(callback_data->pMessage);
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
- PWARN(callback_data->pMessage);
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
- PINFO(callback_data->pMessage);
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
- PTRACE(callback_data->pMessage);
- break;
- }
- return VK_FALSE;
+ switch (message_severity) {
+ default:
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ PERROR(callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
+ PWARN(callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
+ PINFO(callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
+ PTRACE(callback_data->pMessage);
+ break;
+ }
+ return VK_FALSE;
}
@@ -1908,278 +1677,280 @@ rend_vk_debug_func(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDe
static void
rend_vk_pipeline_destroy(RendVkPipeline *pipeline)
{
- VkDevice dev = vk_device.logical_device;
+ VkDevice dev = vk_device.logical_device;
- if (pipeline->handle != VK_NULL_HANDLE) {
- vkDestroyPipeline(dev, pipeline->handle, vk_allocator);
- }
+ if (pipeline->handle != VK_NULL_HANDLE) {
+ vkDestroyPipeline(dev, pipeline->handle, vk_allocator);
+ }
- if (pipeline->layout != VK_NULL_HANDLE) {
- vkDestroyPipelineLayout(dev, pipeline->layout, vk_allocator);
- }
+ if (pipeline->layout != VK_NULL_HANDLE) {
+ vkDestroyPipelineLayout(dev, pipeline->layout, vk_allocator);
+ }
}
static void
rend_vk_swapchain_create(RendVk14Context *ctx, RendVkSwapchain *swapchain)
{
- RASSERT(ctx && "No context provided.");
- RASSERT(swapchain && "No swapchain provided.");
+ uint32_t i;
+ RASSERT(ctx && "No context provided.");
+ RASSERT(swapchain && "No swapchain provided.");
- VkSurfaceCapabilitiesKHR surface_caps;
- uint32_t width;
- uint32_t height;
- VkExtent2D swapchain_extent;
+ VkSurfaceCapabilitiesKHR surface_caps;
+ uint32_t width;
+ uint32_t height;
+ VkExtent2D swapchain_extent;
- vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_device.physical_device, ctx->surface, &surface_caps);
- width = surface_caps.currentExtent.width;
- height = surface_caps.currentExtent.height;
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_device.physical_device, ctx->surface, &surface_caps);
+ width = surface_caps.currentExtent.width;
+ height = surface_caps.currentExtent.height;
- /* 0xffffffff means the surface size is defined by the swapchain extent */
- if (width == 0xffffffffu || height == 0xffffffffu) {
- width = ctx->window ? ctx->window->width : 0;
- height = ctx->window ? ctx->window->height : 0;
- }
- if (width == 0) width = 1;
- if (height == 0) height = 1;
+ /* 0xffffffff means the surface size is defined by the swapchain extent */
+ if (width == 0xffffffffu || height == 0xffffffffu) {
+ width = ctx->window ? ctx->window->width : 0;
+ height = ctx->window ? ctx->window->height : 0;
+ }
+ if (width == 0) width = 1;
+ if (height == 0) height = 1;
- swapchain_extent = (VkExtent2D){width, height};
+ swapchain_extent = (VkExtent2D){width, height};
- ctx->max_frames_in_flight = REND_MIN_FRAMES_IN_FLIGHT;
+ ctx->max_frames_in_flight = REND_MIN_FRAMES_IN_FLIGHT;
- if (surface_caps.minImageCount > ctx->max_frames_in_flight) {
- ctx->max_frames_in_flight = surface_caps.minImageCount;
- }
+ if (surface_caps.minImageCount > ctx->max_frames_in_flight) {
+ ctx->max_frames_in_flight = surface_caps.minImageCount;
+ }
- /* maxImageCount == 0 means there is no maximum */
- if (surface_caps.maxImageCount > 0 && surface_caps.maxImageCount < ctx->max_frames_in_flight) {
- ctx->max_frames_in_flight = surface_caps.maxImageCount;
- }
- if (ctx->max_frames_in_flight > REND_MAX_FRAMES_IN_FLIGHT) {
- ctx->max_frames_in_flight = REND_MAX_FRAMES_IN_FLIGHT;
- }
- if (ctx->max_frames_in_flight == 0) {
- ctx->max_frames_in_flight = 1;
- }
+ /* maxImageCount == 0 means there is no maximum */
+ if (surface_caps.maxImageCount > 0 && surface_caps.maxImageCount < ctx->max_frames_in_flight) {
+ ctx->max_frames_in_flight = surface_caps.maxImageCount;
+ }
+ if (ctx->max_frames_in_flight > REND_MAX_FRAMES_IN_FLIGHT) {
+ ctx->max_frames_in_flight = REND_MAX_FRAMES_IN_FLIGHT;
+ }
+ if (ctx->max_frames_in_flight == 0) {
+ ctx->max_frames_in_flight = 1;
+ }
- bool found = false;
- for (uint32_t i = 0; i < vk_device.swapchain_support.format_count; i++) {
- VkSurfaceFormatKHR format = vk_device.swapchain_support.format[i];
+ bool found = false;
+ for (i = 0; i < vk_device.swapchain_support.format_count; i++) {
+ VkSurfaceFormatKHR format = vk_device.swapchain_support.format[i];
- /* preferred format */
- if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
- format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
- swapchain->format = format;
- found = true;
- break;
- }
- }
+ /* preferred format */
+ if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
+ format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
+ swapchain->format = format;
+ found = true;
+ break;
+ }
+ }
- /* default format */
- if (!found) {
- swapchain->format = vk_device.swapchain_support.format[0];
- }
+ /* default format */
+ if (!found) {
+ swapchain->format = vk_device.swapchain_support.format[0];
+ }
- /* NOTE: mailbox is probably the best for most applications
- * but I may want the ability to pick a different mode in
- * very niche circumstances.
- *
- * We also may want immediate mode if we want to disable VSYNC.
- */
+ /* NOTE: mailbox is probably the best for most applications
+ * but I may want the ability to pick a different mode in
+ * very niche circumstances.
+ *
+ * We also may want immediate mode if we want to disable VSYNC.
+ */
- /* default present mode */
- VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
- for (uint32_t i = 0; i < vk_device.swapchain_support.present_mode_count; i++) {
- VkPresentModeKHR pres = vk_device.swapchain_support.present_modes[i];
- /* preferred format is mailbox */
- if (ctx->vsync) {
- if (pres == VK_PRESENT_MODE_MAILBOX_KHR) {
- present_mode = pres;
- break;
- }
- } else {
- if (pres == VK_PRESENT_MODE_IMMEDIATE_KHR) {
- present_mode = pres;
- break;
- }
- }
- }
+ /* default present mode */
+ VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
+ for (i = 0; i < vk_device.swapchain_support.present_mode_count; i++) {
+ VkPresentModeKHR pres = vk_device.swapchain_support.present_modes[i];
+ /* preferred format is mailbox */
+ if (ctx->vsync) {
+ if (pres == VK_PRESENT_MODE_MAILBOX_KHR) {
+ present_mode = pres;
+ break;
+ }
+ } else {
+ if (pres == VK_PRESENT_MODE_IMMEDIATE_KHR) {
+ present_mode = pres;
+ break;
+ }
+ }
+ }
#ifdef REND_DEBUG
- static const char* present_mode_names[] = {
- [VK_PRESENT_MODE_IMMEDIATE_KHR] = "IMMEDIATE",
- [VK_PRESENT_MODE_MAILBOX_KHR] = "MAILBOX",
- [VK_PRESENT_MODE_FIFO_KHR] = "FIFO",
- [VK_PRESENT_MODE_FIFO_RELAXED_KHR] = "FIFO_RELAXED"
- };
- PDEBUG("Present mode %s was chosen!", present_mode_names[present_mode]);
+ static const char* present_mode_names[] = {
+ [VK_PRESENT_MODE_IMMEDIATE_KHR] = "IMMEDIATE",
+ [VK_PRESENT_MODE_MAILBOX_KHR] = "MAILBOX",
+ [VK_PRESENT_MODE_FIFO_KHR] = "FIFO",
+ [VK_PRESENT_MODE_FIFO_RELAXED_KHR] = "FIFO_RELAXED"
+ };
+ PDEBUG("Present mode %s was chosen!", present_mode_names[present_mode]);
#endif
- VkExtent2D min = surface_caps.minImageExtent;
- VkExtent2D max = surface_caps.maxImageExtent;
- swapchain_extent.width = (swapchain_extent.width < min.width) ? min.width : swapchain_extent.width;
- swapchain_extent.width = (swapchain_extent.width > max.width) ? max.width : swapchain_extent.width;
- swapchain_extent.height = (swapchain_extent.height < min.height) ? min.height : swapchain_extent.height;
- swapchain_extent.height = (swapchain_extent.height > max.height) ? max.height : swapchain_extent.height;
+ VkExtent2D min = surface_caps.minImageExtent;
+ VkExtent2D max = surface_caps.maxImageExtent;
+ swapchain_extent.width = (swapchain_extent.width < min.width) ? min.width : swapchain_extent.width;
+ swapchain_extent.width = (swapchain_extent.width > max.width) ? max.width : swapchain_extent.width;
+ swapchain_extent.height = (swapchain_extent.height < min.height) ? min.height : swapchain_extent.height;
+ swapchain_extent.height = (swapchain_extent.height > max.height) ? max.height : swapchain_extent.height;
- uint32_t img_count = surface_caps.minImageCount + 1;
- if (surface_caps.maxImageCount > 0 && img_count > surface_caps.maxImageCount) {
- img_count = surface_caps.maxImageCount;
- }
+ uint32_t img_count = surface_caps.minImageCount + 1;
+ if (surface_caps.maxImageCount > 0 && img_count > surface_caps.maxImageCount) {
+ img_count = surface_caps.maxImageCount;
+ }
- VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
- swapchain_create_info.surface = ctx->surface;
- swapchain_create_info.minImageCount = img_count;
- swapchain_create_info.imageFormat = swapchain->format.format;
- swapchain_create_info.imageColorSpace = swapchain->format.colorSpace;
- swapchain_create_info.imageExtent = swapchain_extent;
- swapchain_create_info.imageArrayLayers = 1;
- swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
+ swapchain_create_info.surface = ctx->surface;
+ swapchain_create_info.minImageCount = img_count;
+ swapchain_create_info.imageFormat = swapchain->format.format;
+ swapchain_create_info.imageColorSpace = swapchain->format.colorSpace;
+ swapchain_create_info.imageExtent = swapchain_extent;
+ swapchain_create_info.imageArrayLayers = 1;
+ swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- /* index sharing */
- if (vk_device.graphics_family_index != vk_device.present_family_index) {
- uint32_t queueFamilyIndices[] = {vk_device.graphics_family_index, vk_device.present_family_index};
- swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- swapchain_create_info.queueFamilyIndexCount = 2;
- swapchain_create_info.pQueueFamilyIndices = queueFamilyIndices;
- } else {
- swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchain_create_info.queueFamilyIndexCount = 0;
- swapchain_create_info.pQueueFamilyIndices = 0;
- }
+ /* index sharing */
+ if (vk_device.graphics_family_index != vk_device.present_family_index) {
+ uint32_t queueFamilyIndices[] = {vk_device.graphics_family_index, vk_device.present_family_index};
+ swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ swapchain_create_info.queueFamilyIndexCount = 2;
+ swapchain_create_info.pQueueFamilyIndices = queueFamilyIndices;
+ } else {
+ swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchain_create_info.queueFamilyIndexCount = 0;
+ swapchain_create_info.pQueueFamilyIndices = 0;
+ }
- swapchain_create_info.preTransform = surface_caps.currentTransform;
- swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- swapchain_create_info.presentMode = present_mode;
- swapchain_create_info.clipped = VK_TRUE;
- swapchain_create_info.oldSwapchain = 0;
+ swapchain_create_info.preTransform = surface_caps.currentTransform;
+ swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ swapchain_create_info.presentMode = present_mode;
+ swapchain_create_info.clipped = VK_TRUE;
+ swapchain_create_info.oldSwapchain = 0;
- if (vkCreateSwapchainKHR(vk_device.logical_device, &swapchain_create_info, vk_allocator, &swapchain->handle) != VK_SUCCESS) {
- REND__CRASH("Swapchain creation failed, you are probably trying to create two renderers for the same surface!");
- }
+ if (vkCreateSwapchainKHR(vk_device.logical_device, &swapchain_create_info, vk_allocator, &swapchain->handle) != VK_SUCCESS) {
+ REND__CRASH("Swapchain creation failed, you are probably trying to create two renderers for the same surface!");
+ }
- swapchain->image_count = 0;
- CHECK_VK_RESULT(vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, 0));
+ swapchain->image_count = 0;
+ CHECK_VK_RESULT(vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, 0));
- if (!swapchain->images) {
- swapchain->images = rmalloc(swapchain->image_count * sizeof *swapchain->images);
- }
- if (!swapchain->views) {
- swapchain->views = rmalloc(swapchain->image_count * sizeof *swapchain->views);
- }
+ if (!swapchain->images) {
+ swapchain->images = rmalloc(swapchain->image_count * sizeof(*swapchain->images));
+ }
+ if (!swapchain->views) {
+ swapchain->views = rmalloc(swapchain->image_count * sizeof(*swapchain->views));
+ }
- CHECK_VK_RESULT( vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, swapchain->images));
+ CHECK_VK_RESULT( vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, swapchain->images));
- for (uint32_t i = 0; i < swapchain->image_count; i++) {
+ for (i = 0; i < swapchain->image_count; i++) {
- VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
- view_info.image = swapchain->images[i];
- view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- view_info.format = swapchain->format.format;
- view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- view_info.subresourceRange.baseMipLevel = 0;
- view_info.subresourceRange.levelCount = 1;
- view_info.subresourceRange.baseArrayLayer = 0;
- view_info.subresourceRange.layerCount = 1;
+ VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
+ view_info.image = swapchain->images[i];
+ view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ view_info.format = swapchain->format.format;
+ view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ view_info.subresourceRange.baseMipLevel = 0;
+ view_info.subresourceRange.levelCount = 1;
+ view_info.subresourceRange.baseArrayLayer = 0;
+ view_info.subresourceRange.layerCount = 1;
- CHECK_VK_RESULT(vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, &swapchain->views[i]));
- }
+ CHECK_VK_RESULT(vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, &swapchain->views[i]));
+ }
- /* depth resources */
- if (!rend_vk_device_detect_depth_format(&vk_device)) {
- vk_device.depth_format = VK_FORMAT_UNDEFINED;
- PFATAL("Failed to find a supported depth buffer format!");
- }
+ /* depth resources */
+ if (!rend_vk_device_detect_depth_format(&vk_device)) {
+ vk_device.depth_format = VK_FORMAT_UNDEFINED;
+ PFATAL("Failed to find a supported depth buffer format!");
+ }
- swapchain->depth_attachment = rend_vk_image_create(
- vk_device.logical_device,
- VK_IMAGE_TYPE_2D,
- swapchain_extent.width, swapchain_extent.height,
- vk_device.depth_format,
- VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
- 1, // depth
- 1, // mip level
- 1, // layers
- VK_SAMPLE_COUNT_1_BIT,
- VK_SHARING_MODE_EXCLUSIVE
- );
+ swapchain->depth_attachment = rend_vk_image_create(
+ vk_device.logical_device,
+ VK_IMAGE_TYPE_2D,
+ swapchain_extent.width, swapchain_extent.height,
+ vk_device.depth_format,
+ VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ 1, /* depth */
+ 1, /* mip level */
+ 1, /* layers */
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_SHARING_MODE_EXCLUSIVE
+ );
- uint32_t mem_type = rend_vk_image_required_memory_type(&swapchain->depth_attachment);
- uint32_t depth_index = rend_vk_get_heap_index(mem_type, vk_device.device_index);
+ uint32_t mem_type = rend_vk_image_required_memory_type(&swapchain->depth_attachment);
+ uint32_t depth_index = rend_vk_get_heap_index(mem_type, vk_device.device_index);
- RASSERT(ctx);
- RendMemory depth_mem = rend_vk_arena_alloc(&ctx->arena_persistent, swapchain->depth_attachment.requirements.size, depth_index);
+ RASSERT(ctx);
+ RendMemory depth_mem = rend_vk_arena_alloc(&ctx->arena_persistent, swapchain->depth_attachment.requirements.size, depth_index);
- rend_vk_image_bind_memory(&swapchain->depth_attachment, &depth_mem);
+ rend_vk_image_bind_memory(&swapchain->depth_attachment, &depth_mem);
- rend_vk_image_view_create(
- &swapchain->depth_attachment,
- VK_IMAGE_VIEW_TYPE_2D,
- VK_IMAGE_ASPECT_DEPTH_BIT
- );
+ rend_vk_image_view_create(
+ &swapchain->depth_attachment,
+ VK_IMAGE_VIEW_TYPE_2D,
+ VK_IMAGE_ASPECT_DEPTH_BIT
+ );
- swapchain->extent = swapchain_extent;
+ swapchain->extent = swapchain_extent;
}
static void
rend_vk_swapchain_destroy(RendVk14Context *ctx, RendVkSwapchain *swapchain)
{
- if (!swapchain || swapchain->handle == VK_NULL_HANDLE) return;
- RASSERT(vk_device.logical_device);
+ uint32_t i;
+ if (!swapchain || swapchain->handle == VK_NULL_HANDLE) return;
+ RASSERT(vk_device.logical_device);
- rend_vk_image_destroy(&swapchain->depth_attachment);
+ rend_vk_image_destroy(&swapchain->depth_attachment);
- if (swapchain->views) {
- for (uint32_t i = 0; i < swapchain->image_count; i++) {
- vkDestroyImageView(vk_device.logical_device, swapchain->views[i], vk_allocator);
- }
- rfree(swapchain->views);
- swapchain->views = 0;
- }
+ if (swapchain->views) {
+ for (i = 0; i < swapchain->image_count; i++) {
+ vkDestroyImageView(vk_device.logical_device, swapchain->views[i], vk_allocator);
+ }
+ rfree(swapchain->views);
+ swapchain->views = 0;
+ }
- if (swapchain->images) {
- rfree(swapchain->images);
- swapchain->images = 0;
- }
+ if (swapchain->images) {
+ rfree(swapchain->images);
+ swapchain->images = 0;
+ }
- swapchain->image_count = 0;
- vkDestroySwapchainKHR(vk_device.logical_device, swapchain->handle, vk_allocator);
- swapchain->handle = VK_NULL_HANDLE;
+ swapchain->image_count = 0;
+ vkDestroySwapchainKHR(vk_device.logical_device, swapchain->handle, vk_allocator);
+ swapchain->handle = VK_NULL_HANDLE;
}
static VkShaderModule
rend_vk_shader_module_create(const void *data, size_t size)
{
- VkShaderModuleCreateInfo create_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
- create_info.codeSize = size;
- create_info.pCode = (const uint32_t *)data;
+ VkShaderModuleCreateInfo create_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
+ create_info.codeSize = size;
+ create_info.pCode = (const uint32_t *)data;
+
+ VkShaderModule module;
+ VkResult res = vkCreateShaderModule(vk_device.logical_device, &create_info, vk_allocator, &module);
- VkShaderModule module;
- VkResult res = vkCreateShaderModule(vk_device.logical_device, &create_info, vk_allocator, &module);
+ if (res != VK_SUCCESS) {
+ PWARN("Failed to create shader module for %p", data);
+ return VK_NULL_HANDLE;
+ }
- if (res != VK_SUCCESS) {
- PWARN("Failed to create shader module for %p", data);
- return VK_NULL_HANDLE;
- }
-
- return module;
+ return module;
}
static uint32_t
rend_vk_get_heap_index(uint32_t memory_type_bits, uint32_t preferred_index)
{
- if (memory_type_bits & (1u << preferred_index)) {
- return preferred_index;
- }
+ uint32_t i;
+ if (memory_type_bits & (1u << preferred_index)) {
+ return preferred_index;
+ }
- for (uint32_t i = 0; i < 32; i++) {
- if (memory_type_bits & (1u << i)) {
- return i;
- }
- }
+ for (i = 0; i < 32; i++) {
+ if (memory_type_bits & (1u << i)) {
+ return i;
+ }
+ }
- return UINT32_MAX;
+ return UINT32_MAX;
}
diff --git a/Rend/rend_vk_allocator.c b/Rend/rend_vk_allocator.c
deleted file mode 100644
index 737e566..0000000
--- a/Rend/rend_vk_allocator.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include <stdint.h>
-#include <vulkan/vulkan.h>
-#include <vulkan/vulkan_core.h>
-
-typedef struct RendVkAllocatorState {
- const char *name;
-} RendVkAllocatorState;
-
-typedef struct RendVkAllocatorHeader {
- uint32_t offset;
-} RendVkAllocatorHeader;
-
-static bool rend_vk_allocator_is_power_of_two(uintptr_t x);
-static void *rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
-static void *rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
-static void rend_vk_allocator_free(void *pUserData, void *pMemory);
-static void rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
-static void rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
-
-static VkAllocationCallbacks rend_vk_allocator = {
- .pfnAllocation = rend_vk_allocator_alloc,
- .pfnReallocation = rend_vk_allocator_realloc,
- .pfnFree = rend_vk_allocator_free,
- .pfnInternalAllocation = rend_vk_allocator_internal_notification,
- .pfnInternalFree = rend_vk_allocator_free_notification,
-};
-
-static const char* rend_vk_allocator_scope_name[] = {
- [VK_SYSTEM_ALLOCATION_SCOPE_CACHE] = "Cache",
- [VK_SYSTEM_ALLOCATION_SCOPE_COMMAND] = "Command",
- [VK_SYSTEM_ALLOCATION_SCOPE_DEVICE] = "Device",
- [VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE] = "Instance",
- [VK_SYSTEM_ALLOCATION_SCOPE_OBJECT] = "Object",
-};
-
-
-static bool
-rend_vk_allocator_is_power_of_two(uintptr_t x)
-{
- return (x & (x-1)) == 0;
-}
-
-static uintptr_t
-rend_vk_allocator_align_forward(uintptr_t ptr, size_t align)
-{
- uintptr_t p, a, modulo;
-
- assert(rend_vk_allocator_is_power_of_two(align));
-
- p = ptr;
- a = (uintptr_t)align;
- modulo = p & (a-1);
-
- if (modulo != 0) {
- p += a - modulo;
- }
- return p;
-}
-
-static void*
-rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
-{
- size_t total_size = size + alignment + sizeof (RendVkAllocatorHeader);
- uint8_t *raw_ptr = malloc(total_size);
- uintptr_t unaligned_addr = (uintptr_t)(raw_ptr + sizeof (RendVkAllocatorHeader));
-
- uint8_t *aligned_ptr = (uint8_t*)rend_vk_allocator_align_forward(unaligned_addr, alignment);
- RendVkAllocatorHeader *header = (RendVkAllocatorHeader*) aligned_ptr - 1;
- header->offset = aligned_ptr - raw_ptr;
-
- PDEBUG("[VK_ALLOC] %p - bytes %lu with alignment %lu - scope %s",
- aligned_ptr, size, alignment, rend_vk_allocator_scope_name[allocationScope]);
-
- return (void*) aligned_ptr;
-}
-
-static void*
-rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
-{
- if (!pOriginal) return rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
- if (size == 0) {
- rend_vk_allocator_free(pUserData, pOriginal);
- return NULL;
- }
- void *new_ptr = rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
- if (!new_ptr) return NULL;
- memcpy(new_ptr, pOriginal, size);
- rend_vk_allocator_free(pUserData, pOriginal);
- return new_ptr;
-}
-
-static void
-rend_vk_allocator_free(void *pUserData, void *pMemory)
-{
- RendVkAllocatorHeader *ptr = pMemory;
- uint8_t *raw_ptr = pMemory;
- raw_ptr -= (ptr-1)->offset;
-
- PDEBUG("[VK_FREE] %p", ptr);
- free(raw_ptr);
-}
-
-static void
-rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
-{
- PDEBUG("[VK_ALLOC_INTERNAL] bytes %lu - scope %s",
- size, rend_vk_allocator_scope_name[allocationScope]);
-
-}
-
-static void
-rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
-{
- PDEBUG("[VK_FREE_INTERNAL] bytes %lu - scope %s",
- size, rend_vk_allocator_scope_name[allocationScope]);
-}
diff --git a/Rend/rend_vk_arena.c b/Rend/rend_vk_arena.c
deleted file mode 100644
index b936be4..0000000
--- a/Rend/rend_vk_arena.c
+++ /dev/null
@@ -1,264 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include "rend_vk_internal.h"
-#include <vulkan/vulkan_core.h>
-
-/* arenas need to be subdivided into blocks
- * just like pools because we must respect page size */
-typedef struct RendVkPage {
- RendMemory memory;
- size_t head;
- int reserved;
-} RendVkPage;
-
-typedef struct RendVkPagedArena {
- RendVkPage *page_darr;
- uint32_t capacity;
- uint32_t elements;
-} RendVkPagedArena;
-
-struct RendVkArenaAllocator {
- VkAllocationCallbacks *allocator;
- size_t *heap_idx_alloc_sizes; // allocation size per type of memory available on the gpu
- RendVkPagedArena *mem_arenas; // memory arena per type of memory available on the gpu
- VkDevice logical_device; // virtual device
- VkPhysicalDevice physical_device; // physical device we are allocating memory from
- VkDeviceSize gpu_alignment; // allocations must respect the physical limitations of the gpu
- VkDeviceSize block_min_size; // minimum size per block of memory
- uint64_t total_allocations;
- uint32_t heap_index_count;
- VkPhysicalDeviceMemoryProperties properties; // useful for getting properties per heap index
-};
-
-static RendVkArenaAllocator
-rend_vk_arena_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator)
-{
- RendVkArenaAllocator arena = {
- .allocator = allocator,
- .heap_idx_alloc_sizes = NULL,
- .logical_device = logical_device,
- .physical_device = physical_device,
- .gpu_alignment = 0,
- .block_min_size = 0,
- .total_allocations = 0,
- .heap_index_count = 0,
- .mem_arenas = 0,
- };
-
- VkPhysicalDeviceMemoryProperties mem_properties;
- vkGetPhysicalDeviceMemoryProperties(physical_device, &mem_properties);
- arena.properties = mem_properties;
-
- uint32_t count = mem_properties.memoryTypeCount;
- arena.heap_index_count = count;
-
- arena.heap_idx_alloc_sizes = rmalloc(count * sizeof *arena.heap_idx_alloc_sizes);
- memset(arena.heap_idx_alloc_sizes, 0, count * sizeof *arena.heap_idx_alloc_sizes);
-
- arena.mem_arenas = rmalloc(count * sizeof *arena.mem_arenas);
- for (uint32_t u = 0; u < count; ++u) {
- arena.mem_arenas[u].capacity = 2;
- arena.mem_arenas[u].elements = 0;
- arena.mem_arenas[u].page_darr = rmalloc(2 * sizeof *arena.mem_arenas[u].page_darr);
- memset(arena.mem_arenas[u].page_darr, 0, 2 * sizeof *arena.mem_arenas[u].page_darr);
- }
-
- VkDeviceSize alignment = device_limits.bufferImageGranularity;
- if (device_limits.nonCoherentAtomSize > alignment) {
- alignment = device_limits.nonCoherentAtomSize;
- }
-
- arena.gpu_alignment = alignment;
- arena.block_min_size = arena.gpu_alignment * 10;
-
- return arena;
-}
-
-static uint32_t
-rend_vk_arena_add_page(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index, bool fit_to_alloc)
-{
- VkDeviceSize new_arena_size = fit_to_alloc ? size : (size * 2);
- new_arena_size = (new_arena_size < arena->block_min_size) ? arena->block_min_size : new_arena_size;
-
- VkMemoryPropertyFlags properties = arena->properties.memoryTypes[heap_index].propertyFlags;
-
- RendVkPage page = (RendVkPage) {0};
- page.head = 0;
-
- VkMemoryAllocateFlagsInfo flags_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
- .pNext = NULL,
- .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
- .deviceMask = 0
- };
-
- VkMemoryAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .allocationSize = new_arena_size,
- .pNext = &flags_info,
- .memoryTypeIndex = heap_index
- };
-
- page.memory = (RendMemory) {0};
- page.memory.offset = 0;
- page.memory.size = new_arena_size;
-
- VkResult res = vkAllocateMemory(arena->logical_device, &alloc_info, arena->allocator, (VkDeviceMemory*) &page.memory.device_memory);
- if (res != VK_SUCCESS) {
- return UINT32_MAX;
- }
-
- if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
- vkMapMemory(
- arena->logical_device,
- (VkDeviceMemory) page.memory.device_memory,
- 0, // Offset inside VkDeviceMemory!!!1
- new_arena_size, // MUST match alloc_info.allocationSize and NOT raw size!!!
- 0,
- &page.memory.host_mapped_memory
- );
- }
-
- RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index];
-
- if (mem_arena->elements + 1 >= mem_arena->capacity) {
- uint32_t new_capacity = mem_arena->capacity * 2;
- void *new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof *mem_arena->page_darr);
- if (!new_darr) {
- vkFreeMemory(arena->logical_device, (VkDeviceMemory) page.memory.device_memory, arena->allocator);
- return UINT32_MAX;
- }
- mem_arena->page_darr = new_darr;
- mem_arena->capacity = new_capacity;
- }
-
- uint32_t page_index = mem_arena->elements;
- mem_arena->page_darr[mem_arena->elements++] = page;
-
- arena->total_allocations++;
-
- return page_index;
-}
-
-static RendMemory
-rend_vk_arena_alloc(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index)
-{
- assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
- RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index];
-
- VkMemoryPropertyFlags properties = arena->properties.memoryTypes[heap_index].propertyFlags;
-
- /* align to allocation to fit page size */
- VkDeviceSize align = arena->gpu_alignment;
- VkDeviceSize aligned_size = (size + align - 1) & ~(align - 1);
-
- /* check if fits in previous blocks */
- int whole_page = !(properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- uint32_t page_idx = UINT32_MAX;
- for (uint32_t u = 0; u < mem_arena->elements; ++u) {
- RendVkPage page = mem_arena->page_darr[u];
- int valid = (whole_page) ? (page.head == 0) : 1;
- if ((page.head + aligned_size <= page.memory.size) && valid) {
- page_idx = u;
- break;
- }
- }
-
- /* page not found, add new page */
- if (page_idx == UINT32_MAX) {
- page_idx = rend_vk_arena_add_page(arena, aligned_size, heap_index, whole_page);
- if (page_idx == UINT32_MAX) {
- REND__CRASH("[REND_VK] Arena page allocation failed!");
- }
- }
-
- mem_arena->page_darr[page_idx].reserved = whole_page;
-
- RendMemory memory = {
- .device_memory = mem_arena->page_darr[page_idx].memory.device_memory,
- .size = aligned_size,
- .offset = mem_arena->page_darr[page_idx].head,
- .host_mapped_memory = 0,
- .heap_index = heap_index,
- .id = page_idx,
- };
-
- if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
- memory.host_mapped_memory = mem_arena->page_darr[page_idx].memory.host_mapped_memory + memory.offset;
- }
-
- /* move head */
- arena->heap_idx_alloc_sizes[heap_index] += aligned_size;
- mem_arena->page_darr[page_idx].head += aligned_size;
- return memory;
-}
-
-
-static void
-rend_vk_arena_clear(RendVkArenaAllocator *arena, uint32_t heap_index)
-{
- assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
- RendVkPagedArena mem_arena = arena->mem_arenas[heap_index];
- if (mem_arena.page_darr) {
- for (uint32_t u = 0; u < mem_arena.elements; ++u) {
- mem_arena.page_darr[u].head = 0;
- mem_arena.page_darr[u].reserved = 0;
- }
- }
-}
-
-static void
-rend_vk_arena_clear_all(RendVkArenaAllocator *arena)
-{
- for (uint32_t u = 0; u < arena->properties.memoryTypeCount; ++u) {
- rend_vk_arena_clear(arena, u);
- }
-}
-
-static void
-rend_vk_arena_shrink(RendVkArenaAllocator *arena, uint32_t heap_index)
-{
- assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
- RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index];
- if (mem_arena->capacity > 4) {
- uint32_t new_capacity = mem_arena->capacity / 2;
- void *new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof *mem_arena->page_darr);
- if (!new_darr) return;
- mem_arena->page_darr = new_darr;
- mem_arena->capacity = new_capacity;
- }
-}
-
-static void
-rend_vk_arena_destroy(RendVkArenaAllocator *arena)
-{
- if (arena->mem_arenas) {
- for (size_t u = 0; u < arena->heap_index_count; ++u) {
- RendVkPagedArena *mem_arena = &arena->mem_arenas[u];
- for (uint32_t p = 0; p < mem_arena->elements; ++p) {
-
- RendMemory memory = mem_arena->page_darr[p].memory ;
- if (memory.offset == 0) {
- if (memory.host_mapped_memory) {
- vkUnmapMemory(arena->logical_device, (VkDeviceMemory) memory.device_memory);
- }
- vkFreeMemory(arena->logical_device, (VkDeviceMemory) memory.device_memory, arena->allocator);
- } else {
- PWARN("[REND_VK] Attempted to free memory with an offset!");
- }
-
- }
- if (mem_arena->page_darr) {
- rfree(mem_arena->page_darr);
- mem_arena->page_darr = 0;
- }
- }
- rfree(arena->mem_arenas);
- arena->mem_arenas = 0;
- }
- if (arena->heap_idx_alloc_sizes) {
- rfree(arena->heap_idx_alloc_sizes);
- arena->heap_idx_alloc_sizes = 0;
- }
- memset(arena, 0, sizeof *arena);
-}
diff --git a/Rend/rend_vk_device.c b/Rend/rend_vk_device.c
deleted file mode 100644
index 6f25557..0000000
--- a/Rend/rend_vk_device.c
+++ /dev/null
@@ -1,377 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include "rend_vk_internal.h"
-#include <vulkan/vulkan_core.h>
-
-// struct RendDevice {
-// bool anisotropy_support;
-// bool bindless_support;
-// };
-
-
-static bool
-rend_vk_device_create(VkSurfaceKHR surface, RendSpecs specs, RendVkDevice *out_device, uint32_t (*score_devices)(RendVkDevice *, RendSpecs, const char **, uint32_t))
-{
- assert(out_device);
-
- uint32_t device_count = 0;
- CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, VK_NULL_HANDLE));
- if (device_count == 0) {
- PFATAL("No GPU with Vulkan support found!");
- return false;
- }
-
- VkPhysicalDevice physical_devices[device_count];
- CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, physical_devices));
-
- const char *extension_names[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
-
- uint32_t best_score = 1; // 1 so that devices that do not meet specs get ignored
- RendVkDevice best_device = {0};
-
- PDEBUG("DEVICE SCORE");
- for (uint32_t i = 0; i < device_count; i++) {
-
- /* populate device struct */
- RendVkDevice scoring = {0};
- scoring.surface = surface;
- scoring.physical_device = physical_devices[i];
- vkGetPhysicalDeviceProperties(physical_devices[i], &scoring.properties);
- vkGetPhysicalDeviceFeatures(physical_devices[i], &scoring.features);
- vkGetPhysicalDeviceMemoryProperties(physical_devices[i], &scoring.memory);
-
- /* score device */
- uint32_t dev_score = score_devices(&scoring, specs, extension_names, 1);
- PDEBUG("%-20.20s %5d", scoring.properties.deviceName, dev_score);
- if (dev_score >= best_score) {
- if (best_device.swapchain_support.format) {
- rfree(best_device.swapchain_support.format);
- }
- if (best_device.swapchain_support.present_modes) {
- rfree(best_device.swapchain_support.present_modes);
- }
- best_score = dev_score;
- best_device = scoring;
- } else {
- if (scoring.swapchain_support.format) {
- rfree(scoring.swapchain_support.format);
- }
- if (scoring.swapchain_support.present_modes) {
- rfree(scoring.swapchain_support.present_modes);
- }
- }
-
- }
-
- if (best_score > 1) {
- PDEBUG("Driver version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.driverVersion), VK_VERSION_MINOR(best_device.properties.driverVersion), VK_VERSION_PATCH(best_device.properties.driverVersion));
- PDEBUG("Vulkan API version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.apiVersion), VK_VERSION_MINOR(best_device.properties.apiVersion), VK_VERSION_PATCH(best_device.properties.apiVersion));
- }
-
- if (!best_device.physical_device) {
- PERROR("No physical devices were found that meet specs!");
- return false;
- }
-
- /* update out device to use best selected device */
- *out_device = best_device;
-
- PDEBUG("Graphics Family Index: %u", out_device->graphics_family_index);
- PDEBUG("Present Family Index: %u", out_device->present_family_index);
- PDEBUG("Compute Family Index: %u", out_device->compute_family_index);
- PDEBUG("Transfer Family Index: %u", out_device->transfer_family_index);
-
- bool present_shares_graphics_q = out_device->present_family_index == out_device->graphics_family_index;
- bool transfer_shares_graphics_q = out_device->transfer_family_index == out_device->graphics_family_index;
-
- uint32_t index_count = 1;
- if (!present_shares_graphics_q) index_count++;
- if (!transfer_shares_graphics_q) index_count++;
-
- uint32_t indices[index_count];
- uint8_t index = 0;
-
- indices[index++] = out_device->graphics_family_index;
- if (!present_shares_graphics_q) {
- indices[index++] = out_device->present_family_index;
- }
- if (!transfer_shares_graphics_q) {
- indices[index++] = out_device->transfer_family_index;
- }
-
- VkDeviceQueueCreateInfo q_create_info[index_count];
-
- float queue_priority[2] = {1.0f, 1.0f};
- for (uint32_t i = 0; i < index_count; i++) {
- q_create_info[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- q_create_info[i].queueFamilyIndex = indices[i];
- // TODO: request 2 queues when possible
- // q_create_info[i].queueCount = (indices[i] == out_device->graphics_family_index) ? 2 : 1;
- q_create_info[i].queueCount = 1;
- q_create_info[i].flags = 0;
- q_create_info[i].pNext = 0;
- q_create_info[i].pQueuePriorities = queue_priority;
- }
-
- // TODO: driven by the same config as the check_specs function
- // used earlier
-
- VkPhysicalDeviceFeatures device_features = {0};
- device_features.samplerAnisotropy = specs.sampler_anisotropy;
- device_features.fillModeNonSolid = VK_TRUE;
- device_features.shaderInt64 = VK_TRUE;
-
- // vulkan 1.3 features (dynamic rendering + sync2)
- VkPhysicalDeviceVulkan13Features vk13_features = {0};
- vk13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
- vk13_features.dynamicRendering = VK_TRUE;
- vk13_features.synchronization2 = VK_TRUE;
-
- // vulkan 1.2 features (timeline semaphores)
- VkPhysicalDeviceVulkan12Features vk12_features = {0};
- vk12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
- vk12_features.timelineSemaphore = VK_TRUE;
-
- // vk12_features.descriptorIndexing = VK_TRUE;
- // vk12_features.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE;
- vk12_features.descriptorBindingPartiallyBound = VK_TRUE;
- // vk12_features.descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE;
- // vk12_features.descriptorBindingVariableDescriptorCount = VK_TRUE;
- // vk12_features.runtimeDescriptorArray = VK_TRUE;
-
- vk12_features.bufferDeviceAddress = VK_TRUE;
- vk12_features.scalarBlockLayout = VK_TRUE;
- vk12_features.pNext = &vk13_features;
-
- // vulkan 1.1 features (draw parameters)
- VkPhysicalDeviceVulkan11Features vk11_features = {0};
- vk11_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
- vk11_features.shaderDrawParameters = VK_TRUE;
- vk11_features.pNext = &vk12_features;
-
- VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
- device_create_info.pNext = &vk11_features;
- device_create_info.queueCreateInfoCount = index_count;
- device_create_info.pQueueCreateInfos = q_create_info;
- device_create_info.pEnabledFeatures = &device_features;
- device_create_info.enabledExtensionCount = 1;
-
- const char *extention_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
- device_create_info.ppEnabledExtensionNames = &extention_names;
-
- /* deprecated and ignored */
- device_create_info.enabledLayerCount = 0;
- device_create_info.ppEnabledLayerNames = 0;
-
- CHECK_VK_RESULT(vkCreateDevice(out_device->physical_device, &device_create_info, vk_allocator, &out_device->logical_device));
-
- vkGetDeviceQueue(out_device->logical_device, out_device->graphics_family_index, 0, &out_device->graphics_queue);
- vkGetDeviceQueue(out_device->logical_device, out_device->present_family_index, 0, &out_device->present_queue);
- vkGetDeviceQueue(out_device->logical_device, out_device->transfer_family_index, 0, &out_device->transfer_queue);
-
- PDEBUG("GRAPHICS | PRESENT | COMPUTE | TRANSFER | DEVICE");
- PDEBUG(" %02d | %02d | %02d | %02d | %s",
- out_device->graphics_family_index != UINT32_MAX,
- out_device->present_family_index != UINT32_MAX,
- out_device->compute_family_index != UINT32_MAX,
- out_device->transfer_family_index != UINT32_MAX,
- out_device->properties.deviceName);
-
- VkPhysicalDeviceMemoryProperties mem_props = out_device->memory;
- out_device->device_index = UINT32_MAX;
- for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) {
- if ((mem_props.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
- out_device->device_index = i;
- break;
- }
- }
-
- VkMemoryPropertyFlags host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- out_device->host_index = UINT32_MAX;
- for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) {
- if ((mem_props.memoryTypes[i].propertyFlags & host_flags) == host_flags) {
- out_device->host_index = i;
- break;
- }
- }
-
- PDEBUG("Device local heap: %2u", out_device->device_index);
- PDEBUG("Host mapped heap: %2u", out_device->host_index);
- return true;
-}
-
-static void
-rend_vk_device_destroy(RendVkDevice *device)
-{
- RASSERT(device && device->logical_device, "Invalid or uninitialized device.");
-
- vkDeviceWaitIdle(device->logical_device); // safe when destroying device
- vkDestroyDevice(device->logical_device, vk_allocator);
- if (device->swapchain_support.format) rfree(vk_device.swapchain_support.format);
- if (device->swapchain_support.present_modes) rfree(vk_device.swapchain_support.present_modes);
-
- *device = (RendVkDevice){0};
-}
-
-static void
-rend_vk_device_query_swapchain_support(RendVkDevice *device)
-{
- RASSERT(device->physical_device, "Invalid device pointer.");
-
- /* surface capabilities */
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physical_device, device->surface, &device->swapchain_support.capabilities));
-
- /* surface formats */
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, VK_NULL_HANDLE));
- if (device->swapchain_support.format_count != 0) {
- if (!device->swapchain_support.format) {
- device->swapchain_support.format = rmalloc(device->swapchain_support.format_count * sizeof(*device->swapchain_support.format));
- }
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, device->swapchain_support.format));
- }
-
- /* present modes */
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, VK_NULL_HANDLE));
- if (device->swapchain_support.present_mode_count != 0) {
- if (!device->swapchain_support.present_modes) {
- device->swapchain_support.present_modes = rmalloc(device->swapchain_support.present_mode_count * sizeof(*device->swapchain_support.present_modes));
- }
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, device->swapchain_support.present_modes));
- }
-}
-
-static bool
-rend_vk_device_detect_depth_format(RendVkDevice *device)
-{
- const uint64_t candidate_count = 3;
- VkFormat candidates[] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT};
-
- uint32_t flags = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
- for (uint32_t i = 0; i < candidate_count; i++) {
- VkFormatProperties properties;
- vkGetPhysicalDeviceFormatProperties(device->physical_device, candidates[i], &properties);
- if ((properties.linearTilingFeatures & flags) == flags) {
- device->depth_format = candidates[i];
- return true;
- } else if ((properties.optimalTilingFeatures & flags) == flags) {
- device->depth_format = candidates[i];
- return true;
- }
- }
-
- return false;
-}
-
-static uint32_t
-rend_vk_device_score_default(RendVkDevice *device, RendSpecs minimum_specs, const char **required_extensions, uint32_t required_extension_count)
-{
- /* NOTE: When we score the device we will also check for specs. Not meeting a spec
- * leads to 0 score and continue. We will assume device already contains some information
- * about properties when this function is called. */
-
- uint32_t score = 0;
-
- device->graphics_family_index = UINT32_MAX;
- device->present_family_index = UINT32_MAX;
- device->compute_family_index = UINT32_MAX;
- device->transfer_family_index = UINT32_MAX;
-
- if (minimum_specs.discrete_gpu) {
- if (device->properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
- return 0;
- }
- }
-
- uint32_t q_family_count = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, VK_NULL_HANDLE);
-
- VkQueueFamilyProperties q_family[q_family_count];
- vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, q_family);
-
- uint8_t min_transfer_score = 255;
- for (uint32_t i = 0; i < q_family_count; i++) {
-
- uint8_t transfer_score = 0;
- if (q_family[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
- device->graphics_family_index = i;
- transfer_score++;
- }
-
- if (q_family[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
- device->compute_family_index = i;
- transfer_score++;
- }
-
- if (q_family[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
- // take the index if the transfer score is minimal
- if (transfer_score <= min_transfer_score) {
- min_transfer_score = transfer_score;
- device->transfer_family_index = i;
- }
- }
-
- VkBool32 supports_present = VK_FALSE;
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceSupportKHR(device->physical_device, i, device->surface, &supports_present));
- if (supports_present) {
- device->present_family_index = i;
- }
- }
-
- if ( (minimum_specs.graphics && device->graphics_family_index == UINT32_MAX) ||
- (minimum_specs.present && device->present_family_index == UINT32_MAX) ||
- (minimum_specs.compute && device->compute_family_index == UINT32_MAX) ||
- (minimum_specs.transfer && device->transfer_family_index == UINT32_MAX)) {
- return 0;
- }
-
- // swapchain support
- rend_vk_device_query_swapchain_support(device);
-
- if (device->swapchain_support.format_count < 1 || device->swapchain_support.present_mode_count < 1) {
- return 0;
- }
-
- // check for extension specs
- if (required_extensions) {
- uint32_t available_extentions_count = 0;
- VkExtensionProperties *available_extentions = NULL;
- CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, VK_NULL_HANDLE));
-
- if (available_extentions_count != 0) {
-
- available_extentions = rmalloc(available_extentions_count * sizeof(*available_extentions));
- CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, available_extentions));
-
- bool overall_found = true;
- for (uint32_t i = 0; i < required_extension_count; ++i) {
- bool found = false;
- for (uint32_t j = 0; j < available_extentions_count; ++j) {
- if (strcmp(required_extensions[i], available_extentions[j].extensionName) == 0) {
- found = true;
- break;
- }
- }
- if (!found) {
- overall_found = false;
- break;
- }
- }
-
- rfree(available_extentions);
- if (!overall_found) {
- return 0;
- }
- }
- }
-
- if (minimum_specs.sampler_anisotropy && !device->features.samplerAnisotropy) {
- return 0;
- }
-
- score = 10;
- if (device->properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
- score += 1000;
- }
-
- return score;
-}
diff --git a/Rend/rend_vk_image.c b/Rend/rend_vk_image.c
deleted file mode 100644
index e842bf0..0000000
--- a/Rend/rend_vk_image.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include "rend_vk_internal.h"
-#include <vulkan/vulkan_core.h>
-
-struct RendVkImage {
- VkDevice logical_device;
- VkImage handle;
- VkImageView view;
-
- VkMemoryRequirements requirements;
-
- VkImageType img_type;
- uint32_t width, height;
- VkFormat format;
- VkImageTiling tiling;
- VkImageUsageFlags usage;
- uint32_t depth;
- uint32_t mip_levels;
- uint32_t layers;
- VkSampleCountFlags sample_count_flags;
- VkSharingMode sharing_mode;
-
- RendMemory *memory;
-};
-
-static RendVkImage
-rend_vk_image_create(VkDevice logical_device, VkImageType img_type, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
- VkImageUsageFlags usage, VkMemoryPropertyFlags memory_flags, uint32_t depth, uint32_t mip_levels, uint32_t layers,
- VkSampleCountFlags sample_count_flags, VkSharingMode sharing_mode)
-{
- RendVkImage image = {
- .handle = VK_NULL_HANDLE,
- .memory = VK_NULL_HANDLE,
- .logical_device = logical_device,
- .img_type = img_type,
- .width = width,
- .height = height,
- .format = format,
- .tiling = tiling,
- .usage = usage,
- .depth = depth,
- .mip_levels = mip_levels,
- .layers = layers,
- .sample_count_flags = sample_count_flags,
- .sharing_mode = sharing_mode
- };
-
- VkImageCreateInfo img_create_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
- img_create_info.imageType = img_type;
- img_create_info.extent.width = width;
- img_create_info.extent.height = height;
- img_create_info.extent.depth = depth;
- img_create_info.mipLevels = mip_levels;
- img_create_info.arrayLayers = layers;
- img_create_info.format = format;
- img_create_info.tiling = tiling;
- img_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- img_create_info.usage = usage;
- img_create_info.samples = sample_count_flags;
- img_create_info.sharingMode = sharing_mode;
-
-
- if (vkCreateImage(logical_device, &img_create_info, vk_allocator, &image.handle) != VK_SUCCESS) {
- return image;
- }
-
- return image;
-}
-
-static uint32_t
-rend_vk_image_required_memory_type(RendVkImage *img)
-{
- assert(img->memory == NULL && "Image already bound to memory");
- VkMemoryRequirements memory_requirements = {0};
- vkGetImageMemoryRequirements(img->logical_device, img->handle, &memory_requirements);
- img->requirements = memory_requirements;
- return memory_requirements.memoryTypeBits;
-}
-
-static void
-rend_vk_image_bind_memory(RendVkImage *img, RendMemory *memory)
-{
- assert(img->memory == NULL && "Image already bound to memory");
- vkBindImageMemory(img->logical_device, img->handle, (VkDeviceMemory) memory->device_memory, memory->offset);
-}
-
-static void
-rend_vk_image_destroy(RendVkImage *img)
-{
- if (img->view) {
- vkDestroyImageView(img->logical_device, img->view, vk_allocator);
- img->view = 0;
- }
-
- if (img->handle) {
- vkDestroyImage(img->logical_device, img->handle, vk_allocator);
- img->handle = 0;
- }
-}
-
-static void
-rend_vk_image_view_create(RendVkImage *image, VkImageViewType view_type, VkImageAspectFlags view_aspect_flags)
-{
- VkImageViewCreateInfo view_create_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = image->handle,
- .format = image->format,
- .viewType = view_type,
- .subresourceRange.aspectMask = view_aspect_flags,
- .subresourceRange.baseMipLevel = 0, // offset starts at 0
- .subresourceRange.levelCount = image->mip_levels, // number of mips
- .subresourceRange.baseArrayLayer = 0, // offset starts at 0
- .subresourceRange.layerCount = image->layers, // number of layers
- };
-
- vkCreateImageView(image->logical_device, &view_create_info, vk_allocator, &image->view);
-}
-
-static uint64_t
-rend_vk_image_address(RendVkImage *image)
-{
- assert(image->memory == NULL && "Image already bound to memory");
- return (uint64_t) image->memory->device_memory + image->memory->offset;
-}
diff --git a/Rend/rend_vk_internal.c b/Rend/rend_vk_internal.c
new file mode 100644
index 0000000..4f1679f
--- /dev/null
+++ b/Rend/rend_vk_internal.c
@@ -0,0 +1,1014 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_core.h>
+
+#include "rend.h"
+#include "rend_internal.h"
+
+#define CHECK_VK_RESULT(r) \
+{ \
+ assert(r == VK_SUCCESS && __LINE__); \
+}
+
+typedef struct RendVkImage RendVkImage;
+typedef struct RendVkArenaAllocator RendVkArenaAllocator;
+
+typedef struct {
+ VkSurfaceCapabilitiesKHR capabilities;
+ VkSurfaceFormatKHR *format;
+ VkPresentModeKHR *present_modes;
+ uint32_t format_count;
+ uint32_t present_mode_count;
+} RendVkSwapchainSupport;
+
+typedef struct {
+ VkDevice logical_device;
+
+ VkPhysicalDeviceProperties properties;
+ VkPhysicalDeviceMemoryProperties memory;
+ VkPhysicalDevice physical_device;
+ VkPhysicalDeviceFeatures features;
+
+ VkSurfaceKHR surface;
+ RendVkSwapchainSupport swapchain_support;
+ VkFormat depth_format;
+
+ VkQueue graphics_queue;
+ VkQueue present_queue;
+ VkQueue compute_queue;
+ VkQueue transfer_queue;
+ uint32_t graphics_family_index;
+ uint32_t present_family_index;
+ uint32_t compute_family_index;
+ uint32_t transfer_family_index;
+
+ uint32_t host_index;
+ uint32_t device_index;
+} RendVkDevice;
+
+typedef struct RendVkPage {
+ RendMemory memory;
+ size_t head;
+ int reserved;
+} RendVkPage;
+
+typedef struct RendVkPagedArena {
+ RendVkPage *page_darr;
+ uint32_t capacity;
+ uint32_t elements;
+} RendVkPagedArena;
+
+struct RendVkArenaAllocator {
+ VkAllocationCallbacks *allocator;
+ RendVkPagedArena *mem_arenas;
+ VkDevice logical_device;
+ VkPhysicalDevice physical_device;
+ VkDeviceSize gpu_alignment;
+ VkDeviceSize block_min_size;
+ uint32_t heap_index_count;
+ VkPhysicalDeviceMemoryProperties properties;
+};
+
+struct RendVkImage {
+ VkDevice logical_device;
+ VkImage handle;
+ VkImageView view;
+
+ VkMemoryRequirements requirements;
+
+ VkImageType img_type;
+ uint32_t width, height;
+ VkFormat format;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ uint32_t depth;
+ uint32_t mip_levels;
+ uint32_t layers;
+ VkSampleCountFlags sample_count_flags;
+ VkSharingMode sharing_mode;
+
+ RendMemory *memory;
+};
+
+typedef struct RendVkAllocatorState {
+ const char *name;
+} RendVkAllocatorState;
+
+typedef struct RendVkAllocatorHeader {
+ uint32_t offset;
+} RendVkAllocatorHeader;
+
+static bool rend_vk_allocator_is_power_of_two(uintptr_t x);
+static uintptr_t rend_vk_allocator_align_forward(uintptr_t ptr, size_t align);
+static void *rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
+static void *rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
+static void rend_vk_allocator_free(void *pUserData, void *pMemory);
+static void rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
+static void rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
+
+static VkAllocationCallbacks rend_vk_allocator = {
+ .pfnAllocation = rend_vk_allocator_alloc,
+ .pfnReallocation = rend_vk_allocator_realloc,
+ .pfnFree = rend_vk_allocator_free,
+ .pfnInternalAllocation = rend_vk_allocator_internal_notification,
+ .pfnInternalFree = rend_vk_allocator_free_notification,
+};
+
+static const char *rend_vk_allocator_scope_name[] = {
+ [VK_SYSTEM_ALLOCATION_SCOPE_CACHE] = "Cache",
+ [VK_SYSTEM_ALLOCATION_SCOPE_COMMAND] = "Command",
+ [VK_SYSTEM_ALLOCATION_SCOPE_DEVICE] = "Device",
+ [VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE] = "Instance",
+ [VK_SYSTEM_ALLOCATION_SCOPE_OBJECT] = "Object",
+};
+
+static VkInstance vk_instance = 0;
+static VkDebugUtilsMessengerEXT vk_debug_messenger = 0;
+static RendVkDevice vk_device = {0};
+static VkAllocationCallbacks *vk_allocator = &rend_vk_allocator;
+
+static VkFormat vk_format_from_rend_format[] = {
+ [REND_FORMAT_R8_UNORM] = VK_FORMAT_R8_UNORM,
+ [REND_FORMAT_R8G8_UNORM] = VK_FORMAT_R8G8_UNORM,
+ [REND_FORMAT_R8G8B8A8_UNORM] = VK_FORMAT_R8G8B8A8_UNORM,
+ [REND_FORMAT_B8G8R8A8_UNORM] = VK_FORMAT_B8G8R8A8_UNORM,
+ [REND_FORMAT_R8G8B8A8_SRGB] = VK_FORMAT_R8G8B8A8_SRGB,
+ [REND_FORMAT_B8G8R8A8_SRGB] = VK_FORMAT_B8G8R8A8_SRGB,
+ [REND_FORMAT_R32_SFLOAT] = VK_FORMAT_R32_SFLOAT,
+ [REND_FORMAT_R32G32_SFLOAT] = VK_FORMAT_R32G32_SFLOAT,
+ [REND_FORMAT_R32G32B32_SFLOAT] = VK_FORMAT_R32G32B32_SFLOAT,
+ [REND_FORMAT_R32G32B32A32_SFLOAT]= VK_FORMAT_R32G32B32A32_SFLOAT,
+ [REND_FORMAT_R16_SFLOAT] = VK_FORMAT_R16_SFLOAT,
+ [REND_FORMAT_R16G16_SFLOAT] = VK_FORMAT_R16G16_SFLOAT,
+ [REND_FORMAT_R16G16B16A16_SFLOAT]= VK_FORMAT_R16G16B16A16_SFLOAT,
+ [REND_FORMAT_R32_UINT] = VK_FORMAT_R32_UINT,
+ [REND_FORMAT_R32_SINT] = VK_FORMAT_R32_SINT,
+ [REND_FORMAT_R32G32B32A32_UINT] = VK_FORMAT_R32G32B32A32_UINT,
+ [REND_FORMAT_R16G16B16A16_UINT] = VK_FORMAT_R16G16B16A16_UINT,
+ [REND_FORMAT_R8G8B8A8_UINT] = VK_FORMAT_R8G8B8A8_UINT,
+ [REND_FORMAT_D32_SFLOAT] = VK_FORMAT_D32_SFLOAT,
+ [REND_FORMAT_D24_UNORM_S8_UINT] = VK_FORMAT_D24_UNORM_S8_UINT,
+ [REND_FORMAT_D32_SFLOAT_S8_UINT] = VK_FORMAT_D32_SFLOAT_S8_UINT,
+};
+
+static VkPrimitiveTopology vk_topology[] = {
+ [REND_TOPOLOGY_TRIANGLE_LIST] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+ [REND_TOPOLOGY_TRIANGLE_STRIP] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
+ [REND_TOPOLOGY_LINE_LIST] = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
+ [REND_TOPOLOGY_LINE_STRIP] = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
+ [REND_TOPOLOGY_POINT_LIST] = VK_PRIMITIVE_TOPOLOGY_POINT_LIST
+};
+
+static VkPolygonMode vk_polymode[] = {
+ [REND_POLYGON_MODE_FILL] = VK_POLYGON_MODE_FILL,
+ [REND_POLYGON_MODE_LINE] = VK_POLYGON_MODE_LINE,
+ [REND_POLYGON_MODE_POINT] = VK_POLYGON_MODE_POINT,
+};
+
+static VkCullModeFlags vk_cullflags[] = {
+ [REND_CULL_MODE_NONE] = VK_CULL_MODE_NONE,
+ [REND_CULL_MODE_FRONT] = VK_CULL_MODE_FRONT_BIT,
+ [REND_CULL_MODE_BACK] = VK_CULL_MODE_BACK_BIT,
+ [REND_CULL_MODE_FRONT_AND_BACK] = VK_CULL_MODE_FRONT_AND_BACK,
+};
+
+static const VkBufferUsageFlags vk_buffer_usage[] = {
+ [REND_BUFFER_VERTEX] = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ [REND_BUFFER_INDEX] = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ [REND_BUFFER_UNIFORM] = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ [REND_BUFFER_STORAGE] = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ [REND_BUFFER_TRANSFER] = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+};
+
+static const VkShaderStageFlagBits vk_pipeline_stages[][3] = {
+ [REND__PIPELINE_GRAPHICS] = { VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT },
+ [REND__PIPELINE_COMPUTE] = { VK_SHADER_STAGE_COMPUTE_BIT },
+ [REND__PIPELINE_MESH] = { VK_SHADER_STAGE_MESH_BIT_EXT, VK_SHADER_STAGE_FRAGMENT_BIT },
+};
+
+/* --- host allocator --- */
+
+static bool
+rend_vk_allocator_is_power_of_two(uintptr_t x)
+{
+ return (x & (x - 1)) == 0;
+}
+
+static uintptr_t
+rend_vk_allocator_align_forward(uintptr_t ptr, size_t align)
+{
+ uintptr_t p, a, modulo;
+
+ assert(rend_vk_allocator_is_power_of_two(align));
+
+ p = ptr;
+ a = (uintptr_t)align;
+ modulo = p & (a - 1);
+
+ if (modulo != 0) {
+ p += a - modulo;
+ }
+ return p;
+}
+
+static void *
+rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
+{
+ size_t total_size;
+ uint8_t *raw_ptr;
+ uintptr_t unaligned_addr;
+ uint8_t *aligned_ptr;
+ RendVkAllocatorHeader *header;
+
+ (void)pUserData;
+ total_size = size + alignment + sizeof(RendVkAllocatorHeader);
+ raw_ptr = malloc(total_size);
+ unaligned_addr = (uintptr_t)(raw_ptr + sizeof(RendVkAllocatorHeader));
+
+ aligned_ptr = (uint8_t *)rend_vk_allocator_align_forward(unaligned_addr, alignment);
+ header = (RendVkAllocatorHeader *)aligned_ptr - 1;
+ header->offset = aligned_ptr - raw_ptr;
+
+ PDEBUG("[VK_ALLOC] %p - bytes %lu with alignment %lu - scope %s",
+ aligned_ptr, size, alignment, rend_vk_allocator_scope_name[allocationScope]);
+
+ return (void *)aligned_ptr;
+}
+
+static void *
+rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
+{
+ void *new_ptr;
+
+ if (!pOriginal)
+ return rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
+ if (size == 0) {
+ rend_vk_allocator_free(pUserData, pOriginal);
+ return NULL;
+ }
+ new_ptr = rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
+ if (!new_ptr)
+ return NULL;
+ memcpy(new_ptr, pOriginal, size);
+ rend_vk_allocator_free(pUserData, pOriginal);
+ return new_ptr;
+}
+
+static void
+rend_vk_allocator_free(void *pUserData, void *pMemory)
+{
+ RendVkAllocatorHeader *ptr;
+ uint8_t *raw_ptr;
+
+ (void)pUserData;
+ if (!pMemory)
+ return;
+ ptr = pMemory;
+ raw_ptr = pMemory;
+ raw_ptr -= (ptr - 1)->offset;
+
+ PDEBUG("[VK_FREE] %p", ptr);
+ free(raw_ptr);
+}
+
+static void
+rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
+{
+ (void)pUserData;
+ (void)allocationType;
+ PDEBUG("[VK_ALLOC_INTERNAL] bytes %lu - scope %s",
+ size, rend_vk_allocator_scope_name[allocationScope]);
+}
+
+static void
+rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
+{
+ (void)pUserData;
+ (void)allocationType;
+ PDEBUG("[VK_FREE_INTERNAL] bytes %lu - scope %s",
+ size, rend_vk_allocator_scope_name[allocationScope]);
+}
+
+/* --- device --- */
+
+static void
+rend_vk_device_query_swapchain_support(RendVkDevice *device)
+{
+ RASSERT(device->physical_device, "Invalid device pointer.");
+
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physical_device, device->surface, &device->swapchain_support.capabilities));
+
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, VK_NULL_HANDLE));
+ if (device->swapchain_support.format_count != 0) {
+ if (!device->swapchain_support.format) {
+ device->swapchain_support.format = rmalloc(device->swapchain_support.format_count * sizeof(*device->swapchain_support.format));
+ }
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, device->swapchain_support.format));
+ }
+
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, VK_NULL_HANDLE));
+ if (device->swapchain_support.present_mode_count != 0) {
+ if (!device->swapchain_support.present_modes) {
+ device->swapchain_support.present_modes = rmalloc(device->swapchain_support.present_mode_count * sizeof(*device->swapchain_support.present_modes));
+ }
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, device->swapchain_support.present_modes));
+ }
+}
+
+static uint32_t
+rend_vk_device_score_default(RendVkDevice *device, RendSpecs minimum_specs, const char **required_extensions, uint32_t required_extension_count)
+{
+ uint32_t score;
+ uint32_t q_family_count;
+ uint8_t min_transfer_score;
+ uint32_t i;
+
+ score = 0;
+
+ device->graphics_family_index = UINT32_MAX;
+ device->present_family_index = UINT32_MAX;
+ device->compute_family_index = UINT32_MAX;
+ device->transfer_family_index = UINT32_MAX;
+
+ if (minimum_specs.discrete_gpu) {
+ if (device->properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
+ return 0;
+ }
+ }
+
+ q_family_count = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, VK_NULL_HANDLE);
+
+ {
+ VkQueueFamilyProperties q_family[q_family_count];
+
+ vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, q_family);
+
+ min_transfer_score = 255;
+ for (i = 0; i < q_family_count; i++) {
+ uint8_t transfer_score;
+ VkBool32 supports_present;
+
+ transfer_score = 0;
+ if (q_family[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ device->graphics_family_index = i;
+ transfer_score++;
+ }
+
+ if (q_family[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
+ device->compute_family_index = i;
+ transfer_score++;
+ }
+
+ if (q_family[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
+ if (transfer_score <= min_transfer_score) {
+ min_transfer_score = transfer_score;
+ device->transfer_family_index = i;
+ }
+ }
+
+ supports_present = VK_FALSE;
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceSupportKHR(device->physical_device, i, device->surface, &supports_present));
+ if (supports_present) {
+ device->present_family_index = i;
+ }
+ }
+ }
+
+ if ((minimum_specs.graphics && device->graphics_family_index == UINT32_MAX) ||
+ (minimum_specs.present && device->present_family_index == UINT32_MAX) ||
+ (minimum_specs.compute && device->compute_family_index == UINT32_MAX) ||
+ (minimum_specs.transfer && device->transfer_family_index == UINT32_MAX)) {
+ return 0;
+ }
+
+ rend_vk_device_query_swapchain_support(device);
+
+ if (device->swapchain_support.format_count < 1 || device->swapchain_support.present_mode_count < 1) {
+ return 0;
+ }
+
+ if (required_extensions) {
+ uint32_t available_extentions_count;
+ VkExtensionProperties *available_extentions;
+
+ available_extentions_count = 0;
+ available_extentions = NULL;
+ CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, VK_NULL_HANDLE));
+
+ if (available_extentions_count != 0) {
+ bool overall_found;
+ uint32_t j;
+
+ available_extentions = rmalloc(available_extentions_count * sizeof(*available_extentions));
+ CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, available_extentions));
+
+ overall_found = true;
+ for (i = 0; i < required_extension_count; ++i) {
+ bool found;
+
+ found = false;
+ for (j = 0; j < available_extentions_count; ++j) {
+ if (strcmp(required_extensions[i], available_extentions[j].extensionName) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ overall_found = false;
+ break;
+ }
+ }
+
+ rfree(available_extentions);
+ if (!overall_found) {
+ return 0;
+ }
+ }
+ }
+
+ if (minimum_specs.sampler_anisotropy && !device->features.samplerAnisotropy) {
+ return 0;
+ }
+
+ score = 10;
+ if (device->properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
+ score += 1000;
+ }
+
+ return score;
+}
+
+static bool
+rend_vk_device_create(VkSurfaceKHR surface, RendSpecs specs, RendVkDevice *out_device)
+{
+ uint32_t device_count;
+ const char *extension_names[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
+ uint32_t best_score;
+ RendVkDevice best_device;
+ uint32_t i;
+ bool present_shares_graphics_q;
+ bool transfer_shares_graphics_q;
+ uint32_t index_count;
+ uint8_t index;
+ float queue_priority[2];
+ VkPhysicalDeviceFeatures device_features;
+ VkPhysicalDeviceVulkan13Features vk13_features;
+ VkPhysicalDeviceVulkan12Features vk12_features;
+ VkPhysicalDeviceVulkan11Features vk11_features;
+ VkDeviceCreateInfo device_create_info;
+ const char *extention_names;
+ VkPhysicalDeviceMemoryProperties mem_props;
+ VkMemoryPropertyFlags host_flags;
+
+ assert(out_device);
+
+ device_count = 0;
+ CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, VK_NULL_HANDLE));
+ if (device_count == 0) {
+ PFATAL("No GPU with Vulkan support found!");
+ return false;
+ }
+
+ {
+ VkPhysicalDevice physical_devices[device_count];
+
+ CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, physical_devices));
+
+ best_score = 1;
+ best_device = (RendVkDevice){0};
+
+ PDEBUG("DEVICE SCORE");
+ for (i = 0; i < device_count; i++) {
+ RendVkDevice scoring;
+ uint32_t dev_score;
+
+ scoring = (RendVkDevice){0};
+ scoring.surface = surface;
+ scoring.physical_device = physical_devices[i];
+ vkGetPhysicalDeviceProperties(physical_devices[i], &scoring.properties);
+ vkGetPhysicalDeviceFeatures(physical_devices[i], &scoring.features);
+ vkGetPhysicalDeviceMemoryProperties(physical_devices[i], &scoring.memory);
+
+ dev_score = rend_vk_device_score_default(&scoring, specs, extension_names, 1);
+ PDEBUG("%-20.20s %5d", scoring.properties.deviceName, dev_score);
+ if (dev_score >= best_score) {
+ if (best_device.swapchain_support.format) {
+ rfree(best_device.swapchain_support.format);
+ }
+ if (best_device.swapchain_support.present_modes) {
+ rfree(best_device.swapchain_support.present_modes);
+ }
+ best_score = dev_score;
+ best_device = scoring;
+ } else {
+ if (scoring.swapchain_support.format) {
+ rfree(scoring.swapchain_support.format);
+ }
+ if (scoring.swapchain_support.present_modes) {
+ rfree(scoring.swapchain_support.present_modes);
+ }
+ }
+ }
+ }
+
+ if (best_score > 1) {
+ PDEBUG("Driver version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.driverVersion), VK_VERSION_MINOR(best_device.properties.driverVersion), VK_VERSION_PATCH(best_device.properties.driverVersion));
+ PDEBUG("Vulkan API version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.apiVersion), VK_VERSION_MINOR(best_device.properties.apiVersion), VK_VERSION_PATCH(best_device.properties.apiVersion));
+ }
+
+ if (!best_device.physical_device) {
+ PERROR("No physical devices were found that meet specs!");
+ return false;
+ }
+
+ *out_device = best_device;
+
+ PDEBUG("Graphics Family Index: %u", out_device->graphics_family_index);
+ PDEBUG("Present Family Index: %u", out_device->present_family_index);
+ PDEBUG("Compute Family Index: %u", out_device->compute_family_index);
+ PDEBUG("Transfer Family Index: %u", out_device->transfer_family_index);
+
+ present_shares_graphics_q = out_device->present_family_index == out_device->graphics_family_index;
+ transfer_shares_graphics_q = out_device->transfer_family_index == out_device->graphics_family_index;
+
+ index_count = 1;
+ if (!present_shares_graphics_q)
+ index_count++;
+ if (!transfer_shares_graphics_q)
+ index_count++;
+
+ {
+ uint32_t indices[index_count];
+ VkDeviceQueueCreateInfo q_create_info[index_count];
+
+ index = 0;
+ indices[index++] = out_device->graphics_family_index;
+ if (!present_shares_graphics_q) {
+ indices[index++] = out_device->present_family_index;
+ }
+ if (!transfer_shares_graphics_q) {
+ indices[index++] = out_device->transfer_family_index;
+ }
+
+ queue_priority[0] = 1.0f;
+ queue_priority[1] = 1.0f;
+ for (i = 0; i < index_count; i++) {
+ q_create_info[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ q_create_info[i].queueFamilyIndex = indices[i];
+ q_create_info[i].queueCount = 1;
+ q_create_info[i].flags = 0;
+ q_create_info[i].pNext = 0;
+ q_create_info[i].pQueuePriorities = queue_priority;
+ }
+
+ device_features = (VkPhysicalDeviceFeatures){0};
+ device_features.samplerAnisotropy = specs.sampler_anisotropy;
+ device_features.fillModeNonSolid = VK_TRUE;
+ device_features.shaderInt64 = VK_TRUE;
+
+ vk13_features = (VkPhysicalDeviceVulkan13Features){0};
+ vk13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
+ vk13_features.dynamicRendering = VK_TRUE;
+ vk13_features.synchronization2 = VK_TRUE;
+
+ vk12_features = (VkPhysicalDeviceVulkan12Features){0};
+ vk12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
+ vk12_features.timelineSemaphore = VK_TRUE;
+ vk12_features.descriptorBindingPartiallyBound = VK_TRUE;
+ vk12_features.bufferDeviceAddress = VK_TRUE;
+ vk12_features.scalarBlockLayout = VK_TRUE;
+ vk12_features.pNext = &vk13_features;
+
+ vk11_features = (VkPhysicalDeviceVulkan11Features){0};
+ vk11_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
+ vk11_features.shaderDrawParameters = VK_TRUE;
+ vk11_features.pNext = &vk12_features;
+
+ device_create_info = (VkDeviceCreateInfo){ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+ device_create_info.pNext = &vk11_features;
+ device_create_info.queueCreateInfoCount = index_count;
+ device_create_info.pQueueCreateInfos = q_create_info;
+ device_create_info.pEnabledFeatures = &device_features;
+ device_create_info.enabledExtensionCount = 1;
+
+ extention_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+ device_create_info.ppEnabledExtensionNames = &extention_names;
+
+ device_create_info.enabledLayerCount = 0;
+ device_create_info.ppEnabledLayerNames = 0;
+
+ CHECK_VK_RESULT(vkCreateDevice(out_device->physical_device, &device_create_info, vk_allocator, &out_device->logical_device));
+ }
+
+ vkGetDeviceQueue(out_device->logical_device, out_device->graphics_family_index, 0, &out_device->graphics_queue);
+ vkGetDeviceQueue(out_device->logical_device, out_device->present_family_index, 0, &out_device->present_queue);
+ vkGetDeviceQueue(out_device->logical_device, out_device->transfer_family_index, 0, &out_device->transfer_queue);
+
+ PDEBUG("GRAPHICS | PRESENT | COMPUTE | TRANSFER | DEVICE");
+ PDEBUG(" %02d | %02d | %02d | %02d | %s",
+ out_device->graphics_family_index != UINT32_MAX,
+ out_device->present_family_index != UINT32_MAX,
+ out_device->compute_family_index != UINT32_MAX,
+ out_device->transfer_family_index != UINT32_MAX,
+ out_device->properties.deviceName);
+
+ mem_props = out_device->memory;
+ out_device->device_index = UINT32_MAX;
+ for (i = 0; i < mem_props.memoryTypeCount; i++) {
+ if ((mem_props.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
+ out_device->device_index = i;
+ break;
+ }
+ }
+
+ host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ out_device->host_index = UINT32_MAX;
+ for (i = 0; i < mem_props.memoryTypeCount; i++) {
+ if ((mem_props.memoryTypes[i].propertyFlags & host_flags) == host_flags) {
+ out_device->host_index = i;
+ break;
+ }
+ }
+
+ PDEBUG("Device local heap: %2u", out_device->device_index);
+ PDEBUG("Host mapped heap: %2u", out_device->host_index);
+ return true;
+}
+
+static void
+rend_vk_device_destroy(RendVkDevice *device)
+{
+ RASSERT(device && device->logical_device, "Invalid or uninitialized device.");
+
+ vkDeviceWaitIdle(device->logical_device);
+ vkDestroyDevice(device->logical_device, vk_allocator);
+ if (device->swapchain_support.format)
+ rfree(vk_device.swapchain_support.format);
+ if (device->swapchain_support.present_modes)
+ rfree(vk_device.swapchain_support.present_modes);
+
+ *device = (RendVkDevice){0};
+}
+
+static bool
+rend_vk_device_detect_depth_format(RendVkDevice *device)
+{
+ const uint64_t candidate_count = 3;
+ VkFormat candidates[] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT};
+ uint32_t flags;
+ uint32_t i;
+ VkFormatProperties properties;
+
+ flags = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ for (i = 0; i < candidate_count; i++) {
+ vkGetPhysicalDeviceFormatProperties(device->physical_device, candidates[i], &properties);
+ if ((properties.linearTilingFeatures & flags) == flags) {
+ device->depth_format = candidates[i];
+ return true;
+ } else if ((properties.optimalTilingFeatures & flags) == flags) {
+ device->depth_format = candidates[i];
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* --- arena --- */
+
+static RendVkArenaAllocator
+rend_vk_arena_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator)
+{
+ RendVkArenaAllocator arena;
+ VkPhysicalDeviceMemoryProperties mem_properties;
+ VkDeviceSize alignment;
+ uint32_t count;
+ uint32_t u;
+
+ arena = (RendVkArenaAllocator){
+ .allocator = allocator,
+ .logical_device = logical_device,
+ .physical_device = physical_device,
+ .gpu_alignment = 0,
+ .block_min_size = 0,
+ .heap_index_count = 0,
+ .mem_arenas = 0,
+ };
+
+ vkGetPhysicalDeviceMemoryProperties(physical_device, &mem_properties);
+ arena.properties = mem_properties;
+
+ count = mem_properties.memoryTypeCount;
+ arena.heap_index_count = count;
+
+ arena.mem_arenas = rmalloc(count * sizeof(*arena.mem_arenas));
+ for (u = 0; u < count; ++u) {
+ arena.mem_arenas[u].capacity = 2;
+ arena.mem_arenas[u].elements = 0;
+ arena.mem_arenas[u].page_darr = rmalloc(2 * sizeof(*arena.mem_arenas[u].page_darr));
+ memset(arena.mem_arenas[u].page_darr, 0, 2 * sizeof(*arena.mem_arenas[u].page_darr));
+ }
+
+ alignment = device_limits.bufferImageGranularity;
+ if (device_limits.nonCoherentAtomSize > alignment) {
+ alignment = device_limits.nonCoherentAtomSize;
+ }
+
+ arena.gpu_alignment = alignment;
+ arena.block_min_size = arena.gpu_alignment * 10;
+
+ return arena;
+}
+
+static uint32_t
+rend_vk_arena_add_page(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index, bool fit_to_alloc)
+{
+ VkDeviceSize new_arena_size;
+ VkMemoryPropertyFlags properties;
+ RendVkPage page;
+ VkMemoryAllocateFlagsInfo flags_info;
+ VkMemoryAllocateInfo alloc_info;
+ VkResult res;
+ RendVkPagedArena *mem_arena;
+ uint32_t page_index;
+ uint32_t new_capacity;
+ void *new_darr;
+
+ new_arena_size = fit_to_alloc ? size : (size * 2);
+ new_arena_size = (new_arena_size < arena->block_min_size) ? arena->block_min_size : new_arena_size;
+
+ properties = arena->properties.memoryTypes[heap_index].propertyFlags;
+
+ page = (RendVkPage){0};
+ page.head = 0;
+
+ flags_info = (VkMemoryAllocateFlagsInfo){
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
+ .pNext = NULL,
+ .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
+ .deviceMask = 0
+ };
+
+ alloc_info = (VkMemoryAllocateInfo){
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .allocationSize = new_arena_size,
+ .pNext = &flags_info,
+ .memoryTypeIndex = heap_index
+ };
+
+ page.memory = (RendMemory){0};
+ page.memory.offset = 0;
+ page.memory.size = new_arena_size;
+
+ res = vkAllocateMemory(arena->logical_device, &alloc_info, arena->allocator, (VkDeviceMemory *)&page.memory.device_memory);
+ if (res != VK_SUCCESS) {
+ return UINT32_MAX;
+ }
+
+ if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
+ vkMapMemory(
+ arena->logical_device,
+ (VkDeviceMemory)page.memory.device_memory,
+ 0,
+ new_arena_size,
+ 0,
+ &page.memory.host_mapped_memory
+ );
+ }
+
+ mem_arena = &arena->mem_arenas[heap_index];
+
+ if (mem_arena->elements + 1 >= mem_arena->capacity) {
+ new_capacity = mem_arena->capacity * 2;
+ new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof(*mem_arena->page_darr));
+ if (!new_darr) {
+ vkFreeMemory(arena->logical_device, (VkDeviceMemory)page.memory.device_memory, arena->allocator);
+ return UINT32_MAX;
+ }
+ mem_arena->page_darr = new_darr;
+ mem_arena->capacity = new_capacity;
+ }
+
+ page_index = mem_arena->elements;
+ mem_arena->page_darr[mem_arena->elements++] = page;
+
+ return page_index;
+}
+
+static RendMemory
+rend_vk_arena_alloc(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index)
+{
+ RendVkPagedArena *mem_arena;
+ VkMemoryPropertyFlags properties;
+ VkDeviceSize align;
+ VkDeviceSize aligned_size;
+ int whole_page;
+ uint32_t page_idx;
+ uint32_t u;
+ RendVkPage page;
+ int valid;
+ RendMemory memory;
+
+ assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
+ mem_arena = &arena->mem_arenas[heap_index];
+
+ properties = arena->properties.memoryTypes[heap_index].propertyFlags;
+
+ align = arena->gpu_alignment;
+ aligned_size = (size + align - 1) & ~(align - 1);
+
+ whole_page = !(properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ page_idx = UINT32_MAX;
+ for (u = 0; u < mem_arena->elements; ++u) {
+ page = mem_arena->page_darr[u];
+ valid = (whole_page) ? (page.head == 0) : 1;
+ if ((page.head + aligned_size <= page.memory.size) && valid) {
+ page_idx = u;
+ break;
+ }
+ }
+
+ if (page_idx == UINT32_MAX) {
+ page_idx = rend_vk_arena_add_page(arena, aligned_size, heap_index, whole_page);
+ if (page_idx == UINT32_MAX) {
+ REND__CRASH("[REND_VK] Arena page allocation failed!");
+ }
+ }
+
+ mem_arena->page_darr[page_idx].reserved = whole_page;
+
+ memory = (RendMemory){
+ .device_memory = mem_arena->page_darr[page_idx].memory.device_memory,
+ .size = aligned_size,
+ .offset = mem_arena->page_darr[page_idx].head,
+ .host_mapped_memory = 0,
+ .heap_index = heap_index,
+ .id = page_idx,
+ };
+
+ if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
+ memory.host_mapped_memory = mem_arena->page_darr[page_idx].memory.host_mapped_memory + memory.offset;
+ }
+
+ mem_arena->page_darr[page_idx].head += aligned_size;
+ return memory;
+}
+
+static void
+rend_vk_arena_clear(RendVkArenaAllocator *arena, uint32_t heap_index)
+{
+ RendVkPagedArena mem_arena;
+ uint32_t u;
+
+ assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
+ mem_arena = arena->mem_arenas[heap_index];
+ if (mem_arena.page_darr) {
+ for (u = 0; u < mem_arena.elements; ++u) {
+ mem_arena.page_darr[u].head = 0;
+ mem_arena.page_darr[u].reserved = 0;
+ }
+ }
+}
+
+static void
+rend_vk_arena_clear_all(RendVkArenaAllocator *arena)
+{
+ uint32_t u;
+
+ for (u = 0; u < arena->properties.memoryTypeCount; ++u) {
+ rend_vk_arena_clear(arena, u);
+ }
+}
+
+static void
+rend_vk_arena_destroy(RendVkArenaAllocator *arena)
+{
+ size_t u;
+ uint32_t p;
+ RendVkPagedArena *mem_arena;
+ RendMemory memory;
+
+ if (arena->mem_arenas) {
+ for (u = 0; u < arena->heap_index_count; ++u) {
+ mem_arena = &arena->mem_arenas[u];
+ for (p = 0; p < mem_arena->elements; ++p) {
+ memory = mem_arena->page_darr[p].memory;
+ if (memory.offset == 0) {
+ if (memory.host_mapped_memory) {
+ vkUnmapMemory(arena->logical_device, (VkDeviceMemory)memory.device_memory);
+ }
+ vkFreeMemory(arena->logical_device, (VkDeviceMemory)memory.device_memory, arena->allocator);
+ } else {
+ PWARN("[REND_VK] Attempted to free memory with an offset!");
+ }
+ }
+ if (mem_arena->page_darr) {
+ rfree(mem_arena->page_darr);
+ mem_arena->page_darr = 0;
+ }
+ }
+ rfree(arena->mem_arenas);
+ arena->mem_arenas = 0;
+ }
+ memset(arena, 0, sizeof(*arena));
+}
+
+/* --- image --- */
+
+static RendVkImage
+rend_vk_image_create(VkDevice logical_device, VkImageType img_type, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
+ VkImageUsageFlags usage, uint32_t depth, uint32_t mip_levels, uint32_t layers,
+ VkSampleCountFlags sample_count_flags, VkSharingMode sharing_mode)
+{
+ RendVkImage image = {
+ .handle = VK_NULL_HANDLE,
+ .memory = VK_NULL_HANDLE,
+ .logical_device = logical_device,
+ .img_type = img_type,
+ .width = width,
+ .height = height,
+ .format = format,
+ .tiling = tiling,
+ .usage = usage,
+ .depth = depth,
+ .mip_levels = mip_levels,
+ .layers = layers,
+ .sample_count_flags = sample_count_flags,
+ .sharing_mode = sharing_mode
+ };
+
+ VkImageCreateInfo img_create_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
+ img_create_info.imageType = img_type;
+ img_create_info.extent.width = width;
+ img_create_info.extent.height = height;
+ img_create_info.extent.depth = depth;
+ img_create_info.mipLevels = mip_levels;
+ img_create_info.arrayLayers = layers;
+ img_create_info.format = format;
+ img_create_info.tiling = tiling;
+ img_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ img_create_info.usage = usage;
+ img_create_info.samples = sample_count_flags;
+ img_create_info.sharingMode = sharing_mode;
+
+ if (vkCreateImage(logical_device, &img_create_info, vk_allocator, &image.handle) != VK_SUCCESS) {
+ return image;
+ }
+
+ return image;
+}
+
+static uint32_t
+rend_vk_image_required_memory_type(RendVkImage *img)
+{
+ VkMemoryRequirements memory_requirements;
+
+ assert(img->memory == NULL && "Image already bound to memory");
+ memory_requirements = (VkMemoryRequirements){0};
+ vkGetImageMemoryRequirements(img->logical_device, img->handle, &memory_requirements);
+ img->requirements = memory_requirements;
+ return memory_requirements.memoryTypeBits;
+}
+
+static void
+rend_vk_image_bind_memory(RendVkImage *img, RendMemory *memory)
+{
+ assert(img->memory == NULL && "Image already bound to memory");
+ vkBindImageMemory(img->logical_device, img->handle, (VkDeviceMemory) memory->device_memory, memory->offset);
+}
+
+static void
+rend_vk_image_destroy(RendVkImage *img)
+{
+ if (img->view) {
+ vkDestroyImageView(img->logical_device, img->view, vk_allocator);
+ img->view = 0;
+ }
+
+ if (img->handle) {
+ vkDestroyImage(img->logical_device, img->handle, vk_allocator);
+ img->handle = 0;
+ }
+}
+
+static void
+rend_vk_image_view_create(RendVkImage *image, VkImageViewType view_type, VkImageAspectFlags view_aspect_flags)
+{
+ VkImageViewCreateInfo view_create_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = image->handle,
+ .format = image->format,
+ .viewType = view_type,
+ .subresourceRange.aspectMask = view_aspect_flags,
+ .subresourceRange.baseMipLevel = 0,
+ .subresourceRange.levelCount = image->mip_levels,
+ .subresourceRange.baseArrayLayer = 0,
+ .subresourceRange.layerCount = image->layers,
+ };
+
+ vkCreateImageView(image->logical_device, &view_create_info, vk_allocator, &image->view);
+}
diff --git a/Rend/rend_vk_internal.h b/Rend/rend_vk_internal.h
deleted file mode 100644
index 5a03aea..0000000
--- a/Rend/rend_vk_internal.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef REND_VK_INTERNAL_H
-#define REND_VK_INTERNAL_H
-
-#include <vulkan/vulkan.h>
-#include <vulkan/vulkan_core.h>
-#include <assert.h>
-
-#define CHECK_VK_RESULT(r) \
-{ \
- assert(r == VK_SUCCESS && __LINE__); \
-}
-
-
-typedef struct RendVkImage RendVkImage;
-typedef struct RendVkArenaAllocator RendVkArenaAllocator;
-typedef struct RendVkSbta RendVkSbta;
-
-typedef struct RendVkPendingCmd RendVkPendingCmd;
-typedef struct RendVkDeferredCmds RendVkDeferredCmds;
-
-typedef struct {
- const char **extention_names_darray;
- bool sampler_anisotropy;
- bool discrete_gpu;
- bool graphics;
- bool present;
- bool compute;
- bool transfer;
-} RendVkDevicespecs;
-
-typedef struct {
- uint32_t graphics_family_index;
- uint32_t present_family_index;
- uint32_t compute_family_index;
- uint32_t transfer_family_index;
-} RendVkQueueFamily;
-
-typedef struct {
- VkSurfaceCapabilitiesKHR capabilities;
- VkSurfaceFormatKHR *format;
- VkPresentModeKHR *present_modes;
- uint32_t format_count;
- uint32_t present_mode_count;
-} RendVkSwapchainSupport;
-
-typedef struct {
- /* logical device handle */
- VkDevice logical_device;
-
- /* physical device limitation */
- VkPhysicalDeviceProperties properties;
- VkPhysicalDeviceMemoryProperties memory;
- VkPhysicalDevice physical_device;
- VkPhysicalDeviceFeatures features;
- VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_props;
-
- /* swapchain support */
- VkSurfaceKHR surface;
- RendVkSwapchainSupport swapchain_support;
- VkFormat depth_format;
-
- /* queues */
- VkQueue graphics_queue;
- VkQueue present_queue;
- VkQueue compute_queue;
- VkQueue transfer_queue;
- uint32_t graphics_family_index;
- uint32_t present_family_index;
- uint32_t compute_family_index;
- uint32_t transfer_family_index;
-
- /* memory heap indices */
- uint32_t host_index;
- uint32_t device_index;
-} RendVkDevice;
-
-static VkInstance vk_instance = 0;
-static VkDebugUtilsMessengerEXT vk_debug_messenger = 0;
-static RendVkDevice vk_device = {0};
-
-/* helper functions */
-static int32_t rend_vk_memory_find_index(VkPhysicalDevice device, uint32_t type_filter, VkMemoryPropertyFlags property_flags);
-
-/* rend_vk_device.c */
-static bool rend_vk_device_create(VkSurfaceKHR surface, RendSpecs specs, RendVkDevice *out_device, uint32_t (*score_devices)(RendVkDevice *, RendSpecs, const char **, uint32_t));
-static uint32_t rend_vk_device_score_default(RendVkDevice *device, RendSpecs minimum_specs, const char **required_extensions, uint32_t required_extension_count);
-static void rend_vk_physical_device_query_swapchain_support(RendVkDevice *device);
-static bool rend_vk_device_detect_depth_format(RendVkDevice *device);
-static void rend_vk_device_destroy(RendVkDevice *device);
-
-/* rend_vk_arena.c */
-static RendVkArenaAllocator rend_vk_arena_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator);
-static uint32_t rend_vk_arena_add_page(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index, bool fit_to_alloc);
-static RendMemory rend_vk_arena_alloc(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index);
-static void rend_vk_arena_clear(RendVkArenaAllocator *arena, uint32_t memory_type);
-static void rend_vk_arena_clear_all(RendVkArenaAllocator *arena);
-static void rend_vk_arena_shrink(RendVkArenaAllocator *arena, uint32_t memory_type);
-static void rend_vk_arena_destroy(RendVkArenaAllocator *arena);
-
-/* rend_vk_command_queue.c */
-static inline RendVkDeferredCmds rend_vk_cmdbuf_deferred_create(void);
-static inline void rend_vk_cmdbuf_deferred_destroy(RendVkDeferredCmds *tracker);
-static inline uint64_t rend_vk_cmdbuf_deferred_submit(RendVkDeferredCmds *tracker, VkCommandPool pool, VkCommandBuffer cmd, VkQueue queue, uint64_t wait_value, VkPipelineStageFlags2 wait_stage, VkPipelineStageFlags2 signal_stage);
-static inline void rend_vk_cmdbuf_deferred_push(RendVkDeferredCmds *tracker, VkCommandPool pool, VkCommandBuffer cmd, uint64_t wait_value);
-static inline void rend_vk_cmdbuf_deferred_flush(RendVkDeferredCmds *tracker);
-
-/* rend_vk_image.c */
-static RendVkImage rend_vk_image_create(VkDevice logical_device, VkImageType img_type, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags memory_flags, uint32_t depth, uint32_t mip_levels, uint32_t layers, VkSampleCountFlags sample_count_flags, VkSharingMode sharing_mode);
-static uint32_t rend_vk_image_required_memory_type(RendVkImage *img);
-static void rend_vk_image_bind_memory(RendVkImage *image, RendMemory *memory);
-static void rend_vk_image_destroy(RendVkImage *img);
-static void rend_vk_image_view_create(RendVkImage *image, VkImageViewType view_type, VkImageAspectFlags view_aspect_flags);
-static uint64_t rend_vk_image_address(RendVkImage *image);
-
-
-static VkAllocationCallbacks *vk_allocator = 0; // we are only ever going to use one, either the default one or the custom one
-
-static VkFormat vk_format_from_rend_format[] = {
- [REND_FORMAT_R8_UNORM] = VK_FORMAT_R8_UNORM,
- [REND_FORMAT_R8G8_UNORM] = VK_FORMAT_R8G8_UNORM,
- [REND_FORMAT_R8G8B8A8_UNORM] = VK_FORMAT_R8G8B8A8_UNORM,
- [REND_FORMAT_B8G8R8A8_UNORM] = VK_FORMAT_B8G8R8A8_UNORM,
- [REND_FORMAT_R8G8B8A8_SRGB] = VK_FORMAT_R8G8B8A8_SRGB,
- [REND_FORMAT_B8G8R8A8_SRGB] = VK_FORMAT_B8G8R8A8_SRGB,
- [REND_FORMAT_R32_SFLOAT] = VK_FORMAT_R32_SFLOAT,
- [REND_FORMAT_R32G32_SFLOAT] = VK_FORMAT_R32G32_SFLOAT,
- [REND_FORMAT_R32G32B32_SFLOAT] = VK_FORMAT_R32G32B32_SFLOAT,
- [REND_FORMAT_R32G32B32A32_SFLOAT]= VK_FORMAT_R32G32B32A32_SFLOAT,
- [REND_FORMAT_R16_SFLOAT] = VK_FORMAT_R16_SFLOAT,
- [REND_FORMAT_R16G16_SFLOAT] = VK_FORMAT_R16G16_SFLOAT,
- [REND_FORMAT_R16G16B16A16_SFLOAT]= VK_FORMAT_R16G16B16A16_SFLOAT,
- [REND_FORMAT_R32_UINT] = VK_FORMAT_R32_UINT,
- [REND_FORMAT_R32_SINT] = VK_FORMAT_R32_SINT,
- [REND_FORMAT_R32G32B32A32_UINT] = VK_FORMAT_R32G32B32A32_UINT,
- [REND_FORMAT_R16G16B16A16_UINT] = VK_FORMAT_R16G16B16A16_UINT,
- [REND_FORMAT_R8G8B8A8_UINT] = VK_FORMAT_R8G8B8A8_UINT,
- [REND_FORMAT_D32_SFLOAT] = VK_FORMAT_D32_SFLOAT,
- [REND_FORMAT_D24_UNORM_S8_UINT] = VK_FORMAT_D24_UNORM_S8_UINT,
- [REND_FORMAT_D32_SFLOAT_S8_UINT] = VK_FORMAT_D32_SFLOAT_S8_UINT,
-};
-
-static VkPrimitiveTopology vk_topology[] = {
- [REND_TOPOLOGY_TRIANGLE_LIST] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
- [REND_TOPOLOGY_TRIANGLE_STRIP] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
- [REND_TOPOLOGY_LINE_LIST] = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
- [REND_TOPOLOGY_LINE_STRIP] = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
- [REND_TOPOLOGY_POINT_LIST] = VK_PRIMITIVE_TOPOLOGY_POINT_LIST
-};
-
-static VkPolygonMode vk_polymode[] = {
- [REND_POLYGON_MODE_FILL] = VK_POLYGON_MODE_FILL,
- [REND_POLYGON_MODE_LINE] = VK_POLYGON_MODE_LINE,
- [REND_POLYGON_MODE_POINT] = VK_POLYGON_MODE_POINT,
-};
-
-static VkCullModeFlags vk_cullflags[] = {
- [REND_CULL_MODE_NONE] = VK_CULL_MODE_NONE,
- [REND_CULL_MODE_FRONT] = VK_CULL_MODE_FRONT_BIT,
- [REND_CULL_MODE_BACK] = VK_CULL_MODE_BACK_BIT,
- [REND_CULL_MODE_FRONT_AND_BACK] = VK_CULL_MODE_FRONT_AND_BACK,
-};
-
-static int32_t
-rend_vk_memory_find_index(VkPhysicalDevice device, uint32_t type_filter, VkMemoryPropertyFlags property_flags)
-{
- VkPhysicalDeviceMemoryProperties memory_properties;
- vkGetPhysicalDeviceMemoryProperties(device, &memory_properties);
- for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) {
- if (type_filter & (1 << i) && (memory_properties.memoryTypes[i].propertyFlags & property_flags) == property_flags) {
- return i;
- }
- }
-
- return -1;
-}
-
-#endif
diff --git a/build.c b/build.c
index 7c34e42..966a481 100644
--- a/build.c
+++ b/build.c
@@ -44,11 +44,14 @@ add_rend_demo(Poof_Batch *batch, const char *src, const char *out, uint32_t opt,
cc.optimization = opt;
cc.output = out;
poof_cmd_append(&cc.inputs, src);
- poof_cmd_append(&cc.includes, ".", "Rend", "Peak", "demos", "demos/teapot");
+ poof_cmd_append(&cc.includes, ".", "Rend", "Peak");
poof_cmd_append(&cc.defines, "PEAK_VULKAN");
+#if !defined(_WIN32)
+ poof_cmd_append(&cc.defines, "_POSIX_C_SOURCE=200809L");
+#endif
if (define) poof_cmd_append(&cc.defines, define);
poof_cmd_append(&cc.libs, "m");
- poof_cmd_append(&cc.extra_flags, "-std=c99", "-Wall");
+ poof_cmd_append(&cc.extra_flags, "-std=c99", "-Wall", "-Werror");
add_peak_config(&cc);
poof_batch_append_cc(batch, &cc);
}
@@ -65,12 +68,14 @@ build_peak_header(void)
static bool
build_peak_demos(void)
{
+ poof_mkdir("demos/multiplatform");
+
Poof_CC cc = {0};
poof_cc_init(&cc, POOF_CC_GCC | POOF_CC_CLANG, POOF_TARGET_HOST);
cc.debug_mode = true;
cc.optimization = POOF_O0;
- cc.output = "demos/demo";
- poof_cc_append(&cc.inputs, "demos/demo.c");
+ cc.output = "demos/multiplatform/demo";
+ poof_cc_append(&cc.inputs, "demos/multiplatform/demo.c");
poof_cc_append(&cc.extra_flags, "-std=c99", "-Wall", "-Wno-deprecated-declarations", "-pthread");
poof_cc_append(&cc.libs, "m", "pthread");
if (!poof_cc_run(&cc)) return false;
@@ -79,14 +84,14 @@ build_peak_demos(void)
poof_cc_init(&cc, POOF_CC_GCC | POOF_CC_CLANG, POOF_TARGET_HOST);
cc.debug_mode = true;
cc.optimization = POOF_O0;
- cc.output = "demos/demo_run";
- poof_cc_append(&cc.inputs, "demos/demo_run.c");
+ cc.output = "demos/multiplatform/demo_run";
+ poof_cc_append(&cc.inputs, "demos/multiplatform/demo_run.c");
poof_cc_append(&cc.extra_flags, "-std=c99", "-Wall", "-Wno-deprecated-declarations", "-pthread");
poof_cc_append(&cc.libs, "m", "pthread");
if (!poof_cc_run(&cc)) return false;
Poof_Cmd cmd = {0};
- poof_cmd_append(&cmd, "emcc", "demos/demo_run.c", "-o", "demos/demo.js",
+ poof_cmd_append(&cmd, "emcc", "demos/multiplatform/demo_run.c", "-o", "demos/multiplatform/demo.js",
"-std=c99", "-Wall", "-Wno-deprecated-declarations",
"-sALLOW_MEMORY_GROWTH=1", "-sENVIRONMENT=web");
return poof_cmd_run(&cmd);
@@ -100,19 +105,19 @@ build_rend_demos(void)
Poof_Batch batch = {0};
- slangc_entry(&batch, "demos/rend_compute.slang", "particleMain", "compute", "demos/compute/particle.spv");
- slangc_entry(&batch, "demos/rend_compute.slang", "sandMain", "compute", "demos/compute/sand.spv");
- slangc_entry(&batch, "demos/rend_compute.slang", "vertMain", "vertex", "demos/compute/vert.spv");
- slangc_entry(&batch, "demos/rend_compute.slang", "fragMain", "fragment", "demos/compute/frag.spv");
+ slangc_entry(&batch, "demos/compute/rend_compute.slang", "particleMain", "compute", "demos/compute/particle.spv");
+ slangc_entry(&batch, "demos/compute/rend_compute.slang", "sandMain", "compute", "demos/compute/sand.spv");
+ slangc_entry(&batch, "demos/compute/rend_compute.slang", "vertMain", "vertex", "demos/compute/vert.spv");
+ slangc_entry(&batch, "demos/compute/rend_compute.slang", "fragMain", "fragment", "demos/compute/frag.spv");
slangc_entry(&batch, "demos/teapot/shaders/basic.slang", "vertMain", "vertex", "demos/teapot/basic.vert.spv");
slangc_entry(&batch, "demos/teapot/shaders/basic.slang", "fragMain", "fragment", "demos/teapot/basic.frag.spv");
slangc_entry(&batch, "demos/teapot/shaders/texture.slang", "vertMain", "vertex", "demos/teapot/texture.vert.spv");
slangc_entry(&batch, "demos/teapot/shaders/texture.slang", "fragMain", "fragment", "demos/teapot/texture.frag.spv");
- add_rend_demo(&batch, "demos/rend_compute.c", "demos/compute/rend_compute_demo", POOF_O0, "REND_DEBUG");
- add_rend_demo(&batch, "demos/rend_compute.c", "demos/compute/rend_compute_fast", POOF_O3 | POOF_MSSE2, NULL);
- add_rend_demo(&batch, "demos/rend_teapot.c", "demos/teapot/rend_teapot", POOF_O0, "REND_DEBUG");
+ add_rend_demo(&batch, "demos/compute/rend_compute.c", "demos/compute/rend_compute_demo", POOF_O0, "REND_DEBUG");
+ // add_rend_demo(&batch, "demos/compute/rend_compute.c", "demos/compute/rend_compute_fast", POOF_O3 | POOF_MSSE2, NULL);
+ add_rend_demo(&batch, "demos/teapot/rend_teapot.c", "demos/teapot/rend_teapot", POOF_O0, "REND_DEBUG");
return poof_batch_run(&batch, "Rend Demos");
}
diff --git a/demos/rend_compute.c b/demos/compute/rend_compute.c
index f82836a..37ee207 100644
--- a/demos/rend_compute.c
+++ b/demos/compute/rend_compute.c
@@ -1,15 +1,12 @@
+#define PEAK_IMPLEMENTATION
+#include "../Rend/rend.h"
+#include "../Rend/rend.c"
+#include <stddef.h>
#include <string.h>
-#ifdef DEBUG_MEMORY
#define malloc(size) peak_debug_malloc_impl((size), __FILE__, __LINE__, __func__)
#define realloc(ptr, size) peak_debug_realloc_impl((ptr), (size), __FILE__, __LINE__, __func__)
#define free(ptr) peak_debug_free_impl((ptr), __FILE__, __LINE__, __func__)
-#endif
-
-#define PEAK_IMPLEMENTATION
-#include "../Rend/rend.h"
-#include "../Rend/rend.c"
-#include <stddef.h>
float delta = 0;
PeakWindow win;
@@ -219,13 +216,11 @@ int main() {
rend_buffer_destroy(&dst_buf);
rend_renderer_destroy(renderer);
- rend_quit();
+ // rend_quit();
peak_window_close(&win);
peak_quit();
-#if DEBUG_MEMORY
peak_debug_memory_report();
-#endif
return 0;
}
diff --git a/demos/rend_compute.slang b/demos/compute/rend_compute.slang
index 5fb124b..5fb124b 100644
--- a/demos/rend_compute.slang
+++ b/demos/compute/rend_compute.slang
diff --git a/demos/compute/rend_compute_demo b/demos/compute/rend_compute_demo
index 1aecc00..46734c6 100755
--- a/demos/compute/rend_compute_demo
+++ b/demos/compute/rend_compute_demo
Binary files differ
diff --git a/demos/compute/rend_compute_fast b/demos/compute/rend_compute_fast
deleted file mode 100755
index d9583f6..0000000
--- a/demos/compute/rend_compute_fast
+++ /dev/null
Binary files differ
diff --git a/demos/demo b/demos/multiplatform/demo
index 9f9b6ee..5086695 100755
--- a/demos/demo
+++ b/demos/multiplatform/demo
Binary files differ
diff --git a/demos/demo.c b/demos/multiplatform/demo.c
index c095fdb..4e8295f 100644
--- a/demos/demo.c
+++ b/demos/multiplatform/demo.c
@@ -1,7 +1,7 @@
#include <stdio.h>
#define PEAK_IMPLEMENTATION
-#include "../Peak/peak.h"
+#include "../../Peak/peak.h"
void print_window_resize(PeakEvent ev) {
printf("window: %u %u\n", ev.resize.width, ev.resize.height);
diff --git a/demos/demo.html b/demos/multiplatform/demo.html
index a10e85e..a10e85e 100644
--- a/demos/demo.html
+++ b/demos/multiplatform/demo.html
diff --git a/demos/demo.js b/demos/multiplatform/demo.js
index 1de6b03..1de6b03 100644
--- a/demos/demo.js
+++ b/demos/multiplatform/demo.js
diff --git a/demos/demo.wasm b/demos/multiplatform/demo.wasm
index 6dbbbd6..4da868a 100755
--- a/demos/demo.wasm
+++ b/demos/multiplatform/demo.wasm
Binary files differ
diff --git a/demos/demo_run b/demos/multiplatform/demo_run
index 45a51e9..f9b8721 100755
--- a/demos/demo_run
+++ b/demos/multiplatform/demo_run
Binary files differ
diff --git a/demos/demo_run.c b/demos/multiplatform/demo_run.c
index db3e56a..2b7d681 100644
--- a/demos/demo_run.c
+++ b/demos/multiplatform/demo_run.c
@@ -1,7 +1,7 @@
#include <stdio.h>
#define PEAK_IMPLEMENTATION
-#include "../Peak/peak.h"
+#include "../../Peak/peak.h"
void print_window_resize(PeakEvent ev) {
diff --git a/demos/teapot/rend_teapot b/demos/teapot/rend_teapot
index c1d3a30..f9a4bb9 100755
--- a/demos/teapot/rend_teapot
+++ b/demos/teapot/rend_teapot
Binary files differ
diff --git a/demos/rend_teapot.c b/demos/teapot/rend_teapot.c
index b4430e9..b4430e9 100644
--- a/demos/rend_teapot.c
+++ b/demos/teapot/rend_teapot.c
diff --git a/demos/teapot.h b/demos/teapot/teapot.h
index dfde9be..dfde9be 100644
--- a/demos/teapot.h
+++ b/demos/teapot/teapot.h