Jackalope / jen (public) (License: GPLv3 or later version) (since 2018-10-24) (hash sha1)
----> ABOUT:

3D rendering and computing framework based on Vulkan API.

Libraries:
- simdcpp submodule (see my simdcpp repo)
- jmath submodule (see my jmath repo)
- mesh (constexpr generation of cubes, spheres, icosahedrons subdivisions)
- atlas (1D lines and 2D rectangles cutting)
- jlib submodule (see my jlib repo)
- jrf submodule (see my jrf repo)
- vkw (Vulkan API C++ wrapper)
Modules:
- compute (run compute shaders on gpu)
- graphics (draw models with clustered forward rendering and onscreen text)
- resource manager (load meshes, models, textures, scene data from
files and create related objects in graphics module)

----> INSTALLING:

To download all the parts of this framework it's enough to launch
git clone with recursive flag:

$ git clone —recursive ssh://rocketgit@ssh.rocketgit.com/user/Jackalope/jen

After this look at git tags:

$ git tag

It is recommended to use a tagged version instead of the latest commit,
because the first commit after the tagged one mostly includes incompatible
parts of future changes for the next version.

$ git checkout v0.1.0

----> DEPENDENCIES:

To use JEN as CMake subdirectory and successfully build programs with it
you need to make sure you have all of its dependencies:
- compiler: Clang or GCC, support for C++17. Clang 10+ or GCC 9+ is recommended,
compiling on Windows OS is tricky and requires something like MinGW with MSYS,
there are also some complications to go through to make dependencies work;
- GLFW3 library, supported version is 3.2.1;
- FreeType library, if graphics module will be used;
- Vulkan API headers, and optional validation layers to debug sneaky problems,
you also need Vulkan support in your graphics driver to run compiled programs;
- LibZip can be necessary, if JRF is used to read zip files;
- CMake, for obvious reasons;
- glslangValidator to compile shader for the graphics module.

CMake must be able to find GLFW3, Vulkan and FreeType (for graphics)
with find_package().

----> HOW TO USE IT:

To use JEN, you need to add it as a subdirectory:

add_subdirecroty(${PATH_TO_JEN})

There are several configuration options:
- JEN_MODULE_COMPUTE - turn compute module on for compiling and including;
- JEN_MODULE_GRAPHICS - turn graphics module on ...;
- JEN_MULTITHREADED_DRAW_FRAME - draw_frame function will use thread pool queue
instead of linear executing;
- JEN_MODULE_RESOURCE_MANAGER - resource manager module ON, if graphics is ON;
- JEN_VLK_VALIDATION - enable Vulkan Validation Layers to debug some errors
related to JEN. This will often produce false-positive,
as well as true-positive errors.

Look in CMakeLists.txt at JenExamples repo for details on how to use and
configure JEN automatically:

$ git clone ssh://rocketgit@ssh.rocketgit.com/user/Jackalope/JenExamples

Also I recommend to compile and run examples to make sure it works correctly.

----> SUPPORTED HARDWARE:

JEN has not been tested well, because it requires running it on large amount of
different hardware to do so. It must work with mesa driver and modern
Intel i965 GPUs as well as AMD GPUs.


----> DOCUMENTATION:

You can generate Doxygen documentation, to do so
turn on any of JEN_DOXYGEN_* options and run documentation target in cmake:

$ cmake -G %1 -DJEN_DOXYGEN_HTML=ON -DJEN_DOXYGEN_LATEX=ON
$ cmake —build —target documentation

