Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial (readonly) storage buffer support. #1007

Merged
merged 33 commits into from
May 9, 2024
Merged

Initial (readonly) storage buffer support. #1007

merged 33 commits into from
May 9, 2024

Conversation

floooh
Copy link
Owner

@floooh floooh commented Mar 9, 2024

First step will introduce storage buffers without compute shaders. This allows more flexibility for providing random-access data to the GPU (e.g. replacing float textures as 'poor man's storage buffers').

  • Not supported on WebGL2 and on the macOS GL backend (since macOS GL only goes up to 4.1)
  • Will require to bump the minimum GL version to 4.3 on Linux and Windows.
  • Unrelated: while at it, bump minimum GL version to 4.1 on macOS (will enable to fill some feature gaps later)
  • ??? GLES3.1 on Anrdoid and iOS ??? (not on iOS since it only supports GLES 3.0, not initially on Android)
  • on D3D11 uses HLSL ByteAddressBuffers as opposed to StructuredBuffers, this is more flexible but more awkward when used with manually written HLSL (convenient again with sokol-shdc though)
  • only

To investigate:

  • Allow multiple bind points? (e.g. allow to bind as storage buffer, but also as vertex buffer) => means getting rid of 'buffer type' in favour of 'bind flags' => not initially
  • D3D11: when is using an UnorderedAccessView instead of a regular BufferView required?
  • ReadOnly vs ReadWrite vs WriteOnly storage buffers? Possible to write to StorageBuffers without compute shaders? => possible but non-trivial, initially only support readonly buffers, writing from vertex- oder fragment-shaders requires resource barriers even in OpenGL. Delay until compute shader support.
  • Add a special flag sg_buffer_desc.d3d11_structured_buffer as fallback to allow using more convenient StructureBuffer in shader? Does this require providing the element size when creating the shader resource view?
  • ???

TODO:

  • fix broken shadows-depthtex sample
  • update samples webpage
  • query GL version for glGetIntegerv() and roll back the changes in sg_environment.
  • pixel noise artifacts in the sbuftex-sapp on my NVIDIA RTX 2070 Win10 PC across WebGPU, D3D11 and OpenGL (fixed, turned out to be a precision problem when converting between float and integer which only seems to manifest on NVIDIA)
  • final smoke test:
    • sapp-samples on:
      • macOS + Metal
      • macOS + GL
      • iOS + Metal
      • iOS + GL
      • Windows + D3D11
      • Windows + GL
      • WebGL2
      • WebGPU
      • Linux
      • Android
    • backend-specific samples:
      • d3d11 samples
      • metal samples
      • emsc samples
      • wgpu samples
      • glfw samples
        • macOS
        • Windows
        • Linux
    • bindings:
      • zig
      • odin
      • nim
      • rust
  • deploy samples webpage
    • WebGPU
    • WebGL2
  • blog post
  • update changelog
  • merge:
  • update:
  • publish sokol-tools-bin
  • add 'unsupported' debug text to storage buffer samples
  • documentation update:
    • sokol_gfx.h
    • sokol_app.h
  • fix sokol-shdc + webgpu problems
  • only allow readonly storage buffers in shader desc (validation layer check)
  • cleanup SG_BUFFERTYPE_* naming? (e.g. SG_BUFFERTYPE_VERTEXBUFFER => SG_BUFFERTYPE_VERTEX)? => not worth the hassle
  • rename config define SOKOL_GLCORE33 => SOKOL_GLCORE
  • pass major and minor GL version in sg_environment.gl
  • basic storage buffer support in sokol_gfx.h:
    • glcore
    • gles3? (unsupported)
    • d3d11
    • metal
    • wgpu
  • 'raw' 3D API samples:
    • vertex pulling via storage buffers
      • d3d11
      • metal
      • wgpu
      • glfw
  • sokol-app samples:
    • simple vertex pulling sample
    • new instancing sample which uses vertex pulling
    • new ozz-skinning sample which passes bone info via storage-buffer
    • a sample which uses matrices in storage buffers
    • a sample which read storage buffer from fragment shader - use the uniformtypes-sapp as base, and also bind a texture to the same stage (to check if bind slots are assigned correctly):
      • macOS + Metal
      • WebGPU (currently broken: Binding size (768) is larger than the size (96) of [Buffer "color-palette"].)
      • Linux + GL
      • Windows + D3D11
      • Windows + GL
    • shader-write to storage buffer
  • sokol_app.h + sokol_glue.h updates:
    • sg_environment => gl major/minor version
  • fix sokol_gfx_imgui.h
    • buffer panel => storage buffer
    • update shader-desc panel
    • update apply-bindings-panel
  • recompile embedded WebGPU and GLSL shaders (because WGPU bind slots and GLSL versions have changed):
    • sokol_imgui.h
    • sokol_gl.h
    • sokol_nuklear.h
    • sokol_debugtext.h
    • sokol_spine.h
    • sokol_fontstash.h
  • update bindings (plus a new vertex pulling sample):
    • zig
    • odin
    • nim
    • rust
  • sokol-shdc update:
    • glsl330 => glsl410 and glsl430
    • remove glsl100
    • cleanup reflection parsing (also need to parse regular structs)
    • reflection parsing: SSBOs
    • 'skip' the internal struct for code-generated ssbo struct
    • SPIRVCross writes gl_InstanceIndex as gl_InstanceID + SPIRV_Cross_BaseInstance (fixed: SPIRVCross has options for that)
  • figure out how to deal with write/read barriers for storage buffers, e.g. https://registry.khronos.org/OpenGL-Refpages/gl4/html/glMemoryBarrier.xhtml, conservative solution: issue a barrier after each draw that involves writable storage buffers. => defer storage buffer write support into a followup update since it comes with a couple of problems that need solving:
    • barriers must be injected between a draw call writing to a storage buffer and another draw call reading from that buffer, so need to come with a basic concept of how to handle such resource barriers (make a backend API survey first)
    • SPIRVCross seems to generate no return value for (vertex) shaders which write to storage buffers
    • might want to handle the following situations properly:
      • shaders that only have a vertex- but no fragment-shaders
      • render passes without any attachments (and essentially only serve as barriers => do we want to have something like a "barrier pass"?

@floooh floooh marked this pull request as draft March 9, 2024 16:55
@floooh floooh changed the title Initial storage buffer support. Initial (readonly) storage buffer support. Apr 15, 2024
@jakubtomsu
Copy link
Contributor

Oh, are you planning to eventually support compute shaders, on selected backends? That would be absolutely amazing, it's probably the number one feature I'm missing in sokol_gfx right now. Especially now I've moved on to 3D graphics. The storage buffers seem like a good first step!

@floooh
Copy link
Owner Author

floooh commented Apr 26, 2024

Yes, compute shaders is planned afterward for the next 'big update' after this initial storage buffer support update. I need to come up with a 'resource barrier strategy' though, I'll most likely take WebGPU as a blueprint.

@floooh floooh merged commit fa70e64 into master May 9, 2024
32 of 48 checks passed
@floooh floooh deleted the storage-buffers branch May 9, 2024 13:58
@fiserj
Copy link

fiserj commented May 10, 2024

This is great milestone, thank you! (I can finally stop abusing uniforms for that 🙈)

@roig
Copy link

roig commented May 13, 2024

Amazing work, thank you for this update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants