Compare commits
21 Commits
master
...
cpp-rewrit
| Author | SHA1 | Date | |
|---|---|---|---|
| 6664860dbf | |||
| b72ed8557b | |||
| 6e13ceb267 | |||
| 2655c2be3e | |||
| 29d8d8cc8a | |||
| 0187ed9442 | |||
| d364b88db4 | |||
| 360b8410a6 | |||
| 3f52c14011 | |||
| a8ad12a9e7 | |||
| c17fe88e5d | |||
| 15089cf7b5 | |||
| 2367ce1e9d | |||
| 248b81f2ec | |||
| b05c64a131 | |||
| bca52758cc | |||
| 8cc0b43a5d | |||
| 5b8ecd8020 | |||
| 71f73964cf | |||
| 4f06ecb7ac | |||
| 8c928841ad |
53
.clang-format
Normal file
53
.clang-format
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: true
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBraces: Custom
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
ColumnLimit: 120
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
IncludeCategories:
|
||||
- Regex: '^<.*'
|
||||
Priority: 1
|
||||
- Regex: '^".*'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IndentWidth: 4
|
||||
InsertNewlineAtEOF: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
PointerAlignment: Left
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
TabWidth: 4
|
||||
...
|
||||
@ -1,10 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.30)
|
||||
project(prototype1 C)
|
||||
project(prototype1 C CXX)
|
||||
|
||||
#include_directories(${CMAKE_SOURCE_DIR})
|
||||
set(CMAKE_C_FLAGS "-Wno-unused-parameter \
|
||||
-Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type \
|
||||
--std=c99 -g -ggdb -O0")
|
||||
set(CMAKE_CXX_FLAGS "-Wno-unused-parameter \
|
||||
-Wall -Wextra -Werror=return-type \
|
||||
--std=c++20 -g -ggdb -O0")
|
||||
|
||||
execute_process(
|
||||
COMMAND pkg-config --cflags libpipewire-0.3
|
||||
@ -66,3 +69,11 @@ target_link_libraries(l2_tex_gen -lm -lpng)
|
||||
|
||||
add_executable(l3_r4 src/l3/r4/r4.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
target_link_libraries(l3_r4 -lvulkan -lwayland-client -lm -lxkbcommon -lpng -lfreetype)
|
||||
|
||||
add_executable(codegen_l1_allie_cpp src/l1/allie_cpp/anne/codegen.cpp)
|
||||
|
||||
add_executable(l3_r4c
|
||||
src/l3/r4/r4c.cpp
|
||||
src/l2/allie_cpp/glue.c
|
||||
gen/l_wl_protocols/xdg-shell-private.c)
|
||||
target_link_libraries(l3_r4c -lvulkan -lwayland-client -lm -lxkbcommon -lpng -lfreetype)
|
||||
|
||||
106
Makefile
106
Makefile
@ -9,7 +9,7 @@ HEADERS_src_l1_5 = $(HEADERS_gen_l1) $(call find_headers,l1_5)
|
||||
#HEADERS_gen_l1_5 := $(HEADERS_src_l1_5) gen/l1_5/dorothy.txt
|
||||
HEADERS_gen_l1_5 := gen/l1_5/dorothy.txt
|
||||
|
||||
ASSETS_src_l_adele = $($call find_assets,l_adele)
|
||||
ASSETS_src_l_adele = $(call find_assets,l_adele)
|
||||
ASSETS_gen_l_adele = gen/l_adele/dorothy.txt
|
||||
|
||||
HEADERS_src_l2 := $(HEADERS_gen_l1_5) $(call find_headers,l2)
|
||||
@ -19,7 +19,7 @@ HEADERS_gen_l2 := gen/l2/dorothy.txt
|
||||
HEADERS_src_l3 := $(HEADERS_gen_l2) $(call find_headers,l3)
|
||||
|
||||
cflags := -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type -Wno-unused-parameter \
|
||||
--std=c99 -g -ggdb -O0 \
|
||||
--std=c99 -g -ggdb -O0 -D_FORTIFY_SOURCE=0 \
|
||||
-fno-trapping-math -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE
|
||||
cc := gcc
|
||||
|
||||
@ -44,15 +44,6 @@ gen/l1/dorothy.txt: out/l1/codegen
|
||||
mkdir -p gen
|
||||
cd gen && ../out/l1/codegen
|
||||
|
||||
out/l1_4/t0: src/l1_4/tests/t0.c $(HEADERS_gen_l1)
|
||||
mkdir -p out/l1_4
|
||||
$(cc) $(cflags) -o $@ $<
|
||||
|
||||
out/l1_4/t1: src/l1_4/tests/t1.c $(HEADERS_gen_l1)
|
||||
mkdir -p out/l1_4
|
||||
$(cc) $(cflags) -o $@ $<
|
||||
|
||||
|
||||
out/l1_5/codegen: src/l1_5/anne/codegen.c $(HEADERS_src_l1_5)
|
||||
mkdir -p out/l1_5
|
||||
$(cc) $(cflags) -o $@ $<
|
||||
@ -95,6 +86,7 @@ gen/l_adele/dorothy.txt: $(ASSETS_src_l_adele)
|
||||
$(call compile_shader,alice/0gen,0gen)
|
||||
$(call compile_shader,alice/0sh,0sh)
|
||||
$(call compile_shader,alice/1,1)
|
||||
$(call compile_shader,drawer_2d/plain,plain)
|
||||
touch gen/l_adele/dorothy.txt
|
||||
|
||||
out/l2/t0: src/l2/tests/data_structures/t0.c $(HEADERS_gen_l1_5)
|
||||
@ -131,22 +123,6 @@ out/l2/r3: src/l2/tests/r3/r3.c $(HEADERS_src_l2) $(l_wl_protocols)
|
||||
run_r3: out/l2/r3
|
||||
./out/l2/r3
|
||||
|
||||
# Whoever needs this will also need out/l_wl_protocols
|
||||
out/l2/allie.o: src/l2/allie/allie.c $(HEADERS_src_l2) $(xdg_shell_client_h) gen/l_adele/dorothy.txt $(HEADERS_gen_l2)
|
||||
mkdir -p out/l2
|
||||
$(cc) $(cflags) -o $@ -c $< -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
|
||||
|
||||
full_allie_obj := out/l2/allie.o $(xdg_shell_private_o)
|
||||
|
||||
out/l3/r4: src/l3/r4/R4.hs src/l2/allie/Allie.hs $(full_allie_obj)
|
||||
mkdir -p out/l3
|
||||
ghc -isrc/l2/allie -hidir out/l3/ -odir out/l3 -o $@ $< $(full_allie_obj) \
|
||||
-lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
|
||||
|
||||
.PHONY: run_r4
|
||||
run_r4: out/l3/r4
|
||||
./out/l3/r4
|
||||
|
||||
out/l3/r4b: src/l3/r4/r4.c $(HEADERS_src_l3) $(l_wl_protocols) $(ASSETS_gen_l_adele)
|
||||
mkdir -p out/l3
|
||||
$(cc) $(cflags) -o $@ $< $(xdg_shell_private_c) -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
|
||||
@ -157,4 +133,78 @@ run_r4b: out/l3/r4b
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf gen out
|
||||
rm -rf gen out
|
||||
|
||||
# ======================= Daria ВСЁ ===========================
|
||||
# =============================================================
|
||||
# -------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# =============================================================
|
||||
# ====================== ПЛЮСЫ ================================
|
||||
|
||||
find_hpp_cpp = $(shell find src/$(1) -type f -name '*.hpp' )
|
||||
|
||||
HEADERS_src_l1_allie_cpp := $(call find_hpp_cpp,l1/allie_cpp)
|
||||
|
||||
cxx_cpp := g++
|
||||
cxxflags_cpp := -Wall -Wextra -Werror=return-type -Wno-unused-parameter \
|
||||
--std=c++20 -g -ggdb -O0 -D_FORTIFY_SOURCE=0 \
|
||||
-fno-trapping-math -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE
|
||||
|
||||
out/l1/allie_cpp/codegen: src/l1/allie_cpp/anne/codegen.cpp $(HEADERS_src_l1_allie_cpp)
|
||||
mkdir -p out/l1/allie_cpp
|
||||
$(cxx_cpp) $(cxxflags_cpp) -o $@ $<
|
||||
|
||||
gen/l1/allie_cpp/dorothy.txt: out/l1/allie_cpp/codegen
|
||||
mkdir -p gen
|
||||
cd gen && ../out/l1/allie_cpp/codegen
|
||||
|
||||
out/l2/allie_cpp/glue.o: src/l2/allie_cpp/glue.c $(HEADERS_src_l2) $(xdg_shell_client_h) gen/l_adele/dorothy.txt $(HEADERS_gen_l2)
|
||||
mkdir -p out/l2/allie_cpp/
|
||||
$(cc) $(cflags) -o $@ -c $< -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
|
||||
|
||||
full_allie_cpp_obj := out/l2/allie_cpp/glue.o $(xdg_shell_private_o)
|
||||
|
||||
# todo: add a call to a function that obtains all .hpp files from l2/allie_cpp
|
||||
out/l3/allie_cpp/r4c: src/l3/r4/r4c.cpp src/l1/allie_cpp/anne/utils.hpp \
|
||||
src/l2/allie_cpp/alice.hpp $(full_allie_cpp_obj)
|
||||
mkdir -p out/l3/allie_cpp
|
||||
$(cxx_cpp) $(cxxflags_cpp) -o $@ $< $(full_allie_cpp_obj) \
|
||||
-lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
|
||||
|
||||
.PHONY: run_r4c
|
||||
run_r4c: out/l3/allie_cpp/r4c
|
||||
./out/l3/allie_cpp/r4c
|
||||
|
||||
# ======================== ПЛЮСЫ ВСЁ ==========================
|
||||
# =============================================================
|
||||
# -------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# =============================================================
|
||||
# ========================== ХАСКЕЛЬ ==========================
|
||||
|
||||
find_haskell_hs = $(shell find src/$(1) -type f -name '*.hs' )
|
||||
|
||||
# Whoever needs this will also need out/l_wl_protocols
|
||||
out/l2/allie_hs/glue.o: src/l2/allie_hs/glue.c $(HEADERS_src_l2) $(xdg_shell_client_h) gen/l_adele/dorothy.txt $(HEADERS_gen_l2)
|
||||
mkdir -p out/l2/allie_hs/
|
||||
$(cc) $(cflags) -o $@ -c $< -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
|
||||
|
||||
full_allie_hs_obj := out/l2/allie_hs/glue.o $(xdg_shell_private_o)
|
||||
|
||||
# todo: write a function that gets all .hs files from l2/allie_hs. Call it
|
||||
out/l3/allie_hs/r4: src/l3/r4/R4.hs src/l2/allie_hs/Alice.hs \
|
||||
src/l2/allie_hs/Geom.hs $(full_allie_hs_obj)
|
||||
mkdir -p out/l3/allie_hs
|
||||
ghc -isrc/l2/allie_hs -hidir out/l3/ -odir out/l3 -o $@ $< $(full_allie_hs_obj) \
|
||||
-lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
|
||||
|
||||
.PHONY: run_r4
|
||||
run_r4: out/l3/allie_hs/r4
|
||||
./out/l3/allie_hs/r4
|
||||
|
||||
# ========================== ХАСКЕЛЬ ВСЁ ======================
|
||||
# =============================================================
|
||||
# -------------------------------------------------------------
|
||||
|
||||
@ -69,7 +69,7 @@ haskell и rust. Самые высшие уровни Дарьи это те, ч
|
||||
|
||||
Вот какие уровни есть в данный момент:
|
||||
|
||||
`l_wl_protocls` (написан не мной, не нумеруется), `l1`, `l1_4`, `l1_5`, `l2`
|
||||
`l_wl_protocls` (написан не мной, не нумеруется), `l1`, `l1_5`, `l2`
|
||||
|
||||
Весь код хранится в папках `src/<имя уровня>` и `gen/<имя уровня>`.
|
||||
Код с более высокого уровня может использовать код с более низкого уровня.
|
||||
@ -133,8 +133,6 @@ _Не спрашивай как я написал `src/l1/core/chicken_VecU8.h`
|
||||
генерации.
|
||||
]]
|
||||
|
||||
- `l1_4` -- Тут просто лежат тесты для шаблонов `l1`.
|
||||
|
||||
- `l1_5`
|
||||
- - Инстанциация `Box`, `Ref`, `RefMut` для трейта (инстанциация
|
||||
'громадных' ссылок).
|
||||
|
||||
7
src/l1/allie_cpp/anne/codegen.cpp
Normal file
7
src/l1/allie_cpp/anne/codegen.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "geom.hpp"
|
||||
|
||||
int main() {
|
||||
l1_generate_geom_hpp();
|
||||
touch_file("l1/allie_cpp/dorothy.txt");
|
||||
return 0;
|
||||
}
|
||||
533
src/l1/allie_cpp/anne/geom.hpp
Normal file
533
src/l1/allie_cpp/anne/geom.hpp
Normal file
@ -0,0 +1,533 @@
|
||||
#pragma once
|
||||
|
||||
#include "../codegen.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
/* This file is vibecoded. It requires more rewriting */
|
||||
|
||||
inline constexpr std::array<std::string_view, 4> kGeomFieldNames = {"x", "y", "z", "w"};
|
||||
|
||||
struct GeomVecFamilySpec {
|
||||
std::string_view prefix;
|
||||
std::string_view scalar;
|
||||
bool geometric_methods;
|
||||
};
|
||||
|
||||
struct GeomMatFamilySpec {
|
||||
std::string_view mat_prefix;
|
||||
std::string_view vec_prefix;
|
||||
std::string_view scalar;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
concept GeomIndexCallable =
|
||||
requires(F&& f) {
|
||||
std::invoke(std::forward<F>(f), int{});
|
||||
};
|
||||
|
||||
template <class F>
|
||||
concept GeomIndexStringCallable =
|
||||
requires(F&& f) {
|
||||
{ std::invoke(std::forward<F>(f), int{}) } -> std::convertible_to<std::string>;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
concept GeomIndexPairStringCallable =
|
||||
requires(F&& f) {
|
||||
{ std::invoke(std::forward<F>(f), int{}, int{}) } -> std::convertible_to<std::string>;
|
||||
};
|
||||
|
||||
template <GeomIndexCallable F>
|
||||
inline void geom_append_joined(std::string& out, int count, std::string_view separator, F&& emit_one) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (i > 0) {
|
||||
out += separator;
|
||||
}
|
||||
emit_one(i);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string_view geom_field_name(int index) {
|
||||
return kGeomFieldNames[index];
|
||||
}
|
||||
|
||||
inline std::string geom_vec_name(std::string_view prefix, int n) {
|
||||
return std::string(prefix) + std::to_string(n);
|
||||
}
|
||||
|
||||
inline std::string geom_mat_name(std::string_view prefix, int cols, int rows) {
|
||||
if (cols == rows) {
|
||||
return std::string(prefix) + std::to_string(cols);
|
||||
}
|
||||
return std::string(prefix) + std::to_string(cols) + "x" + std::to_string(rows);
|
||||
}
|
||||
|
||||
template <GeomIndexStringCallable F>
|
||||
inline void geom_append_constructor_call(std::string& out, std::string_view type_name, int count, F&& arg_expression) {
|
||||
out += std::string(type_name);
|
||||
out += "(";
|
||||
geom_append_joined(out, count, ", ", [&](int index) {
|
||||
out += arg_expression(index);
|
||||
});
|
||||
out += ")";
|
||||
}
|
||||
|
||||
template <GeomIndexStringCallable F>
|
||||
inline void geom_append_vector_return(std::string& out, std::string_view vec_name, int count, F&& component_expression) {
|
||||
out += " return ";
|
||||
geom_append_constructor_call(out, vec_name, count, component_expression);
|
||||
out += ";\n";
|
||||
}
|
||||
|
||||
template <GeomIndexPairStringCallable F>
|
||||
inline void geom_append_matrix_return(
|
||||
std::string& out,
|
||||
std::string_view mat_name,
|
||||
std::string_view vec_name,
|
||||
int cols,
|
||||
int rows,
|
||||
F&& component_expression) {
|
||||
out += " return ";
|
||||
out += std::string(mat_name);
|
||||
out += "(";
|
||||
geom_append_joined(out, cols, ", ", [&](int col) {
|
||||
geom_append_constructor_call(out, vec_name, rows, [&](int row) {
|
||||
return component_expression(col, row);
|
||||
});
|
||||
});
|
||||
out += ");\n";
|
||||
}
|
||||
|
||||
template <GeomIndexStringCallable F>
|
||||
inline void geom_append_matrix_column_return(std::string& out, std::string_view mat_name, int cols, F&& column_expression) {
|
||||
out += " return ";
|
||||
geom_append_constructor_call(out, mat_name, cols, column_expression);
|
||||
out += ";\n";
|
||||
}
|
||||
|
||||
inline void geom_append_vector_family(std::string& out, GeomVecFamilySpec spec, int n) {
|
||||
const std::string vec_name = geom_vec_name(spec.prefix, n);
|
||||
|
||||
out += "struct " + vec_name + " {\n";
|
||||
for (int i = 0; i < n; ++i) {
|
||||
out += " " + std::string(spec.scalar) + " " + std::string(geom_field_name(i)) + ";\n";
|
||||
}
|
||||
out += "\n";
|
||||
out += " constexpr " + vec_name + "() noexcept = default;\n";
|
||||
out += " constexpr " + vec_name + "(";
|
||||
geom_append_joined(out, n, ", ", [&](int index) {
|
||||
out += std::string(spec.scalar) + " " + std::string(geom_field_name(index));
|
||||
});
|
||||
out += ") noexcept : ";
|
||||
geom_append_joined(out, n, ", ", [&](int index) {
|
||||
const std::string field = std::string(geom_field_name(index));
|
||||
out += field + "(" + field + ")";
|
||||
});
|
||||
out += " {}\n";
|
||||
out += "};\n\n";
|
||||
|
||||
out += "inline " + vec_name + " operator+(" + vec_name + " A, " + vec_name + " B) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_name, n, [&](int index) {
|
||||
const std::string field = std::string(geom_field_name(index));
|
||||
return "A." + field + " + B." + field;
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + vec_name + " operator-(" + vec_name + " A, " + vec_name + " B) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_name, n, [&](int index) {
|
||||
const std::string field = std::string(geom_field_name(index));
|
||||
return "A." + field + " - B." + field;
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + vec_name + " operator-(" + vec_name + " A) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_name, n, [&](int index) {
|
||||
return "-A." + std::string(geom_field_name(index));
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + vec_name + " operator*(" + vec_name + " A, " + std::string(spec.scalar) + " B) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_name, n, [&](int index) {
|
||||
return "A." + std::string(geom_field_name(index)) + " * B";
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + vec_name + " operator*(" + std::string(spec.scalar) + " A, " + vec_name + " B) noexcept {\n";
|
||||
out += " return B * A;\n}\n\n";
|
||||
|
||||
out += "inline " + vec_name + " operator/(" + vec_name + " A, " + std::string(spec.scalar) + " B) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_name, n, [&](int index) {
|
||||
return "A." + std::string(geom_field_name(index)) + " / B";
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + vec_name + " operator*(" + vec_name + " A, " + vec_name + " B) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_name, n, [&](int index) {
|
||||
const std::string field = std::string(geom_field_name(index));
|
||||
return "A." + field + " * B." + field;
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + std::string(spec.scalar) + " dot(" + vec_name + " A, " + vec_name + " B) noexcept {\n";
|
||||
out += " return " + [&]() {
|
||||
std::string expression;
|
||||
geom_append_joined(expression, n, " + ", [&](int index) {
|
||||
const std::string field = std::string(geom_field_name(index));
|
||||
expression += "A." + field + " * B." + field;
|
||||
});
|
||||
return expression;
|
||||
}() + ";\n}\n\n";
|
||||
|
||||
if (spec.geometric_methods) {
|
||||
out += "inline " + std::string(spec.scalar) + " length(" + vec_name + " A) noexcept {\n";
|
||||
out += " return std::sqrt(dot(A, A));\n}\n\n";
|
||||
|
||||
out += "inline " + vec_name + " normalize(" + vec_name + " A) noexcept {\n";
|
||||
out += " return A / length(A);\n}\n\n";
|
||||
|
||||
if (n == 3) {
|
||||
out += "inline " + vec_name + " cross(" + vec_name + " A, " + vec_name + " B) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_name, 3, [&](int index) {
|
||||
if (index == 0) {
|
||||
return "A.y * B.z - A.z * B.y";
|
||||
}
|
||||
if (index == 1) {
|
||||
return "-A.x * B.z + A.z * B.x";
|
||||
}
|
||||
return "A.x * B.y - A.y * B.x";
|
||||
});
|
||||
out += "}\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void geom_append_vector_and_one(std::string& out, GeomVecFamilySpec spec, int n) {
|
||||
const std::string vec_name = geom_vec_name(spec.prefix, n);
|
||||
const std::string vec_next = geom_vec_name(spec.prefix, n + 1);
|
||||
|
||||
out += "inline " + vec_next + " and_one(" + vec_name + " A) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_next, n + 1, [&](int index) {
|
||||
if (index == n) {
|
||||
return std::string("1");
|
||||
}
|
||||
return "A." + std::string(geom_field_name(index));
|
||||
});
|
||||
out += "}\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_matrix_struct(std::string& out, GeomMatFamilySpec spec, int cols, int rows) {
|
||||
const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows);
|
||||
const std::string vec_rows = geom_vec_name(spec.vec_prefix, rows);
|
||||
|
||||
out += "struct " + mat_name + " {\n";
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
out += " " + vec_rows + " " + std::string(geom_field_name(col)) + ";\n";
|
||||
}
|
||||
out += "\n";
|
||||
out += " constexpr " + mat_name + "() noexcept = default;\n";
|
||||
out += " constexpr " + mat_name + "(";
|
||||
geom_append_joined(out, cols, ", ", [&](int col) {
|
||||
out += vec_rows + " " + std::string(geom_field_name(col));
|
||||
});
|
||||
out += ") noexcept : ";
|
||||
geom_append_joined(out, cols, ", ", [&](int col) {
|
||||
const std::string field = std::string(geom_field_name(col));
|
||||
out += field + "(" + field + ")";
|
||||
});
|
||||
out += " {}\n";
|
||||
out += "};\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_matrix_new(std::string& out, GeomMatFamilySpec spec, int cols, int rows) {
|
||||
const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows);
|
||||
const std::string vec_rows = geom_vec_name(spec.vec_prefix, rows);
|
||||
|
||||
out += "inline " + mat_name + " " + mat_name + "_new(";
|
||||
bool first = true;
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
if (!first) {
|
||||
out += ", ";
|
||||
}
|
||||
first = false;
|
||||
out += std::string(spec.scalar) + " ";
|
||||
out += std::string(geom_field_name(col));
|
||||
out += std::string(geom_field_name(row));
|
||||
}
|
||||
}
|
||||
out += ") noexcept {\n";
|
||||
geom_append_matrix_return(out, mat_name, vec_rows, cols, rows, [&](int col, int row) {
|
||||
return std::string(geom_field_name(col)) + std::string(geom_field_name(row));
|
||||
});
|
||||
out += "}\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_matrix_base_operators(std::string& out, GeomMatFamilySpec spec, int cols, int rows) {
|
||||
const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows);
|
||||
const std::string scalar = std::string(spec.scalar);
|
||||
const std::string vec_cols = geom_vec_name(spec.vec_prefix, cols);
|
||||
const std::string vec_rows = geom_vec_name(spec.vec_prefix, rows);
|
||||
|
||||
out += "inline " + mat_name + " operator+(" + mat_name + " A, " + mat_name + " B) noexcept {\n";
|
||||
geom_append_matrix_column_return(out, mat_name, cols, [&](int col) {
|
||||
const std::string field = std::string(geom_field_name(col));
|
||||
return "A." + field + " + B." + field;
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + mat_name + " operator-(" + mat_name + " A, " + mat_name + " B) noexcept {\n";
|
||||
geom_append_matrix_column_return(out, mat_name, cols, [&](int col) {
|
||||
const std::string field = std::string(geom_field_name(col));
|
||||
return "A." + field + " - B." + field;
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + mat_name + " operator-(" + mat_name + " A) noexcept {\n";
|
||||
geom_append_matrix_column_return(out, mat_name, cols, [&](int col) {
|
||||
return "-A." + std::string(geom_field_name(col));
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + mat_name + " operator*(" + mat_name + " A, " + scalar + " B) noexcept {\n";
|
||||
geom_append_matrix_column_return(out, mat_name, cols, [&](int col) {
|
||||
return "A." + std::string(geom_field_name(col)) + " * B";
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + mat_name + " operator*(" + scalar + " A, " + mat_name + " B) noexcept {\n";
|
||||
out += " return B * A;\n}\n\n";
|
||||
|
||||
out += "inline " + mat_name + " operator/(" + mat_name + " A, " + scalar + " B) noexcept {\n";
|
||||
geom_append_matrix_column_return(out, mat_name, cols, [&](int col) {
|
||||
return "A." + std::string(geom_field_name(col)) + " / B";
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + vec_rows + " operator*(" + mat_name + " A, " + vec_cols + " B) noexcept {\n";
|
||||
geom_append_vector_return(out, vec_rows, rows, [&](int row) {
|
||||
std::string expression;
|
||||
geom_append_joined(expression, cols, " + ", [&](int col) {
|
||||
expression += "A." + std::string(geom_field_name(col));
|
||||
expression += ".";
|
||||
expression += std::string(geom_field_name(row));
|
||||
expression += " * B.";
|
||||
expression += std::string(geom_field_name(col));
|
||||
});
|
||||
return expression;
|
||||
});
|
||||
out += "}\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_matrix_transpose(std::string& out, GeomMatFamilySpec spec, int cols, int rows) {
|
||||
const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows);
|
||||
const std::string mat_transposed = geom_mat_name(spec.mat_prefix, rows, cols);
|
||||
const std::string vec_cols = geom_vec_name(spec.vec_prefix, cols);
|
||||
|
||||
out += "inline " + mat_transposed + " transpose(" + mat_name + " A) noexcept {\n";
|
||||
geom_append_matrix_return(out, mat_transposed, vec_cols, rows, cols, [&](int new_col, int new_row) {
|
||||
return "A." + std::string(geom_field_name(new_row)) + "." + std::string(geom_field_name(new_col));
|
||||
});
|
||||
out += "}\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_square_identity(std::string& out, GeomMatFamilySpec spec, int n) {
|
||||
const std::string mat_name = geom_mat_name(spec.mat_prefix, n, n);
|
||||
const std::string vec_name = geom_vec_name(spec.vec_prefix, n);
|
||||
|
||||
out += "inline constexpr " + mat_name + " " + mat_name + "_E = ";
|
||||
geom_append_constructor_call(out, mat_name, n, [&](int col) {
|
||||
std::string column;
|
||||
geom_append_constructor_call(column, vec_name, n, [&](int row) {
|
||||
return std::string(col == row ? "1" : "0");
|
||||
});
|
||||
return column;
|
||||
});
|
||||
out += ";\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_square_outer_product(std::string& out, GeomMatFamilySpec spec, int n) {
|
||||
const std::string mat_name = geom_mat_name(spec.mat_prefix, n, n);
|
||||
const std::string vec_name = geom_vec_name(spec.vec_prefix, n);
|
||||
|
||||
out += "inline " + mat_name + " outer_product(" + vec_name + " v) noexcept {\n";
|
||||
geom_append_matrix_return(out, mat_name, vec_name, n, n, [&](int col, int row) {
|
||||
const std::string col_field = std::string(geom_field_name(col));
|
||||
return "v." + col_field + " * v." + std::string(geom_field_name(row));
|
||||
});
|
||||
out += "}\n\n";
|
||||
|
||||
out += "inline " + mat_name + " " + mat_name + "_new_for_proj(" + vec_name + " v) noexcept {\n";
|
||||
out += " return outer_product(v);\n}\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_matrix_times_matrix(std::string& out, GeomMatFamilySpec spec, int n, int m, int k) {
|
||||
const std::string left_name = geom_mat_name(spec.mat_prefix, n, m);
|
||||
const std::string right_name = geom_mat_name(spec.mat_prefix, k, n);
|
||||
const std::string result_name = geom_mat_name(spec.mat_prefix, k, m);
|
||||
const std::string vec_m = geom_vec_name(spec.vec_prefix, m);
|
||||
|
||||
out += "inline " + result_name + " operator*(" + left_name + " A, " + right_name + " B) noexcept {\n";
|
||||
geom_append_matrix_return(out, result_name, vec_m, k, m, [&](int result_col, int result_row) {
|
||||
std::string expression;
|
||||
geom_append_joined(expression, n, " + ", [&](int inner) {
|
||||
expression += "A." + std::string(geom_field_name(inner));
|
||||
expression += ".";
|
||||
expression += std::string(geom_field_name(result_row));
|
||||
expression += " * B.";
|
||||
expression += std::string(geom_field_name(result_col));
|
||||
expression += ".";
|
||||
expression += std::string(geom_field_name(inner));
|
||||
});
|
||||
return expression;
|
||||
});
|
||||
out += "}\n\n";
|
||||
}
|
||||
|
||||
inline void geom_append_det_function(std::string& out, GeomMatFamilySpec spec, int n) {
|
||||
const std::string mat_name = geom_mat_name(spec.mat_prefix, n, n);
|
||||
const std::string scalar = std::string(spec.scalar);
|
||||
|
||||
out += "inline " + scalar + " det(" + mat_name + " a) noexcept {\n";
|
||||
out += " return " + [&]() {
|
||||
std::string expression;
|
||||
if (n == 2) {
|
||||
expression = "a.x.x * a.y.y - a.x.y * a.y.x";
|
||||
return expression;
|
||||
}
|
||||
geom_append_joined(expression, n, "\n ", [&](int i) {
|
||||
if (i > 0) {
|
||||
expression += "";
|
||||
}
|
||||
for (int j = 0; j < n; ++j) {
|
||||
if (j == i) {
|
||||
continue;
|
||||
}
|
||||
const int k = (n == 3) ? (3 - i - j) : -1;
|
||||
if (n == 3) {
|
||||
const bool minus =
|
||||
(((i > j) ? 1 : 0) + ((j > k) ? 1 : 0) + ((i > k) ? 1 : 0)) % 2 != 0;
|
||||
if (!expression.empty()) {
|
||||
expression += " ";
|
||||
}
|
||||
expression += minus ? "-" : "+";
|
||||
expression += " a.x.";
|
||||
expression += std::string(geom_field_name(i));
|
||||
expression += " * a.y.";
|
||||
expression += std::string(geom_field_name(j));
|
||||
expression += " * a.z.";
|
||||
expression += std::string(geom_field_name(k));
|
||||
}
|
||||
}
|
||||
if (n == 4) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
if (j == i) {
|
||||
continue;
|
||||
}
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
if (k == i || k == j) {
|
||||
continue;
|
||||
}
|
||||
const int u = 6 - i - j - k;
|
||||
const bool minus =
|
||||
(((i > j) ? 1 : 0) + ((j > k) ? 1 : 0) + ((i > k) ? 1 : 0) +
|
||||
((i > u) ? 1 : 0) + ((j > u) ? 1 : 0) + ((k > u) ? 1 : 0)) % 2 != 0;
|
||||
if (!expression.empty()) {
|
||||
expression += " ";
|
||||
}
|
||||
expression += minus ? "-" : "+";
|
||||
expression += " a.x.";
|
||||
expression += std::string(geom_field_name(i));
|
||||
expression += " * a.y.";
|
||||
expression += std::string(geom_field_name(j));
|
||||
expression += " * a.z.";
|
||||
expression += std::string(geom_field_name(k));
|
||||
expression += " * a.w.";
|
||||
expression += std::string(geom_field_name(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return expression;
|
||||
}() + ";\n}\n\n";
|
||||
}
|
||||
|
||||
inline std::string geom_build_hpp() {
|
||||
std::string out;
|
||||
out.reserve(131072);
|
||||
|
||||
out += "#pragma once\n";
|
||||
out += "/* Automatically generated file. Do not edit it. */\n\n";
|
||||
out += "#include <cmath>\n";
|
||||
out += "#include <cstdint>\n\n";
|
||||
|
||||
constexpr std::array<GeomVecFamilySpec, 6> vec_specs = {{
|
||||
{"cvec", "std::uint8_t", false},
|
||||
{"uvec", "std::uint32_t", false},
|
||||
{"s64vec", "std::int64_t", false},
|
||||
{"ivec", "std::int32_t", false},
|
||||
{"vec", "float", true},
|
||||
{"dvec", "double", true},
|
||||
}};
|
||||
|
||||
for (const GeomVecFamilySpec& spec : vec_specs) {
|
||||
for (int n = 2; n <= 4; ++n) {
|
||||
geom_append_vector_family(out, spec, n);
|
||||
}
|
||||
if (spec.geometric_methods) {
|
||||
for (int n = 2; n <= 3; ++n) {
|
||||
geom_append_vector_and_one(out, spec, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int n = 2; n <= 4; ++n) {
|
||||
out += "using s32vec" + std::to_string(n) + " = ivec" + std::to_string(n) + ";\n";
|
||||
}
|
||||
out += "\n";
|
||||
|
||||
constexpr std::array<GeomMatFamilySpec, 2> mat_specs = {{
|
||||
{"mat", "vec", "float"},
|
||||
{"s64mat", "s64vec", "std::int64_t"},
|
||||
}};
|
||||
|
||||
for (const GeomMatFamilySpec& spec : mat_specs) {
|
||||
for (int cols = 2; cols <= 4; ++cols) {
|
||||
for (int rows = 2; rows <= 4; ++rows) {
|
||||
geom_append_matrix_struct(out, spec, cols, rows);
|
||||
geom_append_matrix_new(out, spec, cols, rows);
|
||||
geom_append_matrix_base_operators(out, spec, cols, rows);
|
||||
}
|
||||
}
|
||||
for (int cols = 2; cols <= 4; ++cols) {
|
||||
for (int rows = 2; rows <= 4; ++rows) {
|
||||
geom_append_matrix_transpose(out, spec, cols, rows);
|
||||
}
|
||||
}
|
||||
for (int n = 2; n <= 4; ++n) {
|
||||
geom_append_square_identity(out, spec, n);
|
||||
geom_append_square_outer_product(out, spec, n);
|
||||
}
|
||||
for (int n = 2; n <= 4; ++n) {
|
||||
for (int m = 2; m <= 4; ++m) {
|
||||
for (int k = 2; k <= 4; ++k) {
|
||||
geom_append_matrix_times_matrix(out, spec, n, m, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int n = 2; n <= 4; ++n) {
|
||||
geom_append_det_function(out, spec, n);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline void l1_generate_geom_hpp() {
|
||||
write_text_file("l1/allie_cpp/geom.hpp", geom_build_hpp());
|
||||
}
|
||||
97
src/l1/allie_cpp/anne/utils.hpp
Normal file
97
src/l1/allie_cpp/anne/utils.hpp
Normal file
@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <string_view>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
typedef uint8_t U8;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef uint64_t U64;
|
||||
typedef int8_t S8;
|
||||
typedef int16_t S16;
|
||||
typedef int32_t S32;
|
||||
typedef int64_t S64;
|
||||
|
||||
struct allie_SpanU8 {
|
||||
const U8* data;
|
||||
U64 len;
|
||||
|
||||
explicit allie_SpanU8(std::string_view cpp_span): data(reinterpret_cast<const U8*>(cpp_span.data())), len(cpp_span.size()){}
|
||||
};
|
||||
|
||||
struct allie_VecU8 {
|
||||
const U8* buf;
|
||||
U64 len;
|
||||
};
|
||||
|
||||
struct U32Segment {
|
||||
U32 start;
|
||||
U32 len;
|
||||
};
|
||||
|
||||
struct allie_VecU32Segment {
|
||||
U32Segment* buf;
|
||||
U64 len;
|
||||
U64 capacity;
|
||||
};
|
||||
|
||||
#define ALLIE_CPP_OPAQUE(T) \
|
||||
void* opa; \
|
||||
T& operator=(T&)=delete; \
|
||||
T(T&)=delete; \
|
||||
T& operator=(T&& other) noexcept { \
|
||||
std::swap(opa, other.opa); \
|
||||
return *this; \
|
||||
} \
|
||||
T(T&& other) noexcept: opa(other.opa){ \
|
||||
other.opa = NULL; \
|
||||
}
|
||||
|
||||
void* safe_malloc(size_t n) {
|
||||
void* res = malloc(n);
|
||||
if (!res) {
|
||||
std::fprintf(stderr, "Allocation failure");
|
||||
abort();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void* safe_calloc(size_t nmemb, size_t size) {
|
||||
void* res = calloc(nmemb, size);
|
||||
if (!res) {
|
||||
std::fprintf(stderr, "Calloc died");
|
||||
abort();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class F, class DstT, class SrcT>
|
||||
concept AllieCopyingFunction = requires(F&& f, DstT& dst, const SrcT& src) {
|
||||
std::invoke(std::forward<F>(f), dst, src);
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename VecT>
|
||||
void allie_form_a_cvec_of_matching_types(VecT& dst, const std::vector<T>& src) {
|
||||
dst.len = dst.capacity = src.size();
|
||||
dst.buf = static_cast<T*>(safe_malloc( src.size() * sizeof(T) ));
|
||||
memcpy(dst.buf, src.data(), src.size() * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename DstT, typename SrcT, typename VecDstT, typename F>
|
||||
requires AllieCopyingFunction<F, DstT, SrcT>
|
||||
void allie_form_a_cvec_of_non_primitive_type(VecDstT& dst, const std::vector<SrcT>& src, F&& f) {
|
||||
dst.len = dst.capacity = src.size();
|
||||
dst.buf = static_cast<DstT*>(safe_malloc( src.size() * sizeof(DstT) ));
|
||||
for (U64 i = 0; i < src.size(); i++) {
|
||||
f(dst.buf[i], src[i]);
|
||||
}
|
||||
}
|
||||
20
src/l1/allie_cpp/codegen.hpp
Normal file
20
src/l1/allie_cpp/codegen.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
inline void write_text_file(std::string_view path_string, std::string_view text) {
|
||||
const std::filesystem::path path(path_string);
|
||||
std::ofstream out(path);
|
||||
if (!out) {
|
||||
throw std::runtime_error("failed to open " + path.string());
|
||||
}
|
||||
out << text;
|
||||
}
|
||||
|
||||
inline void touch_file(std::string_view path_string) {
|
||||
write_text_file(path_string, "");
|
||||
}
|
||||
@ -10,8 +10,12 @@ void generate_code_for_alice_on_l1(){
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("GenericMeshVertexInc"), true, true);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("ShinyMeshVertexInc"), true, true);
|
||||
|
||||
/* Helpful utils for sticking your butt into rendering mainloop (transferring stuff to device local
|
||||
* memory at the right time) */
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("RefAliceBufferUplOnce"), true, false);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("RefAliceTextureUplOnce"), true, false);
|
||||
|
||||
/* Engine stuff */
|
||||
// todo: yes, maybe right now it is not primitive but I surely will make it primitive someday. Right now I don't care
|
||||
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){
|
||||
.T = cstr("AliceGenericMeshHand"), .t_primitive = true}, true);
|
||||
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){
|
||||
@ -23,4 +27,6 @@ void generate_code_for_alice_on_l1(){
|
||||
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
|
||||
.T = cstr("GenericMeshTopology")
|
||||
});
|
||||
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("AliceTextureSlot"), true, false);
|
||||
}
|
||||
|
||||
@ -152,21 +152,13 @@ NODISCARD VecU8 codegen_name_xmatnm(SpanU8 xmat, int cols, int rows) {
|
||||
return VecU8_fmt("%s%cx%c", xmat, '0' + cols, '0' + rows);
|
||||
}
|
||||
|
||||
void codegen_append_xmatnm_struct_and_methods(VecU8* res,
|
||||
SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int cols, int rows, int sizeof_member
|
||||
) {
|
||||
void codegen_append_xmatnm_struct_and_methods(VecU8* res, SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int cols, int rows) {
|
||||
VecU8 xmatnm = codegen_name_xmatnm(xmat, cols, rows);
|
||||
VecU8 xvecm = codegen_name_xvecn(xvec, rows);
|
||||
|
||||
/* Structure xmatnm. todo: NO, std140 is NOT OUR EVERYTHING. TODO: get rid of padding
|
||||
* With columns padded to 16 bytes (for std140, std140 is our everything) */
|
||||
int sv = (rows * sizeof_member) % 16;
|
||||
VecU8_append_cstr(res, "typedef struct {\n");
|
||||
for (int x = 0; x < cols; x++) {
|
||||
VecU8_append_fmt(res, SPACE "%r %s;\n", xvecm, vec_field_name(x));
|
||||
if (sv) {
|
||||
VecU8_append_fmt(res, SPACE "char _padding_%u[%u];\n", (U64)x, (U64)(16 - sv));
|
||||
}
|
||||
}
|
||||
VecU8_append_fmt(res, "} %r;\n\n", xmatnm);
|
||||
/* xmatnm_new method */
|
||||
@ -503,12 +495,10 @@ void codegen_append_xvec234_structs_and_cool_methods(VecU8* res, SpanU8 xvec, Sp
|
||||
codegen_append_xvec3_method_cross(res, xvec);
|
||||
}
|
||||
|
||||
void codegen_append_xmat234x234_structs_and_base_methods(VecU8* res,
|
||||
SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int sizeof_member
|
||||
){
|
||||
void codegen_append_xmat234x234_structs_and_base_methods(VecU8* res,SpanU8 xmat, SpanU8 xvec, SpanU8 memb){
|
||||
for (int cols = 2; cols <= 4; cols++) {
|
||||
for (int rows = 2; rows <= 4; rows++) {
|
||||
codegen_append_xmatnm_struct_and_methods(res, xmat, xvec, memb, cols, rows, sizeof_member);
|
||||
codegen_append_xmatnm_struct_and_methods(res, xmat, xvec, memb, cols, rows);
|
||||
}
|
||||
}
|
||||
for (int cols = 2; cols <= 4; cols++) {
|
||||
@ -529,10 +519,8 @@ void codegen_append_xmat234x234_structs_and_base_methods(VecU8* res,
|
||||
codegen_append_xmat234_det_method(res, xmat, xvec, memb);
|
||||
}
|
||||
|
||||
void codegen_append_xmat234x234_structs_and_cool_methods(VecU8* res,
|
||||
SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int sizeof_member
|
||||
){
|
||||
codegen_append_xmat234x234_structs_and_base_methods(res, xmat, xvec, memb, sizeof_member);
|
||||
void codegen_append_xmat234x234_structs_and_cool_methods(VecU8* res, SpanU8 xmat, SpanU8 xvec, SpanU8 memb){
|
||||
codegen_append_xmat234x234_structs_and_base_methods(res, xmat, xvec, memb);
|
||||
codegen_append_xmat_inverse_methods(res, xmat, xvec, memb);
|
||||
}
|
||||
|
||||
@ -552,9 +540,8 @@ void generate_geom_header() {
|
||||
codegen_append_xvec234_structs_and_cool_methods(&res.result, cstr("vec"), cstr("float"), cstr("sqrtf"));
|
||||
codegen_append_xvec234_structs_and_cool_methods(&res.result, cstr("dvec"), cstr("double"), cstr("sqrt"));
|
||||
|
||||
// todo: remove padding from matrix structure. VERY IMPORTANT!!! Add padding on the fly when transferring to vulkan
|
||||
codegen_append_xmat234x234_structs_and_cool_methods(&res.result, cstr("mat"), cstr("vec"), cstr("float"), sizeof(float));
|
||||
codegen_append_xmat234x234_structs_and_base_methods(&res.result, cstr("s64mat"), cstr("s64vec"), cstr("S64"), sizeof(S64));
|
||||
codegen_append_xmat234x234_structs_and_cool_methods(&res.result, cstr("mat"), cstr("vec"), cstr("float"));
|
||||
codegen_append_xmat234x234_structs_and_base_methods(&res.result, cstr("s64mat"), cstr("s64vec"), cstr("S64"));
|
||||
|
||||
finish_header(res);
|
||||
}
|
||||
|
||||
@ -24,6 +24,10 @@ void generate_margaret_eve_for_vulkan_utils() {
|
||||
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
|
||||
.T = cstr("BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment")});
|
||||
|
||||
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretImgAllocatorOneBlock"), true, false);
|
||||
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){.T = cstr("MargaretBufAllocatorOneBlock")}, true);
|
||||
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){.T = cstr("MargaretImgAllocatorOneBlock")}, true);
|
||||
|
||||
/* Used in utilities such as Abigail */
|
||||
generate_guarded_span_company_for_primitive(l, ns, cstr("MargaretSubbuf"),
|
||||
cstr("#include \"../../../src/l2/margaret/vulkan_utils.h\"\n"), true, false);
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include "../codegen/util_template_inst.h"
|
||||
|
||||
void generate_util_temp_geom_headers() {
|
||||
SpanU8 T[] = {cstr("cvec3"), cstr("cvec4"), cstr("vec2"), cstr("vec3"), cstr("vec4"), cstr("s64vec2")};
|
||||
SpanU8 T[] = {cstr("cvec3"), cstr("cvec4"), cstr("vec2"), cstr("vec3"), cstr("vec4"), cstr("s64vec2"), cstr("ivec2")};
|
||||
for (size_t i = 0; i < ARRAY_SIZE(T); i++) {
|
||||
generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), T[i],
|
||||
cstr("#include \"geom.h\"\n"), true, true);
|
||||
|
||||
@ -73,4 +73,8 @@ void generate_util_temp_very_base_headers() {
|
||||
|
||||
generate_Option_templ_inst_eve_header(l, ns,
|
||||
(option_template_instantiation_op){.T = cstr("Json"), .t_clonable = false});
|
||||
|
||||
mkdir_nofail("l1/gui");
|
||||
generate_guarded_span_company_for_primitive(l, cstr("gui"), cstr("MutRefWidget"),
|
||||
cstr("#include \"../../../src/l2/gui/widget.h\""), true, false);
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ NODISCARD VecU8 generate_List_template_instantiation(list_instantiation_op op, b
|
||||
"} List%s;\n\n", /* op.T */
|
||||
op.T, op.T);
|
||||
VecU8_append_fmt(&res,
|
||||
"#define List%s_new() {0}\n\n" /* op.T */
|
||||
"#define List%s_new() ((List%s){0})\n\n" /* op.T, op.T */
|
||||
"void List%s_drop(List%s self) {\n" /* op.T, op.T */
|
||||
SPACE "ListNode%s* cur = self.first;\n" /* op.T */
|
||||
SPACE "while (cur){\n"
|
||||
@ -40,7 +40,7 @@ NODISCARD VecU8 generate_List_template_instantiation(list_instantiation_op op, b
|
||||
SPACE SPACE "cur = next;\n"
|
||||
SPACE "}\n"
|
||||
"}\n\n",
|
||||
op.T, op.T, op.T, op.T, op.T,
|
||||
op.T, op.T, op.T, op.T, op.T, op.T,
|
||||
op.t_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE "%s_drop(cur->el);\n", op.T));
|
||||
VecU8_append_fmt(&res,
|
||||
"ListNode%s* List%s_insert(List%s* self, %s el) {\n" /* op.T, op.T, op.T, op.T */
|
||||
|
||||
@ -46,7 +46,7 @@ mat4 marie_mat3_to_mat4_transposed(mat3 A) {
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 marie_3d_rot_mat4(vec3 r, double a) {
|
||||
mat4 marie_3d_rot_mat4(vec3 r, float a) {
|
||||
return marie_mat3_to_mat4(marie_3d_rot_mat3(r, a));
|
||||
}
|
||||
|
||||
@ -100,3 +100,26 @@ mat4 marie_3d_scal_mat4(float scale){
|
||||
vec2 ivec2_to_vec2(ivec2 v){
|
||||
return (vec2){(float)v.x, (float)v.y};
|
||||
}
|
||||
|
||||
uvec2 ivec2_to_uvec2(ivec2 v) {
|
||||
return (uvec2){v.x, v.y};
|
||||
}
|
||||
|
||||
ivec2 uvec2_to_ivec2(uvec2 v) {
|
||||
return (ivec2){(S32)v.x, (S32)v.y};
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
ivec2 lt, rb;
|
||||
} BorderS32;
|
||||
|
||||
bool BorderS32_empty(BorderS32 self){
|
||||
return self.lt.x >= self.rb.x || self.lt.y >= self.rb.y;
|
||||
}
|
||||
|
||||
BorderS32 BorderS32_intersect(BorderS32 a, BorderS32 b){
|
||||
return (BorderS32){
|
||||
{MAX_S32(a.lt.x, b.lt.x), MAX_S32(a.lt.y, b.lt.y)},
|
||||
{MIN_S32(a.rb.x, b.rb.x), MIN_S32(a.rb.y, b.rb.y)},
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,7 +34,6 @@ GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) {
|
||||
|
||||
/* non-primitive */
|
||||
typedef struct {
|
||||
VecU8 diffuse_texture_path;
|
||||
VecU8 normal_texture_path;
|
||||
VecU8 specular_texture_path;
|
||||
} AliceGenericMeshTexturePaths;
|
||||
@ -124,10 +123,8 @@ typedef struct {
|
||||
#define pipeline_0_ubo_point_light_max_count 120
|
||||
#define pipeline_0_ubo_spotlight_max_count 20
|
||||
|
||||
/* This structure will be coupled with point_light and spotlight arrays */
|
||||
typedef struct {
|
||||
int point_light_count;
|
||||
int spotlight_count;
|
||||
char _padding_1[8];
|
||||
Pipeline0PointLight point_light_arr[pipeline_0_ubo_point_light_max_count];
|
||||
Pipeline0Spotlight spotlight_arr[pipeline_0_ubo_spotlight_max_count];
|
||||
S32 point_light_count;
|
||||
S32 spotlight_count;
|
||||
} Pipeline0UBO;
|
||||
|
||||
32
src/l2/alice/camera.h
Normal file
32
src/l2/alice/camera.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../gen/l1/geom.h"
|
||||
|
||||
typedef struct {
|
||||
float fov;
|
||||
mat3 cam_basis;
|
||||
vec3 pos;
|
||||
} AliceCam;
|
||||
|
||||
typedef struct{
|
||||
AliceCam cam;
|
||||
float sensitivity;
|
||||
float pitch_cap;
|
||||
} AliceCamVerticalControl;
|
||||
|
||||
AliceCamVerticalControl AliceCamVerticalControl_new() {
|
||||
return (AliceCamVerticalControl){
|
||||
.cam.fov = 1.5f, .cam.cam_basis = marie_simple_camera_rot_m_basis_in_cols(0, 0, 0), .cam.pos = {0, 0, 0},
|
||||
.sensitivity = 0.5f * M_PIf / 180, .pitch_cap = M_PIf * 0.49f
|
||||
};
|
||||
}
|
||||
|
||||
void AliceCamVerticalControl_update_direction(
|
||||
AliceCamVerticalControl* self, int win_width, int win_height, float pointer_x, float pointer_y) {
|
||||
float yaw = ((float)win_width / 2 - pointer_x) * self->sensitivity;
|
||||
float pitch = marie_clamp_float(
|
||||
((float)win_height / 2 - pointer_y) * self->sensitivity,
|
||||
-self->pitch_cap, self->pitch_cap
|
||||
);
|
||||
self->cam.cam_basis = marie_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
73
src/l2/alice/transfer_in_mainloop.h
Normal file
73
src/l2/alice/transfer_in_mainloop.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
/* I sometimes call this sub-namespace of Alice namespace Abigail. Though I hadn't renamed it to Abigail yet.
|
||||
* Abigail does not depend on Alice Engine. It only depends on margaret. So systems like Lucy can use it
|
||||
* without creating any sus circular dependencies.
|
||||
*/
|
||||
|
||||
#include "../margaret/vulkan_utils.h"
|
||||
#include "../../../gen/l1/margaret/VecMargaretSubbuf.h"
|
||||
|
||||
typedef struct {
|
||||
U64 count;
|
||||
MargaretSubbuf staging;
|
||||
MargaretSubbuf device_local;
|
||||
} PatriciaBuf;
|
||||
|
||||
typedef struct {
|
||||
VecMargaretSubbuf to_del;
|
||||
} Abigail;
|
||||
|
||||
/* You know the deal, the buffer, returned in ret_dev_local_buf, cannot be deleted in the same `_another_frame`
|
||||
* callback as this function was called. And it should be obvious that this function can only be called when the
|
||||
* frame is not in flight. And ret_mapped_staging region is guaranteed to be len bytes long, also, it cannot be
|
||||
* used when current init/another_frame phase is over
|
||||
*/
|
||||
MargaretSubbuf /* ret_dev_local_buf */ Abigail_register_new_buffer(Abigail* self, U64 len,
|
||||
VkCommandBuffer transfer_cmd_buffer, MargaretBufAllocator* staging_buffers, MargaretBufAllocator* dev_local_buffers,
|
||||
void** ret_mapped_staging
|
||||
) {
|
||||
MargaretSubbuf staging = MargaretBufAllocator_alloc(staging_buffers, len);
|
||||
MargaretSubbuf dev_local = MargaretBufAllocator_alloc(dev_local_buffers, len);
|
||||
margaret_rec_cmd_copy_buffer_one_to_one(transfer_cmd_buffer, &staging, &dev_local);
|
||||
*ret_mapped_staging = MargaretSubbuf_get_mapped(&staging);
|
||||
VecMargaretSubbuf_append(&self->to_del, staging);
|
||||
return dev_local;
|
||||
}
|
||||
|
||||
/* Same deal as Abigail_register_new_buffer, but for textures. I say textures, because returned object also includes
|
||||
* VkImageView, created for this image.
|
||||
* Returned device localimage cannot be deleted in the same 'no-frame-in-flight' stage. We have to wait for it
|
||||
* to undergo copying, only then, on another frame, can you delete it. ret_mapped_staging points to staging buffer,
|
||||
* it is a memory region of width * height * pixed_sz bytes long. Here pixel_sz is a size of pixel in image of format
|
||||
* `foramt`. This memory can only be edited in the same `on-another-frame` phrase where it was given. But not later
|
||||
*/
|
||||
MargaretTexture /* ret_dev_local_texture */ Abigail_register_new_texture(Abigail* self, U64 width, U64 height, U64 pixel_sz,
|
||||
VkFormat format, VkImageUsageFlags usage,
|
||||
VkCommandBuffer transfer_cmd_buffer, MargaretBufAllocator* staging_buffers, MargaretImgAllocator* dev_local_images,
|
||||
void** ret_mapped_staging
|
||||
) {
|
||||
MargaretSubbuf staging = MargaretBufAllocator_alloc(staging_buffers, width * height * pixel_sz);
|
||||
MargaretImg dev_local = MargaretImgAllocator_alloc(dev_local_images, width, height, format, usage);
|
||||
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(transfer_cmd_buffer,
|
||||
&staging, &dev_local, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||
*ret_mapped_staging = MargaretSubbuf_get_mapped(&staging);
|
||||
VecMargaretSubbuf_append(&self->to_del, staging);
|
||||
return (MargaretTexture){.img = dev_local, .view = margaret_create_view_for_image(
|
||||
dev_local_images->device, dev_local.a.image, format, VK_IMAGE_ASPECT_COLOR_BIT)};
|
||||
}
|
||||
|
||||
void Abigail_wipe_old_staging(Abigail* self, VkDevice device, MargaretBufAllocator* staging_buffers) {
|
||||
for (U64 i = 0; i < self->to_del.len; i++) {
|
||||
MargaretSubbuf staging = self->to_del.buf[i];
|
||||
MargaretBufAllocator_free(staging_buffers, staging);
|
||||
}
|
||||
self->to_del.len = 0;
|
||||
}
|
||||
|
||||
void Abigail_drop(Abigail self) {
|
||||
assert(self.to_del.len == 0);
|
||||
VecMargaretSubbuf_drop(self.to_del);
|
||||
}
|
||||
|
||||
166
src/l2/allie_cpp/alice.hpp
Normal file
166
src/l2/allie_cpp/alice.hpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include "../../l1/allie_cpp/anne/utils.hpp"
|
||||
|
||||
#include "../../../gen/l1/allie_cpp/geom.hpp"
|
||||
|
||||
#include "assets.hpp"
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
|
||||
typedef void* allie_LucyFaceFixedSize;
|
||||
typedef void* allie_LucyFace;
|
||||
typedef void* allie_AliceAcknGenericMesh;
|
||||
typedef void* allie_Alice;
|
||||
|
||||
/* Actually it is RBTreeNodeLucyFaceFixedSize */
|
||||
struct LucyFaceFixedSize {
|
||||
ALLIE_CPP_OPAQUE(LucyFaceFixedSize)
|
||||
/* For internal use, don't actually use it */
|
||||
explicit LucyFaceFixedSize(void* new_opa) noexcept : opa(new_opa) {}
|
||||
/* Need to implement */
|
||||
~LucyFaceFixedSize() = default;
|
||||
};
|
||||
|
||||
struct allie_LucyGlyphCachingRequest {
|
||||
allie_LucyFaceFixedSize sized_face;
|
||||
allie_VecU32Segment codepoint_ranges;
|
||||
};
|
||||
|
||||
struct allie_VecLucyGlyphCachingRequest {
|
||||
allie_LucyGlyphCachingRequest* buf;
|
||||
U64 len;
|
||||
U64 capacity;
|
||||
};
|
||||
|
||||
struct LucyGlyphCachingRequest {
|
||||
LucyFaceFixedSize& sized_face;
|
||||
std::vector<U32Segment> codepoint_ranges;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
allie_LucyFaceFixedSize allie_LucyFace_of_size(allie_LucyFace self, U32 size);
|
||||
}
|
||||
|
||||
struct LucyFace {
|
||||
ALLIE_CPP_OPAQUE(LucyFace)
|
||||
/* For internal use, don't actually use it */
|
||||
explicit LucyFace(void* new_opa) noexcept : opa(new_opa) {}
|
||||
/* I just don't have it right now */
|
||||
~LucyFace() = default;
|
||||
|
||||
LucyFaceFixedSize of_size(U32 size) noexcept {
|
||||
return LucyFaceFixedSize{allie_LucyFace_of_size(opa, size)};
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void allie_AliceAcknGenericMesh_resize_instance_arr(allie_AliceAcknGenericMesh self, U64 new_count);
|
||||
void allie_AliceAcknGenericMesh_set_inst(allie_AliceAcknGenericMesh self, U64 index, GenericMeshInstanceInc uncomp);
|
||||
}
|
||||
|
||||
struct AliceAcknGenericMesh {
|
||||
/* ListNodeAliceGenericMeshHand */
|
||||
ALLIE_CPP_OPAQUE(AliceAcknGenericMesh)
|
||||
explicit AliceAcknGenericMesh(void* opa): opa(opa){}
|
||||
|
||||
// todo: implement
|
||||
~AliceAcknGenericMesh() = default;
|
||||
|
||||
void resize_instance_arr(U64 new_count) noexcept {
|
||||
allie_AliceAcknGenericMesh_resize_instance_arr(opa, new_count);
|
||||
}
|
||||
|
||||
void set_inst(U64 index, GenericMeshInstanceInc uncomp) noexcept {
|
||||
allie_AliceAcknGenericMesh_set_inst(opa, index, uncomp);
|
||||
}
|
||||
};
|
||||
|
||||
struct Alice;
|
||||
|
||||
struct AliceCallbacks {
|
||||
void* guest;
|
||||
/* guest data, button, button action (wl_pointer_button_state) */
|
||||
void (*on_wl_pointer_button)(void*, U32, U32);
|
||||
/* guest data, keysym, key action (wl_keyboard_key_state) */
|
||||
void (*on_wl_keyboard_key)(void*, U32, U32);
|
||||
void (*on_another_frame)(void*, float);
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
allie_Alice allie_Alice_new();
|
||||
void allie_Alice_mainloop(allie_Alice, const AliceCallbacks*);
|
||||
allie_LucyFace allie_Alice_new_LucyFace(allie_Alice alice, allie_SpanU8 path);
|
||||
void allie_Alice_lucy_cache_add_glyphs(allie_Alice alice, allie_VecLucyGlyphCachingRequest req);
|
||||
void allie_Alice_lucy_renderer_add_simple_label(allie_Alice alice, void* ffs,
|
||||
vec4 color, S32 additional_y_advance, allie_SpanU8 text, ivec2 start_pos);
|
||||
U32 allie_Alice_load_r8g8b8a8_texture(allie_Alice alice, allie_SpanU8 file_path);
|
||||
U32 allie_Alice_load_r8_texture(allie_Alice alice, allie_SpanU8 file_path);
|
||||
allie_AliceAcknGenericMesh allie_Alice_add_generic_mesh(allie_Alice alice,
|
||||
const allie_AliceGenericMeshTopology* topology, U32 diffuse_tex, U32 normal_tex, U32 specular_tex);
|
||||
}
|
||||
|
||||
struct AliceTextureSlot {
|
||||
U32 id;
|
||||
};
|
||||
|
||||
/* You are supposed to pass */
|
||||
struct Alice {
|
||||
ALLIE_CPP_OPAQUE(Alice)
|
||||
Alice() noexcept: opa(allie_Alice_new()){}
|
||||
~Alice() {
|
||||
// todo: do something about it
|
||||
}
|
||||
|
||||
void mainloop(const AliceCallbacks& callbacks) noexcept {
|
||||
allie_Alice_mainloop(opa, &callbacks);
|
||||
}
|
||||
|
||||
LucyFace new_lucy_face (std::string_view path) noexcept {
|
||||
return LucyFace{allie_Alice_new_LucyFace(opa, allie_SpanU8(path))};
|
||||
}
|
||||
|
||||
void lucy_cache_add_glyphs(std::vector<LucyGlyphCachingRequest>&& reqs) {
|
||||
allie_VecLucyGlyphCachingRequest a_reqs{};
|
||||
a_reqs.len = a_reqs.capacity = reqs.size();
|
||||
a_reqs.buf = static_cast<allie_LucyGlyphCachingRequest*>( safe_malloc(reqs.size() * sizeof(allie_LucyGlyphCachingRequest) ));
|
||||
for (U64 i = 0; i < reqs.size(); i++) {
|
||||
allie_LucyGlyphCachingRequest& a_r = a_reqs.buf[i];
|
||||
LucyGlyphCachingRequest& r = reqs[i];
|
||||
a_r.sized_face = r.sized_face.opa;
|
||||
a_r.codepoint_ranges.len = a_r.codepoint_ranges.capacity = r.codepoint_ranges.size();
|
||||
a_r.codepoint_ranges.buf = static_cast<U32Segment*>(safe_malloc( r.codepoint_ranges.size() * sizeof(U32Segment) ));
|
||||
memcpy(a_r.codepoint_ranges.buf, r.codepoint_ranges.data(), r.codepoint_ranges.size() * sizeof(U32Segment) );
|
||||
}
|
||||
allie_Alice_lucy_cache_add_glyphs(opa, a_reqs);
|
||||
}
|
||||
|
||||
void lucy_renderer_add_simple_label(LucyFaceFixedSize& ffs,
|
||||
vec4 color, S32 additional_y_advance,std::string_view text, ivec2 start_pos
|
||||
) noexcept {
|
||||
allie_Alice_lucy_renderer_add_simple_label(opa, ffs.opa,
|
||||
color, additional_y_advance, allie_SpanU8(text), start_pos);
|
||||
}
|
||||
|
||||
AliceTextureSlot load_r8g8b8a8_texture(std::string_view path) {
|
||||
return {.id = allie_Alice_load_r8g8b8a8_texture(opa, allie_SpanU8(path))};
|
||||
}
|
||||
|
||||
AliceTextureSlot load_r8_texture(std::string_view path) {
|
||||
return {.id = allie_Alice_load_r8_texture(opa, allie_SpanU8(path))};
|
||||
}
|
||||
|
||||
AliceAcknGenericMesh add_generic_mesh(
|
||||
const AliceGenericMeshTopology& top,
|
||||
AliceTextureSlot& diffuse_tex, AliceTextureSlot& normal_tex, AliceTextureSlot& specular_tex) {
|
||||
|
||||
allie_AliceGenericMeshTopology a_top{};
|
||||
allie_form_a_cvec_of_matching_types<AliceGenericMeshVertexInc, allie_VecAliceGenericMeshVertexInc>(a_top.vertices, top.vertices);
|
||||
allie_form_a_cvec_of_matching_types<U32, allie_VecU32>(a_top.indexes, top.indexes);
|
||||
|
||||
allie_AliceAcknGenericMesh hand = allie_Alice_add_generic_mesh(opa, &a_top,
|
||||
diffuse_tex.id, normal_tex.id, specular_tex.id);
|
||||
|
||||
free(a_top.vertices.buf);
|
||||
free(a_top.indexes.buf);
|
||||
return AliceAcknGenericMesh(hand);
|
||||
}
|
||||
};
|
||||
57
src/l2/allie_cpp/assets.hpp
Normal file
57
src/l2/allie_cpp/assets.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../gen/l1/allie_cpp/geom.hpp"
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
struct AliceGenericMeshVertexInc {
|
||||
vec3 pos;
|
||||
vec2 tex;
|
||||
};
|
||||
|
||||
struct allie_VecAliceGenericMeshVertexInc {
|
||||
AliceGenericMeshVertexInc* buf;
|
||||
U64 len;
|
||||
U64 capacity;
|
||||
};
|
||||
|
||||
struct allie_VecU32 {
|
||||
U32* buf;
|
||||
U64 len;
|
||||
U64 capacity;
|
||||
};
|
||||
|
||||
struct allie_AliceGenericMeshTopology {
|
||||
allie_VecAliceGenericMeshVertexInc vertices;
|
||||
allie_VecU32 indexes;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
allie_AliceGenericMeshTopology allie_alice_expect_read_generic_mesh_from_file(allie_SpanU8 file_path);
|
||||
}
|
||||
|
||||
struct AliceGenericMeshTopology {
|
||||
std::vector<AliceGenericMeshVertexInc> vertices;
|
||||
std::vector<U32> indexes;
|
||||
};
|
||||
|
||||
AliceGenericMeshTopology alice_expect_read_generic_mesh_from_file(std::string_view file_path) {
|
||||
allie_AliceGenericMeshTopology a_top = allie_alice_expect_read_generic_mesh_from_file(allie_SpanU8(file_path));
|
||||
AliceGenericMeshTopology top{};
|
||||
top.vertices.resize(a_top.vertices.len);
|
||||
memcpy(top.vertices.data(), a_top.vertices.buf, a_top.vertices.len * sizeof(AliceGenericMeshVertexInc));
|
||||
|
||||
top.indexes.resize(a_top.indexes.len);
|
||||
memcpy(top.indexes.data(), a_top.indexes.buf, a_top.indexes.len * sizeof(U32));
|
||||
return top;
|
||||
}
|
||||
|
||||
struct GenericMeshInstanceInc {
|
||||
mat4 model_t;
|
||||
};
|
||||
|
||||
|
||||
// struct AliceShinyMeshVertexInc {
|
||||
// vec3 pos;
|
||||
// vec3 color;
|
||||
// };
|
||||
59
src/l2/allie_cpp/glue.c
Normal file
59
src/l2/allie_cpp/glue.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include "../alice/engine.h"
|
||||
|
||||
Alice* allie_Alice_new(){
|
||||
return Alice_new();
|
||||
}
|
||||
|
||||
void allie_Alice_mainloop(Alice* self, const AliceCallbacks* callbacks) {
|
||||
Alice_mainloop(self, callbacks);
|
||||
}
|
||||
|
||||
void allie_Alice_drop(Alice* self) {
|
||||
// todo: implment
|
||||
}
|
||||
|
||||
LucyFace* allie_Alice_new_LucyFace(Alice* alice, SpanU8 path) {
|
||||
return Alice_new_LucyFace(alice, VecU8_from_span(path));
|
||||
}
|
||||
|
||||
|
||||
RBTreeNodeLucyFaceFixedSize* allie_LucyFace_of_size(LucyFace* self, U32 size) {
|
||||
return LucyFace_of_size(self, size);
|
||||
}
|
||||
|
||||
void allie_Alice_lucy_cache_add_glyphs(Alice* alice, VecLucyGlyphCachingRequest req) {
|
||||
Alice_lucy_cache_add_glyphs(alice, req);
|
||||
}
|
||||
|
||||
void allie_Alice_lucy_renderer_add_simple_label(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs,
|
||||
vec4 color, S32 additional_y_advance, SpanU8 text, ivec2 start_pos
|
||||
) {
|
||||
Alice_lucy_renderer_add_simple_label(alice, ffs, color, additional_y_advance, text, start_pos);
|
||||
}
|
||||
|
||||
/* This has nothing to do with game engine API, GenericMeshTopology is just a datatype that holds model data */
|
||||
GenericMeshTopology allie_alice_expect_read_generic_mesh_from_file(SpanU8 file_path) {
|
||||
return alice_expect_read_generic_mesh_from_file(VecU8_from_span(file_path));
|
||||
}
|
||||
|
||||
U32 allie_Alice_load_r8g8b8a8_texture(Alice* alice, SpanU8 file_path) {
|
||||
return Alice_load_r8g8b8a8_texture(alice, VecU8_from_span(file_path));
|
||||
}
|
||||
|
||||
U32 allie_Alice_load_r8_texture(Alice* alice, SpanU8 file_path) {
|
||||
return Alice_load_r8_texture(alice, VecU8_from_span(file_path));
|
||||
}
|
||||
|
||||
|
||||
AliceAcknGenericMesh allie_Alice_add_generic_mesh(Alice* alice,
|
||||
const GenericMeshTopology* top, U32 diffuse_tex_slot, U32 normal_tex_slot, U32 specular_tex_slot) {
|
||||
return Alice_add_generic_mesh(alice, top, diffuse_tex_slot, normal_tex_slot, specular_tex_slot);
|
||||
}
|
||||
|
||||
void allie_AliceAcknGenericMesh_resize_instance_arr(AliceAcknGenericMesh self, U64 new_count) {
|
||||
AliceAcknGenericMesh_resize_instance_arr(self, new_count);
|
||||
}
|
||||
|
||||
void allie_AliceAcknGenericMesh_set_inst(AliceAcknGenericMesh self, U64 index, GenericMeshInstanceInc uncomp) {
|
||||
AliceAcknGenericMesh_set_inst(self, index, uncomp);
|
||||
}
|
||||
127
src/l2/allie_cpp/graphics_geom.hpp
Normal file
127
src/l2/allie_cpp/graphics_geom.hpp
Normal file
@ -0,0 +1,127 @@
|
||||
/* This is just the exact copy of l1_5/marie/graphics_geom.h */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../../gen/l1/allie_cpp/geom.hpp"
|
||||
|
||||
// todo: rewrite this shit after I rewrite
|
||||
|
||||
mat4 marie_translation_mat4(vec3 vec) {
|
||||
return mat4_new(
|
||||
1, 0, 0, vec.x,
|
||||
0, 1, 0, vec.y,
|
||||
0, 0, 1, vec.z,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat2 marie_2d_rot_mat2(float a) {
|
||||
float cosa = cosf(a);
|
||||
float sina = sinf(a);
|
||||
return mat2_new(
|
||||
cosa, -sina,
|
||||
sina, cosa);
|
||||
}
|
||||
|
||||
mat3 marie_3d_rot_mat3(vec3 r, float a) {
|
||||
float cosa = cosf(a);
|
||||
float sina = sinf(a);
|
||||
return mat3_new(
|
||||
r.x * r.x * (1 - cosa) + cosa, r.x * r.y * (1 - cosa) - sina * r.z, r.x * r.z * (1 - cosa) + sina * r.y,
|
||||
r.x * r.y * (1 - cosa) + sina * r.z, r.y * r.y * (1 - cosa) + cosa, r.y * r.z * (1 - cosa) - sina * r.x,
|
||||
r.x * r.z * (1 - cosa) - sina * r.y, r.y * r.z * (1 - cosa) + sina * r.x, r.z * r.z * (1 - cosa) + cosa
|
||||
);
|
||||
}
|
||||
|
||||
mat4 marie_mat3_to_mat4(mat3 A) {
|
||||
return mat4_new(
|
||||
A.x.x, A.y.x, A.z.x, 0,
|
||||
A.x.y, A.y.y, A.z.y, 0,
|
||||
A.x.z, A.y.z, A.z.z, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 marie_mat3_to_mat4_transposed(mat3 A) {
|
||||
return mat4_new(
|
||||
A.x.x, A.x.y, A.x.z, 0,
|
||||
A.y.x, A.y.y, A.y.z, 0,
|
||||
A.z.x, A.z.y, A.z.z, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 marie_3d_rot_mat4(vec3 r, float a) {
|
||||
return marie_mat3_to_mat4(marie_3d_rot_mat3(r, a));
|
||||
}
|
||||
|
||||
|
||||
mat4 marie_perspective_projection_mat4(float right, float top, float near, float far) {
|
||||
return mat4_new(
|
||||
near/right, 0, 0, 0,
|
||||
0, -near/top, 0, 0,
|
||||
0, 0, (far + near) / (near - far), 2 * far * near / (near - far),
|
||||
0, 0, -1, 0 );
|
||||
}
|
||||
|
||||
mat4 marie_perspective_projection_fov_mat4(float win_width, float win_height, float fov,
|
||||
float spat_frustum_near, float spat_frustum_far) {
|
||||
float right = tanf(fov / 2) * spat_frustum_near;
|
||||
float top = win_height * right / win_width;
|
||||
return marie_perspective_projection_mat4(right, top, spat_frustum_near, spat_frustum_far);
|
||||
}
|
||||
|
||||
|
||||
mat3 marie_simple_camera_rot_m_basis_in_cols(float yaw, float pitch, float roll) {
|
||||
float cos_ya = cosf(yaw);
|
||||
float sin_ya = sinf(yaw);
|
||||
float cos_pi = cosf(pitch);
|
||||
float sin_pi = sinf(pitch);
|
||||
float cos_ro = cosf(roll);
|
||||
float sin_ro = sinf(roll);
|
||||
return mat3(
|
||||
vec3{cos_ro * cos_ya + sin_ro * sin_pi * sin_ya, sin_ro * cos_pi, -cos_ro * sin_ya + sin_ro * sin_pi * cos_ya},
|
||||
vec3{-sin_ro * cos_ya + cos_ro * sin_pi * sin_ya, cos_ro * cos_pi, sin_ro * sin_ya + cos_ro * sin_pi * cos_ya},
|
||||
vec3{cos_pi * sin_ya, -sin_pi, cos_pi * cos_ya}
|
||||
);
|
||||
}
|
||||
|
||||
vec2 marie_trigonom_circle(float angle) {
|
||||
return vec2{.x=cosf(angle), .y=sinf(angle)};
|
||||
}
|
||||
|
||||
vec3 marie_normal_from_tang_space_gradient(float delt_x, float delta_z) {
|
||||
float N = 1 / sqrtf(delt_x * delt_x + delta_z * delta_z + 1);
|
||||
return vec3(-delt_x * N, N, -delta_z * N);
|
||||
}
|
||||
|
||||
mat4 marie_3d_scal_mat4(float scale){
|
||||
return mat4_new(scale, 0, 0, 0,
|
||||
0, scale, 0, 0,
|
||||
0, 0, scale, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
// vec2 ivec2_to_vec2(ivec2 v){
|
||||
// return (vec2){(float)v.x, (float)v.y};
|
||||
// }
|
||||
//
|
||||
// uvec2 ivec2_to_uvec2(ivec2 v) {
|
||||
// return uvec2{v.x, v.y};
|
||||
// }
|
||||
|
||||
// ivec2 uvec2_to_ivec2(uvec2 v) {
|
||||
// return (ivec2){(S32)v.x, (S32)v.y};
|
||||
// }
|
||||
|
||||
typedef struct{
|
||||
ivec2 lt, rb;
|
||||
} BorderS32;
|
||||
|
||||
bool BorderS32_empty(BorderS32 self){
|
||||
return self.lt.x >= self.rb.x || self.lt.y >= self.rb.y;
|
||||
}
|
||||
|
||||
BorderS32 BorderS32_intersect(BorderS32 a, BorderS32 b){
|
||||
return (BorderS32){
|
||||
{std::max(a.lt.x, b.lt.x), std::min(a.lt.y, b.lt.y)},
|
||||
{std::max(a.rb.x, b.rb.x), std::min(a.rb.y, b.rb.y)},
|
||||
};
|
||||
}
|
||||
@ -20,6 +20,7 @@ RBTreeNodeLucyFaceFixedSize* allie_alice_lucy_face_of_size(LucyFace* face, U32 h
|
||||
return LucyFace_of_size(face, height);
|
||||
}
|
||||
|
||||
// todo: rewrite this too
|
||||
/* lol */
|
||||
void allie_lucy_face_add_glyphs(RBTreeNodeLucyFaceFixedSize* face_fs, U32 start, U32 seg_len){
|
||||
VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new();
|
||||
@ -28,12 +29,12 @@ void allie_lucy_face_add_glyphs(RBTreeNodeLucyFaceFixedSize* face_fs, U32 start,
|
||||
VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){
|
||||
.sized_face = face_fs, .codepoint_ranges = ranges_needed,
|
||||
});
|
||||
LucyGlyphCache_add_glyphs(lucy_requests);
|
||||
// LucyGlyphCache_add_glyphs(lucy_requests, );
|
||||
}
|
||||
|
||||
void allie_alice_clear_text(Alice* alice){
|
||||
LucyRenderer_clear(&alice->lucy_renderer);
|
||||
}
|
||||
// void allie_alice_clear_text(Alice* alice){
|
||||
// LucyRenderer_clear(&alice->lucy_renderer);
|
||||
// }
|
||||
|
||||
void allie_alice_add_text(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs,
|
||||
float color_x, float color_y, float color_z, float color_w, const U8* text_data, U64 text_len,
|
||||
118
src/l2/drawer_2d.h
Normal file
118
src/l2/drawer_2d.h
Normal file
@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include "margaret/vulkan_utils.h"
|
||||
#include "../../gen/l1/geom.h"
|
||||
#include "../l1_5/marie/graphics_geom.h"
|
||||
|
||||
/* todo: replace vec4 color with cvec4 color */
|
||||
typedef struct {
|
||||
vec2 pos;
|
||||
vec4 color;
|
||||
} Plain2dShapeVertex;
|
||||
|
||||
typedef struct {
|
||||
MargaretEngineReference ve;
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VkPipeline pipeline;
|
||||
|
||||
U64 vertex_count;
|
||||
MargaretSubbuf staging_vbo;
|
||||
MargaretSubbuf vbo;
|
||||
bool need_to_transfer;
|
||||
} Plain2dShapeRenderer;
|
||||
|
||||
Plain2dShapeRenderer Plain2dShapeRenderer_new(MargaretEngineReference ve, SpanU8 root_dir,
|
||||
VkRenderPass render_pass, U32 renderpass_subpass) {
|
||||
VkPipelineLayout pipeline_layout;
|
||||
vkCreatePipelineLayout(ve.device, &(VkPipelineLayoutCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = (VkPushConstantRange[]){{
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT, .offset = 0, .size = sizeof(vec2)
|
||||
}},
|
||||
}, NULL, &pipeline_layout);
|
||||
|
||||
VkPipeline pipeline = margaret_create_triangle_pipeline_one_attachment(ve.device,
|
||||
render_pass, renderpass_subpass, (MargaretMostImportantPipelineOptions){
|
||||
.pipeline_layout = pipeline_layout,
|
||||
.vertex_shader_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/drawer_2d/plain/vert.spv", root_dir)),
|
||||
.fragment_shader_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/drawer_2d/plain/frag.spv", root_dir)),
|
||||
.vertexBindingDescriptionCount = 1,
|
||||
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]){
|
||||
{ .binding = 0, .stride = sizeof(Plain2dShapeVertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX } },
|
||||
.vertexAttributeDescriptionCount = 2,
|
||||
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]){
|
||||
{.location = 0, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(Plain2dShapeVertex, pos)},
|
||||
{.location = 1, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(Plain2dShapeVertex, color)},
|
||||
},
|
||||
.depthTestEnable = false, .depthWriteEnable = false, .blendEnable = true,
|
||||
});
|
||||
|
||||
return (Plain2dShapeRenderer){
|
||||
.ve = ve, .pipeline_layout = pipeline_layout, .pipeline = pipeline,
|
||||
.vertex_count = 0,
|
||||
.staging_vbo = MargaretBufAllocator_alloc(ve.staging_buffers, 67),
|
||||
.vbo = MargaretBufAllocator_alloc(ve.dev_local_buffers, 67)
|
||||
};
|
||||
}
|
||||
|
||||
void Plain2dShapeRenderer_clear(Plain2dShapeRenderer* self) {
|
||||
self->vertex_count = 0;
|
||||
}
|
||||
|
||||
/* Sadly, we don't use rbo right now. Might fix it when I get enough rizz */
|
||||
void Plain2dShapeRenderer_add_triangle(Plain2dShapeRenderer* self, vec4 color, vec2 A, vec2 B, vec2 C) {
|
||||
U64 needed_vbo_length = (self->vertex_count + 3) * sizeof(Plain2dShapeVertex);
|
||||
if (needed_vbo_length > self->staging_vbo.len) {
|
||||
MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length);
|
||||
}
|
||||
Plain2dShapeVertex* vbo_data = (Plain2dShapeVertex*)MargaretSubbuf_get_mapped(&self->staging_vbo);
|
||||
vbo_data[self->vertex_count++] = (Plain2dShapeVertex){.pos = A, .color = color};
|
||||
vbo_data[self->vertex_count++] = (Plain2dShapeVertex){.pos = B, .color = color};
|
||||
vbo_data[self->vertex_count++] = (Plain2dShapeVertex){.pos = C, .color = color};
|
||||
self->need_to_transfer = true;
|
||||
}
|
||||
|
||||
void Plain2dShapeRenderer_another_frame(Plain2dShapeRenderer* self){
|
||||
U64 needed_vbo_length = self->vertex_count * sizeof(Plain2dShapeVertex);
|
||||
if (self->vbo.len < needed_vbo_length) {
|
||||
MargaretBufAllocator_expand_or_free_old(self->ve.dev_local_buffers, &self->vbo, needed_vbo_length);
|
||||
}
|
||||
if ((self->need_to_transfer) && self->vertex_count > 0) {
|
||||
self->need_to_transfer = false;
|
||||
margaret_rec_cmd_copy_buffer_one_to_one_part(self->ve.transfer_cmd_buffer,
|
||||
&self->staging_vbo, &self->vbo, 0, needed_vbo_length);
|
||||
}
|
||||
}
|
||||
|
||||
void Plain2dShapeRenderer_frame_rec_drawing(Plain2dShapeRenderer* self,
|
||||
VkCommandBuffer drawing_cmd_buf, VkExtent2D image_extent
|
||||
){
|
||||
vkCmdBindPipeline(drawing_cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, self->pipeline);
|
||||
vkCmdBindVertexBuffers(drawing_cmd_buf, 0, 1,
|
||||
(VkBuffer[]){MargaretSubbuf_get_buffer( &self->vbo )}, (U64[]){ self->vbo.start });
|
||||
vkCmdPushConstants(drawing_cmd_buf, self->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0, sizeof(vec2), &(vec2){
|
||||
.x /* aka width */ = (float)image_extent.width, .y /* aka height */ = (float)image_extent.height });
|
||||
vkCmdDraw(drawing_cmd_buf, self->vertex_count, 1, 0, 0);
|
||||
}
|
||||
|
||||
void Plain2dShapeRenderer_add_rectangle(Plain2dShapeRenderer* self, vec4 color, vec2 start, float width, float height) {
|
||||
Plain2dShapeRenderer_add_triangle(self, color,
|
||||
(vec2){start.x + width, start.y}, start, (vec2){start.x, start.y + height});
|
||||
Plain2dShapeRenderer_add_triangle(self, color,
|
||||
(vec2){start.x + width, start.y}, (vec2){start.x, start.y + height}, (vec2){start.x + width, start.y + height});
|
||||
}
|
||||
|
||||
void Plain2dShapeRenderer_add_rect_clipped(Plain2dShapeRenderer* self, vec4 color,
|
||||
ivec2 start, S32 width, S32 height, BorderS32 border) {
|
||||
BorderS32 rect = BorderS32_intersect(border,
|
||||
(BorderS32){.lt = start, .rb.x = start.x + width, .rb.y = start.y + height});
|
||||
if (!BorderS32_empty(rect)) {
|
||||
Plain2dShapeRenderer_add_rectangle(self, color, ivec2_to_vec2(rect.lt),
|
||||
(float)(rect.rb.x - rect.lt.x), (float)(rect.rb.y - rect.lt.y));
|
||||
}
|
||||
}
|
||||
41
src/l2/gui/colorblock.h
Normal file
41
src/l2/gui/colorblock.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "../drawer_2d.h"
|
||||
#include "widget.h"
|
||||
|
||||
typedef struct {
|
||||
EmptyWidget base;
|
||||
Plain2dShapeRenderer* drawer;
|
||||
vec4 color;
|
||||
} ColorblockWidget;
|
||||
|
||||
uvec2 Widget_Table_ColorblockWidget_DRAW_PREPARE(Widget* ug, uvec2 limits) {
|
||||
return Widget_Table_EmptyWidget_DRAW_PREPARE(ug, limits);
|
||||
}
|
||||
|
||||
void Widget_Table_ColorblockWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border) {
|
||||
ColorblockWidget* self = (ColorblockWidget*)ug;
|
||||
assert_sane_widget_size(self->base.base.sz_my_choice);
|
||||
S32 width = (S32)self->base.base.sz_my_choice.x;
|
||||
S32 height = (S32)self->base.base.sz_my_choice.y;
|
||||
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color, drawing_offset, width, height, border);
|
||||
}
|
||||
|
||||
void Widget_Table_ColorblockWidget_drop(Widget* ug) {}
|
||||
|
||||
const Widget_Table Widget_Table_ColorblockWidget = {
|
||||
.DRAW_PREPARE = Widget_Table_ColorblockWidget_DRAW_PREPARE,
|
||||
.DRAW = Widget_Table_ColorblockWidget_DRAW,
|
||||
.drop = Widget_Table_ColorblockWidget_drop,
|
||||
};
|
||||
|
||||
ColorblockWidget ColorblockWidget_new(S32 width, S32 height, vec4 color, Plain2dShapeRenderer* drawer) {
|
||||
return (ColorblockWidget){.base = (EmptyWidget){.base = Widget_new(), .width = width, .height = height},
|
||||
.color = color, .drawer = drawer};
|
||||
}
|
||||
|
||||
// BoxWidget ColorblockWidget_new_box(U32 width, U32 height, vec4 color, Plain2dShapeRenderer* drawer){
|
||||
// ColorblockWidget* r = (ColorblockWidget*)safe_malloc(sizeof(ColorblockWidget));
|
||||
// *r = ColorblockWidget_new(width, height, color, drawer);
|
||||
// return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_ColorblockWidget};
|
||||
// }
|
||||
63
src/l2/gui/colorframe.h
Normal file
63
src/l2/gui/colorframe.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "../drawer_2d.h"
|
||||
#include "widget.h"
|
||||
|
||||
typedef struct {
|
||||
Widget base;
|
||||
S32 left_p, right_p, bottom_p, top_p;
|
||||
Plain2dShapeRenderer* drawer;
|
||||
vec4 color;
|
||||
MutRefWidget child;
|
||||
} ColorframeWidget;
|
||||
|
||||
uvec2 Widget_Table_ColorframeWidget_DRAW_PREPARE(Widget* ug, uvec2 limits) {
|
||||
ColorframeWidget* self = (ColorframeWidget*)ug;
|
||||
S32 taken_width = self->left_p + self->right_p;
|
||||
S32 taken_height = self->top_p + self->bottom_p;
|
||||
S32 rem_width = MAX_S32((S32)limits.x - taken_width, 0);
|
||||
S32 rem_height = MAX_S32((S32)limits.y - taken_height, 0);
|
||||
/* It can be useful even when one of the dimensions is zero */
|
||||
uvec2 child_chose = MutRefWidget_draw_prepare(self->child, (uvec2){rem_width, rem_height});
|
||||
return widget_size_min_of_all(limits, (uvec2){child_chose.x + taken_width, child_chose.y + taken_height});
|
||||
}
|
||||
|
||||
void Widget_Table_ColorframeWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border) {
|
||||
ColorframeWidget* self = (ColorframeWidget*)ug;
|
||||
S32 taken_width = self->left_p + self->right_p;
|
||||
S32 taken_height = self->top_p + self->bottom_p;
|
||||
S32 width = (S32)self->base.sz_my_choice.x;
|
||||
S32 height = (S32)self->base.sz_my_choice.y;
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
if (taken_width >= width || taken_height >= height) {
|
||||
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color, drawing_offset, width, height, border);
|
||||
} else {
|
||||
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color, drawing_offset, width, self->top_p, border);
|
||||
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color,
|
||||
(ivec2){drawing_offset.x, drawing_offset.y + self->top_p}, self->left_p, height - taken_height, border);
|
||||
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color,
|
||||
(ivec2){drawing_offset.x + width - self->right_p, drawing_offset.y + self->top_p}, self->right_p, height - taken_height, border);
|
||||
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color,
|
||||
(ivec2){drawing_offset.x, drawing_offset.y + height - self->bottom_p}, width, self->bottom_p, border);
|
||||
MutRefWidget_draw(self->child, (ivec2){drawing_offset.x + self->left_p, drawing_offset.y + self->top_p}, surface_sz, border);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget_Table_ColorframeWidget_drop(Widget* ug){}
|
||||
|
||||
const Widget_Table Widget_Table_ColorframeWidget = {
|
||||
.DRAW_PREPARE = Widget_Table_ColorframeWidget_DRAW_PREPARE,
|
||||
.DRAW = Widget_Table_ColorframeWidget_DRAW,
|
||||
.drop = Widget_Table_ColorframeWidget_drop,
|
||||
};
|
||||
|
||||
|
||||
ColorframeWidget ColorframeWidget_new(S32 left_p, S32 right_p, S32 bottom_p, S32 top_p,
|
||||
Plain2dShapeRenderer* drawer, vec4 color, MutRefWidget child
|
||||
) {
|
||||
return (ColorframeWidget){.base = Widget_new(),
|
||||
.left_p = left_p, .right_p = right_p, .bottom_p = bottom_p, .top_p = top_p,
|
||||
.drawer = drawer, .color = color, .child = child
|
||||
};
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lucy/glyph_render.h"
|
||||
|
||||
// todo: add что-то
|
||||
57
src/l2/gui/stacks.h
Normal file
57
src/l2/gui/stacks.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "widget.h"
|
||||
#include "../../../gen/l1/gui/VecMutRefWidget.h"
|
||||
#include "../../../gen/l1/VecAndSpan_S32.h"
|
||||
|
||||
typedef struct {
|
||||
Widget base;
|
||||
VecMutRefWidget children;
|
||||
VecS32 decided_positions;
|
||||
} LtoRStackWidget;
|
||||
|
||||
uvec2 Widget_Table_LtoRStackWidget_DRAW_PREPARE(Widget* ug, uvec2 limits) {
|
||||
LtoRStackWidget* self = (LtoRStackWidget*)ug;
|
||||
S32 pos = 0;
|
||||
S32 max_w = 0;
|
||||
self->decided_positions.len = 0;
|
||||
U64 n = self->children.len;
|
||||
for (U64 i = 0; i < n; i++) {
|
||||
if (pos >= (S32)limits.y)
|
||||
break;
|
||||
uvec2 child_sz = MutRefWidget_draw_prepare(self->children.buf[i], (uvec2){.x = limits.x, .y = limits.y - pos});
|
||||
max_w = MAX_S32(max_w, child_sz.x);
|
||||
VecS32_append(&self->decided_positions, pos);
|
||||
pos += (S32)child_sz.y;
|
||||
}
|
||||
return (uvec2){max_w, pos};
|
||||
}
|
||||
|
||||
void Widget_Table_LtoRStackWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border) {
|
||||
LtoRStackWidget* self = (LtoRStackWidget*)ug;
|
||||
for (U64 i = 0; i < self->decided_positions.len; i++) {
|
||||
S32 pos = self->decided_positions.buf[i];
|
||||
assert(i < self->children.len);
|
||||
MutRefWidget_draw(self->children.buf[i], (ivec2){drawing_offset.x, drawing_offset.y + pos}, surface_sz, border);
|
||||
}
|
||||
}
|
||||
|
||||
void LtoRStackWidget_drop(LtoRStackWidget self) {
|
||||
VecMutRefWidget_drop(self.children);
|
||||
VecS32_drop(self.decided_positions);
|
||||
}
|
||||
|
||||
void Widget_Table_LtoRStackWidget_drop(Widget* self) {
|
||||
LtoRStackWidget_drop(*(LtoRStackWidget*)self);
|
||||
}
|
||||
|
||||
const Widget_Table Widget_Table_LtoRStack = {
|
||||
.DRAW_PREPARE = Widget_Table_LtoRStackWidget_DRAW_PREPARE,
|
||||
.DRAW = Widget_Table_LtoRStackWidget_DRAW,
|
||||
.drop = Widget_Table_LtoRStackWidget_drop,
|
||||
};
|
||||
|
||||
LtoRStackWidget LtoRStackWidget_new() {
|
||||
return (LtoRStackWidget){.base = Widget_new(),
|
||||
.children = VecMutRefWidget_new(), .decided_positions = VecS32_new()};
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../gen/l1/geom.h"
|
||||
#include "../../l1/core/util.h"
|
||||
#include "../../l1_5/marie/graphics_geom.h"
|
||||
|
||||
#define WIDGET_DIM_INF 1000000
|
||||
|
||||
@ -17,21 +16,6 @@ void assert_sane_widget_size_limits(uvec2 max_limits){
|
||||
assert(max_limits.x <= WIDGET_DIM_INF || max_limits.y <= WIDGET_DIM_INF);
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
ivec2 lt, rb;
|
||||
} BorderS32;
|
||||
|
||||
bool BorderS32_empty(BorderS32 self){
|
||||
return self.lt.x >= self.rb.x || self.lt.y >= self.rb.y;
|
||||
}
|
||||
|
||||
BorderS32 BorderS32_intersect(BorderS32 a, BorderS32 b){
|
||||
return (BorderS32){
|
||||
{MAX_S32(a.lt.x, b.lt.x), MAX_S32(a.lt.y, b.lt.y)},
|
||||
{MAX_S32(a.rb.x, b.rb.x), MAX_S32(a.rb.y, b.rb.y)},
|
||||
};
|
||||
}
|
||||
|
||||
uvec2 widget_size_max_of_all(uvec2 a, uvec2 b){
|
||||
return (uvec2){MAX_U32(a.x, b.x), MAX_U32(a.y, b.y)};
|
||||
}
|
||||
@ -53,6 +37,7 @@ Widget Widget_new(){
|
||||
|
||||
#include "../../../gen/l1_5/eve/gui/Widget.h"
|
||||
|
||||
/* NULL can be passed here */
|
||||
uvec2 MutRefWidget_draw_prepare(MutRefWidget self, uvec2 max_limits){
|
||||
if (!self.r)
|
||||
return (uvec2){0};
|
||||
@ -61,12 +46,13 @@ uvec2 MutRefWidget_draw_prepare(MutRefWidget self, uvec2 max_limits){
|
||||
return self.r->sz_my_choice;
|
||||
}
|
||||
|
||||
/* NULL can be passed here */
|
||||
void MutRefWidget_draw(MutRefWidget self, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border){
|
||||
if (!self.r)
|
||||
return;
|
||||
if (self.r->sz_my_choice.x >= WIDGET_DIM_INF)
|
||||
abortf("Drawing widget before negotiating it's size\n");
|
||||
MutRefWidget_draw(self, drawing_offset, surface_sz, border);
|
||||
MutRefWidget_DRAW(self, drawing_offset, surface_sz, border);
|
||||
self.r->sz_my_choice = (uvec2){WIDGET_DIM_INF, 0};
|
||||
}
|
||||
|
||||
@ -74,16 +60,18 @@ void MutRefWidget_draw(MutRefWidget self, ivec2 drawing_offset, uvec2 surface_sz
|
||||
|
||||
typedef struct {
|
||||
Widget base;
|
||||
U32 width;
|
||||
U32 height;
|
||||
S32 width;
|
||||
S32 height;
|
||||
} EmptyWidget;
|
||||
|
||||
uvec2 Widget_Table_EmptyWidget_DRAW_PREPARE(Widget* ug, uvec2 limits){
|
||||
EmptyWidget* self = (EmptyWidget*)ug;
|
||||
uvec2 R = widget_size_min_of_all((uvec2){self->width, self->height}, limits);
|
||||
/* Please, do not put infinite widget into infinite box, I don't want to see what happens */
|
||||
return is_widget_size_limit_contain_inf(R) ? (uvec2){0, 0} : R;
|
||||
}
|
||||
|
||||
// todo: remove `surface_sz` argument
|
||||
void Widget_Table_EmptyWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border){}
|
||||
|
||||
void Widget_Table_EmptyWidget_drop(Widget* ug){}
|
||||
@ -94,8 +82,13 @@ const Widget_Table Widget_Table_EmptyWidget = {
|
||||
.drop = Widget_Table_EmptyWidget_drop,
|
||||
};
|
||||
|
||||
BoxWidget EmptyWidget_new_box(U32 width, U32 height){
|
||||
EmptyWidget* r = safe_malloc(sizeof(EmptyWidget));
|
||||
*r = (EmptyWidget){.base = Widget_new(), .width = width, .height = height};
|
||||
return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_EmptyWidget};
|
||||
EmptyWidget EmptyWidget_new(S32 width, S32 height) {
|
||||
assert(width >= 0 && height >= 0);
|
||||
return (EmptyWidget){.base = Widget_new(), .width = width, .height = height};
|
||||
}
|
||||
|
||||
// BoxWidget EmptyWidget_new_box(U32 width, U32 height){
|
||||
// EmptyWidget* r = safe_malloc(sizeof(EmptyWidget));
|
||||
// *r = (EmptyWidget){.base = Widget_new(), .width = width, .height = height};
|
||||
// return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_EmptyWidget};
|
||||
// }
|
||||
|
||||
@ -1,30 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "../margaret/vulkan_utils.h"
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include "../../../gen/l1/VecAndSpan_U32Segment.h"
|
||||
#include "../../../gen/l1/vulkan/VecVkDescriptorImageInfo.h"
|
||||
#include "../../../gen/l1/pixel_masses.h"
|
||||
#include "../../../gen/l1/VecAndSpan_U32.h"
|
||||
|
||||
#include "../../l1_5/core/buff_rb_tree_node.h"
|
||||
#include "../../l1_5/core/rb_tree_node.h"
|
||||
#include "../alice/transfer_in_mainloop.h"
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#define LUCY_MAX_DESCRIPTOR_COUNT 100
|
||||
|
||||
typedef U32 lucy_image_index_t;
|
||||
|
||||
typedef struct {
|
||||
/* This value is actually Option<MargaretSubbuf>. If staging_buffer is already deleted (after it is no longer used),
|
||||
* staging_buffer.len will be 0 */
|
||||
MargaretSubbuf staging_buffer;
|
||||
MargaretImg img;
|
||||
VkImageView img_view;
|
||||
MargaretTexture tex;
|
||||
U64 usage;
|
||||
/* 0 if this image isn't scheduled for deletion on th next cycle.
|
||||
* 1 if it is */
|
||||
int scheduled_for_deletion;
|
||||
/* I just could not avoid storing this here. But yeah, after the copying is done, this field stops being used */
|
||||
void* staging;
|
||||
} LucyImage;
|
||||
|
||||
#include "../../../gen/l1/eve/lucy/OptionLucyImage.h"
|
||||
@ -71,19 +64,19 @@ struct LucyFace {
|
||||
|
||||
struct LucyGlyphCache {
|
||||
MargaretEngineReference ve;
|
||||
Abigail* abigail;
|
||||
|
||||
VecOptionLucyImage image_slots;
|
||||
VkDescriptorSetLayout descriptor_set_layout;
|
||||
VkDescriptorSet descriptor_set;
|
||||
|
||||
/* to_be_freed_of_old_staging_next_cycle never intersect with to_be_copied_to_device_next_cycle */
|
||||
VecU32 to_be_freed_of_old_staging_next_cycle;
|
||||
VecU32 to_be_copied_to_device_next_cycle;
|
||||
/* deletion will be performed last */
|
||||
/* We can delete images and link images to descriptor set only when frame isn't in flight */
|
||||
VecU32 to_be_written_to_descriptor_set;
|
||||
VecU32 to_be_deleted;
|
||||
};
|
||||
|
||||
|
||||
LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve){
|
||||
LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve, Abigail* abigail){
|
||||
VkDescriptorSetLayout my_desc_set_layout;
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo set_layout_crinfo_flags = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
|
||||
@ -108,10 +101,9 @@ LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve){
|
||||
image_slots.buf[i].variant = Option_None;
|
||||
}
|
||||
return (LucyGlyphCache){
|
||||
.ve = ve, .image_slots = image_slots,
|
||||
.ve = ve, .abigail = abigail, .image_slots = image_slots,
|
||||
.descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set,
|
||||
.to_be_freed_of_old_staging_next_cycle = VecU32_new(),
|
||||
.to_be_copied_to_device_next_cycle = VecU32_new(),
|
||||
.to_be_written_to_descriptor_set = VecU32_new(),
|
||||
.to_be_deleted = VecU32_new()};
|
||||
}
|
||||
|
||||
@ -125,9 +117,8 @@ void LucyFaceFixedSize_get_rid_of_myself(LucyFaceFixedSize* self){
|
||||
LucyImage* img = &img_slot->some;
|
||||
assert(img->usage > 0);
|
||||
if (--img->usage) {
|
||||
assert(!img->scheduled_for_deletion);
|
||||
img->scheduled_for_deletion = 1;
|
||||
VecU32_append(&cache->to_be_deleted, slot_id);
|
||||
/* Nothing is written to descriptor set. And luckily, we don't have to */
|
||||
img_slot->variant = Option_None;
|
||||
}
|
||||
}
|
||||
BufRBTree_MapU32ToLucyStoredGlyph_sink(glyphs);
|
||||
@ -172,7 +163,6 @@ U32 LucyGlyphCache_add_glyphs__find_image_slot(LucyGlyphCache* cache){
|
||||
OptionLucyImage* slot = &cache->image_slots.buf[i];
|
||||
if (slot->variant == Option_None) {
|
||||
slot->variant = Option_Some;
|
||||
slot->some.scheduled_for_deletion = 0;
|
||||
slot->some.usage = 0;
|
||||
return i;
|
||||
}
|
||||
@ -189,21 +179,30 @@ void LucyGlyphCache_add_glyphs__close_img(
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
assert(img->usage > 0);
|
||||
assert(!img->scheduled_for_deletion);
|
||||
img_width = MAX_U32(img_width, 10); // Just a precaution. empty buffers aren't supported by Margaret
|
||||
img_height = MAX_U32(img_height, 10);
|
||||
VecU32_append(&cache->to_be_copied_to_device_next_cycle, img_slot_id);
|
||||
img->staging_buffer = MargaretBufAllocator_alloc(cache->ve.staging_buffers, img_width * img_height * 1);
|
||||
img->img = MargaretImgAllocator_alloc(cache->ve.dev_local_images, img_width, img_height, VK_FORMAT_R8_UNORM,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
img->img_view = margaret_create_view_for_image(cache->ve.device, img->img.a.image,
|
||||
VK_FORMAT_R8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
|
||||
img->tex = Abigail_register_new_texture(cache->abigail,
|
||||
img_width, img_height, sizeof(U8), VK_FORMAT_R8_UNORM,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, cache->ve.transfer_cmd_buffer,
|
||||
cache->ve.staging_buffers, cache->ve.dev_local_images, &(img->staging));
|
||||
assert(img->staging);
|
||||
/* We are writing to descriptor set RIGHT NOW. That is why this function, and as such
|
||||
* LucyGlyphCache_add_glyphs too, must be called when no frame is in flight */
|
||||
|
||||
vkUpdateDescriptorSets(cache->ve.device, 1, &(VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = cache->descriptor_set, .dstBinding = 0, .dstArrayElement = img_slot_id,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = &(VkDescriptorImageInfo){
|
||||
.sampler = cache->ve.nearest_sampler, .imageView = img->tex.view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
}
|
||||
}, 0, NULL);
|
||||
}
|
||||
|
||||
void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
|
||||
if (requests_for_faces.len == 0)
|
||||
return;
|
||||
LucyGlyphCache* cache = requests_for_faces.buf[0].sized_face->value.p->p;
|
||||
void LucyGlyphCache_add_glyphs(LucyGlyphCache* cache, VecLucyGlyphCachingRequest requests_for_faces){
|
||||
for (size_t fi = 0; fi < requests_for_faces.len; fi++) {
|
||||
assert(cache == requests_for_faces.buf[fi].sized_face->value.p->p);
|
||||
}
|
||||
@ -269,7 +268,6 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
|
||||
LucyPositionedStagingGlyph* p_glyph;
|
||||
one_more_chance:
|
||||
{}
|
||||
int s = 23123;
|
||||
p_glyph = &ready.buf[j];
|
||||
LucyImage* img = &VecOptionLucyImage_mat(&cache->image_slots, img_slot_id)->some;
|
||||
U64 new_width_required = p_glyph->bitmap.width + starting_x;
|
||||
@ -319,8 +317,8 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
|
||||
for (size_t j = 0; j < ready.len; j++) {
|
||||
LucyPositionedStagingGlyph* p_glyph = &ready.buf[j];
|
||||
LucyImage* image = &VecOptionLucyImage_mat(&cache->image_slots, p_glyph->img_slot_id)->some;
|
||||
U64 staging_width = image->img.width;
|
||||
U8* staging = (U8*)MargaretSubbuf_get_mapped(&image->staging_buffer);
|
||||
U64 staging_width = image->tex.img.width;
|
||||
U8* staging = (U8*)image->staging;
|
||||
for (U64 y = 0; y < p_glyph->bitmap.height; y++) {
|
||||
U64 Y = y + p_glyph->pos.y;
|
||||
for (U64 x = 0; x < p_glyph->bitmap.width; x++) {
|
||||
@ -339,62 +337,10 @@ void LucyGlyphCache_drop(LucyGlyphCache self){
|
||||
for (size_t i = 0; i < self.image_slots.len; i++) {
|
||||
assert(self.image_slots.buf[i].variant == Option_None);
|
||||
}
|
||||
VecU32_drop(self.to_be_freed_of_old_staging_next_cycle);
|
||||
VecU32_drop(self.to_be_copied_to_device_next_cycle);
|
||||
VecU32_drop(self.to_be_written_to_descriptor_set);
|
||||
VecU32_drop(self.to_be_deleted);
|
||||
}
|
||||
|
||||
void LucyGlyphCache_another_frame(LucyGlyphCache* self){
|
||||
for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) {
|
||||
U32 slot_id = self->to_be_freed_of_old_staging_next_cycle.buf[i];
|
||||
LucyImage* img = &self->image_slots.buf[slot_id].some;
|
||||
assert(img->staging_buffer.len != 0);
|
||||
MargaretBufAllocator_free(self->ve.staging_buffers, img->staging_buffer);
|
||||
img->staging_buffer.len = 0;
|
||||
}
|
||||
for (size_t i = 0; i < self->to_be_copied_to_device_next_cycle.len; i++) {
|
||||
U32 slot_id = self->to_be_copied_to_device_next_cycle.buf[i];
|
||||
OptionLucyImage* img_slot = &self->image_slots.buf[slot_id];
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
assert(img->staging_buffer.len != 0);
|
||||
if (img->scheduled_for_deletion)
|
||||
continue;
|
||||
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(self->ve.transfer_cmd_buffer,
|
||||
&img->staging_buffer, &img->img, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||
VecU32_append(&self->to_be_freed_of_old_staging_next_cycle, slot_id);
|
||||
|
||||
vkUpdateDescriptorSets(self->ve.device, 1, &(VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self->descriptor_set, .dstBinding = 0, .dstArrayElement = slot_id,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = &(VkDescriptorImageInfo){
|
||||
.sampler = self->ve.nearest_sampler, .imageView = img->img_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
}
|
||||
}, 0, NULL);
|
||||
}
|
||||
/* We technically could carry out each deletion request in O(1) and each img creation request in O(1),
|
||||
* but who cares, it's no problem going over the entire descriptor set when something get's added or deleted */
|
||||
for (size_t i = 0; i < self->to_be_deleted.len; i++) {
|
||||
U32 slot_id = self->to_be_copied_to_device_next_cycle.buf[i];
|
||||
OptionLucyImage* img_slot = &self->image_slots.buf[slot_id];
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
assert(img->scheduled_for_deletion);
|
||||
assert(img->usage == 0);
|
||||
if (img->staging_buffer.len != 0)
|
||||
MargaretBufAllocator_free(self->ve.staging_buffers, img->staging_buffer);
|
||||
MargaretImgAllocator_free(self->ve.dev_local_images, img->img.a);
|
||||
img_slot->variant = Option_None;
|
||||
}
|
||||
self->to_be_freed_of_old_staging_next_cycle.len = 0;
|
||||
self->to_be_copied_to_device_next_cycle.len = 0;
|
||||
self->to_be_deleted.len = 0;
|
||||
}
|
||||
|
||||
/* This function does not check font file for correctness, use only with trusted fonts */
|
||||
LucyFace* LucyFace_new(FT_Library lib, LucyGlyphCache* cache, VecU8 path){
|
||||
VecU8_append(&path, 0); // Making it null-terminated
|
||||
|
||||
@ -97,14 +97,12 @@ void LucyRenderer_draw_char_glyph(LucyRenderer* self, vec4 color, ivec2 pos, Luc
|
||||
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&self->cache->image_slots, glyph->img_slot_id);
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
float atlas_w = (float)img->img.width;
|
||||
float atlas_h = (float)img->img.height;
|
||||
float atlas_w = (float)img->tex.img.width;
|
||||
float atlas_h = (float)img->tex.img.height;
|
||||
ivec2 positioned = ivec2_add_ivec2(pos, glyph->bearing);
|
||||
|
||||
U64 needed_vbo_length = (self->glyphs_count + 1) * sizeof(LucyRenderInstance);
|
||||
if (self->staging_vbo.len < needed_vbo_length) {
|
||||
printf("LucyRenderer Staging Buffer: Gotta replace %lu with %lu\n",
|
||||
self->staging_vbo.len, needed_vbo_length);
|
||||
MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length);
|
||||
}
|
||||
@ -131,7 +129,7 @@ void LucyRenderer_draw_char_glyph(LucyRenderer* self, vec4 color, ivec2 pos, Luc
|
||||
*/
|
||||
void LucyRenderer_add_simple_label(
|
||||
LucyRenderer* self, RBTreeNodeLucyFaceFixedSize* ffs, vec4 color,
|
||||
U32 additional_y_advance, SpanU8 text, ivec2 start_pos
|
||||
S32 additional_y_advance, SpanU8 text, ivec2 start_pos
|
||||
){
|
||||
self->need_to_transfer = true;
|
||||
U32 font_height = ffs->key;
|
||||
@ -140,7 +138,7 @@ void LucyRenderer_add_simple_label(
|
||||
while (text.len > 0) {
|
||||
U32 codepoint = SpanU8_decode_as_utf8(&text);
|
||||
if (codepoint == (U32)'\n') {
|
||||
pos = (ivec2){start_pos.x, pos.y + (S32)font_height + (S32)additional_y_advance};
|
||||
pos = (ivec2){start_pos.x, pos.y + (S32)font_height + additional_y_advance};
|
||||
continue;
|
||||
}
|
||||
BufRBTree_MapU32ToLucyStoredGlyph *glyphs = &ffs->value.glyphs;
|
||||
|
||||
@ -34,13 +34,16 @@ typedef struct {
|
||||
U64 len;
|
||||
} MargaretSubbuf;
|
||||
|
||||
struct MargaretBufAllocatorOneBlock{
|
||||
typedef struct MargaretBufAllocator MargaretBufAllocator;
|
||||
|
||||
struct MargaretBufAllocatorOneBlock {
|
||||
BufRBTree_MapU64ToU64 occupants;
|
||||
U64 capacity;
|
||||
U64 occupation_counter;
|
||||
VkDeviceMemory mem_hand;
|
||||
VkBuffer buf_hand;
|
||||
void* mapped_memory;
|
||||
MargaretBufAllocator* p;
|
||||
};
|
||||
|
||||
void MargaretBufAllocatorOneBlock_drop(MargaretBufAllocatorOneBlock self){
|
||||
@ -52,7 +55,7 @@ void MargaretBufAllocatorOneBlock_drop(MargaretBufAllocatorOneBlock self){
|
||||
#include "../../../gen/l1/eve/margaret/VecMargaretBAFreeSegment.h"
|
||||
#include "../../../gen/l1_5/eve/margaret/BufRBTreeByLen_SetMargaretBAFreeSegment.h"
|
||||
|
||||
typedef struct {
|
||||
struct MargaretBufAllocator {
|
||||
ListMargaretBufAllocatorOneBlock blocks;
|
||||
BufRBTreeByLen_SetMargaretBAFreeSegment mem_free_space;
|
||||
VkDevice device;
|
||||
@ -61,7 +64,8 @@ typedef struct {
|
||||
U8 memory_type_id;
|
||||
U8 alignment_exp;
|
||||
bool host_visible;
|
||||
} MargaretBufAllocator;
|
||||
bool ban_non_envisaged_blocks;
|
||||
};
|
||||
|
||||
|
||||
void MargaretBufAllocator__erase_gap(
|
||||
@ -120,22 +124,26 @@ void MargaretBufAllocator__add_block(MargaretBufAllocator* self, U64 capacity){
|
||||
.occupants = BufRBTree_MapU64ToU64_new_reserved(1),
|
||||
.capacity = capacity,
|
||||
.occupation_counter = capacity,
|
||||
.mem_hand = memory, .buf_hand = buffer, .mapped_memory = mapped_memory
|
||||
});
|
||||
.mem_hand = memory, .buf_hand = buffer, .mapped_memory = mapped_memory,
|
||||
.p = self });
|
||||
}
|
||||
|
||||
MargaretBufAllocator MargaretBufAllocator_new(
|
||||
MargaretBufAllocator* MargaretBufAllocator_new(
|
||||
VkDevice device, VkPhysicalDevice physical_device,
|
||||
VkBufferUsageFlags usage, U8 memory_type_id, U8 alignment_exp, bool host_visible, U64 initial_block_size
|
||||
VkBufferUsageFlags usage,
|
||||
U8 memory_type_id, U8 alignment_exp, bool host_visible,
|
||||
U64 initial_block_size, bool ban_non_envisaged_blocks
|
||||
){
|
||||
MargaretBufAllocator self = {
|
||||
MargaretBufAllocator* self = (MargaretBufAllocator*)safe_malloc(sizeof(MargaretBufAllocator));
|
||||
*self = (MargaretBufAllocator){
|
||||
.blocks = ListMargaretBufAllocatorOneBlock_new(),
|
||||
.mem_free_space = BufRBTreeByLen_SetMargaretBAFreeSegment_new_reserved(1),
|
||||
.device = device, .physical_device = physical_device, .usage = usage, .memory_type_id = memory_type_id,
|
||||
.alignment_exp = alignment_exp, .host_visible = host_visible
|
||||
.alignment_exp = alignment_exp, .host_visible = host_visible,
|
||||
.ban_non_envisaged_blocks = ban_non_envisaged_blocks,
|
||||
};
|
||||
MargaretBufAllocator__add_block(&self, initial_block_size);
|
||||
MargaretBufAllocator__insert_gap(&self, &self.blocks.first->el, 0, initial_block_size);
|
||||
MargaretBufAllocator__add_block(self, initial_block_size);
|
||||
MargaretBufAllocator__insert_gap(self, &self->blocks.first->el, 0, initial_block_size);
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -230,6 +238,7 @@ void MargaretBufAllocator_debug(const MargaretBufAllocator* self){
|
||||
|
||||
/* Free one subbuffer, not a whole MBA :) */
|
||||
void MargaretBufAllocator_free(MargaretBufAllocator* self, MargaretSubbuf allocation){
|
||||
assert(allocation.block->p == self); // Vibe check
|
||||
U64Segment left_free_space = MargaretBufAllocator__get_left_free_space(self, &allocation);
|
||||
U64Segment right_free_space = MargaretBufAllocator__get_right_free_space(self, &allocation);
|
||||
|
||||
@ -245,7 +254,6 @@ void MargaretBufAllocator_free(MargaretBufAllocator* self, MargaretSubbuf alloca
|
||||
}
|
||||
|
||||
NODISCARD MargaretSubbuf MargaretBufAllocator_alloc(MargaretBufAllocator* self, U64 req_size){
|
||||
// MargaretBufAllocator_debug(self);
|
||||
req_size = margaret_bump_buffer_size_to_alignment(req_size, self->alignment_exp);
|
||||
|
||||
VkPhysicalDeviceMaintenance3Properties maintenance3_properties = {
|
||||
@ -261,6 +269,8 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_alloc(MargaretBufAllocator* self,
|
||||
OptionMargaretBAFreeSegment free_gap = MargaretBufAllocator__search_gap(self, req_size);
|
||||
if (free_gap.variant == Option_None) {
|
||||
assert(self->blocks.first != NULL);
|
||||
if (self->ban_non_envisaged_blocks)
|
||||
abortf("Exceeded the size of the initial memory block in a buffer allocator that bans additional blocks\n");
|
||||
U64 pitch = self->blocks.first->el.capacity;
|
||||
// Old blocks remain intact
|
||||
U64 new_capacity = MAX_U64(req_size, MIN_U64(2 * pitch, maintenance3_properties.maxMemoryAllocationSize));
|
||||
@ -274,7 +284,6 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_alloc(MargaretBufAllocator* self,
|
||||
return (MargaretSubbuf){.block = &self->blocks.first->el, 0, req_size};
|
||||
}
|
||||
MargaretBufAllocator__put_buf_to_a_gap(self, free_gap.some, req_size);
|
||||
// MargaretBufAllocator_debug(self);
|
||||
return (MargaretSubbuf){.block = free_gap.some.block, .start = free_gap.some.start, req_size};
|
||||
}
|
||||
|
||||
@ -298,14 +307,15 @@ void MargaretBufAllocator_shrink(MargaretBufAllocator* self, MargaretSubbuf* all
|
||||
* `allocation` argument was untouched. It remains a valid object, you need to deallocate it yourself
|
||||
*/
|
||||
NODISCARD MargaretSubbuf MargaretBufAllocator_expand(
|
||||
MargaretBufAllocator* self, MargaretSubbuf* allocation, U64 bigger_size){
|
||||
MargaretBufAllocator* self, MargaretSubbuf* allocation, U64 bigger_size
|
||||
){
|
||||
assert(allocation->block->p == self); // Vibe check
|
||||
bigger_size = margaret_bump_buffer_size_to_alignment(bigger_size, self->alignment_exp);
|
||||
|
||||
U64Segment right_free_space = MargaretBufAllocator__get_right_free_space(self, allocation);
|
||||
if (allocation->start + bigger_size > right_free_space.start + right_free_space.len){
|
||||
return MargaretBufAllocator_alloc(self, bigger_size);
|
||||
}
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator__erase_gap(self, allocation->block, right_free_space.start, right_free_space.len);
|
||||
MargaretBufAllocator__insert_gap(self, allocation->block,
|
||||
allocation->start + bigger_size,
|
||||
@ -358,4 +368,4 @@ void MargaretBufAllocator_expand_or_free_old(
|
||||
MargaretBufAllocator_free(self, *allocation);
|
||||
*allocation = maybe_bigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,8 +176,10 @@
|
||||
#include "../../l1_5/core/buff_rb_tree_node.h"
|
||||
#include "../../../gen/l1_5/BufRBTree_MapU64ToU64.h"
|
||||
|
||||
typedef struct{
|
||||
U64 block;
|
||||
typedef struct MargaretImgAllocatorOneBlock MargaretImgAllocatorOneBlock;
|
||||
|
||||
typedef struct {
|
||||
MargaretImgAllocatorOneBlock* block;
|
||||
U64 start;
|
||||
U64 len;
|
||||
} MargaretIAFreeSegment;
|
||||
@ -199,7 +201,7 @@ bool MargaretIAFreeSegment_less_resp_align(const MargaretIAFreeSegment* A, const
|
||||
if (A->block == B->block) {
|
||||
return A->start < B->start;
|
||||
}
|
||||
return A->block < B->block;
|
||||
return (uintptr_t)A->block < (uintptr_t)B->block;
|
||||
}
|
||||
return A_len < B_len;
|
||||
}
|
||||
@ -208,25 +210,28 @@ bool MargaretIAFreeSegment_less_resp_align(const MargaretIAFreeSegment* A, const
|
||||
/* Does not include all parameters needed for relocation. Because relocation is needed only
|
||||
* during controlled defragmentation */
|
||||
typedef struct {
|
||||
U64 block;
|
||||
MargaretImgAllocatorOneBlock* block;
|
||||
VkImage image;
|
||||
U64 start;
|
||||
} MargaretImgAllocation;
|
||||
|
||||
typedef struct MargaretImgAllocator MargaretImgAllocator;
|
||||
|
||||
/* Not primitive */
|
||||
typedef struct {
|
||||
struct MargaretImgAllocatorOneBlock {
|
||||
BufRBTree_MapU64ToU64 images;
|
||||
U64 capacity;
|
||||
U64 occupation_counter;
|
||||
VkDeviceMemory mem_hand;
|
||||
void* mapped_memory;
|
||||
} MargaretImgAllocatorOneBlock;
|
||||
MargaretImgAllocator* p;
|
||||
};
|
||||
|
||||
void MargaretImgAllocatorOneBlock_drop(MargaretImgAllocatorOneBlock self){
|
||||
BufRBTree_MapU64ToU64_drop(self.images);
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/eve/margaret/VecMargaretImgAllocatorOneBlock.h"
|
||||
#include "../../../gen/l1/eve/margaret/ListMargaretImgAllocatorOneBlock.h"
|
||||
|
||||
#include "../../../gen/l1/VecAndSpan_U8.h"
|
||||
#include "../../../gen/l1/eve/margaret/VecMargaretIAFreeSegment.h"
|
||||
@ -258,7 +263,9 @@ void MargaretMemFreeSpaceManager_drop(MargaretMemFreeSpaceManager self){
|
||||
VecU8_drop(self.set_present);
|
||||
}
|
||||
|
||||
void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){
|
||||
void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man,
|
||||
MargaretImgAllocatorOneBlock* block, U64 start, U64 len
|
||||
){
|
||||
if (len == 0)
|
||||
return;
|
||||
assert(man->set_present.len > 0);
|
||||
@ -273,7 +280,9 @@ void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man, U64 blo
|
||||
}
|
||||
}
|
||||
|
||||
void MargaretMemFreeSpaceManager_insert(MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){
|
||||
void MargaretMemFreeSpaceManager_insert(MargaretMemFreeSpaceManager* man,
|
||||
MargaretImgAllocatorOneBlock* block, U64 start, U64 len
|
||||
){
|
||||
if (len == 0)
|
||||
return;
|
||||
assert(man->set_present.len > 0); /* MargaretMemFreeSpaceManager will do that for us with 2^3 */
|
||||
@ -313,49 +322,51 @@ OptionMargaretIAFreeSegment MargaretMemFreeSpaceManager_search(
|
||||
}
|
||||
|
||||
/* VkDevice and VkPhysicalDevice stay remembered here. Don't forget that, please */
|
||||
typedef struct {
|
||||
VecMargaretImgAllocatorOneBlock blocks;
|
||||
struct MargaretImgAllocator {
|
||||
ListMargaretImgAllocatorOneBlock blocks;
|
||||
MargaretMemFreeSpaceManager mem_free_space;
|
||||
VkDevice device;
|
||||
VkPhysicalDevice physical_device;
|
||||
U8 memory_type_id;
|
||||
} MargaretImgAllocator;
|
||||
};
|
||||
|
||||
void MargaretImgAllocator__erase_gap(MargaretImgAllocator* self, U64 block_id, U64 start, U64 len){
|
||||
MargaretMemFreeSpaceManager_erase(&self->mem_free_space, block_id, start, len);
|
||||
MargaretImgAllocatorOneBlock* BLOCK = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, block_id);
|
||||
BLOCK->occupation_counter += len;
|
||||
assert(BLOCK->occupation_counter <= BLOCK->capacity);
|
||||
void MargaretImgAllocator__erase_gap(MargaretImgAllocator* self,
|
||||
MargaretImgAllocatorOneBlock* block, U64 start, U64 len
|
||||
){
|
||||
MargaretMemFreeSpaceManager_erase(&self->mem_free_space, block, start, len);
|
||||
block->occupation_counter += len;
|
||||
assert(block->occupation_counter <= block->capacity);
|
||||
}
|
||||
|
||||
void MargaretImgAllocator__insert_gap(MargaretImgAllocator* self, U64 block_id, U64 start, U64 len){
|
||||
MargaretMemFreeSpaceManager_insert(&self->mem_free_space, block_id, start, len);
|
||||
MargaretImgAllocatorOneBlock* BLOCK = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, block_id);
|
||||
assert(len <= BLOCK->occupation_counter);
|
||||
BLOCK->occupation_counter -= len;
|
||||
void MargaretImgAllocator__insert_gap(MargaretImgAllocator* self,
|
||||
MargaretImgAllocatorOneBlock* block, U64 start, U64 len
|
||||
){
|
||||
MargaretMemFreeSpaceManager_insert(&self->mem_free_space, block, start, len);
|
||||
assert(len <= block->occupation_counter);
|
||||
block->occupation_counter -= len;
|
||||
}
|
||||
|
||||
void MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){
|
||||
VkDeviceMemory memory;
|
||||
printf("DEBUG MargaretImgAllocator: allocating block of size %lu\n", capacity);
|
||||
// printf("DEBUG MargaretImgAllocator: allocating block of size %lu\n", capacity);
|
||||
check(vkAllocateMemory(self->device, &(VkMemoryAllocateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = capacity, .memoryTypeIndex = self->memory_type_id
|
||||
}, NULL, &memory) == VK_SUCCESS);
|
||||
VecMargaretImgAllocatorOneBlock_append(&self->blocks, (MargaretImgAllocatorOneBlock){
|
||||
ListMargaretImgAllocatorOneBlock_insert(&self->blocks, (MargaretImgAllocatorOneBlock){
|
||||
.images = BufRBTree_MapU64ToU64_new_reserved(1),
|
||||
.capacity = capacity,
|
||||
.occupation_counter = capacity, // sounds sus
|
||||
.mem_hand = memory,
|
||||
.mapped_memory = NULL /* not supported */});
|
||||
.mapped_memory = NULL /* not supported */, .p = self });
|
||||
}
|
||||
|
||||
/* Idk where to put it */
|
||||
void MargaretImgAllocator__debug(const MargaretImgAllocator* self){
|
||||
printf("=============================== MargaretImgAllocator ============\n"
|
||||
"All blocks: { ");
|
||||
for (size_t i = 0; i < self->blocks.len; i++) {
|
||||
printf(" %lu/%lu ", self->blocks.buf[i].occupation_counter, self->blocks.buf[i].capacity);
|
||||
for (ListNodeMargaretImgAllocatorOneBlock* i = 0; i; i = i->next) {
|
||||
printf(" %lu/%lu ", i->el.occupation_counter, i->el.capacity);
|
||||
}
|
||||
printf("}\n");
|
||||
for (size_t ai = 0; ai < self->mem_free_space.set_present.len; ai++) {
|
||||
@ -367,24 +378,25 @@ void MargaretImgAllocator__debug(const MargaretImgAllocator* self){
|
||||
assert(set->guest == alignment_exp);
|
||||
for (size_t i = 0; i < set->el.len; i++) {
|
||||
const MargaretIAFreeSegment *free_seg = &set->el.buf[i];
|
||||
printf(" Block %lu, start %lu, len %lu\n", free_seg->block, free_seg->start, free_seg->len);
|
||||
printf(" Block %p, start %lu, len %lu\n", (void*)free_seg->block, free_seg->start, free_seg->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MargaretImgAllocator MargaretImgAllocator_new(
|
||||
MargaretImgAllocator* MargaretImgAllocator_new(
|
||||
VkDevice device, VkPhysicalDevice physical_device, U8 memory_type_id, U64 initial_block_size
|
||||
){
|
||||
MargaretImgAllocator self = {
|
||||
.blocks = VecMargaretImgAllocatorOneBlock_new(),
|
||||
MargaretImgAllocator* self = (MargaretImgAllocator*)safe_malloc(sizeof(MargaretImgAllocator));
|
||||
*self = (MargaretImgAllocator){
|
||||
.blocks = ListMargaretImgAllocatorOneBlock_new(),
|
||||
.mem_free_space = MargaretMemFreeSpaceManager_new(),
|
||||
.device = device,
|
||||
.physical_device = physical_device,
|
||||
.memory_type_id = memory_type_id,
|
||||
};
|
||||
MargaretImgAllocator__add_block(&self, initial_block_size);
|
||||
MargaretImgAllocator__insert_gap(&self, 0, 0, initial_block_size);
|
||||
// MargaretImgAllocator__debug(&self);
|
||||
MargaretImgAllocator__add_block(self, initial_block_size);
|
||||
assert(self->blocks.first != NULL);
|
||||
MargaretImgAllocator__insert_gap(self, &self->blocks.first->el, 0, initial_block_size);
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -407,7 +419,7 @@ U64 MargaretImgAllocator__add_img_given_gap(
|
||||
MargaretImgAllocator__insert_gap(self, segment.block, aligned_start + required_size,
|
||||
gap_start + gap_len - (aligned_start + required_size));
|
||||
|
||||
BufRBTree_MapU64ToU64* images = &VecMargaretImgAllocatorOneBlock_mat(&self->blocks, segment.block)->images;
|
||||
BufRBTree_MapU64ToU64* images = &segment.block->images;
|
||||
bool iret = BufRBTree_MapU64ToU64_insert(images, aligned_start, required_size);
|
||||
assert(iret);
|
||||
return aligned_start;
|
||||
@ -415,7 +427,7 @@ U64 MargaretImgAllocator__add_img_given_gap(
|
||||
|
||||
U64Segment MargaretImgAllocator__get_left_free_space(
|
||||
const MargaretImgAllocator* self, MargaretImgAllocation allocation){
|
||||
const MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_at(&self->blocks, allocation.block);
|
||||
const MargaretImgAllocatorOneBlock* block = allocation.block;
|
||||
U64 occ_start = allocation.start;
|
||||
|
||||
U64 prev_occ_it = BufRBTree_MapU64ToU64_find_max_less(&block->images, allocation.start);
|
||||
@ -434,7 +446,7 @@ U64Segment MargaretImgAllocator__get_left_free_space(
|
||||
|
||||
U64Segment MargaretImgAllocator__get_right_free_space(
|
||||
const MargaretImgAllocator* self, MargaretImgAllocation allocation){
|
||||
const MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_at(&self->blocks, allocation.block);
|
||||
const MargaretImgAllocatorOneBlock* block = allocation.block;
|
||||
U64 occ_start = allocation.start;
|
||||
VkMemoryRequirements occ_memory_requirements;
|
||||
vkGetImageMemoryRequirements(self->device, allocation.image, &occ_memory_requirements);
|
||||
@ -451,27 +463,29 @@ U64Segment MargaretImgAllocator__get_right_free_space(
|
||||
return (U64Segment){.start = occ_start + occ_taken_size, .len = block->capacity - (occ_start + occ_taken_size)};
|
||||
}
|
||||
|
||||
/* Also frees blocks */
|
||||
void MargaretImgAllocator_drop(MargaretImgAllocator self){
|
||||
for (size_t bi = 0; bi < self.blocks.len; bi++) {
|
||||
vkFreeMemory(self.device, self.blocks.buf[bi].mem_hand, NULL);
|
||||
for (ListNodeMargaretImgAllocatorOneBlock* bi = self.blocks.first; bi; bi = bi->next) {
|
||||
vkFreeMemory(self.device, bi->el.mem_hand, NULL);
|
||||
}
|
||||
VecMargaretImgAllocatorOneBlock_drop(self.blocks);
|
||||
ListMargaretImgAllocatorOneBlock_drop(self.blocks);
|
||||
MargaretMemFreeSpaceManager_drop(self.mem_free_space);
|
||||
}
|
||||
|
||||
void MargaretImgAllocator_free(MargaretImgAllocator* self, MargaretImgAllocation allocation){
|
||||
assert(allocation.block->p == self); // Vibe check
|
||||
U64Segment left_free_space = MargaretImgAllocator__get_left_free_space(self, allocation);
|
||||
U64Segment right_free_space = MargaretImgAllocator__get_right_free_space(self, allocation);
|
||||
|
||||
vkDestroyImage(self->device, allocation.image, NULL);
|
||||
|
||||
MargaretImgAllocator__erase_gap(self, allocation.block, left_free_space.start, left_free_space.len);
|
||||
MargaretImgAllocator__erase_gap(self, allocation.block, right_free_space.start, right_free_space.len);
|
||||
MargaretImgAllocator__insert_gap(self, allocation.block,
|
||||
MargaretImgAllocatorOneBlock* block = allocation.block;
|
||||
MargaretImgAllocator__erase_gap(self, block, left_free_space.start, left_free_space.len);
|
||||
MargaretImgAllocator__erase_gap(self, block, right_free_space.start, right_free_space.len);
|
||||
MargaretImgAllocator__insert_gap(self, block,
|
||||
left_free_space.start,
|
||||
right_free_space.start + right_free_space.len - left_free_space.start);
|
||||
|
||||
MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, allocation.block);
|
||||
bool eret = BufRBTree_MapU64ToU64_erase(&block->images, allocation.start);
|
||||
assert(eret);
|
||||
}
|
||||
@ -514,24 +528,23 @@ NODISCARD MargaretImgAllocation MargaretImgAllocator__alloc(
|
||||
MargaretMemFreeSpaceManager_search(&self->mem_free_space, alignment_exp, mem_requirements.size);
|
||||
|
||||
if (free_gap.variant == Option_None) {
|
||||
assert(self->blocks.len > 0);
|
||||
U64 pitch = self->blocks.buf[self->blocks.len - 1].capacity;
|
||||
assert(self->blocks.first != NULL);
|
||||
U64 pitch = self->blocks.first->el.capacity;
|
||||
// Old blocks remain intact
|
||||
U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(2 * pitch, maintenance3_properties.maxMemoryAllocationSize));
|
||||
// U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(pitch, maintenance3_properties.maxMemoryAllocationSize));
|
||||
MargaretImgAllocator__add_block(self, new_capacity);
|
||||
U64 bid = self->blocks.len - 1;
|
||||
MargaretImgAllocator__insert_gap(self, bid, mem_requirements.size, new_capacity - mem_requirements.size);
|
||||
MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, bid);
|
||||
MargaretImgAllocatorOneBlock* block = &self->blocks.first->el;
|
||||
MargaretImgAllocator__insert_gap(self, block, mem_requirements.size, new_capacity - mem_requirements.size);
|
||||
block->occupation_counter = mem_requirements.size;
|
||||
bool iret = BufRBTree_MapU64ToU64_insert(&block->images, 0, mem_requirements.size);
|
||||
assert(iret);
|
||||
check(vkBindImageMemory(self->device, fresh_img, block->mem_hand, 0) == VK_SUCCESS);
|
||||
// MargaretImgAllocator__debug(self);
|
||||
return (MargaretImgAllocation){.block = bid, fresh_img, 0};
|
||||
return (MargaretImgAllocation){.block = block, fresh_img, 0};
|
||||
}
|
||||
U64 aligned_pos = MargaretImgAllocator__add_img_given_gap(self, free_gap.some, mem_requirements.size, alignment_exp);
|
||||
VkDeviceMemory memory = VecMargaretImgAllocatorOneBlock_at(&self->blocks, free_gap.some.block)->mem_hand;
|
||||
VkDeviceMemory memory = free_gap.some.block->mem_hand;
|
||||
check(vkBindImageMemory(self->device, fresh_img, memory, aligned_pos) == VK_SUCCESS);
|
||||
// MargaretImgAllocator__debug(self);
|
||||
return (MargaretImgAllocation){.block = free_gap.some.block, .image = fresh_img, .start = aligned_pos};
|
||||
|
||||
@ -145,6 +145,7 @@ void MargaretInstanceAndItsDebug_drop(MargaretInstanceAndItsDebug instance) {
|
||||
typedef struct {
|
||||
U32 for_graphics;
|
||||
U32 for_presentation;
|
||||
U32 for_compute;
|
||||
} MargaretChosenQueueFamilies;
|
||||
|
||||
/* MargaretChosenQueueFamilies or a static string, describing which part could not be found
|
||||
@ -163,13 +164,13 @@ ResultMargaretChosenQueueFamiliesOrSpanU8 margaret_choose_good_queue_families(Vk
|
||||
VecVkQueueFamilyProperties queue_families = VecVkQueueFamilyProperties_new_zeroinit(queue_family_count);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(dev, &queue_family_count, queue_families.buf);
|
||||
|
||||
OptionU32 index_for_graphics = None_U32();
|
||||
OptionU32 index_for_graph_and_comp = None_U32();
|
||||
OptionU32 index_for_presentation = None_U32();
|
||||
|
||||
for (uint32_t i = 0; i < queue_family_count; i++) {
|
||||
const VkQueueFamilyProperties* props = VecVkQueueFamilyProperties_at(&queue_families, i);
|
||||
if (props->queueFlags & VK_QUEUE_GRAPHICS_BIT && props->queueCount >= 1) {
|
||||
index_for_graphics = Some_U32(i);
|
||||
if (props->queueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT) && props->queueCount >= 1) {
|
||||
index_for_graph_and_comp = Some_U32(i);
|
||||
}
|
||||
VkBool32 isPres = false;
|
||||
if (vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, surface, &isPres) != VK_SUCCESS)
|
||||
@ -178,15 +179,45 @@ ResultMargaretChosenQueueFamiliesOrSpanU8 margaret_choose_good_queue_families(Vk
|
||||
index_for_presentation = Some_U32(i);
|
||||
}
|
||||
VecVkQueueFamilyProperties_drop(queue_families);
|
||||
if (index_for_graphics.variant == Option_None)
|
||||
return (ResultMargaretChosenQueueFamiliesOrSpanU8){ .variant = Result_Err, .err = cstr("No graphics queue family") };
|
||||
if (index_for_graph_and_comp.variant == Option_None)
|
||||
return (ResultMargaretChosenQueueFamiliesOrSpanU8){ .variant = Result_Err,
|
||||
.err = cstr("No queue family for both graphics and compute") };
|
||||
if (index_for_presentation.variant == Option_None)
|
||||
return (ResultMargaretChosenQueueFamiliesOrSpanU8){ .variant = Result_Err, .err = cstr("No presentation queue family") };
|
||||
return (ResultMargaretChosenQueueFamiliesOrSpanU8){ .variant = Result_Ok, .ok = (MargaretChosenQueueFamilies){
|
||||
.for_graphics = index_for_graphics.some, .for_presentation = index_for_presentation.some
|
||||
.for_graphics = index_for_graph_and_comp.some,
|
||||
.for_compute = index_for_graph_and_comp.some,
|
||||
.for_presentation = index_for_presentation.some
|
||||
} };
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
VkQueue graphics;
|
||||
VkQueue presentation;
|
||||
VkQueue compute;
|
||||
} MargaretUsedQueues;
|
||||
|
||||
MargaretUsedQueues margaret_get_device_queues(VkDevice device, MargaretChosenQueueFamilies family) {
|
||||
MargaretUsedQueues queues;
|
||||
vkGetDeviceQueue(device, family.for_graphics, 0, &queues.graphics);
|
||||
|
||||
if (family.for_presentation == family.for_graphics) {
|
||||
queues.presentation = queues.graphics;
|
||||
} else {
|
||||
vkGetDeviceQueue(device, family.for_presentation, 0, &queues.presentation);
|
||||
}
|
||||
|
||||
if (family.for_compute == family.for_graphics) {
|
||||
queues.compute = queues.graphics;
|
||||
} else if (family.for_compute == family.for_presentation) {
|
||||
queues.compute = queues.presentation;
|
||||
} else {
|
||||
vkGetDeviceQueue(device, family.for_compute, 0, &queues.compute);
|
||||
}
|
||||
return queues;
|
||||
}
|
||||
|
||||
|
||||
// These are not the same as instance extensions
|
||||
VecVecU8 margaret_get_extensions_of_physical_device(VkPhysicalDevice physical_device) {
|
||||
uint32_t extensions_count = 0;
|
||||
@ -311,14 +342,20 @@ VkDevice margaret_create_logical_device(VkPhysicalDevice physical_device, Margar
|
||||
float qfam_queue_priorities[1] = {1.f};
|
||||
VkDeviceQueueCreateInfo queue_crinfo[2] = { 0 };
|
||||
int queue_c = 0;
|
||||
if (queue_fam.for_graphics == queue_fam.for_presentation) {
|
||||
queue_c = 1;
|
||||
queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
|
||||
} else {
|
||||
queue_c = 2;
|
||||
queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
|
||||
queue_crinfo[1].queueFamilyIndex = queue_fam.for_presentation;
|
||||
|
||||
queue_crinfo[queue_c].queueFamilyIndex = queue_fam.for_graphics;
|
||||
queue_c++;
|
||||
|
||||
if (queue_fam.for_graphics != queue_fam.for_presentation) {
|
||||
queue_crinfo[queue_c].queueFamilyIndex = queue_fam.for_presentation;
|
||||
queue_c++;
|
||||
}
|
||||
|
||||
if (queue_fam.for_compute != queue_fam.for_presentation && queue_fam.for_compute != queue_fam.for_graphics) {
|
||||
queue_crinfo[queue_c].queueFamilyIndex = queue_fam.for_compute;
|
||||
queue_c++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < queue_c; i++) {
|
||||
queue_crinfo[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue_crinfo[i].queueCount = 1;
|
||||
@ -839,22 +876,6 @@ void MargaretSwapchainBundle_drop_with_device(VkDevice device, MargaretSwapchain
|
||||
// Now swapchain bundle is 100% dropped
|
||||
}
|
||||
|
||||
VkShaderModule margaret_VkShaderModule_new(VkDevice device, VecU8 code) {
|
||||
if (code.len < 4)
|
||||
abortf("Kill yourself, please\n");
|
||||
VkShaderModule shad_module;
|
||||
check(vkCreateShaderModule(device, &(VkShaderModuleCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = code.len,
|
||||
// Now this is funny, we can't put arbitrary byte-string here, it should be 4-byte aligned
|
||||
// Thanks goodness all the strings in VecU8 are allocated with calloc, which gives high alignment to
|
||||
// virtually everything
|
||||
.pCode = (const uint32_t*)code.buf
|
||||
}, NULL, &shad_module) == VK_SUCCESS);
|
||||
VecU8_drop(code);
|
||||
return shad_module;
|
||||
}
|
||||
|
||||
VkCommandPool margaret_create_resettable_command_pool(VkDevice device, uint32_t wanted_queue_family) {
|
||||
VkCommandPoolCreateInfo crinfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
@ -965,9 +986,11 @@ VkSampler margaret_create_sampler(VkPhysicalDevice physical_device, VkDevice dev
|
||||
}
|
||||
|
||||
VkDescriptorPool margaret_create_descriptor_set_pool(
|
||||
VkDevice device, uint32_t ubo_descriptor_count, uint32_t image_sampler_descriptor_count, uint32_t max_sets
|
||||
VkDevice device,
|
||||
uint32_t ubo_descriptor_count, uint32_t image_sampler_descriptor_count, uint32_t storage_buffer_descriptor_count,
|
||||
uint32_t max_sets
|
||||
) {
|
||||
VkDescriptorPoolSize sizes[2];
|
||||
VkDescriptorPoolSize sizes[3];
|
||||
int sizes_c = 0;
|
||||
if (ubo_descriptor_count > 0) {
|
||||
sizes[sizes_c] = (VkDescriptorPoolSize){
|
||||
@ -983,6 +1006,13 @@ VkDescriptorPool margaret_create_descriptor_set_pool(
|
||||
};
|
||||
sizes_c++;
|
||||
}
|
||||
if (storage_buffer_descriptor_count > 0) {
|
||||
sizes[sizes_c] = (VkDescriptorPoolSize){
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = storage_buffer_descriptor_count
|
||||
};
|
||||
sizes_c++;
|
||||
}
|
||||
VkDescriptorPool descriptor_pool;
|
||||
check(vkCreateDescriptorPool(device, &(VkDescriptorPoolCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
@ -1018,6 +1048,31 @@ void margaret_end_command_buffer(VkCommandBuffer command_buffer){
|
||||
check(vkEndCommandBuffer(command_buffer) == VK_SUCCESS);
|
||||
}
|
||||
|
||||
VkShaderModule margaret_VkShaderModule_new(VkDevice device, VecU8 code) {
|
||||
if (code.len < 4)
|
||||
abortf("Kill yourself, please\n");
|
||||
VkShaderModule shad_module;
|
||||
check(vkCreateShaderModule(device, &(VkShaderModuleCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = code.len,
|
||||
// Now this is funny, we can't put arbitrary byte-string here, it should be 4-byte aligned
|
||||
// Thanks goodness all the strings in VecU8 are allocated with calloc, which gives high alignment to
|
||||
// virtually everything
|
||||
.pCode = (const uint32_t*)code.buf
|
||||
}, NULL, &shad_module) == VK_SUCCESS);
|
||||
VecU8_drop(code);
|
||||
return shad_module;
|
||||
}
|
||||
|
||||
VkPipelineShaderStageCreateInfo margaret_VkPipelineShaderStageCreateInfo_init(
|
||||
VkShaderStageFlags stage, VkShaderModule module
|
||||
) {
|
||||
return (VkPipelineShaderStageCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.module = module, .stage = stage, .pName = "main",
|
||||
};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VecU8 vertex_shader_code;
|
||||
@ -1037,24 +1092,15 @@ VkPipeline margaret_create_triangle_pipeline_one_attachment(
|
||||
MargaretMostImportantPipelineOptions op
|
||||
){
|
||||
VkPipelineShaderStageCreateInfo shader_modules[3] = {
|
||||
(VkPipelineShaderStageCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.module = margaret_VkShaderModule_new(device, op.vertex_shader_code),
|
||||
.stage = VK_SHADER_STAGE_VERTEX_BIT, .pName = "main",
|
||||
},
|
||||
(VkPipelineShaderStageCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.module = margaret_VkShaderModule_new(device, op.fragment_shader_code),
|
||||
.stage = VK_SHADER_STAGE_FRAGMENT_BIT, .pName = "main",
|
||||
},
|
||||
margaret_VkPipelineShaderStageCreateInfo_init(VK_SHADER_STAGE_VERTEX_BIT,
|
||||
margaret_VkShaderModule_new(device, op.vertex_shader_code)),
|
||||
margaret_VkPipelineShaderStageCreateInfo_init(VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
margaret_VkShaderModule_new(device, op.fragment_shader_code)),
|
||||
};
|
||||
U32 shader_modules_c = 2;
|
||||
if (op.geometry_shader_code.len > 0) {
|
||||
shader_modules[shader_modules_c] = (VkPipelineShaderStageCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.module = margaret_VkShaderModule_new(device, op.geometry_shader_code),
|
||||
.stage = VK_SHADER_STAGE_GEOMETRY_BIT, .pName = "main",
|
||||
};
|
||||
shader_modules[shader_modules_c] = margaret_VkPipelineShaderStageCreateInfo_init(
|
||||
VK_SHADER_STAGE_GEOMETRY_BIT, margaret_VkShaderModule_new(device, op.geometry_shader_code)),
|
||||
shader_modules_c++;
|
||||
}
|
||||
|
||||
@ -1120,7 +1166,7 @@ VkPipeline margaret_create_triangle_pipeline_one_attachment(
|
||||
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
|
||||
@ -1146,9 +1192,21 @@ VkPipeline margaret_create_triangle_pipeline_one_attachment(
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
#include "vulkan_memory.h"
|
||||
VkPipeline margaret_create_compute_pipeline(VkDevice device, VkPipelineLayout layout, VecU8 code) {
|
||||
VkPipeline pipeline;
|
||||
VkShaderModule comp_module = margaret_VkShaderModule_new(device, code);
|
||||
vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &(VkComputePipelineCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
|
||||
.flags = 0,
|
||||
.layout = layout,
|
||||
.stage = margaret_VkPipelineShaderStageCreateInfo_init(VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
margaret_VkShaderModule_new(device, code)),
|
||||
}, NULL, &pipeline);
|
||||
vkDestroyShaderModule(device, comp_module, NULL);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
// todo: move image copying function here
|
||||
#include "vulkan_memory.h"
|
||||
|
||||
typedef struct {
|
||||
VkDevice device;
|
||||
@ -1246,3 +1304,40 @@ void margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(
|
||||
});
|
||||
dst->current_layout = dst_new_layout;
|
||||
}
|
||||
|
||||
U64 margaret_singleplane_format_to_sizeof_type(VkFormat type){
|
||||
switch (type) {
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT: return 16;
|
||||
case VK_FORMAT_R32G32B32_SFLOAT: return 12;
|
||||
case VK_FORMAT_R32G32_SFLOAT: return 8;
|
||||
case VK_FORMAT_R32_SFLOAT: return 4;
|
||||
case VK_FORMAT_R16_SFLOAT: return 2;
|
||||
case VK_FORMAT_R16G16_SFLOAT: return 4;
|
||||
case VK_FORMAT_R16G16B16_SFLOAT: return 6;
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT: return 8;
|
||||
|
||||
case VK_FORMAT_R16_UNORM: return 2;
|
||||
case VK_FORMAT_R16G16_UNORM: return 4;
|
||||
case VK_FORMAT_R16G16B16_UNORM: return 6;
|
||||
case VK_FORMAT_R16G16B16A16_UNORM: return 8;
|
||||
case VK_FORMAT_R8G8B8A8_UNORM: return 4;
|
||||
case VK_FORMAT_R8G8B8_UNORM: return 3;
|
||||
case VK_FORMAT_R8G8_UNORM: return 2;
|
||||
case VK_FORMAT_R8_UNORM: return 1;
|
||||
|
||||
|
||||
case VK_FORMAT_R32_UINT: return 4;
|
||||
case VK_FORMAT_R32G32_UINT: return 8;
|
||||
case VK_FORMAT_R32G32B32_UINT: return 12;
|
||||
case VK_FORMAT_R32G32B32A32_UINT: return 16;
|
||||
|
||||
case VK_FORMAT_R8G8B8A8_SRGB: return 4;
|
||||
default:
|
||||
abortf("Jokes on you\n");
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
MargaretImg img;
|
||||
VkImageView view;
|
||||
} MargaretTexture;
|
||||
|
||||
133
src/l3/r4/r4.c
133
src/l3/r4/r4.c
@ -3,7 +3,10 @@
|
||||
#include "../../l1_5/marie/prim_shape_geom.h"
|
||||
#include "../../../gen/l1/VecAndSpan_vec3.h"
|
||||
#include "../../l1_5/core/color.h"
|
||||
|
||||
#include "../../l2/gui/colorblock.h"
|
||||
#include "../../l2/gui/colorframe.h"
|
||||
#include "../../l2/gui/stacks.h"
|
||||
#include "../../l2/alice/camera.h"
|
||||
#include "linux/input-event-codes.h"
|
||||
|
||||
|
||||
@ -25,7 +28,7 @@ typedef struct{
|
||||
|
||||
typedef struct {
|
||||
float mass; /* In kg, Not zero */
|
||||
quad_form3_t inertia_moment; /* Qadratic form, yields kg*m^2 */
|
||||
quad_form3_t inertia_moment; /* Quadratic form, yields kg*m^2 */
|
||||
/* Center of mass relative to "center of mesh" */
|
||||
vec3 mass_center;
|
||||
} RigidBodyConfig;
|
||||
@ -83,8 +86,14 @@ typedef struct{
|
||||
Alice* alice;
|
||||
LucyFace* font_face;
|
||||
RBTreeNodeLucyFaceFixedSize* font_face_of_size_40;
|
||||
|
||||
AliceCamVerticalControl cam;
|
||||
vec3 hero_pos;
|
||||
|
||||
U32 ROA_diffuse_tex_slot;
|
||||
U32 ROA_normal_tex_slot;
|
||||
U32 ROA_specular_tex_slot;
|
||||
|
||||
ListNodeAliceGenericMeshHand* ROA_mesh;
|
||||
GenericMeshTopology ROA_topology;
|
||||
RigidBodyState ROA_state;
|
||||
@ -96,6 +105,14 @@ typedef struct{
|
||||
U64 misses_count;
|
||||
U64 hits_count;
|
||||
Vecvec3 bullets_stuck_on_ROA;
|
||||
|
||||
/* overlay ui */
|
||||
ColorblockWidget gui_0;
|
||||
ColorframeWidget gui_1;
|
||||
ColorblockWidget gui_2;
|
||||
ColorblockWidget gui_3;
|
||||
LtoRStackWidget gui_4;
|
||||
ColorframeWidget gui_5;
|
||||
} R4BetaState;
|
||||
|
||||
/* We are surrounded by a giant cubic mesh of light sources */
|
||||
@ -123,16 +140,8 @@ void physics_update(R4BetaState* st, float t){
|
||||
* m2 is the mass of bullet. `v` is the speed of bullet */
|
||||
void RigidBodyState_when_shot(RigidBodyState* self, vec3 imp, float m2, vec3 v){
|
||||
vec3 IO = vec3_minus(imp);
|
||||
float IO_norm_sq = vec3_dot(IO, IO);
|
||||
|
||||
vec3 linear_speed_gain;
|
||||
if (IO_norm_sq < 0.00001f) {
|
||||
linear_speed_gain = v;
|
||||
} else {
|
||||
vec3 v_projected = vec3_mul_scal(IO, vec3_dot(IO, v) / IO_norm_sq);
|
||||
linear_speed_gain = vec3_mul_scal(v_projected, m2 / self->p.mass);
|
||||
}
|
||||
self->speed = vec3_add_vec3(self->speed, linear_speed_gain);
|
||||
self->speed = vec3_add_vec3(self->speed, vec3_mul_scal(v, m2 / self->p.mass));
|
||||
|
||||
|
||||
vec3 www = vec3_mul_scal(vec3_cross(v, IO), m2);
|
||||
@ -146,8 +155,8 @@ void main_h_on_wl_pointer_button(void* data, U32 button, U32 act){
|
||||
R4BetaState *st = data;
|
||||
Alice* alice = st->alice;
|
||||
if (button == BTN_LEFT && act == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
vec3 P = alice->cam_info.cam.pos;
|
||||
vec3 dir = vec3_minus(alice->cam_info.cam.cam_basis.z);
|
||||
vec3 P = st->cam.cam.pos;
|
||||
vec3 dir = vec3_minus(st->cam.cam.cam_basis.z);
|
||||
vec3 Q = vec3_add_vec3(P, dir);
|
||||
bool hit = false;
|
||||
vec3 impact;
|
||||
@ -222,11 +231,27 @@ void main_h_on_wl_keyboard_key(void* data, U32 keysym, U32 act){
|
||||
}
|
||||
}
|
||||
|
||||
void main_h_on_wl_pointer_motion(void* data, vec2 pos) {
|
||||
R4BetaState* st = data;
|
||||
ivec2 win_sz = Alice_get_wl_confirmed_win_sz(st->alice);
|
||||
AliceCamVerticalControl_update_direction(&st->cam, win_sz.x, win_sz.y, pos.x, pos.y);
|
||||
}
|
||||
|
||||
// todo: fuck, return this to Alice. Frustum config is needed in uh, later it will be needed
|
||||
mat4 get_t_mat(R4BetaState* st) {
|
||||
ivec2 win_sz = Alice_get_wl_confirmed_win_sz(st->alice);
|
||||
mat4 projection_matrix = marie_perspective_projection_fov_mat4(
|
||||
(float)win_sz.x, (float)win_sz.y, st->cam.cam.fov, 0.01f, 1000);
|
||||
mat4 camera_rotation_matrix = marie_mat3_to_mat4_transposed(st->cam.cam.cam_basis);
|
||||
mat4 camera_translation_matrix = marie_translation_mat4(vec3_minus(st->cam.cam.pos));
|
||||
return mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix));
|
||||
}
|
||||
|
||||
void main_h_on_another_frame(void* data, float fl){
|
||||
R4BetaState *st = data;
|
||||
Alice* alice = st->alice;
|
||||
vec3 proj_back = project_dir_onto_plane_xz(alice->cam_info.cam.cam_basis.z);
|
||||
vec3 proj_right = project_dir_onto_plane_xz(alice->cam_info.cam.cam_basis.x);
|
||||
vec3 proj_back = project_dir_onto_plane_xz(st->cam.cam.cam_basis.z);
|
||||
vec3 proj_right = project_dir_onto_plane_xz(st->cam.cam.cam_basis.x);
|
||||
const float max_speed = 10.f;
|
||||
if (alice->wl.first_0x80_keys['w']) {
|
||||
st->hero_pos = vec3_minus_vec3(st->hero_pos, vec3_mul_scal(proj_back, fl * max_speed));
|
||||
@ -246,33 +271,36 @@ void main_h_on_another_frame(void* data, float fl){
|
||||
if (alice->wl.first_0x80_keys['q']) {
|
||||
st->hero_pos = vec3_add_vec3(st->hero_pos, (vec3){0, -max_speed * fl, 0});
|
||||
}
|
||||
alice->cam_info.cam.pos = st->hero_pos;
|
||||
st->cam.cam.pos = st->hero_pos;
|
||||
|
||||
physics_update(st, fl);
|
||||
|
||||
AliceGenericMeshHand_set_inst(&st->ROA_mesh->el, 0, (GenericMeshInstanceInc){
|
||||
AliceAcknGenericMesh_set_inst(st->ROA_mesh, 0, (GenericMeshInstanceInc){
|
||||
.model_t = RigidBodyState_get_tran_mat_of_mesh(&st->ROA_state),
|
||||
});
|
||||
|
||||
Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st->alice->pipeline0_ubo.staging);
|
||||
assert(pipeline_0_ubo_point_light_max_count >= st->LS_state.len);
|
||||
// Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st->alice->pipeline0_ubo.staging);
|
||||
// assert(pipeline_0_ubo_point_light_max_count >= st->LS_state.len);
|
||||
|
||||
if (st->LS_state.len > alice->pipeline0_light_conf.point_lights.count) {
|
||||
Alice_set_point_light_count(alice, st->LS_state.len);
|
||||
}
|
||||
if (st->LS_state.len + st->bullets_stuck_on_ROA.len > st->LS_mesh->el.instance_attr.count) {
|
||||
AliceAcknShinyMesh_resize_instance_arr(st->LS_mesh, st->LS_state.len + st->bullets_stuck_on_ROA.len);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < st->LS_state.len; i++) {
|
||||
LightSourceState* ls = &st->LS_state.buf[i];
|
||||
AliceShinyMeshHand_set_inst(&st->LS_mesh->el, i, (ShinyMeshInstanceInc){
|
||||
AliceAcknShinyMesh_set_inst(&st->LS_mesh->el, i, (ShinyMeshInstanceInc){
|
||||
.color_on = ls->color,
|
||||
.model_t = marie_translation_mat4(ls->pos),
|
||||
});
|
||||
ubo->point_light_arr[i] = (Pipeline0PointLight){
|
||||
.pos = ls->pos, .color = vec3_mul_scal(ls->color, 21)};
|
||||
}
|
||||
if (st->LS_state.len + st->bullets_stuck_on_ROA.len > st->LS_mesh->el.instance_attr.count) {
|
||||
AliceShinyMeshHand_resize_instance_arr(alice, &st->LS_mesh->el, st->LS_state.len + st->bullets_stuck_on_ROA.len);
|
||||
Alice_set_point_light(alice, i, (Pipeline0PointLight){.pos = ls->pos, .color = vec3_mul_scal(ls->color, 21)});
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < st->bullets_stuck_on_ROA.len; i++) {
|
||||
vec3 bul_pos = st->bullets_stuck_on_ROA.buf[i];
|
||||
AliceShinyMeshHand_set_inst(&st->LS_mesh->el, st->LS_state.len + i, (ShinyMeshInstanceInc){
|
||||
AliceAcknShinyMesh_set_inst(&st->LS_mesh->el, st->LS_state.len + i, (ShinyMeshInstanceInc){
|
||||
.color_on = (vec3){2, 0, 0},
|
||||
.model_t = mat4_mul_mat4(mat4_mul_mat4(
|
||||
RigidBodyState_get_tran_mat(&st->ROA_state),
|
||||
@ -281,7 +309,9 @@ void main_h_on_another_frame(void* data, float fl){
|
||||
});
|
||||
}
|
||||
|
||||
LucyRenderer_clear(&alice->lucy_renderer);
|
||||
Alice_set_camera_info(alice, get_t_mat(st), st->cam.cam.pos);
|
||||
|
||||
|
||||
VecU8 text = VecU8_new();
|
||||
VecU8_append_fmt(&text, "Bullet mass = %v ; bullet velocity = %v\n",
|
||||
VecU8_format("%.4f", st->bullet_config.mass), VecU8_format("%.4f", st->bullet_config.velocity));
|
||||
@ -294,7 +324,7 @@ void main_h_on_another_frame(void* data, float fl){
|
||||
if (st->hits_count > 0) {
|
||||
VecU8_append_fmt(&text, "You hit ROA %u times\n", st->hits_count);
|
||||
}
|
||||
LucyRenderer_add_simple_label(&alice->lucy_renderer, st->font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
|
||||
Alice_lucy_renderer_add_simple_label(alice, st->font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
|
||||
VecU8_to_span(&text), (ivec2){10, 10});
|
||||
VecU8_drop(text);
|
||||
}
|
||||
@ -302,12 +332,12 @@ void main_h_on_another_frame(void* data, float fl){
|
||||
void run_app(){
|
||||
R4BetaState st;
|
||||
st.hero_pos = (vec3){0, 0.81f, 0};
|
||||
st.cam = AliceCamVerticalControl_new();
|
||||
|
||||
Alice* alice = Alice_new();
|
||||
st.alice = alice;
|
||||
st.alice->guest = &st;
|
||||
|
||||
st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache,
|
||||
vcstr("./src/l3/fonts/DMSerifText-Regular.ttf"));
|
||||
st.font_face = Alice_new_LucyFace(alice, vcstr("./src/l3/fonts/DMSerifText-Regular.ttf"));
|
||||
st.font_face_of_size_40 = LucyFace_of_size(st.font_face, 40);
|
||||
VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new();
|
||||
VecU32Segment ranges_needed = VecU32Segment_new();
|
||||
@ -315,28 +345,43 @@ void run_app(){
|
||||
VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){
|
||||
.sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed,
|
||||
});
|
||||
LucyGlyphCache_add_glyphs(lucy_requests);
|
||||
Alice_lucy_cache_add_glyphs(alice, lucy_requests);
|
||||
lucy_requests = VecLucyGlyphCachingRequest_new();
|
||||
ranges_needed = VecU32Segment_new();
|
||||
VecU32Segment_append(&ranges_needed, (U32Segment){.start = 0x430, .len = 0x44f - 0x430 + 1});
|
||||
VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){
|
||||
.sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed,
|
||||
});
|
||||
Alice_lucy_cache_add_glyphs(alice, lucy_requests);
|
||||
|
||||
LucyGlyphCache_add_glyphs(lucy_requests);
|
||||
LucyRenderer_add_simple_label(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
|
||||
Alice_lucy_renderer_add_simple_label(alice, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
|
||||
cstr("..."), (ivec2){10, 10});
|
||||
|
||||
/* Recursion depth is 2 */
|
||||
// st.gui_0 = ColorblockWidget_new(100, 50, (vec4){0.3f, 0.8f, 0.4f, 0.6f}, &alice->plain_shape_renderer);
|
||||
// st.gui_1 = ColorframeWidget_new(100, 300, 150, 50, &alice->plain_shape_renderer, (vec4){0.7f, 0.4f, 0.2f, 0.5f},
|
||||
// (MutRefWidget){.r = (Widget*)&st.gui_0, .t = &Widget_Table_ColorblockWidget});
|
||||
// st.gui_2 = ColorblockWidget_new(5000, 30, (vec4){0.1f, 0.5f, 0.6f, 0.4f}, &alice->plain_shape_renderer);
|
||||
// st.gui_3 = ColorblockWidget_new(120, 50, (vec4){0.2f, 0.67f, 0.4f, 0.5f}, &alice->plain_shape_renderer);
|
||||
// st.gui_4 = LtoRStackWidget_new();
|
||||
// VecMutRefWidget_append(&st.gui_4.children, (MutRefWidget){.r = (Widget*)&st.gui_1, &Widget_Table_ColorframeWidget});
|
||||
// VecMutRefWidget_append(&st.gui_4.children, (MutRefWidget){.r = (Widget*)&st.gui_2, &Widget_Table_ColorblockWidget});
|
||||
// VecMutRefWidget_append(&st.gui_4.children, (MutRefWidget){.r = (Widget*)&st.gui_3, &Widget_Table_ColorblockWidget});
|
||||
// st.gui_5 = ColorframeWidget_new(70, 70, 0, 70, &alice->plain_shape_renderer, (vec4){0.1f, 0.5f, 0.3f, 0.8f},
|
||||
// (MutRefWidget){.r = (Widget*)&st.gui_4, &Widget_Table_LtoRStack});
|
||||
// alice->overlay_ui_root = (MutRefWidget){.r = &st.gui_5.base, .t = &Widget_Table_ColorframeWidget};
|
||||
|
||||
VecU8 ROA_mesh_path = vcstr("./gen/l2/models/log_10_2_6.AliceGenericMesh");
|
||||
st.ROA_topology = alice_expect_read_generic_mesh_from_file(ROA_mesh_path);
|
||||
|
||||
st.ROA_diffuse_tex_slot = Alice_load_r8g8b8a8_texture(alice, vcstr("./src/l3/textures/log_10_2_6_diffuse.png"));
|
||||
st.ROA_normal_tex_slot = Alice_load_r8g8b8a8_texture(alice, vcstr("./gen/l2/textures/log_10_2_6_NORMAL.png"));
|
||||
st.ROA_specular_tex_slot = Alice_load_r8_texture(alice, vcstr("./src/l3/textures/log_10_2_6_specular.png"));
|
||||
|
||||
st.ROA_mesh = Alice_add_generic_mesh(st.alice, &st.ROA_topology,
|
||||
(AliceGenericMeshTexturePaths){
|
||||
.diffuse_texture_path = vcstr("./src/l3/textures/log_10_2_6_diffuse.png"),
|
||||
.normal_texture_path = vcstr("./gen/l2/textures/log_10_2_6_NORMAL.png"),
|
||||
.specular_texture_path = vcstr("./src/l3/textures/log_10_2_6_specular.png")
|
||||
});
|
||||
AliceGenericMeshHand_resize_instance_arr(st.alice, &st.ROA_mesh->el, 1);
|
||||
st.ROA_diffuse_tex_slot, st.ROA_normal_tex_slot, st.ROA_specular_tex_slot);
|
||||
|
||||
AliceAcknGenericMesh_resize_instance_arr(st.ROA_mesh, 1);
|
||||
const float gamma_l_c = 4.f / 3 / M_PIf;
|
||||
st.ROA_state = (RigidBodyState){
|
||||
.p.mass = 1.f * 1/4 * M_PIf * 2*2 * 10,
|
||||
@ -384,11 +429,7 @@ void run_app(){
|
||||
}
|
||||
}
|
||||
|
||||
AliceShinyMeshHand_resize_instance_arr(st.alice, &st.LS_mesh->el, st.LS_state.len);
|
||||
Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st.alice->pipeline0_ubo.staging);
|
||||
assert(pipeline_0_ubo_point_light_max_count >= st.LS_state.len);
|
||||
ubo->point_light_count = (int)st.LS_state.len;
|
||||
ubo->spotlight_count = 0;
|
||||
AliceAcknShinyMesh_resize_instance_arr(st.LS_mesh, st.LS_state.len);
|
||||
|
||||
st.bullet_config = (BulletConfig){.mass = 0.01f, .velocity = 1000};
|
||||
st.misses_count = 0;
|
||||
@ -396,9 +437,11 @@ void run_app(){
|
||||
st.bullets_stuck_on_ROA = Vecvec3_new();
|
||||
|
||||
Alice_mainloop(st.alice, &(AliceCallbacks){
|
||||
.guest = &st,
|
||||
.on_wl_pointer_button = main_h_on_wl_pointer_button,
|
||||
.on_wl_keyboard_key = main_h_on_wl_keyboard_key,
|
||||
.on_another_frame = main_h_on_another_frame,
|
||||
.on_wl_pointer_motion = main_h_on_wl_pointer_motion,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
62
src/l3/r4/r4c.cpp
Normal file
62
src/l3/r4/r4c.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "../../l2/allie_cpp/alice.hpp"
|
||||
#include "../../../gen/l1/allie_cpp/geom.hpp"
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include "../../l2/allie_cpp/graphics_geom.hpp"
|
||||
|
||||
template<typename T>
|
||||
using unique = std::unique_ptr<T>;
|
||||
|
||||
struct AppMem {
|
||||
float gr = 0;
|
||||
};
|
||||
|
||||
struct R4C_State {
|
||||
unique<Alice> alice;
|
||||
unique<LucyFace> face;
|
||||
unique<LucyFaceFixedSize> sized_face;
|
||||
|
||||
AppMem app;
|
||||
};
|
||||
|
||||
vec4 funky_color(float time) {
|
||||
return vec4{(sinf(0.95f * time + 0.6f) + 1) / 2, (sinf(0.233f * time + 0.2f) + 1) / 2, (sinf(1.433f * time) + 1) / 2, 1};
|
||||
}
|
||||
|
||||
void main_h_on_another_frame(void* data, float fl) {
|
||||
R4C_State& st = *(R4C_State*)data;
|
||||
Alice& alice = *st.alice;
|
||||
LucyFaceFixedSize& ffs = *st.sized_face;
|
||||
st.app.gr += fl;
|
||||
alice.lucy_renderer_add_simple_label(ffs, funky_color(st.app.gr), 0, "Hello from C++", ivec2(500, 50));
|
||||
}
|
||||
|
||||
void main_h_on_wl_keyboard_key(void* data, U32 keysym, U32 act) {
|
||||
|
||||
}
|
||||
|
||||
void main_h_on_wl_pointer_button(void* data, U32 button, U32 act) {
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
R4C_State st{};
|
||||
st.alice = std::make_unique<Alice>();
|
||||
st.face = std::make_unique<LucyFace>(st.alice->new_lucy_face("./src/l3/fonts/DMSerifText-Regular.ttf"));
|
||||
st.sized_face = std::make_unique<LucyFaceFixedSize>(st.face->of_size(40));
|
||||
st.alice->lucy_cache_add_glyphs({LucyGlyphCachingRequest{*st.sized_face, {{ .start = 32, .len = 126 - 32 + 1 }}}});
|
||||
AliceGenericMeshTopology ROA_topology = alice_expect_read_generic_mesh_from_file("./gen/l2/models/log_10_2_6.AliceGenericMesh");
|
||||
AliceTextureSlot ROA_diffuse_tex_slot = st.alice->load_r8g8b8a8_texture("./src/l3/textures/log_10_2_6_diffuse.png");
|
||||
AliceTextureSlot ROA_normal_tex_slot = st.alice->load_r8g8b8a8_texture("./gen/l2/textures/log_10_2_6_NORMAL.png");
|
||||
AliceTextureSlot ROA_specular_tex_slot = st.alice->load_r8_texture("./src/l3/textures/log_10_2_6_specular.png");
|
||||
AliceAcknGenericMesh ROA_mesh = st.alice->add_generic_mesh(ROA_topology, ROA_diffuse_tex_slot, ROA_normal_tex_slot, ROA_specular_tex_slot);
|
||||
ROA_mesh.resize_instance_arr(1);
|
||||
ROA_mesh.set_inst(0, {.model_t = marie_translation_mat4({0.2, -0.4, 0.6})});
|
||||
st.alice->mainloop({
|
||||
.guest = &st,
|
||||
.on_wl_pointer_button = main_h_on_wl_pointer_button,
|
||||
.on_wl_keyboard_key = main_h_on_wl_keyboard_key,
|
||||
.on_another_frame = main_h_on_another_frame,
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
#version 450
|
||||
#version 460
|
||||
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
layout(location = 0) in vec3 tang_norm;
|
||||
layout(location = 1) in vec3 tang_U;
|
||||
@ -6,34 +8,36 @@ layout(location = 2) in vec3 tang_V;
|
||||
layout(location = 3) in vec2 tex;
|
||||
layout(location = 4) in vec3 pos;
|
||||
|
||||
/* Right now all in set 0 */
|
||||
layout(location = 0) out vec4 fin_color;
|
||||
/* Yes, even these guys */
|
||||
layout(binding = 1) uniform sampler2D color_tex;
|
||||
layout(binding = 2) uniform sampler2D normal_map;
|
||||
layout(binding = 3) uniform sampler2D specular_map;
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D textures[];
|
||||
|
||||
layout(push_constant, std430) uniform pc {
|
||||
layout(offset = 64) vec3 camera_pos;
|
||||
uint diffuse_tex_slot;
|
||||
uint normal_tex_slot;
|
||||
uint specular_tex_slot;
|
||||
};
|
||||
|
||||
struct Pipeline0PointLight {
|
||||
struct PointLight {
|
||||
vec3 pos;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
struct Pipeline0Spotlight {
|
||||
struct Spotlight {
|
||||
vec3 pos;
|
||||
vec3 dir;
|
||||
vec3 color;
|
||||
float range;
|
||||
};
|
||||
|
||||
layout(std140, binding = 0) uniform Pipeline0UBO {
|
||||
layout (std140, set = 0, binding = 0) uniform NumUBO {
|
||||
int point_light_count;
|
||||
int spotlight_count;
|
||||
Pipeline0PointLight point_light_arr[120];
|
||||
Pipeline0Spotlight spotlight_arr [20];
|
||||
};
|
||||
|
||||
layout (std430, set = 0, binding = 1) readonly buffer PointLightsArray {
|
||||
PointLight point_light_arr[];
|
||||
};
|
||||
|
||||
float get_intensity(float dist){
|
||||
@ -41,13 +45,16 @@ float get_intensity(float dist){
|
||||
}
|
||||
|
||||
void main(){
|
||||
vec3 compressed_normal = texture(normal_map, tex).xyz;
|
||||
vec3 compressed_normal = texture(textures[nonuniformEXT(normal_tex_slot)], tex).xyz;
|
||||
vec3 natural_color = texture(textures[nonuniformEXT(diffuse_tex_slot)], tex).xyz;
|
||||
float specular_c = texture(textures[nonuniformEXT(specular_tex_slot)], tex).x;
|
||||
|
||||
vec3 correct_norm_on_tang = compressed_normal * 2 - 1;
|
||||
vec3 norm = normalize(mat3(tang_U, tang_norm, tang_V) * correct_norm_on_tang);
|
||||
vec3 diffuse_illumination = vec3(0);
|
||||
vec3 specular_illumination = vec3(0);
|
||||
for (int i = 0; i < point_light_count; i++) {
|
||||
Pipeline0PointLight lamp = point_light_arr[i];
|
||||
PointLight lamp = point_light_arr[i];
|
||||
vec3 to_light = -pos + lamp.pos;
|
||||
float dist = length(to_light);
|
||||
vec3 U = to_light / dist;
|
||||
@ -58,11 +65,10 @@ void main(){
|
||||
vec3 B = to_cam / dist_to_cam;
|
||||
specular_illumination += get_intensity(dist) * pow(max(0, dot(A, B)), 32) * lamp.color;
|
||||
}
|
||||
for (int i = 0; i < spotlight_count; i++) {
|
||||
Pipeline0Spotlight lamp = spotlight_arr[i];
|
||||
}
|
||||
vec3 natural_color = texture(color_tex, tex).xyz;
|
||||
float specular_c = texture(specular_map, tex).x;
|
||||
//for (int i = 0; i < spotlight_count; i++) {
|
||||
// Pipeline0Spotlight lamp = spotlight_arr[i];
|
||||
//}
|
||||
|
||||
vec3 color = natural_color * diffuse_illumination + specular_c * specular_illumination;
|
||||
fin_color = vec4(color, 1);
|
||||
}
|
||||
|
||||
@ -11,23 +11,25 @@ layout(push_constant, std430) uniform pc {
|
||||
layout(offset = 64) vec3 camera_pos;
|
||||
};
|
||||
|
||||
struct Pipeline0PointLight {
|
||||
struct PointLight {
|
||||
vec3 pos;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
struct Pipeline0Spotlight {
|
||||
struct Spotlight {
|
||||
vec3 pos;
|
||||
vec3 dir;
|
||||
vec3 color;
|
||||
float range;
|
||||
};
|
||||
|
||||
layout(std140, binding = 0) uniform Pipeline0UBO {
|
||||
layout (std140, set = 0, binding = 0) uniform NumUBO {
|
||||
int point_light_count;
|
||||
int spotlight_count;
|
||||
Pipeline0PointLight point_light_arr[120];
|
||||
Pipeline0Spotlight spotlight_arr [20];
|
||||
};
|
||||
|
||||
layout (std430, set = 0, binding = 1) readonly buffer PointLightsArray {
|
||||
PointLight point_light_arr[];
|
||||
};
|
||||
|
||||
float get_intensity(float dist){
|
||||
@ -38,7 +40,7 @@ void main(){
|
||||
vec3 diffuse_illumination = vec3(0);
|
||||
vec3 specular_illumination = vec3(0);
|
||||
for (int i = 0; i < point_light_count; i++) {
|
||||
Pipeline0PointLight lamp = point_light_arr[i];
|
||||
PointLight lamp = point_light_arr[i];
|
||||
vec3 to_light = -pos + lamp.pos;
|
||||
float dist = length(to_light);
|
||||
vec3 U = to_light / dist;
|
||||
@ -47,9 +49,9 @@ void main(){
|
||||
vec3 B = normalize(-pos+camera_pos);
|
||||
// specular_illumination += get_intensity(dist) * pow(max(0, dot(A, B)), 256) * lamp.color;
|
||||
}
|
||||
for (int i = 0; i < spotlight_count; i++) {
|
||||
Pipeline0Spotlight lamp = spotlight_arr[i];
|
||||
}
|
||||
// for (int i = 0; i < spotlight_count; i++) {
|
||||
// Spotlight lamp = spotlight_arr[i];
|
||||
// }
|
||||
vec3 color = color_off * diffuse_illumination + (0.05 + 0.45 * length(color_off)) * specular_illumination + color_on;
|
||||
fin_color = vec4(color, 1);
|
||||
}
|
||||
|
||||
9
src/l_adele/drawer_2d/plain/plain.frag
Normal file
9
src/l_adele/drawer_2d/plain/plain.frag
Normal file
@ -0,0 +1,9 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 color;
|
||||
|
||||
layout(location = 0) out vec4 fin_color;
|
||||
|
||||
void main(){
|
||||
fin_color = color;
|
||||
}
|
||||
24
src/l_adele/drawer_2d/plain/plain.vert
Normal file
24
src/l_adele/drawer_2d/plain/plain.vert
Normal file
@ -0,0 +1,24 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 pos;
|
||||
layout(location = 1) in vec4 color;
|
||||
|
||||
layout(push_constant, std430) uniform pc {
|
||||
float width;
|
||||
float height;
|
||||
};
|
||||
|
||||
layout (location = 0) out vec4 vsout_color;
|
||||
|
||||
float lint(float A1, float B1, float A2, float B2, float x){
|
||||
return A2 + (B2 - A2) * (x - A1) / (B1 - A1);
|
||||
}
|
||||
|
||||
float deng(float B1, float x){
|
||||
return lint(0, B1, -1, 1, x);
|
||||
}
|
||||
|
||||
void main(){
|
||||
vsout_color = color;
|
||||
gl_Position = vec4(deng(width, pos.x), deng(height, pos.y), 0, 1);
|
||||
}
|
||||
@ -13,5 +13,4 @@ layout (binding=0) uniform sampler2D images[];
|
||||
void main(){
|
||||
float I = texture(images[nonuniformEXT(tex_ind)], tex_cord).r;
|
||||
fin_color = vec4(color.rgb, color.a * I);
|
||||
//fin_color = vec4(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user