Resource manager is not documented because it still requires large enhancements.
List of commits:
Subject Hash Author Date (UTC)
Solved clang compiler warnings from compute module. b9416237761f8648bbddb7e7ba59e833a7879528 Jackalope 2020-05-28 11:09:55
CMake: two shaders targets, instead of single target per shader. a708650319e44c7b98056f3bc85a896dd65d96f3 Jackalope 2020-05-28 11:06:13
Reduced amount of warnings. 18bf33ca4e0e7f0369f6b5fdc59b81a8420dde8e Jackalope 2020-05-27 15:11:37
Replace jl::rarray with generic structure in shader header file. 1cedb5886becc0f70c19d1c649e96f7eac5e0037 Jackalope 2020-05-27 13:07:31
Embedding shaders in obj library. e877e7a688ee4a899480c12acba55c340622f993 Jackalope 2020-05-27 12:40:34
Update jlib 0.3.0 (refactoring of threads, new thread pool). 1c713a320ced91d0ad5f1606c39f1187871d28e5 Jackalope 2020-05-26 14:44:35
Update graphics after change of "wait for monitor" flag. 29d9b749c803646006b9b0071b54256bd3c08ca8 Jackalope 2020-05-26 14:40:34
reduced number of -Wno* warnings bf3ec94ce3020715e246107a47efc9a8772db382 Jackalope 2020-05-25 01:48:40
Disable "find_package(jlib 0.2.0 REQUIRED)" in jrf b4903e20d9128227163119fe73e32cda5050cb67 Jackalope 2020-05-24 16:40:26
Update jrf-0.2.1 3518adb37045d4e4eb4488c8c07e3f674f5fbac3 Jackalope 2020-05-24 14:33:14
Update jrf-0.2.0 8720e50ca5f692a96ba764cab1a250683c6a0c59 Jackalope 2020-05-24 13:42:55
Update jlib-0.2.0 98c73665c12797a530d12e34dc764e72a8767ad1 Jackalope 2020-05-24 00:32:02
Mistake in CMake option 112275a2e0bc8619612ab49d808daeeeb599b8de Jackalope 2020-05-24 00:11:04
Device selection settings: 1. First suitable. 2. User can select with stdin/stdout. 3. User function callback. adcfd55f60dfc6eea019f083019012a0b4aa8f02 Jackalope 2020-05-23 13:52:07
ModuleGraphics: fix for mip level computation was wrong because depth is ignored. 834ceab8e0ea99b6b8c25928c9f3be968679cff3 Jackalope 2020-05-21 11:57:26
Compute module. Image copy staging buffer size limit problem fixed by representing row image memory in staging buffer. 740d8bf1d12352b08da05a63957afcb508ea6fd5 Jackalope 2020-05-21 11:55:31
Math new types update d0069637df7a0f74a9492a2a2a2d7a33102afde6 Jackalope 2020-05-21 11:51:46
Checking for blit support and fix typo in texture write f1adac801689ee3f7905d2582ac26948260bb352 Jackalope 2020-05-20 18:39:36
Added VkFormat properties checks and fallbacks to follow specification rules. 3c38bb0e9916aea31ef796a53a024aa3111e1ec7 Jackalope 2020-05-19 17:42:59
renamed compute::BindingsSet to BindingSet, vkw::BindNo to vkw::Binding, compute::BindingCreateInfo.bindingNo to binding 072430e257166208d6f4a7b759169779f21bf4c8 Jackalope 2020-05-18 17:51:25
Commit b9416237761f8648bbddb7e7ba59e833a7879528 - Solved clang compiler warnings from compute module.
Author: Jackalope
Author date (UTC): 2020-05-28 11:09
Committer name: Jackalope
Committer date (UTC): 2020-05-28 12:21
Parent(s): a708650319e44c7b98056f3bc85a896dd65d96f3
Signing key:
Tree: 71c7a62a7bb2b01142645ead0e2735d33f1e0922
File Lines added Lines deleted
src/compute/cmd_unit.cpp 14 12
src/compute/compute.cpp 11 7
File src/compute/cmd_unit.cpp changed (mode: 100644) (index 1141cac..476c617)
... ... struct jen::ModuleCompute::Data {
26 26 Device device; Device device;
27 27 }; };
28 28
29 void
29 static void
30 30 transitionLayout(Image *p, vkw::CmdBuffer *p_cmd, transitionLayout(Image *p, vkw::CmdBuffer *p_cmd,
31 31 vkw::ImLayout layout, vkw::StageMaskChange stages) { vkw::ImLayout layout, vkw::StageMaskChange stages) {
32 32 vkw::BarrierImMem barrier; { vkw::BarrierImMem barrier; {
 
... ... transitionLayout(Image *p, vkw::CmdBuffer *p_cmd,
44 44 } }
45 45 p_cmd->cmd_barriers(stages, {}, {}, barrier); p_cmd->cmd_barriers(stages, {}, {}, barrier);
46 46 } }
47 void check_transfer(const jen::DeviceBufferPart &part,
47
48 static void
49 check_transfer(const jen::DeviceBufferPart &part,
48 50 vkw::DeviceSize offset, vkw::DeviceSize size) { vkw::DeviceSize offset, vkw::DeviceSize size) {
49 51 jassert(offset + size <= part.size(), "region exceeds buffer"); jassert(offset + size <= part.size(), "region exceeds buffer");
50 52 jassert(part.is_mapped(), "cannot access memory"); jassert(part.is_mapped(), "cannot access memory");
51 53 jassert(not part.is_flush_needed(), "flush not supported"); jassert(not part.is_flush_needed(), "flush not supported");
52 54 } }
53 void
55 static void
54 56 write_to_allocation(void *p_src, jen::DeviceBufferPart *p_dst, write_to_allocation(void *p_src, jen::DeviceBufferPart *p_dst,
55 57 vkw::DeviceSize dst_offset, vkw::DeviceSize size) { vkw::DeviceSize dst_offset, vkw::DeviceSize size) {
56 58 check_transfer(*p_dst, dst_offset, size); check_transfer(*p_dst, dst_offset, size);
57 59 memcpy(p_dst->p_data() + dst_offset, p_src, size); memcpy(p_dst->p_data() + dst_offset, p_src, size);
58 60 } }
59
60 void
61 static void
61 62 read_from_allocation(jen::DeviceBufferPart *p_src, void *p_dst, read_from_allocation(jen::DeviceBufferPart *p_src, void *p_dst,
62 63 vkw::DeviceSize src_offset, vkw::DeviceSize size) { vkw::DeviceSize src_offset, vkw::DeviceSize size) {
63 64 check_transfer(*p_src, src_offset, size); check_transfer(*p_src, src_offset, size);
64 65 memcpy(p_dst, p_src->p_data() + src_offset, size); memcpy(p_dst, p_src->p_data() + src_offset, size);
65 66 } }
66 67
67
68 68 struct jen::ComputeCmdUnit::Data { struct jen::ComputeCmdUnit::Data {
69 69 [[nodiscard]] Result [[nodiscard]] Result
70 70 init(Device*); init(Device*);
 
... ... struct jen::ComputeCmdUnit::Data {
91 91 jl::array<bool, SyncCounts::FENCES> reset_fence; jl::array<bool, SyncCounts::FENCES> reset_fence;
92 92 }; };
93 93 [[nodiscard]] Result ComputeCmdUnit::Data:: [[nodiscard]] Result ComputeCmdUnit::Data::
94 init(Device *p_dev) {
95 this->p_dev = p_dev;
94 init(Device *p_d) {
95 p_dev = p_d;
96 96 Result res; Result res;
97 97 res = compute_cmds res = compute_cmds
98 98 .init(*p_dev, p_dev->queue_indices.compute.family, .init(*p_dev, p_dev->queue_indices.compute.family,
 
... ... proceed_writes(BufferTransfers buffer_writes,
215 215 for (auto &r : w.transfers) { for (auto &r : w.transfers) {
216 216 auto ext = im.extent; auto ext = im.extent;
217 217 uint64_t moffset = 0; uint64_t moffset = 0;
218 for (uint32_t i = 1; i < r.mip_level; ++i) {
218 for (uint32_t j = 1; j < r.mip_level; ++j) {
219 219 moffset += ext.all_scale() * x_size; moffset += ext.all_scale() * x_size;
220 220 ext /= 2; ext /= 2;
221 221 ext.x = jl::max(ext.x, 1u); ext.x = jl::max(ext.x, 1u);
 
... ... proceed_staging_reads(BufferTransfers buffer_reads,
324 324 for (auto &r : w.transfers) { for (auto &r : w.transfers) {
325 325 auto ext = im.extent; auto ext = im.extent;
326 326 uint64_t moffset = 0; uint64_t moffset = 0;
327 for (uint32_t i = 1; i < r.mip_level; ++i) {
327 for (uint32_t j = 1; j < r.mip_level; ++j) {
328 328 moffset += ext.all_scale() * x_size; moffset += ext.all_scale() * x_size;
329 329 ext /= 2; ext /= 2;
330 330 ext.x = jl::max(ext.x, 1u); ext.x = jl::max(ext.x, 1u);
 
... ... proceed_staging_reads(BufferTransfers buffer_reads,
376 376 } }
377 377 return VK_SUCCESS; return VK_SUCCESS;
378 378 } }
379 [[nodiscard]] Result
379
380 [[nodiscard]] static Result
380 381 check_computeInfo(const Device &device, const ComputeInfo &info) { check_computeInfo(const Device &device, const ComputeInfo &info) {
381 382 for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
382 383 if (info.group_count[i] > if (info.group_count[i] >
 
... ... check_computeInfo(const Device &device, const ComputeInfo &info) {
391 392 } }
392 393 return VK_SUCCESS; return VK_SUCCESS;
393 394 } }
395
394 396 [[nodiscard]] Result ComputeCmdUnit:: [[nodiscard]] Result ComputeCmdUnit::
395 397 compute_status() { compute_status() {
396 398 jen::Result res; jen::Result res;
 
... ... read_result(BufferTransfers buffer_reads, ImagesTransfers images_reads) {
501 503 for (auto &r : read.transfers) { for (auto &r : read.transfers) {
502 504 auto ext = im.extent; auto ext = im.extent;
503 505 uint64_t moffset = 0; uint64_t moffset = 0;
504 for (uint32_t i = 1; i < r.mip_level; ++i) {
506 for (uint32_t j = 1; j < r.mip_level; ++j) {
505 507 moffset += ext.all_scale() * x_size; moffset += ext.all_scale() * x_size;
506 508 ext /= 2; ext /= 2;
507 509 ext.x = jl::max(ext.x, 1u); ext.x = jl::max(ext.x, 1u);
File src/compute/compute.cpp changed (mode: 100644) (index 6c9fb54..af5b92a)
... ... destroy_pipeline(Pipeline *p_pl) {
88 88 p_pl->shader.destroy(d); p_pl->shader.destroy(d);
89 89 } }
90 90
91 [[nodiscard]] Result
91 [[nodiscard]] static Result
92 92 init(Device *p_d, BindingBuffer *p, const BindingCreateInfo &info) { init(Device *p_d, BindingBuffer *p, const BindingCreateInfo &info) {
93 93 DevMemUsage mem_use; DevMemUsage mem_use;
94 94 bool map = info.use & BindingUseFlag::TRANSFER_DST bool map = info.use & BindingUseFlag::TRANSFER_DST
 
... ... init(Device *p_d, BindingBuffer *p, const BindingCreateInfo &info) {
126 126 } }
127 127 return res; return res;
128 128 } }
129 void destroy(Device *p_d, BindingBuffer *p) {
129 static void
130 destroy(Device *p_d, BindingBuffer *p) {
130 131 if (p->use_staging) if (p->use_staging)
131 132 p_d->buffer_allocator.deallocate(p->staging); p_d->buffer_allocator.deallocate(p->staging);
132 133 p_d->buffer_allocator.deallocate(p->part); p_d->buffer_allocator.deallocate(p->part);
133 134 } }
134 135
135 [[nodiscard]] Result
136 [[nodiscard]] static Result
136 137 init(Device *p_d, BindingBufferView *p, init(Device *p_d, BindingBufferView *p,
137 138 const BindingCreateInfo &info, VkFormat format) { const BindingCreateInfo &info, VkFormat format) {
138 139 Result res; Result res;
 
... ... init(Device *p_d, BindingBufferView *p,
145 146 p_d->buffer_allocator.deallocate(p->part); p_d->buffer_allocator.deallocate(p->part);
146 147 return res; return res;
147 148 } }
148 void destroy(Device *p_d, BindingBufferView *p) {
149 static void
150 destroy(Device *p_d, BindingBufferView *p) {
149 151 p->view.destroy(*p_d); p->view.destroy(*p_d);
150 152 p_d->buffer_allocator.deallocate(p->part); p_d->buffer_allocator.deallocate(p->part);
151 153 } }
 
... ... init(Device *p_d, Image *p, const ImageCreateInfo &info) {
258 260 p->layer_count = info.layer_count; p->layer_count = info.layer_count;
259 261 return res; return res;
260 262 } }
261 void destroy(Device *p_d, Image *p) {
263 static void
264 destroy(Device *p_d, Image *p) {
262 265 p_d->buffer_allocator.deallocate(p->staging); p_d->buffer_allocator.deallocate(p->staging);
263 266 p->image.destroy(p_d); p->image.destroy(p_d);
264 267 } }
 
... ... create_images(ImageCreateInfos infos, Image *p_dst) {
277 280 return VK_SUCCESS; return VK_SUCCESS;
278 281 } }
279 282
280 [[nodiscard]] Result
283 [[nodiscard]] static Result
281 284 init(Device *p_dev, BindingSet *p, vkw::DescrLayout setLayout, init(Device *p_dev, BindingSet *p, vkw::DescrLayout setLayout,
282 285 const Bindings &bi) const Bindings &bi)
283 286 { {
 
... ... init(Device *p_dev, BindingSet *p, vkw::DescrLayout setLayout,
334 337
335 338 return res; return res;
336 339 } }
337 void destroy(Device *p_dev, BindingSet *p) {
340 static void
341 destroy(Device *p_dev, BindingSet *p) {
338 342 p->pool.destroy(*p_dev); p->pool.destroy(*p_dev);
339 343 } }
340 344
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/Jackalope/jen

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/Jackalope/jen

Clone this repository using git:
git clone git://git.rocketgit.com/user/Jackalope/jen

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main