diff --git a/sapp/CMakeLists.txt b/sapp/CMakeLists.txt index f731aef5..2b0a34e4 100644 --- a/sapp/CMakeLists.txt +++ b/sapp/CMakeLists.txt @@ -317,7 +317,7 @@ fips_end_app() fips_ide_group(Samples) fips_begin_app(customresolve-sapp windowed) fips_files(customresolve-sapp.c) - sokol_shader(customresolve-sapp.glsl ${slang}) + sokol_shader_debuggable(customresolve-sapp.glsl ${slang}) fips_deps(sokol) fips_end_app() fips_ide_group(SamplesWithDebugUI) @@ -325,7 +325,7 @@ fips_begin_app(customresolve-sapp-ui windowed) fips_files(customresolve-sapp.c) sokol_shader(customresolve-sapp.glsl ${slang}) fips_deps(sokol dbgui) - target_compile_options(customresolve-sapp-ui PRIVATE USE_DBG_UI) + target_compile_definitions(customresolve-sapp-ui PRIVATE USE_DBG_UI) fips_end_app() fips_ide_group(Samples) diff --git a/sapp/customresolve-sapp.c b/sapp/customresolve-sapp.c index ecbff08f..0ea4b3ec 100644 --- a/sapp/customresolve-sapp.c +++ b/sapp/customresolve-sapp.c @@ -11,19 +11,29 @@ #include "dbgui/dbgui.h" #include "customresolve-sapp.glsl.h" +#define WIDTH (160) +#define HEIGHT (120) + static struct { struct { sg_image img; sg_pipeline pip; + sg_attachments atts; + sg_pass_action action; } msaa; struct { sg_image img; sg_pipeline pip; - sg_attachments att; + sg_attachments atts; + sg_pass_action action; + sg_bindings bind; } resolve; struct { sg_pipeline pip; + sg_pass_action action; + sg_bindings bind; } display; + sg_sampler smp; // a common non-filtering sampler } state; static void init(void) { @@ -33,44 +43,108 @@ static void init(void) { }); __dbgui_setup(sapp_sample_count()); + // common objects + state.smp = sg_make_sampler(&(sg_sampler_desc){ + .min_filter = SG_FILTER_NEAREST, + .mag_filter = SG_FILTER_NEAREST, + }); + + // msaa-render-pass objects state.msaa.img = sg_make_image(&(sg_image_desc){ - .width = 160, - .height = 120, + .render_target = true, + .width = WIDTH, + .height = HEIGHT, .pixel_format = SG_PIXELFORMAT_RGBA8, .sample_count = 4, .label = "msaa image", }); - - state.resolve.img = sg_make_image(&(sg_image_desc){ - .width = 160, - .height = 120, - .pixel_format = SG_PIXELFORMAT_RGBA8, - .sample_count = 1, - .label = "resolve image", - }); - state.msaa.pip = sg_make_pipeline(&(sg_pipeline_desc){ .shader = sg_make_shader(msaa_shader_desc(sg_query_backend())), .sample_count = 4, + .depth.pixel_format = SG_PIXELFORMAT_NONE, .colors[0].pixel_format = SG_PIXELFORMAT_RGBA8, .label = "msaa pipeline", }); + state.msaa.atts = sg_make_attachments(&(sg_attachments_desc){ + .colors[0].image = state.msaa.img, + .label = "msaa pass attachments", + }); + state.msaa.action = (sg_pass_action){ + .colors[0] = { + .load_action = SG_LOADACTION_CLEAR, + .store_action = SG_STOREACTION_STORE, + .clear_value = { 0, 0, 0, 1 }, + }, + }; + // resolve-render-pass objects + state.resolve.img = sg_make_image(&(sg_image_desc){ + .render_target = true, + .width = WIDTH, + .height = HEIGHT, + .pixel_format = SG_PIXELFORMAT_RGBA8, + .sample_count = 1, + .label = "resolve image", + }); state.resolve.pip = sg_make_pipeline(&(sg_pipeline_desc){ .shader = sg_make_shader(resolve_shader_desc(sg_query_backend())), .sample_count = 1, + .depth.pixel_format = SG_PIXELFORMAT_NONE, .colors[0].pixel_format = SG_PIXELFORMAT_RGBA8, .label = "resolve pipeline", }); + state.resolve.atts = sg_make_attachments(&(sg_attachments_desc){ + .colors[0].image = state.resolve.img, + .label = "resolve pass attachments", + }); + state.resolve.action = (sg_pass_action){ + .colors[0] = { + .load_action = SG_LOADACTION_DONTCARE, + .store_action = SG_STOREACTION_STORE + }, + }; + state.resolve.bind = (sg_bindings){ + .images[IMG_texms] = state.msaa.img, + .samplers[SMP_smp] = state.smp, + }; + // swapchain-render-pass objects state.display.pip = sg_make_pipeline(&(sg_pipeline_desc){ .shader = sg_make_shader(display_shader_desc(sg_query_backend())), .label = "display pipeline", }); + state.display.action = (sg_pass_action){ + .colors[0] = { .load_action = SG_LOADACTION_DONTCARE } + }; + state.display.bind = (sg_bindings){ + .images[IMG_tex] = state.resolve.img, + .samplers[SMP_smp] = state.smp, + }; } static void frame(void) { + // draw a triangle into an msaa render target + sg_begin_pass(&(sg_pass){ .action = state.msaa.action, .attachments = state.msaa.atts }); + sg_apply_pipeline(state.msaa.pip); + sg_draw(0, 3, 1); + sg_end_pass(); + + // custom resolve pass (via a 'fullscreen triangle') + sg_begin_pass(&(sg_pass){ .action = state.resolve.action, .attachments = state.resolve.atts }); + sg_apply_pipeline(state.resolve.pip); + sg_apply_bindings(&state.resolve.bind); + sg_draw(0, 3, 1); + sg_end_pass(); + + // the final swapchain pass (also via a 'fullscreen triangle') + sg_begin_pass(&(sg_pass){ .action = state.display.action, .swapchain = sglue_swapchain() }); + sg_apply_pipeline(state.display.pip); + sg_apply_bindings(&state.display.bind); + sg_draw(0, 3, 1); + __dbgui_draw(); + sg_end_pass(); + sg_commit(); } static void cleanup(void) { diff --git a/sapp/customresolve-sapp.glsl b/sapp/customresolve-sapp.glsl index 6a19579c..a792b864 100644 --- a/sapp/customresolve-sapp.glsl +++ b/sapp/customresolve-sapp.glsl @@ -1,3 +1,4 @@ +// triangle shader which renders into an msaa render target @vs triangle_vs const vec4 colors[3] = { @@ -6,9 +7,9 @@ const vec4 colors[3] = { vec4(1, 0, 1, 1), }; const vec3 positions[3] = { - vec3(0.0, 0.5, 0.5), - vec3(0.5, -0.5, 0.5), - vec3(-0.5, -0.5, 0.5), + vec3(0.0, 0.6, 0.0), + vec3(0.5, -0.6, 0.0), + vec3(-0.5, -0.4, 0.0), }; out vec4 color; @@ -29,3 +30,65 @@ void main() { @end @program msaa triangle_vs triangle_fs + +@block fullscreen_triangle +const vec3 positions[3] = { + vec3(-1.0, -1.0, 0.0), + vec3(3.0, -1.0, 0.0), + vec3(-1.0, 3.0, 0.0), +}; +@end + +// custom resolve shader +@vs resolve_vs +@include_block fullscreen_triangle + +void main() { + gl_Position = vec4(positions[gl_VertexIndex], 1); +} +@end + +@fs resolve_fs +layout(binding=0) uniform texture2DMS texms; +layout(binding=0) uniform sampler smp; + +out vec4 frag_color; + +void main() { + ivec2 uv = ivec2(gl_FragCoord.xy); + vec3 s0 = texelFetch(sampler2DMS(texms, smp), uv, 0).xyz; + vec3 s1 = texelFetch(sampler2DMS(texms, smp), uv, 1).xyz; + vec3 s2 = texelFetch(sampler2DMS(texms, smp), uv, 2).xyz; + vec3 s3 = texelFetch(sampler2DMS(texms, smp), uv, 3).xyz; + vec4 color = vec4((s0 + s1 + s2 + s3) * 0.25, 1); + frag_color = color; +} +@end + +@program resolve resolve_vs resolve_fs + +@vs display_vs +@include_block fullscreen_triangle + +out vec2 uv; + +void main() { + const vec4 pos = vec4(positions[gl_VertexIndex], 1); + gl_Position = pos; + uv = (pos.xy + 1.0) * 0.5; +} +@end + +@fs display_fs +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; + +in vec2 uv; +out vec4 frag_color; + +void main() { + frag_color = texture(sampler2D(tex, smp), uv); +} +@end + +@program display display_vs display_fs