Devsh-Graphics-Programming / Nabla

Vulkan, OptiX and CUDA Interoperation Modular Rendering Library and Framework for PC/Linux/Android
http://devsh.eu
Apache License 2.0
484 stars 59 forks source link

Asset Converter 2.0 #376

Open devshgraphicsprogramming opened 2 years ago

devshgraphicsprogramming commented 2 years ago

Description

Need an asset converter that works.

Description of the related problem

Current converted not suitable for Vulkan, does not:

Perf/Efficiency:

Ergonomics and Correctness:

Solution proposal

  1. As input take a sorted dynamic_refctd_array<IAsset> of root assets + conversion options argument (current SParams)
  2. Do not use templates and perform a Depth First Search to explore the DAG starting from the roots
  3. Figure out what Buffers and Images need to be de-aliased due to format promotion (promotion occurs in the view)
  4. Use unordered_map<cpu_asset_type_and_metadata,gpu_asset_type_and_metadata> to store all assets to convert, the key metadata will probably just be the promoted format if any, the value metadata will contain modifiers like additional usages etc.
  5. Then commence converting assets, starting form the bottom of the logical stack
  6. ALWAYS If you can find the cached asset conversion with the correct metadata (usages, etc.) then use that, otherwise proceed with steps 7 onwards, at each step check all dependents are ready and figure out if can recover from error before creating anything
  7. Create Buffers, bucketed by usage, depending on options trim and merge them into large suballocated buffers (we already do this)
  8. Create Images without any merging
  9. Figure out the heaps and memory types each IGPUBuffer and IGPUImage need, and whether they need to be dedicated, bucket the allocations by that
  10. Allocate Device Memory and bind it to the created Buffers and Images (allows for suballocation)
  11. Fill Buffers and Images with data and convert if needed (remember about de-aliased promoted copies!)
  12. Create Image Views, Buffer Views and Acceleration Structures while remembering to promote and adjust any offsets after any promotion or packing/merging (probably should modified Hash Cons here, try and find duplicate views)
  13. Create Samplers with Hash Consing
  14. Create Descriptor Set Layouts with Hash Consing
  15. Create Pipeline Layouts with Hash Consing
  16. Create Shaders (maybe with Hash Consing, since we can has and compare the source code)
  17. Create Specialized Shaders (with modified Hash Consing - basically compare for equality after hotswapping shaders)
  18. Create Compute and RenderpassIndependentPipelines (with modified Hash Consing)
  19. Create Graphics Pipelines (with modified Hash Consing)
  20. Create MeshBuffers (with modified Hash Consing)
  21. Create Meshes (with modified Hash Consing)
  22. Return an dynamic_refctd_array<IReferenceCounted> wrapped in a utility struct

Special concerns:

Additional context

Hash certain objects to not create needless copies

You can hash samplers, and descriptor set layouts, pipeline layouts (via hash consing).

This will reduce the number of samplers and layouts created (important cause VK has limits on this shit).

You can apply this regardless of if the assetManager has been provided as an external cache (also useful to make it work on hashes of the samplers and layouts).

CPU Asset Usages are hints

When creating a Buffer or Image (or in the future ImageView) remember that usages are hints, you need to patch them up during DAG traversal (add usages which are implied by the DAG if they're not there already).

You cannot however, "narrow down the usages" if a user has explicitly stated that a Buffer has a usage, it must have that usage.

This allows us to handle promotion and de-aliasing better, as de-aliased buffers and images are an extra copy and not the original, hence they need not have any of the usages explicitly enumerated by the original, only the implicit ones from the views that actually use them.

Controlling Options

General Options:

Patching-up BufferViews and VertexAttribute Bindings

After converting an entire buffer range due to a promotion, the relative offset may change due to shrinking and/or having a larger format.

This is also a concern for strides for vertex buffer bindings in graphics pipelines and acceleration structures.

Erfan-Ahmadi commented 2 years ago

Additional Comments based on talk with @devshgraphicsprogramming

devshgraphicsprogramming commented 2 years ago

Additional Comments based on talk with @devshgraphicsprogramming

* Pack buffers with similar usages together into seperate classes (same for images), new BufferAPI allows suballocating buffers from a big IDeviceMemoryAllocation

* We convert assets in several passes : for example 1. batch splitting (figure out all the dependants) and assign to their classes 2. Create GPU resources 3. ????

buffers are packed together already, notice that ICPUBuffer does not produce a IGPUBuffer it produces an SBufferOffset<IGPUBuffer>, but obvs we cant fuse different usage buffers together.

IDeviceMemoryAllocation fusing is what could allow us to put multiple buffers (and images) with different usages in the same memory allocation.