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

gfx2d: complete redesign of Sprite2D #997

Merged
merged 4 commits into from
Sep 14, 2023
Merged

gfx2d: complete redesign of Sprite2D #997

merged 4 commits into from
Sep 14, 2023

Conversation

slimsag
Copy link
Member

@slimsag slimsag commented Sep 11, 2023

This is a complete redesign of Sprite2D, the low-level ECS module for sprite rendering.

Features

  • Sprites can now use custom shaders (and you can specify a shader per batch.)
  • You are no longer limited to one global texture; different sprite batches can have different textures.
  • Multi-texturing support (4 max)
  • A clear path to multiple render-pass support, should you ever want it.
  • The Engine module now manages render passes and frame submission; which means Sprite2D can now be used with other ECS modules that render onto the screen too.

Performance

image

On a Macbook M1, with sprites that are independently CPU animated each frame (single texture/shader), we see gains of +60% in release builds:

Optimization Frame rate Before After Performance Note
ReleaseSafe: 33FPS ~200k sprites ~500k sprites +60% Fill rate bound
Debug 29FPS ~60k sprites ~80k sprites +25% Matrix math bound

Design

GPU memory synchronization

We retain a set of GPU storage buffers per sprite batch (which are used to render multiple sprites per draw call); the goal is to have the buffers ready to go at rendering time with no need to synchronize ECS data -> GPU during rendering a frame

image

The way Sprite2D becomes aware of the fact that ECS data has changed is.. you tell it your batch of sprites changed:

try sprite2d.send(.updated, .{@intFromEnum(Pipeline.default)});

Pipeline creation

When you wish to render sprites, you're going to want to specify your own texture. Sometimes you might want to specify multiple textures, or your use your own shader program. For this reason, we have an explicit pipeline creation step where you specify the shaders/textures corresponding to a batch of sprites:

image

In the final implementation, pipeline creation is just an initPipeline message that you pass some options to:

try sprite2d.send(.initPipeline, .{Sprite2D.PipelineOptions{
    // An integer ID to represent your pipeline/batch of sprites.
    .pipeline = @intFromEnum(Pipeline.default),

    // Specify a texture to use
    .texture = try loadTexture(engine),

    // optional:
    // .shader = myshader,
    // .texture2 = texture2,
    // ...
}});

Rendering a frame

As a result of us doing all the work outside the render API - the GPU storage buffers are already up-to-date with all your sprites, there is no data to synchronize to the GPU during rendering except uniform values (shader program arguments) which is done with a .preRender message:

    // Perform pre-render work
    try sprite2d.send(.preRender, .{@intFromEnum(Pipeline.default)});

Then you can begin a render pass and e.g. specify the background color of the frame:

    try engine.send(.beginPass, .{gpu.Color{ .r = 1.0, .g = 1.0, .b = 1.0, .a = 1.0 }});

Render sprites (you would duplicate this line to render multiple batches of sprites, which also controls draw order for e.g. transparency alpha blending purposes):

    try sprite2d.send(.render, .{@intFromEnum(Pipeline.default)});

And finally end the render pass + present the frame:

    try engine.send(.endPass, .{});
    try engine.send(.present, .{});
  • By selecting this checkbox, I agree to license my contributions to this project under the license(s) described in the LICENSE file, and I have the right to do so or have received permission to do so by an employer or client I am producing work for whom has this right.

@slimsag slimsag merged commit b7ad360 into main Sep 14, 2023
7 checks passed
@slimsag slimsag deleted the sg/sprite2d branch September 14, 2023 01:04
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.

1 participant