From f85702ff457b04b46e8ebdb3b1861c986f2e6658 Mon Sep 17 00:00:00 2001 From: Ion Agorria Date: Sun, 19 May 2024 13:06:05 +0200 Subject: [PATCH] sokol: Implement depth buffer clear --- Source/Render/sokol/SokolRender.cpp | 50 +++++----- Source/Render/sokol/SokolRender.h | 8 +- Source/Render/sokol/SokolRenderState.cpp | 115 ++++++++++++++++++++--- 3 files changed, 130 insertions(+), 43 deletions(-) diff --git a/Source/Render/sokol/SokolRender.cpp b/Source/Render/sokol/SokolRender.cpp index 9090e749..8b890484 100644 --- a/Source/Render/sokol/SokolRender.cpp +++ b/Source/Render/sokol/SokolRender.cpp @@ -81,20 +81,12 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres desc.image_pool_size = 1024 * 4; //1024 is enough for PGW+PET game desc.logger.func = slog_func; - //Setup swapchain pass - swapchain_pass = {}; - swapchain_pass.action.colors[0].load_action = SG_LOADACTION_CLEAR; - swapchain_pass.action.colors[0].store_action = SG_STOREACTION_STORE; - swapchain_pass.action.colors[0].clear_value = sg_color { 0.0f, 0.0f, 0.0f, 1.0f }; - swapchain_pass.action.depth.load_action = SG_LOADACTION_CLEAR; - swapchain_pass.action.depth.store_action = SG_STOREACTION_DONTCARE; - swapchain_pass.action.depth.clear_value = 1.0f; - swapchain_pass.action.stencil.load_action = SG_LOADACTION_CLEAR; - swapchain_pass.action.stencil.store_action = SG_STOREACTION_DONTCARE; - swapchain_pass.action.stencil.clear_value = 0; - swapchain_pass.swapchain.width = ScreenSize.x; - swapchain_pass.swapchain.height = ScreenSize.y; - swapchain_pass.swapchain.sample_count = 1; + //Setup swapchain and fill color + swapchain = {}; + swapchain.width = ScreenSize.x; + swapchain.height = ScreenSize.y; + swapchain.sample_count = 1; + fill_color = sg_color { 0.0f, 0.0f, 0.0f, 1.0f }; //OpenGL / OpenGLES #ifdef SOKOL_GL @@ -138,7 +130,7 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres } printf("GPU vendor: %s, renderer: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDER)); - swapchain_pass.swapchain.gl.framebuffer = 0; + swapchain.gl.framebuffer = 0; #endif //SOKOL_GL //Direct3D @@ -221,7 +213,7 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres dxgiAdapter->Release(); //Create swap chain - uint32_t sample_count = swapchain_pass.swapchain.sample_count; + uint32_t sample_count = swapchain.sample_count; DXGI_SWAP_CHAIN_DESC* swap_chain_desc = &d3d_context->swap_chain_desc; memset(&d3d_context->swap_chain_desc, 0, sizeof(DXGI_SWAP_CHAIN_DESC)); swap_chain_desc->BufferDesc.Width = static_cast(xScr); @@ -258,7 +250,7 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, "metal", SDL_HINT_OVERRIDE); //Setup metal sokol context - sokol_metal_setup(sdl_window, &desc, &swapchain_pass.swapchain, ScreenHZ); + sokol_metal_setup(sdl_window, &desc, &swapchain, ScreenHZ); #endif const char* render_driver = SDL_GetHint(SDL_HINT_RENDER_DRIVER); @@ -325,8 +317,8 @@ bool cSokolRender::ChangeSize(int xScr, int yScr, int mode) { RenderMode |= mode; //Update swapchain - swapchain_pass.swapchain.width = ScreenSize.x; - swapchain_pass.swapchain.height = ScreenSize.y; + swapchain.width = ScreenSize.x; + swapchain.height = ScreenSize.y; #ifdef SOKOL_D3D11 if (d3d_context->swap_chain && need_resize) { @@ -381,9 +373,9 @@ int cSokolRender::Done() { } #endif #ifdef SOKOL_METAL - if (swapchain_pass.swapchain.metal.current_drawable != nullptr) { + if (swapchain.metal.current_drawable != nullptr) { RenderSubmitEvent(RenderEvent::DONE, "Sokol Metal shutdown"); - sokol_metal_destroy(&swapchain_pass.swapchain); + sokol_metal_destroy(&swapchain); } #endif #ifdef SOKOL_GL @@ -582,15 +574,15 @@ void cSokolRender::d3d_CreateDefaultRenderTarget() { assert(SUCCEEDED(hr) && d3d_context->depth_stencil_view); //Apply into swapchain pass - swapchain_pass.swapchain.d3d11.render_view = 1 < sample_count ? d3d_context->msaa_view : d3d_context->render_target_view; - swapchain_pass.swapchain.d3d11.resolve_view = 1 < sample_count ? d3d_context->render_target_view : nullptr; - swapchain_pass.swapchain.d3d11.depth_stencil_view = d3d_context->depth_stencil_view; + swapchain.d3d11.render_view = 1 < sample_count ? d3d_context->msaa_view : d3d_context->render_target_view; + swapchain.d3d11.resolve_view = 1 < sample_count ? d3d_context->render_target_view : nullptr; + swapchain.d3d11.depth_stencil_view = d3d_context->depth_stencil_view; } void cSokolRender::d3d_DestroyDefaultRenderTarget() { - swapchain_pass.swapchain.d3d11.render_view = nullptr; - swapchain_pass.swapchain.d3d11.resolve_view = nullptr; - swapchain_pass.swapchain.d3d11.depth_stencil_view = nullptr; + swapchain.d3d11.render_view = nullptr; + swapchain.d3d11.resolve_view = nullptr; + swapchain.d3d11.depth_stencil_view = nullptr; RELEASE(d3d_context->render_target_texture); RELEASE(d3d_context->render_target_view); RELEASE(d3d_context->depth_stencil_texture); @@ -638,6 +630,10 @@ void SokolCommand::CreateShaderParams() { } void SokolCommand::ClearDrawData() { + if (pass_action) { + delete pass_action; + pass_action = nullptr; + } if (vertex_buffer) { vertex_buffer->DecRef(); vertex_buffer = nullptr; diff --git a/Source/Render/sokol/SokolRender.h b/Source/Render/sokol/SokolRender.h index d3b7132a..eb6666ee 100644 --- a/Source/Render/sokol/SokolRender.h +++ b/Source/Render/sokol/SokolRender.h @@ -21,10 +21,11 @@ struct SokolCommand { void ClearShaderParams(); void SetTexture(size_t index, SokolResource* sokol_texture); void ClearTextures(); - NO_COPY_CONSTRUCTOR(SokolCommand) + NO_COPY_CONSTRUCTOR(SokolCommand); pipeline_id_t pipeline_id = 0; SOKOL_SHADER_ID shader_id = SOKOL_SHADER_ID_NONE; + sg_pass_action* pass_action = nullptr; size_t base_elements = 0; size_t vertices = 0; size_t indices = 0; @@ -73,7 +74,8 @@ class cSokolRender: public cInterfaceRenderDevice { std::unordered_multimap> bufferPool; //For swapchain pass that renders into final device - sg_pass swapchain_pass; + sg_swapchain swapchain = {}; + sg_color fill_color = {}; //Renderer state bool ActiveScene = false; @@ -117,8 +119,10 @@ class cSokolRender: public cInterfaceRenderDevice { Mat4f activeTextureTransform[PERIMETER_SOKOL_TEXTURES]; //Commands handling + void ClearActiveBufferAndPassAction(); void ClearCommands(); void FinishActiveDrawBuffer(); + void CreateCommandEmpty(); void CreateCommand(class VertexBuffer* vb, size_t vertices, class IndexBuffer* ib, size_t indices); void SetVPMatrix(const Mat4f* matrix); void SetTex2Lerp(float lerp); diff --git a/Source/Render/sokol/SokolRenderState.cpp b/Source/Render/sokol/SokolRenderState.cpp index c6c83b3c..d50961e8 100644 --- a/Source/Render/sokol/SokolRenderState.cpp +++ b/Source/Render/sokol/SokolRenderState.cpp @@ -61,13 +61,14 @@ int cSokolRender::EndScene() { } //Make sure there is nothing left to send as command - FinishActiveDrawBuffer(); - + ClearActiveBufferAndPassAction(); xassert(activeDrawBuffer == nullptr); + xassert(activeCommand.pass_action == nullptr); + ActiveScene = false; #ifdef SOKOL_METAL - sokol_metal_render(&swapchain_pass.swapchain, &sokol_metal_render_callback); + sokol_metal_render(&swapchain, &sokol_metal_render_callback); #else DoSokolRendering(); #endif @@ -77,8 +78,22 @@ int cSokolRender::EndScene() { void cSokolRender::DoSokolRendering() { //This function might be called from a callback! - + //Begin main swapchain pass + + //Create the pass, clear all buffers + sg_pass swapchain_pass = {}; + swapchain_pass.label = "PassSwapchain"; + swapchain_pass.swapchain = swapchain; + swapchain_pass.action.colors[0].load_action = SG_LOADACTION_CLEAR; + swapchain_pass.action.colors[0].store_action = SG_STOREACTION_STORE; + swapchain_pass.action.colors[0].clear_value = fill_color; + swapchain_pass.action.depth.load_action = SG_LOADACTION_CLEAR; + swapchain_pass.action.depth.store_action = SG_STOREACTION_DONTCARE; + swapchain_pass.action.depth.clear_value = 1.0f; + swapchain_pass.action.stencil.load_action = SG_LOADACTION_CLEAR; + swapchain_pass.action.stencil.store_action = SG_STOREACTION_DONTCARE; + swapchain_pass.action.stencil.clear_value = 0; sg_begin_pass(&swapchain_pass); //Iterate each command @@ -86,9 +101,16 @@ void cSokolRender::DoSokolRendering() { #ifdef PERIMETER_RENDER_TRACKER_COMMANDS RenderSubmitEvent(RenderEvent::PROCESS_COMMAND, "", command); #endif + //Change pass if set + if (command->pass_action) { + sg_end_pass(); + memcpy(&swapchain_pass.action, command->pass_action, sizeof(sg_pass_action)); + swapchain_pass.swapchain = swapchain; + sg_begin_pass(&swapchain_pass); + } + //Nothing to draw if (3 > command->vertices) { - xassert(0); continue; } @@ -268,6 +290,39 @@ int cSokolRender::Flush(bool wnd) { return 0; } + +void cSokolRender::ClearActiveBufferAndPassAction() { + if (activeDrawBuffer) { + //Send out any active DB before we set a pass action + //otherwise it might be renderer after setting new pass + FinishActiveDrawBuffer(); + } + if (activeCommand.pass_action) { + //Active command has a pass action already and there was no active DB + //Create a empty command + CreateCommandEmpty(); + if (activeCommand.pass_action) { + xassert(0); + delete activeCommand.pass_action; + activeCommand.pass_action = nullptr; + } + } +} + +void cSokolRender::ClearZBuffer() { + //Keep color and stencil buffers, clear depth buffer + ClearActiveBufferAndPassAction(); + sg_pass_action* action = new sg_pass_action(); + action->colors[0].load_action = SG_LOADACTION_LOAD; + action->colors[0].store_action = SG_STOREACTION_STORE; + action->depth.load_action = SG_LOADACTION_CLEAR; + action->depth.store_action = SG_STOREACTION_DONTCARE; + action->depth.clear_value = 1.0f; + action->stencil.load_action = SG_LOADACTION_LOAD; + action->stencil.store_action = SG_STOREACTION_DONTCARE; + activeCommand.pass_action = action; +} + int cSokolRender::Fill(int r, int g, int b, int a) { RenderSubmitEvent(RenderEvent::FILL); if (ActiveScene) { @@ -284,12 +339,10 @@ int cSokolRender::Fill(int r, int g, int b, int a) { } #endif - sg_color fill_color; fill_color.r = static_cast(r) / 255.f; fill_color.g = static_cast(g) / 255.f; fill_color.b = static_cast(b) / 255.f; fill_color.a = static_cast(a) / 255.f; - swapchain_pass.action.colors[0].clear_value = fill_color; return 0; } @@ -383,8 +436,42 @@ void cSokolRender::FinishActiveDrawBuffer() { activeDrawBuffer = nullptr; } +void cSokolRender::CreateCommandEmpty() { + xassert(ActiveScene); + MT_IS_GRAPH(); + +#ifdef PERIMETER_RENDER_TRACKER_COMMANDS + std::string label = "Pipeline: Empty"; + RenderSubmitEvent(RenderEvent::CREATE_COMMAND, label.c_str()); +#endif + + //Create command to be send + SokolCommand* cmd = new SokolCommand(); + memcpy(cmd->viewport, activeCommand.viewport, sizeof(Vect2i) * 2); + memcpy(cmd->clip, activeCommand.clip, sizeof(Vect2i) * 2); + + //Pass the pass action + if (activeCommand.pass_action) { + cmd->pass_action = activeCommand.pass_action; + activeCommand.pass_action = nullptr; + } + + //Submit command + commands.emplace_back(cmd); + +#ifdef PERIMETER_RENDER_TRACKER_COMMANDS + label = "Submit - Pipeline: " + std::to_string(pipeline_id) + + " Vtxs: " + std::to_string(cmd->vertices) + + " Idxs: " + std::to_string(cmd->indices) + + " Tex0: " + std::to_string(reinterpret_cast(cmd->sokol_textures[0])) + + " Tex1: " + std::to_string(reinterpret_cast(cmd->sokol_textures[1])); + RenderSubmitEvent(RenderEvent::CREATE_COMMAND, label.c_str(), cmd); +#endif +} + void cSokolRender::CreateCommand(VertexBuffer* vb, size_t vertices, IndexBuffer* ib, size_t indices) { xassert(ActiveScene); + xassert(vb); MT_IS_GRAPH(); if (0 == vertices) vertices = activeCommand.vertices; if (0 == indices) indices = activeCommand.indices; @@ -510,14 +597,17 @@ void cSokolRender::CreateCommand(VertexBuffer* vb, size_t vertices, IndexBuffer* activeCommand.vertices = 0; activeCommand.indices = 0; + //Pass the pass action + if (activeCommand.pass_action) { + cmd->pass_action = activeCommand.pass_action; + activeCommand.pass_action = nullptr; + } + //Submit command commands.emplace_back(cmd); #ifdef PERIMETER_RENDER_TRACKER_COMMANDS label = "Submit - Pipeline: " + std::to_string(pipeline_id) - + " ColM: " + std::to_string(activeCommand.fs_color_mode) - + " OwVB: " + std::to_string(cmd->owned_vertex_buffer) - + " OwIB: " + std::to_string(cmd->owned_index_buffer) + " Vtxs: " + std::to_string(cmd->vertices) + " Idxs: " + std::to_string(cmd->indices) + " Tex0: " + std::to_string(reinterpret_cast(cmd->sokol_textures[0])) @@ -927,7 +1017,4 @@ void cSokolRender::SetGlobalLight(Vect3f *vLight, sColor4f *Ambient, sColor4f *D activeLightAmbient = *Ambient; activeLightSpecular = *Specular; } -} - -void cSokolRender::ClearZBuffer() { -} +} \ No newline at end of file