VxDraw stands for Vulkan x Draw, Draw being our old drawing implementation and Vulkan being - of course - vulkan , it's just a convenient name but contains no code from our previous drawing implementation, well it did, but not anymore. The name kinda stuck.
VxDraw's goals are: dead simple and deadly fast 2D rendering. VxDraw currently has 4 types of drawables:
DebugTriangles -- Triangles that are drawn on top of everything, to ensure that drawing works or some state is set.
Quads -- Simply colored quads that are drawn under triangles.
Dynamic Textures -- Textures with rectangular sprites (you can animate these!).
Streaming Textures -- Textures whose pixels you can change at runtime, with rectangular sprites.
Most of VxDraw now works, but there is still work to be done:
API
[x] Turn all functions from dyntex into methods
[x] Turn windowing functions into methods
[x] Turn all functions from strtex into methods
[x] Turn all functions from quads into methods
[x] Turn all functions from debtri into methods
[x] Document the API properly, with rich examples for each module
[x] dyntex
[x] strtex
[x] quads
[x] debtri
[x] Rename Windowing to VxDraw
[x] Allow ~destruction~ hiding and ~re-creation~ showing of debtris (useful for turning on quick and dirty visual debugging)
[x] Complete the APIs (complete edits, partial updates)
[x] debtri
[x] quads
[x] dyntex
[x] strtex
[x] Rename push to something more appropriate to remove ideas about the API being stack-based
[x] Add x_all methods
[x] Debug implementations
[x] Use a logger bridge to avoid hard-coding logger
[x] Make LayerOptions expandable by making it builders
[x] Use helper structs to avoid raw data setting (such as Color)
[x] Use Rad for all rotation, even initial rotation
[x] Remove logger from examples (except one)
[x] Change indices to u32
[x] Add caveat comment about scale being able to re-enable old sprites in set_scale_all
[x] Add custom blend states for layers
[x] Simplify blend states (no alpha blend op needed for color for example)
[x] Remove color per dyntex/strtex
[x] Allow setting clearing color
[x] Change tests usage of default to new
Functionality
[x] Correctly resize the window (currently crashes due to out of date swapchain)
[x] Make quads layering-sensitive (Quads are useful in their own right
[x] Allow layers to be swapped ~(May be unnecessary, just allocate all layers up front in the applications, that guarantees ordering, exotic use-case?)~ Absolutely useful.
[x] Hide any layer
[x] debtri
[x] quads
[x] dyntex
[x] strtex
[x] Add font/text rendering
[x] Load/parse ttf files
[x] Generate vertices based on ttf
[x] Upload vertices and display the text
[x] Dynamically resize vertex buffers for dyntex (going over the current limit crashes the application)
[x] Dynamically resize vertex buffers for strtex
[x] Dynamically resize vertex buffers for quads
[x] Dynamically resize vertex buffers for debtri
[x] Use N-buffering for all components (currently dyntex has a single buffer, while it's supposed to have as many as there are swapchain images)
[x] debtri
[x] quads
[x] dyntex
[x] strtex
[x] Add alternative sampling filter mode options to dyntex/strtex
[x] ~Add bulk sprites to strtex (useful for text, since it uses strtex)~ Use specialized Text
[x] Query device Linear image capabilities for strtex (allowing SAMPLED on a LINEAR texture).
[x] Use uploaded strtex if the device does not support LINEAR+SAMPLED images
[x] Allow resizing source texture for text
[x] Correct text positioning
[x] Add wrapmode option to dyntex/strtex
[x] Check blitting capability from the backbuffer (to avoid badly crashing in tests)
[x] Use enum for specifying input data to strtex, (PNG? LinearRgba8?)
[x] Use smarter method of adding colors to sprites (don't just add the color gradient to the sampled fragment)
~How expensive is normalization?~
Normalization is not correct. Maybe we can remove colors per dyntex/strtex and use a special blend mode on Quads to achieve the same effect.
Custom blend states!
[x] ~Allow strtex to load from an image (similar to dyntex)~
We use custom blend states to achieve this :D
[x] Allow textured text
Custom blend states :D
[x] ~Do not descale when removing a sprite~
~When we remove a sprite, we just set its scale to 0 to avoid deallocations and the like. We do need to reupload the entire buffer when this happens. The problem is that doing mass operations now still affect the "removed" sprite.~
~Maybe we should state that using mass-operations isn't a good combination with individual op/erations. I'll need to see what the cost is of... wait... SWAP REMOVE! If we relax the draw order of intra-layer sprites we can swap_remove, which is super efficient. ~
Unfortunately we can't do this, since we need to preserve indices for handles that still exist.
[x] Use holes method for entire layers
[x] Set a fixed perspective
[x] Remove perspective code from most tests/examples (it's unnecessary)
Optimization
[x] Add mockbuffer to debtri
[x] Add mockbuffer to quads
[x] Add mockbuffer to strtex
[x] Add mockbuffer to dyntex
[x] EXPERIMENT: Make dyntex use separate mockbuffers for each vertex attribute (This should increase the throughput of specialized textures, for instance, some textures have sprites that only change UV, so updating all other buffers would be a waste of time).
[x] Pre-compile SPIRV during library compilation (SPIRV compilation is incredibly SLOW during runtime)
[x] EXPERIMENT: Use a counter to stop updating buffers of inactive layers - That is, having a texture with sprites on the screen that never move, animate, change color, etc, then we can simply avoid copying their buffers during each iteration. Only when a single edit is made do we copy the entire buffer. Update: This may only be useful for gigantic buffers of >10k elements.
[x] debtri
[x] Remove optional from debtris.
[x] Circular mockbuffer for strtex:
We make a circular mockbuffer where 1 entry gets cleared each frame, then, on each frame, we consume 1 entry. This allows for updates to cascade through each frame. By making this structure sparse we can ensure that we do the least amount of work. Merging the structures seems to be a waste. We also need to have 3 (swapimages) images in total to avoid waiting.
[x] Upload text texture to the GPU for fast access
Most of the time the font texture won't be edited so we should be good.
[x] Use N-buffered resource destruction
Make that resource-cleaning, instead of using optionals or perturbing the struct, what we do is just deallocate and destroy everything BUT keep the structure in memory.
[x] Use sharerc-rs instead of glsl_to_spirv for compiling glsl
Bugs
[x] Iron out the periodic SIGSEGVs (It's unknown if it's a winit bug or our own fault).
[x] This was a fault in ordering, Rust dropping from structs is in FIFO order!
Performance
Currently, drawing 200k medium-sized sprites which are animated each frame on a little laptop (Intel HD Graphics 620) takes 12 ms. 90% of that time is spent copying the mockbuffer to the GPU buffer. Hence why we want to split up the internal buffer.
VxDraw stands for
Vulkan
xDraw
,Draw
being our old drawing implementation andVulkan
being - of course -vulkan
, it's just a convenient name but contains no code from our previous drawing implementation, well it did, but not anymore. The name kinda stuck.VxDraw's goals are: dead simple and deadly fast 2D rendering. VxDraw currently has 4 types of drawables:
Most of VxDraw now works, but there is still work to be done:
API
dyntex
into methodsstrtex
into methodsquads
into methodsdebtri
into methodspush
to something more appropriate to remove ideas about the API being stack-basedset_scale_all
Functionality
Optimization
Bugs
Performance
Currently, drawing 200k medium-sized sprites which are animated each frame on a little laptop (Intel HD Graphics 620) takes 12 ms. 90% of that time is spent copying the mockbuffer to the GPU buffer. Hence why we want to split up the internal buffer.