Index: source/graphics/LOSTexture.cpp =================================================================== --- source/graphics/LOSTexture.cpp +++ source/graphics/LOSTexture.cpp @@ -160,14 +160,10 @@ (timer_Time() - m_LastTextureRecomputeTime) * 2.0f, 0.0f, 1.0f); deviceCommandContext->SetUniform(shader->GetBindingSlot(str_delta), delta); - const SViewPort oldVp = g_Renderer.GetViewport(); - const SViewPort vp = - { - 0, 0, - static_cast(m_Texture->GetWidth()), - static_cast(m_Texture->GetHeight()) - }; - g_Renderer.SetViewport(vp); + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = m_Texture->GetWidth(); + viewportRect.height = m_Texture->GetHeight(); + deviceCommandContext->SetViewports(1, &viewportRect); float quadVerts[] = { @@ -205,8 +201,6 @@ 1, quadTex, std::size(quadTex) * sizeof(quadTex[0])); deviceCommandContext->Draw(0, 6); - - g_Renderer.SetViewport(oldVp); deviceCommandContext->EndPass(); deviceCommandContext->EndFramebufferPass(); Index: source/graphics/MiniMapTexture.cpp =================================================================== --- source/graphics/MiniMapTexture.cpp +++ source/graphics/MiniMapTexture.cpp @@ -465,9 +465,10 @@ GPU_SCOPED_LABEL(deviceCommandContext, "Render minimap texture"); deviceCommandContext->BeginFramebufferPass(m_FinalTextureFramebuffer.get()); - const SViewPort oldViewPort = g_Renderer.GetViewport(); - const SViewPort viewPort = { 0, 0, FINAL_TEXTURE_SIZE, FINAL_TEXTURE_SIZE }; - g_Renderer.SetViewport(viewPort); + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = FINAL_TEXTURE_SIZE; + viewportRect.height = FINAL_TEXTURE_SIZE; + deviceCommandContext->SetViewports(1, &viewportRect); const float texCoordMax = m_TerrainTexture ? static_cast(m_MapSize - 1) / m_TerrainTexture->GetWidth() : 1.0f; @@ -478,9 +479,8 @@ baseDefines.Add(str_MINIMAP_BASE, str_1); tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, baseDefines); - Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = - tech->GetGraphicsPipelineStateDesc(); - deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); + deviceCommandContext->SetGraphicsPipelineState( + tech->GetGraphicsPipelineStateDesc()); deviceCommandContext->BeginPass(); shader = tech->GetShader(); @@ -513,6 +513,8 @@ DrawTexture(deviceCommandContext); deviceCommandContext->EndPass(); + Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + tech->GetGraphicsPipelineStateDesc(); pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -571,7 +573,6 @@ DrawEntities(deviceCommandContext, entityRadius); deviceCommandContext->EndFramebufferPass(); - g_Renderer.SetViewport(oldViewPort); } void CMiniMapTexture::UpdateAndUploadEntities( Index: source/ps/VideoMode.cpp =================================================================== --- source/ps/VideoMode.cpp +++ source/ps/VideoMode.cpp @@ -673,11 +673,11 @@ SViewPort vp = { 0, 0, w, h }; + if (g_VideoMode.GetBackendDevice()) + g_VideoMode.GetBackendDevice()->OnWindowResize(w, h); + if (CRenderer::IsInitialised()) - { - g_Renderer.SetViewport(vp); g_Renderer.Resize(w, h); - } if (g_GUI) g_GUI->UpdateResolution(); Index: source/renderer/PostprocManager.h =================================================================== --- source/renderer/PostprocManager.h +++ source/renderer/PostprocManager.h @@ -62,11 +62,8 @@ void SetDepthBufferClipPlanes(float nearPlane, float farPlane); - // Clears the two color buffers and depth buffer, and redirects all rendering - // to our textures instead of directly to the system framebuffer. // @note CPostprocManager must be initialized first - void CaptureRenderOutput( - Renderer::Backend::IDeviceCommandContext* deviceCommandContext); + Renderer::Backend::IFramebuffer* PrepareAndGetOutputFramebuffer(); // First renders blur textures, then calls ApplyEffect for each effect pass, // ping-ponging the buffers at each step. @@ -78,7 +75,7 @@ // framebuffer is selected as the output buffer. Should be called before // silhouette rendering. // @note CPostprocManager must be initialized first - void ReleaseRenderOutput( + void BlitOutputFramebuffer( Renderer::Backend::IDeviceCommandContext* deviceCommandContext, Renderer::Backend::IFramebuffer* destination); Index: source/renderer/PostprocManager.cpp =================================================================== --- source/renderer/PostprocManager.cpp +++ source/renderer/PostprocManager.cpp @@ -219,6 +219,11 @@ { deviceCommandContext->BeginFramebufferPass(framebuffer); + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = inWidth / 2; + viewportRect.height = inHeight / 2; + deviceCommandContext->SetViewports(1, &viewportRect); + // Get bloom shader with instructions to simply copy texels. CShaderDefines defines; defines.Add(str_BLOOM_NOP, str_1); @@ -232,10 +237,6 @@ deviceCommandContext->SetTexture( shader->GetBindingSlot(str_renderedTex), inTex); - const SViewPort oldVp = g_Renderer.GetViewport(); - const SViewPort vp = { 0, 0, inWidth / 2, inHeight / 2 }; - g_Renderer.SetViewport(vp); - // TODO: remove the fullscreen quad drawing duplication. float quadVerts[] = { @@ -274,8 +275,6 @@ deviceCommandContext->Draw(0, 6); - g_Renderer.SetViewport(oldVp); - deviceCommandContext->EndPass(); deviceCommandContext->EndFramebufferPass(); } @@ -290,6 +289,11 @@ { deviceCommandContext->BeginFramebufferPass(tempFramebuffer); + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = inWidth; + viewportRect.height = inHeight; + deviceCommandContext->SetViewports(1, &viewportRect); + // Get bloom shader, for a horizontal Gaussian blur pass. CShaderDefines defines2; defines2.Add(str_BLOOM_PASS_H, str_1); @@ -304,10 +308,6 @@ deviceCommandContext->SetUniform( shader->GetBindingSlot(str_texSize), inWidth, inHeight); - const SViewPort oldVp = g_Renderer.GetViewport(); - const SViewPort vp = { 0, 0, inWidth, inHeight }; - g_Renderer.SetViewport(vp); - float quadVerts[] = { 1.0f, 1.0f, @@ -345,13 +345,13 @@ deviceCommandContext->Draw(0, 6); - g_Renderer.SetViewport(oldVp); - deviceCommandContext->EndPass(); deviceCommandContext->EndFramebufferPass(); deviceCommandContext->BeginFramebufferPass(outFramebuffer); + deviceCommandContext->SetViewports(1, &viewportRect); + // Get bloom shader, for a vertical Gaussian blur pass. CShaderDefines defines3; defines3.Add(str_BLOOM_PASS_V, str_1); @@ -368,8 +368,6 @@ deviceCommandContext->SetUniform( shader->GetBindingSlot(str_texSize), inWidth, inHeight); - g_Renderer.SetViewport(vp); - deviceCommandContext->SetVertexAttributeFormat( Renderer::Backend::VertexAttributeStream::POSITION, Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2, @@ -386,8 +384,6 @@ deviceCommandContext->Draw(0, 6); - g_Renderer.SetViewport(oldVp); - deviceCommandContext->EndPass(); deviceCommandContext->EndFramebufferPass(); } @@ -410,22 +406,18 @@ } } - -void CPostprocManager::CaptureRenderOutput( - Renderer::Backend::IDeviceCommandContext* deviceCommandContext) +Renderer::Backend::IFramebuffer* CPostprocManager::PrepareAndGetOutputFramebuffer() { ENSURE(m_IsInitialized); // Leaves m_PingFbo selected for rendering; m_WhichBuffer stays true at this point. - deviceCommandContext->BeginFramebufferPass( - m_UsingMultisampleBuffer ? m_MultisampleFramebuffer.get() : m_CaptureFramebuffer.get()); - m_WhichBuffer = true; -} + return m_UsingMultisampleBuffer ? m_MultisampleFramebuffer.get() : m_CaptureFramebuffer.get(); +} -void CPostprocManager::ReleaseRenderOutput( +void CPostprocManager::BlitOutputFramebuffer( Renderer::Backend::IDeviceCommandContext* deviceCommandContext, Renderer::Backend::IFramebuffer* destination) { @@ -443,8 +435,14 @@ const CShaderTechniquePtr& shaderTech, int pass) { // select the other FBO for rendering - deviceCommandContext->BeginFramebufferPass( - (m_WhichBuffer ? m_PongFramebuffer : m_PingFramebuffer).get()); + Renderer::Backend::IFramebuffer* framebuffer = + (m_WhichBuffer ? m_PongFramebuffer : m_PingFramebuffer).get(); + deviceCommandContext->BeginFramebufferPass(framebuffer); + + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = framebuffer->GetWidth(); + viewportRect.height = framebuffer->GetHeight(); + deviceCommandContext->SetViewports(1, &viewportRect); deviceCommandContext->SetGraphicsPipelineState( shaderTech->GetGraphicsPipelineStateDesc(pass)); Index: source/renderer/Renderer.h =================================================================== --- source/renderer/Renderer.h +++ source/renderer/Renderer.h @@ -99,12 +99,6 @@ // trigger a reload of shaders (when parameters they depend on have changed) void MakeShadersDirty(); - // set the viewport - void SetViewport(const SViewPort &); - - // get the last viewport - SViewPort GetViewport(); - // return stats accumulated for current frame Stats& GetStats() { return m_Stats; } @@ -167,8 +161,6 @@ int m_Width = 0; // view height int m_Height = 0; - - SViewPort m_Viewport; // per-frame renderer stats Stats m_Stats; Index: source/renderer/Renderer.cpp =================================================================== --- source/renderer/Renderer.cpp +++ source/renderer/Renderer.cpp @@ -302,14 +302,6 @@ // the first Frame. GetSceneRenderer().SetLightEnv(&g_LightEnv); - // I haven't seen the camera affecting GUI rendering and such, but the - // viewport has to be updated according to the video mode - SViewPort vp; - vp.m_X = 0; - vp.m_Y = 0; - vp.m_Width = g_xres; - vp.m_Height = g_yres; - SetViewport(vp); ModelDefActivateFastImpl(); ColorActivateFastImpl(); ModelRenderer::Init(); @@ -468,6 +460,8 @@ m->deviceCommandContext->SetGraphicsPipelineState( Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc()); + Renderer::Backend::IFramebuffer* framebuffer = nullptr; + CPostprocManager& postprocManager = g_Renderer.GetPostprocManager(); if (postprocManager.IsEnabled()) { @@ -478,20 +472,27 @@ m->sceneRenderer.GetViewCamera().GetFarPlane() ); postprocManager.Initialize(); - postprocManager.CaptureRenderOutput(m->deviceCommandContext.get()); + framebuffer = postprocManager.PrepareAndGetOutputFramebuffer(); } else { // We don't need to clear the color attachment of the framebuffer as the sky // is going to be rendered anyway. - m->deviceCommandContext->BeginFramebufferPass( + framebuffer = m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer( Renderer::Backend::AttachmentLoadOp::DONT_CARE, Renderer::Backend::AttachmentStoreOp::STORE, Renderer::Backend::AttachmentLoadOp::CLEAR, - Renderer::Backend::AttachmentStoreOp::DONT_CARE)); + Renderer::Backend::AttachmentStoreOp::DONT_CARE); } + m->deviceCommandContext->BeginFramebufferPass(framebuffer); + + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = framebuffer->GetWidth(); + viewportRect.height = framebuffer->GetHeight(); + m->deviceCommandContext->SetViewports(1, &viewportRect); + g_Game->GetView()->Render(m->deviceCommandContext.get()); if (postprocManager.IsEnabled()) @@ -509,10 +510,15 @@ Renderer::Backend::AttachmentStoreOp::STORE, Renderer::Backend::AttachmentLoadOp::LOAD, Renderer::Backend::AttachmentStoreOp::DONT_CARE); - postprocManager.ReleaseRenderOutput( + postprocManager.BlitOutputFramebuffer( m->deviceCommandContext.get(), backbuffer); m->deviceCommandContext->BeginFramebufferPass(backbuffer); + + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = backbuffer->GetWidth(); + viewportRect.height = backbuffer->GetHeight(); + m->deviceCommandContext->SetViewports(1, &viewportRect); } g_Game->GetView()->RenderOverlays(m->deviceCommandContext.get()); @@ -530,12 +536,18 @@ g_AtlasGameLoop && g_AtlasGameLoop->view ? Renderer::Backend::AttachmentLoadOp::CLEAR : Renderer::Backend::AttachmentLoadOp::DONT_CARE; - m->deviceCommandContext->BeginFramebufferPass( + Renderer::Backend::IFramebuffer* backbuffer = m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer( Renderer::Backend::AttachmentLoadOp::DONT_CARE, Renderer::Backend::AttachmentStoreOp::STORE, depthStencilLoadOp, - Renderer::Backend::AttachmentStoreOp::DONT_CARE)); + Renderer::Backend::AttachmentStoreOp::DONT_CARE); + m->deviceCommandContext->BeginFramebufferPass(backbuffer); + + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = backbuffer->GetWidth(); + viewportRect.height = backbuffer->GetHeight(); + m->deviceCommandContext->SetViewports(1, &viewportRect); } // If we're in Atlas game view, render special tools @@ -787,22 +799,6 @@ PROFILE3("end frame"); m->sceneRenderer.EndFrame(); -} - -void CRenderer::SetViewport(const SViewPort &vp) -{ - m_Viewport = vp; - Renderer::Backend::IDeviceCommandContext::Rect viewportRect; - viewportRect.x = vp.m_X; - viewportRect.y = vp.m_Y; - viewportRect.width = vp.m_Width; - viewportRect.height = vp.m_Height; - m->deviceCommandContext->SetViewports(1, &viewportRect); -} - -SViewPort CRenderer::GetViewport() -{ - return m_Viewport; } void CRenderer::MakeShadersDirty() Index: source/renderer/SceneRenderer.cpp =================================================================== --- source/renderer/SceneRenderer.cpp +++ source/renderer/SceneRenderer.cpp @@ -332,8 +332,6 @@ } m->shadow.EndRender(deviceCommandContext); - - g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); } void CSceneRenderer::RenderPatches( @@ -565,8 +563,6 @@ return; } - g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); - // Save the model-view-projection matrix so the shaders can use it for projective texturing wm.m_ReflectionMatrix = m_ViewCamera.GetViewProjection(); @@ -579,6 +575,15 @@ screenScissor.x2 = static_cast(ceil((reflectionScissor[1].X * 0.5f + 0.5f) * vpWidth)); screenScissor.y2 = static_cast(ceil((reflectionScissor[1].Y * 0.5f + 0.5f) * vpHeight)); + deviceCommandContext->SetGraphicsPipelineState( + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc()); + deviceCommandContext->BeginFramebufferPass(wm.m_ReflectionFramebuffer.get()); + + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = vpWidth; + viewportRect.height = vpHeight; + deviceCommandContext->SetViewports(1, &viewportRect); + Renderer::Backend::IDeviceCommandContext::Rect scissorRect; scissorRect.x = screenScissor.x1; scissorRect.y = screenScissor.y1; @@ -586,10 +591,6 @@ scissorRect.height = screenScissor.y2 - screenScissor.y1; deviceCommandContext->SetScissors(1, &scissorRect); - deviceCommandContext->SetGraphicsPipelineState( - Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc()); - deviceCommandContext->BeginFramebufferPass(wm.m_ReflectionFramebuffer.get()); - CShaderDefines reflectionsContext = context; reflectionsContext.Add(str_PASS_REFLECTIONS, str_1); @@ -610,7 +611,6 @@ // Reset old camera m_ViewCamera = normalCamera; - g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); } // RenderRefractions: render the water refractions to the refraction texture @@ -638,8 +638,6 @@ CVector4D camPlane(0, -1, 0, wm.m_WaterHeight + 2.0f); SetObliqueFrustumClipping(m_ViewCamera, camPlane); - g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); - // Save the model-view-projection matrix so the shaders can use it for projective texturing wm.m_RefractionMatrix = m_ViewCamera.GetViewProjection(); wm.m_RefractionProjInvMatrix = m_ViewCamera.GetProjection().GetInverse(); @@ -654,6 +652,15 @@ screenScissor.x2 = static_cast(ceil((refractionScissor[1].X * 0.5f + 0.5f) * vpWidth)); screenScissor.y2 = static_cast(ceil((refractionScissor[1].Y * 0.5f + 0.5f) * vpHeight)); + deviceCommandContext->SetGraphicsPipelineState( + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc()); + deviceCommandContext->BeginFramebufferPass(wm.m_RefractionFramebuffer.get()); + + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = vpWidth; + viewportRect.height = vpHeight; + deviceCommandContext->SetViewports(1, &viewportRect); + Renderer::Backend::IDeviceCommandContext::Rect scissorRect; scissorRect.x = screenScissor.x1; scissorRect.y = screenScissor.y1; @@ -661,10 +668,6 @@ scissorRect.height = screenScissor.y2 - screenScissor.y1; deviceCommandContext->SetScissors(1, &scissorRect); - deviceCommandContext->SetGraphicsPipelineState( - Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc()); - deviceCommandContext->BeginFramebufferPass(wm.m_RefractionFramebuffer.get()); - // Render terrain and models RenderPatches(deviceCommandContext, context, CULL_REFRACTIONS); @@ -679,7 +682,6 @@ // Reset old camera m_ViewCamera = normalCamera; - g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); } void CSceneRenderer::RenderSilhouettes( @@ -769,9 +771,6 @@ deviceCommandContext, GetScene().GetLOSTexture(), GetScene().GetTerritoryTexture()); CShaderDefines context = m->globalContext; - - // Set the camera - g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); // Prepare model renderers { Index: source/renderer/ShadowMap.cpp =================================================================== --- source/renderer/ShadowMap.cpp +++ source/renderer/ShadowMap.cpp @@ -600,8 +600,10 @@ { m->CalculateShadowMatrices(cascade); - const SViewPort vp = { 0, 0, m->EffectiveWidth, m->EffectiveHeight }; - g_Renderer.SetViewport(vp); + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = m->EffectiveWidth; + viewportRect.height = m->EffectiveHeight; + deviceCommandContext->SetViewports(1, &viewportRect); CCamera camera = m->SavedViewCamera; camera.SetProjection(m->Cascades[cascade].LightProjection); @@ -625,9 +627,6 @@ deviceCommandContext->EndFramebufferPass(); g_Renderer.GetSceneRenderer().SetViewCamera(m->SavedViewCamera); - - const SViewPort vp = { 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight() }; - g_Renderer.SetViewport(vp); } void ShadowMap::BindTo( Index: source/renderer/backend/IDevice.h =================================================================== --- source/renderer/backend/IDevice.h +++ source/renderer/backend/IDevice.h @@ -136,6 +136,13 @@ */ virtual void Present() = 0; + /** + * Should be called on window surface resize. It's the device owner + * responsibility to call that function. Shouldn't be called during + * rendering to an acquired backbuffer. + */ + virtual void OnWindowResize(const uint32_t width, const uint32_t height) = 0; + virtual bool IsTextureFormatSupported(const Format format) const = 0; virtual bool IsFramebufferFormatSupported(const Format format) const = 0; Index: source/renderer/backend/IFramebuffer.h =================================================================== --- source/renderer/backend/IFramebuffer.h +++ source/renderer/backend/IFramebuffer.h @@ -89,6 +89,9 @@ * @see IDevice::CreateFramebuffer() */ virtual const CColor& GetClearColor() const = 0; + + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; }; } // namespace Backend Index: source/renderer/backend/dummy/Device.h =================================================================== --- source/renderer/backend/dummy/Device.h +++ source/renderer/backend/dummy/Device.h @@ -79,6 +79,8 @@ void Present() override; + void OnWindowResize(const uint32_t width, const uint32_t height) override; + bool IsTextureFormatSupported(const Format format) const override; bool IsFramebufferFormatSupported(const Format format) const override; Index: source/renderer/backend/dummy/Device.cpp =================================================================== --- source/renderer/backend/dummy/Device.cpp +++ source/renderer/backend/dummy/Device.cpp @@ -126,6 +126,10 @@ // We have nothing to present. } +void CDevice::OnWindowResize(const uint32_t UNUSED(width), const uint32_t UNUSED(height)) +{ +} + bool CDevice::IsTextureFormatSupported(const Format UNUSED(format)) const { return true; Index: source/renderer/backend/dummy/Framebuffer.h =================================================================== --- source/renderer/backend/dummy/Framebuffer.h +++ source/renderer/backend/dummy/Framebuffer.h @@ -42,6 +42,9 @@ const CColor& GetClearColor() const override { return m_ClearColor; } + uint32_t GetWidth() const override { return 1; } + uint32_t GetHeight() const override { return 1; } + private: friend class CDevice; Index: source/renderer/backend/gl/Device.h =================================================================== --- source/renderer/backend/gl/Device.h +++ source/renderer/backend/gl/Device.h @@ -100,6 +100,8 @@ void Present() override; + void OnWindowResize(const uint32_t width, const uint32_t height) override; + bool UseFramebufferInvalidating() const { return m_UseFramebufferInvalidating; } bool IsTextureFormatSupported(const Format format) const override; @@ -113,6 +115,7 @@ SDL_Window* m_Window = nullptr; SDL_GLContext m_Context = nullptr; + int m_SurfaceDrawableWidth = 0, m_SurfaceDrawableHeight = 0; bool m_ARB = false; Index: source/renderer/backend/gl/Device.cpp =================================================================== --- source/renderer/backend/gl/Device.cpp +++ source/renderer/backend/gl/Device.cpp @@ -241,6 +241,8 @@ LOGERROR("SDL_GL_CreateContext failed: '%s'", SDL_GetError()); return nullptr; } + SDL_GL_GetDrawableSize(window, &device->m_SurfaceDrawableWidth, &device->m_SurfaceDrawableHeight); + #if OS_WIN ogl_Init(SDL_GL_GetProcAddress, wutil_GetAppHDC()); #elif (defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND)) && !CONFIG2_GLES @@ -934,7 +936,8 @@ if (it == m_Backbuffers.end()) { it = m_Backbuffers.emplace(key, CFramebuffer::CreateBackbuffer( - this, colorAttachmentLoadOp, colorAttachmentStoreOp, + this, m_SurfaceDrawableWidth, m_SurfaceDrawableHeight, + colorAttachmentLoadOp, colorAttachmentStoreOp, depthStencilAttachmentLoadOp, depthStencilAttachmentStoreOp)).first; } return it->second.get(); @@ -963,6 +966,14 @@ // synchronizations during rendering. if (GLenum err = glGetError()) ONCE(LOGERROR("GL error %s (0x%04x) occurred", ogl_GetErrorName(err), err)); +} + +void CDevice::OnWindowResize(const uint32_t width, const uint32_t height) +{ + ENSURE(!m_BackbufferAcquired); + m_Backbuffers.clear(); + m_SurfaceDrawableWidth = width; + m_SurfaceDrawableHeight = height; } bool CDevice::IsTextureFormatSupported(const Format format) const Index: source/renderer/backend/gl/DeviceCommandContext.cpp =================================================================== --- source/renderer/backend/gl/DeviceCommandContext.cpp +++ source/renderer/backend/gl/DeviceCommandContext.cpp @@ -950,6 +950,7 @@ void CDeviceCommandContext::SetViewports(const uint32_t viewportCount, const Rect* viewports) { + ENSURE(m_InsideFramebufferPass); ENSURE(viewportCount == 1); glViewport(viewports[0].x, viewports[0].y, viewports[0].width, viewports[0].height); ogl_WarnIfError(); Index: source/renderer/backend/gl/Framebuffer.h =================================================================== --- source/renderer/backend/gl/Framebuffer.h +++ source/renderer/backend/gl/Framebuffer.h @@ -46,6 +46,9 @@ const CColor& GetClearColor() const override { return m_ClearColor; } + uint32_t GetWidth() const override { return m_Width; } + uint32_t GetHeight() const override { return m_Height; } + GLuint GetHandle() const { return m_Handle; } GLbitfield GetAttachmentMask() const { return m_AttachmentMask; } @@ -54,9 +57,6 @@ AttachmentLoadOp GetDepthStencilAttachmentLoadOp() const { return m_DepthStencilAttachmentLoadOp; } AttachmentStoreOp GetDepthStencilAttachmentStoreOp() const { return m_DepthStencilAttachmentStoreOp; } - uint32_t GetWidth() const { return m_Width; } - uint32_t GetHeight() const { return m_Height; } - private: friend class CDevice; @@ -65,6 +65,7 @@ SDepthStencilAttachment* depthStencilAttachment); static std::unique_ptr CreateBackbuffer( CDevice* device, + const int surfaceDrawableWidth, const int surfaceDrawableHeight, const AttachmentLoadOp colorAttachmentLoadOp, const AttachmentStoreOp colorAttachmentStoreOp, const AttachmentLoadOp depthStencilAttachmentLoadOp, Index: source/renderer/backend/gl/Framebuffer.cpp =================================================================== --- source/renderer/backend/gl/Framebuffer.cpp +++ source/renderer/backend/gl/Framebuffer.cpp @@ -164,6 +164,7 @@ // static std::unique_ptr CFramebuffer::CreateBackbuffer( CDevice* device, + const int surfaceDrawableWidth, const int surfaceDrawableHeight, const AttachmentLoadOp colorAttachmentLoadOp, const AttachmentStoreOp colorAttachmentStoreOp, const AttachmentLoadOp depthStencilAttachmentLoadOp, @@ -178,6 +179,8 @@ framebuffer->m_ColorAttachmentStoreOp = colorAttachmentStoreOp; framebuffer->m_DepthStencilAttachmentLoadOp = depthStencilAttachmentLoadOp; framebuffer->m_DepthStencilAttachmentStoreOp = depthStencilAttachmentStoreOp; + framebuffer->m_Width = surfaceDrawableWidth; + framebuffer->m_Height = surfaceDrawableHeight; return framebuffer; } Index: source/renderer/backend/vulkan/Device.h =================================================================== --- source/renderer/backend/vulkan/Device.h +++ source/renderer/backend/vulkan/Device.h @@ -86,6 +86,8 @@ void Present() override; + void OnWindowResize(const uint32_t width, const uint32_t height) override; + bool IsTextureFormatSupported(const Format format) const override; bool IsFramebufferFormatSupported(const Format format) const override; Index: source/renderer/backend/vulkan/Device.cpp =================================================================== --- source/renderer/backend/vulkan/Device.cpp +++ source/renderer/backend/vulkan/Device.cpp @@ -156,6 +156,12 @@ { } +void CDevice::OnWindowResize(const uint32_t width, const uint32_t height) +{ + UNUSED2(width); + UNUSED2(height); +} + bool CDevice::IsTextureFormatSupported(const Format format) const { UNUSED2(format); Index: source/tools/atlas/GameInterface/ActorViewer.cpp =================================================================== --- source/tools/atlas/GameInterface/ActorViewer.cpp +++ source/tools/atlas/GameInterface/ActorViewer.cpp @@ -539,12 +539,18 @@ sceneRenderer.PrepareScene(deviceCommandContext, m); - deviceCommandContext->BeginFramebufferPass( + Renderer::Backend::IFramebuffer* backbuffer = deviceCommandContext->GetDevice()->GetCurrentBackbuffer( Renderer::Backend::AttachmentLoadOp::DONT_CARE, Renderer::Backend::AttachmentStoreOp::STORE, Renderer::Backend::AttachmentLoadOp::CLEAR, - Renderer::Backend::AttachmentStoreOp::DONT_CARE)); + Renderer::Backend::AttachmentStoreOp::DONT_CARE); + deviceCommandContext->BeginFramebufferPass(backbuffer); + + Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; + viewportRect.width = backbuffer->GetWidth(); + viewportRect.height = backbuffer->GetHeight(); + deviceCommandContext->SetViewports(1, &viewportRect); sceneRenderer.RenderScene(deviceCommandContext); sceneRenderer.RenderSceneOverlays(deviceCommandContext); Index: source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp @@ -39,6 +39,7 @@ #include "ps/VideoMode.h" #include "ps/GameSetup/Config.h" #include "ps/GameSetup/GameSetup.h" +#include "renderer/backend/IDevice.h" #include "renderer/Renderer.h" #include "renderer/SceneRenderer.h" @@ -117,6 +118,8 @@ UNUSED2(msg); g_VideoMode.CreateBackendDevice(false); + + g_VideoMode.GetBackendDevice()->OnWindowResize(g_xres, g_yres); InitGraphics(g_AtlasGameLoop->args, g_InitFlags, {}); }