mreinstein / cobalt

WebGpu 2D renderer
MIT License
8 stars 1 forks source link

fullscreen quad vs fullscreen triangle #8

Closed jeremy-coleman closed 3 months ago

jeremy-coleman commented 1 year ago

hey, great library - been admiring it for a while actually. what do you think about using a triangle instead of quad? i first heard about doing this on an amd devrel talk about optimizing for amd drivers and vulkan. after some googling i found this comment on the unity forums that seems to summarize the benefit pretty concisely.

"The fullscreen triangle isn't really about optimizing the number of vertices rendered. It's about optimizing the small 2x2 (sometimes bigger) tile the GPU executes fragment shaders in. With a typical fullscreen quad you get a diagonal where the two triangles meet which causes the GPU tile to run fragment shaders on fragments that have already been processed so it does more work. With the fullscreen triangle you don't have that issue which means fragment shaders would run an optimal amount of times. This can make a measurable difference on mid to low end hardware and VR also. In my experience, a fullscreen triangle is no worse than a fullscreen quad but can be a decent improvement over it depending on what shaders are running." link

just brainstorming btw

mreinstein commented 1 year ago

what do you think about using a triangle instead of quad?

Wow that's interesting! I've used the fullscreen quad pattern for a long time and never re-examined it. A few questions:

been admiring it for a while actually

Interesting, how did you find this lib? This is something I've been working on in a vacuum so I'd love any other feedback, thoughts, PRs, etc. !

jeremy-coleman commented 1 year ago

I just periodically search for webgpu and came across it some time ago.

Yea when i first heard ‘full screen triangle’, i did a mental double take. As for the fragment shader running on the empty offscreen portions, i have no idea tbh, but i trust that the gpu vendors know best lol. I think even if it does draw the blank area offscreen its still more efficient because quad has to get shaded two or three times instead of just once

mreinstein commented 1 year ago

Are you doing webgpu stuff now, or are you strictly in research/browse mode?

jeremy-coleman commented 1 year ago

been doing small webgpu stuff for a while, but through frameworks primarily babylon, but a little three and some native through rust, zig, c, cpp and d. mostly been avoiding developing directly with the browser webgpu because it was just breaking all the time plus would have differences between the web and electron so i couldnt even develop for both platforms using the same code. but, its mostly ok now.

mreinstein commented 3 months ago

I've tried this in a brief experiment, and it seems to work very well. The vertex program:

@vertex
fn vert_main(@builtin(vertex_index) index : u32) -> @builtin(position) vec4<f32> {
    var positions = array<vec2<f32>, 3>(
        vec2<f32>(-4.0, -4.0),
        vec2<f32>(4.0, -4.0),
        vec2<f32>(0.0, 4.0)
    );
    return vec4<f32>(positions[index], 0.0, 1.0);
}

The draw call:

passEncoder.draw(3); 
mreinstein commented 3 months ago

bloom, tile, fb-blit, and scene-composite nodes all would likely benefit from switching to fullscreen triangles.

mreinstein commented 3 months ago

fixed via 69bb22659de62ec631902c3924efd9f78dce0f1b ad42180083c4ac732f3a0f58f3f59bc193aacb37 and 4a4bc56dde827c051b78563a164506ffd4711778

Thanks for clueing me in to this @jeremy-coleman !