From 07958f08aebe8076b952987cbe5c99753175a6c6 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Wed, 23 Oct 2019 18:13:28 +0200 Subject: [PATCH] refactor xform matrix out of gles. use xform matrix in vulkan --- core/hw/pvr/Renderer_if.cpp | 3 +- core/rend/gl4/gl4.h | 1 - core/rend/gl4/gles.cpp | 66 +++----- core/rend/gles/gles.cpp | 204 ++----------------------- core/rend/gles/gles.h | 1 - core/rend/osd.cpp | 16 +- core/rend/osd.h | 16 ++ core/rend/transform_matrix.h | 216 +++++++++++++++++++++++++++ core/rend/vulkan/drawer.cpp | 180 +++++----------------- core/rend/vulkan/drawer.h | 6 +- core/rend/vulkan/pipeline.cpp | 2 +- core/rend/vulkan/pipeline.h | 1 - core/rend/vulkan/shaders.cpp | 21 +-- core/rend/vulkan/shaders.h | 7 +- core/rend/vulkan/vulkan_renderer.cpp | 49 +++--- 15 files changed, 349 insertions(+), 440 deletions(-) create mode 100644 core/rend/transform_matrix.h diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index cc20dd27b..11da70781 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -329,7 +329,8 @@ bool rend_single_frame() } while (!_pvrrc); bool do_swp = rend_frame(_pvrrc); - swap_pending = settings.rend.DelayFrameSwapping && do_swp && !_pvrrc->rend.isRenderFramebuffer; + swap_pending = settings.rend.DelayFrameSwapping && do_swp && !_pvrrc->rend.isRenderFramebuffer + && settings.pvr.rend != 4; // TODO Fix vulkan #if !defined(TARGET_NO_THREADS) if (_pvrrc->rend.isRTT) diff --git a/core/rend/gl4/gl4.h b/core/rend/gl4/gl4.h index 6bdfe51de..126e81c39 100755 --- a/core/rend/gl4/gl4.h +++ b/core/rend/gl4/gl4.h @@ -40,7 +40,6 @@ struct gl4_ctx { GLuint program; - GLuint extra_depth_scale; GLuint normal_matrix; } modvol_shader; diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index f97b5e3d3..2ea892013 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -8,6 +8,7 @@ #include "oslib/oslib.h" #include "rend/rend.h" #include "rend/gui.h" +#include "rend/transform_matrix.h" //Fragment and vertex shaders code @@ -513,7 +514,6 @@ static void create_modvol_shader() gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader); gl4.modvol_shader.normal_matrix = glGetUniformLocation(gl4.modvol_shader.program, "normal_matrix"); - gl4.modvol_shader.extra_depth_scale = glGetUniformLocation(gl4.modvol_shader.program, "extra_depth_scale"); } static bool gl_create_resources() @@ -639,38 +639,29 @@ static bool RenderFrame() DoCleanup(); create_modvol_shader(); - bool is_rtt = pvrrc.isRTT; + const bool is_rtt = pvrrc.isRTT; + + TransformMatrix matrices(pvrrc); + gl4ShaderUniforms.normal_mat = matrices.GetNormalMatrix(); + const glm::mat4& scissor_mat = matrices.GetScissorMatrix(); + ViewportMatrix = matrices.GetViewportMatrix(); - //these should be adjusted based on the current PVR scaling etc params - float dc_width; - float dc_height; - GetFramebufferSize(dc_width, dc_height); - if (!is_rtt) gcflip = 0; else gcflip = 1; - float scale_x; - float scale_y; - float scissoring_scale_x; - float scissoring_scale_y; - GetFramebufferScaling(scale_x, scale_y, scissoring_scale_x, scissoring_scale_y); - - dc_width *= scale_x; - dc_height *= scale_y; - /* Handle Dc to screen scaling */ - float screen_scaling = settings.rend.ScreenScaling / 100.f; + const float screen_scaling = settings.rend.ScreenScaling / 100.f; int rendering_width; int rendering_height; if (is_rtt) { int scaling = settings.rend.RenderToTextureBuffer ? 1 : settings.rend.RenderToTextureUpscale; - rendering_width = dc_width * scaling; - rendering_height = dc_height * scaling; + rendering_width = matrices.GetDreamcastViewport().x * scaling; + rendering_height = matrices.GetDreamcastViewport().y * scaling; } else { @@ -679,11 +670,6 @@ static bool RenderFrame() } resize(rendering_width, rendering_height); - float ds2s_offs_x; - - glm::mat4 scissor_mat; - SetupMatrices(dc_width, dc_height, scale_x, scale_y, scissoring_scale_x, scissoring_scale_y, ds2s_offs_x, gl4ShaderUniforms.normal_mat, scissor_mat); - gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale; //DEBUG_LOG(RENDERER, "scale: %f, %f, %f, %f", gl4ShaderUniforms.scale_coefs[0], gl4ShaderUniforms.scale_coefs[1], gl4ShaderUniforms.scale_coefs[2], gl4ShaderUniforms.scale_coefs[3]); @@ -724,7 +710,6 @@ static bool RenderFrame() glcache.UseProgram(gl4.modvol_shader.program); glUniformMatrix4fv(gl4.modvol_shader.normal_matrix, 1, GL_FALSE, &gl4ShaderUniforms.normal_mat[0][0]); - glUniform1f(gl4.modvol_shader.extra_depth_scale, gl4ShaderUniforms.extra_depth_scale); gl4ShaderUniforms.PT_ALPHA=(PT_ALPHA_REF&0xFF)/255.0f; @@ -768,7 +753,8 @@ static bool RenderFrame() } DEBUG_LOG(RENDERER, "RTT packmode=%d stride=%d - %d,%d -> %d,%d", FB_W_CTRL.fb_packmode, FB_W_LINESTRIDE.stride * 8, FB_X_CLIP.min, FB_Y_CLIP.min, FB_X_CLIP.max, FB_Y_CLIP.max); - output_fbo = gl4BindRTT(FB_W_SOF1 & VRAM_MASK, dc_width, dc_height, channels, format); + output_fbo = gl4BindRTT(FB_W_SOF1 & VRAM_MASK, (u32)lroundf(matrices.GetDreamcastViewport().x), + (u32)lroundf(matrices.GetDreamcastViewport().y), channels, format); } else { @@ -809,23 +795,7 @@ static bool RenderFrame() glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(struct PolyParam) * pvrrc.global_param_tr.used(), pvrrc.global_param_tr.head(), GL_STATIC_DRAW); glCheck(); - //not all scaling affects pixel operations, scale to adjust for that - scale_x *= scissoring_scale_x; - - #if 0 - //handy to debug really stupid render-not-working issues ... - DEBUG_LOG(RENDERER, "SS: %dx%d", screen_width, screen_height); - DEBUG_LOG(RENDERER, "SCI: %d, %f", pvrrc.fb_X_CLIP.max, dc2s_scale_h); - DEBUG_LOG(RENDERER, "SCI: %f, %f, %f, %f", offs_x+pvrrc.fb_X_CLIP.min/scale_x,(pvrrc.fb_Y_CLIP.min/scale_y)*dc2s_scale_h,(pvrrc.fb_X_CLIP.max-pvrrc.fb_X_CLIP.min+1)/scale_x*dc2s_scale_h,(pvrrc.fb_Y_CLIP.max-pvrrc.fb_Y_CLIP.min+1)/scale_y*dc2s_scale_h); - #endif - - bool wide_screen_on = !is_rtt && settings.rend.WideScreen - && pvrrc.fb_X_CLIP.min == 0 - && lroundf((pvrrc.fb_X_CLIP.max + 1) / scale_x) == 640L - && pvrrc.fb_Y_CLIP.min == 0 - && lroundf((pvrrc.fb_Y_CLIP.max + 1) / scale_y) == 480L; - - if (!wide_screen_on) + if (is_rtt || !settings.rend.WideScreen || matrices.IsClipped()) { float width; float height; @@ -853,9 +823,9 @@ static bool RenderFrame() min_y += height; height = -height; } - if (ds2s_offs_x > 0) + if (matrices.GetSidebarWidth() > 0) { - float scaled_offs_x = ds2s_offs_x * screen_scaling; + float scaled_offs_x = matrices.GetSidebarWidth() * screen_scaling; glcache.ClearColor(0.f, 0.f, 0.f, 0.f); glcache.Enable(GL_SCISSOR_TEST); @@ -883,8 +853,6 @@ static bool RenderFrame() glcache.Enable(GL_SCISSOR_TEST); } - //restore scale_x - scale_x /= scissoring_scale_x; gl4DrawStrips(output_fbo, rendering_width, rendering_height); } else @@ -895,7 +863,7 @@ static bool RenderFrame() glcache.ClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT); - gl4DrawFramebuffer(dc_width, dc_height); + gl4DrawFramebuffer(640.f, 480.f); } eglCheck(); @@ -917,7 +885,7 @@ struct gl4rend : Renderer { screen_width=w; screen_height=h; - resize(lroundf(w * settings.rend.ScreenScaling / 100.f), lroundf(h * settings.rend.ScreenScaling / 100.f)); + resize((int)lroundf(w * settings.rend.ScreenScaling / 100.f), (int)lroundf(h * settings.rend.ScreenScaling / 100.f)); } void Term() override { diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 34788d2d3..7f1064fdb 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -6,6 +6,7 @@ #include "wsi/gl_context.h" #include "cfg/cfg.h" #include "rend/osd.h" +#include "rend/transform_matrix.h" #ifdef GLES #ifndef GL_RED @@ -20,7 +21,6 @@ #include "oslib/oslib.h" #include "rend/rend.h" #include "input/gamepad.h" -#include float fb_scale_x, fb_scale_y; // FIXME @@ -816,7 +816,6 @@ static void create_modvol_shader() gl.modvol_shader.normal_matrix = glGetUniformLocation(gl.modvol_shader.program, "normal_matrix"); gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor"); gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale"); - gl.modvol_shader.extra_depth_scale = glGetUniformLocation(gl.modvol_shader.program, "extra_depth_scale"); } bool gl_create_resources() @@ -1026,161 +1025,6 @@ static void upload_vertex_indices() glCheck(); } -void GetFramebufferScaling(float& scale_x, float& scale_y, float& scissoring_scale_x, float& scissoring_scale_y) -{ - scale_x = 1; - scale_y = 1; - scissoring_scale_x = 1; - scissoring_scale_y = 1; - - if (!pvrrc.isRTT && !pvrrc.isRenderFramebuffer) - { - scale_x = fb_scale_x; - scale_y = fb_scale_y; - if (SCALER_CTL.vscalefactor >= 0x400) - { - // Interlace mode A (single framebuffer) - if (SCALER_CTL.interlace == 0) - scale_y *= (float)SCALER_CTL.vscalefactor / 0x400; - else - // Interlace mode B (alternating framebuffers) - scissoring_scale_y /= (float)SCALER_CTL.vscalefactor / 0x400; - } - - // VO pixel doubling is done after fb rendering/clipping - // so it should be used for scissoring as well - if (VO_CONTROL.pixel_double) - scale_x *= 0.5f; - - // the X Scaler halves the horizontal resolution but - // before clipping/scissoring - if (SCALER_CTL.hscale) - { - scissoring_scale_x /= 2.f; - scale_x *= 2.f; - } - } -} - -void GetFramebufferSize(float& dc_width, float& dc_height) -{ - if (pvrrc.isRTT) - { - dc_width = pvrrc.fb_X_CLIP.max - pvrrc.fb_X_CLIP.min + 1; - dc_height = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1; - } - else - { - dc_width = 640; - dc_height = 480; - } -} - -void SetupMatrices(float dc_width, float dc_height, - float scale_x, float scale_y, float scissoring_scale_x, float scissoring_scale_y, - float &ds2s_offs_x, glm::mat4& normal_mat, glm::mat4& scissor_mat) -{ - float screen_scaling = settings.rend.ScreenScaling / 100.f; - - if (pvrrc.isRTT) - { - ShaderUniforms.normal_mat = glm::translate(glm::vec3(-1, -1, 0)) - * glm::scale(glm::vec3(2.0f / dc_width, 2.0f / dc_height, 1.f)); - scissor_mat = ShaderUniforms.normal_mat; - } - else - { - float startx = 0; - float starty = 0; - bool vga = FB_R_CTRL.vclk_div == 1; - switch (SPG_LOAD.hcount) - { - case 857: // NTSC, VGA - startx = VO_STARTX.HStart - (vga ? 0xa8 : 0xa4); - break; - case 863: // PAL - startx = VO_STARTX.HStart - 0xae; - break; - default: - INFO_LOG(PVR, "unknown video mode: hcount %d", SPG_LOAD.hcount); - break; - } - switch (SPG_LOAD.vcount) - { - case 524: // NTSC, VGA - starty = VO_STARTY.VStart_field1 - (vga ? 0x28 : 0x12); - break; - case 262: // NTSC 240p - starty = VO_STARTY.VStart_field1 - 0x11; - break; - case 624: // PAL - starty = VO_STARTY.VStart_field1 - 0x2d; - break; - case 312: // PAL 240p - starty = VO_STARTY.VStart_field1 - 0x2e; - break; - default: - INFO_LOG(PVR, "unknown video mode: vcount %d", SPG_LOAD.vcount); - break; - } - // some heuristic... - startx *= 0.8; - starty *= 1.1; - normal_mat = glm::translate(glm::vec3(startx, starty, 0)); - scissor_mat = normal_mat; - - float screen_stretching = settings.rend.ScreenStretching / 100.f; - float dc2s_scale_h; - - if (settings.rend.Rotate90) - { - dc2s_scale_h = screen_height / 640.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2; - float y_coef = 2.0f / (screen_width / dc2s_scale_h * scale_y) * screen_stretching; - float x_coef = -2.0f / dc_width; - glm::mat4 trans_rot = glm::rotate((float)M_PI_2, glm::vec3(0, 0, 1)) - * glm::translate(glm::vec3(1, -1 + 2 * ds2s_offs_x / screen_width, 0)); - normal_mat = trans_rot - * glm::scale(glm::vec3(x_coef, y_coef, 1.f)) - * normal_mat; - scissor_mat = trans_rot - * glm::scale(glm::vec3(x_coef / scissoring_scale_x, - y_coef/ scissoring_scale_y, 1.f)) - * scissor_mat; // FIXME scale_x not used, except in dc_width??? - } - else - { - dc2s_scale_h = screen_height / 480.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2; - float x_coef = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; - float y_coef = -2.0f / dc_height; - normal_mat = glm::translate(glm::vec3(-1 + 2 * ds2s_offs_x / screen_width, 1, 0)) - * glm::scale(glm::vec3(x_coef, y_coef, 1.f)) - * normal_mat; - scissor_mat = glm::translate(glm::vec3(-1 + 2 * ds2s_offs_x / screen_width, 1, 0)) - * glm::scale(glm::vec3(x_coef / scissoring_scale_x, - y_coef / scissoring_scale_y, 1.f)) - * scissor_mat; - } - } - normal_mat = glm::scale(glm::vec3(1, 1, 1 / settings.rend.ExtraDepthScale)) - * normal_mat; - - glm::mat4 vp_trans = glm::translate(glm::vec3(1, 1, 0)); - if (pvrrc.isRTT) - { - vp_trans = glm::scale(glm::vec3(dc_width / 2, dc_height / 2, 1.f)) - * vp_trans; - } - else - { - vp_trans = glm::scale(glm::vec3(screen_width * screen_scaling / 2, screen_height * screen_scaling / 2, 1.f)) - * vp_trans; - } - ViewportMatrix = vp_trans * normal_mat; - scissor_mat = vp_trans * scissor_mat; -} - bool RenderFrame() { DoCleanup(); @@ -1200,39 +1044,16 @@ bool RenderFrame() vtx_min_fZ *= 0.98f; vtx_max_fZ *= 1.001f; - //calculate a projection so that it matches the pvr x,y setup, and - //a) Z is linearly scaled between 0 ... 1 - //b) W is passed though for proper perspective calculations - - //these should be adjusted based on the current PVR scaling etc params - float dc_width; - float dc_height; - GetFramebufferSize(dc_width, dc_height); + TransformMatrix matrices(pvrrc); + ShaderUniforms.normal_mat = matrices.GetNormalMatrix(); + const glm::mat4& scissor_mat = matrices.GetScissorMatrix(); + ViewportMatrix = matrices.GetViewportMatrix(); if (!is_rtt) gcflip = 0; else gcflip = 1; - float scale_x; - float scale_y; - float scissoring_scale_x; - float scissoring_scale_y; - GetFramebufferScaling(scale_x, scale_y, scissoring_scale_x, scissoring_scale_y); - - dc_width *= scale_x; - dc_height *= scale_y; - - /* - Handle Dc to screen scaling - */ - float screen_scaling = settings.rend.ScreenScaling / 100.f; - - float ds2s_offs_x; - - glm::mat4 scissor_mat; - SetupMatrices(dc_width, dc_height, scale_x, scale_y, scissoring_scale_x, scissoring_scale_y, ds2s_offs_x, ShaderUniforms.normal_mat, scissor_mat); - ShaderUniforms.depth_coefs[0] = 2 / (vtx_max_fZ - vtx_min_fZ); ShaderUniforms.depth_coefs[1] = -vtx_min_fZ - 1; ShaderUniforms.depth_coefs[2] = 0; @@ -1276,7 +1097,6 @@ bool RenderFrame() glcache.UseProgram(gl.modvol_shader.program); glUniform4fv( gl.modvol_shader.depth_scale, 1, ShaderUniforms.depth_coefs); - glUniform1f(gl.modvol_shader.extra_depth_scale, ShaderUniforms.extra_depth_scale); glUniformMatrix4fv(gl.modvol_shader.normal_matrix, 1, GL_FALSE, &ShaderUniforms.normal_mat[0][0]); ShaderUniforms.PT_ALPHA=(PT_ALPHA_REF&0xFF)/255.0f; @@ -1287,6 +1107,8 @@ bool RenderFrame() ShaderUniforms.Set(&it.second); } + const float screen_scaling = settings.rend.ScreenScaling / 100.f; + //setup render target first if (is_rtt) { @@ -1325,7 +1147,7 @@ bool RenderFrame() } DEBUG_LOG(RENDERER, "RTT packmode=%d stride=%d - %d,%d -> %d,%d", FB_W_CTRL.fb_packmode, FB_W_LINESTRIDE.stride * 8, FB_X_CLIP.min, FB_Y_CLIP.min, FB_X_CLIP.max, FB_Y_CLIP.max); - BindRTT(FB_W_SOF1 & VRAM_MASK, dc_width, dc_height, channels, format); + BindRTT(FB_W_SOF1 & VRAM_MASK, FB_X_CLIP.max - FB_X_CLIP.min + 1, FB_Y_CLIP.max - FB_Y_CLIP.min + 1, channels, format); } else { @@ -1343,11 +1165,7 @@ bool RenderFrame() } } - bool wide_screen_on = !is_rtt && settings.rend.WideScreen - && pvrrc.fb_X_CLIP.min == 0 - && lroundf((pvrrc.fb_X_CLIP.max + 1) / scale_x) == 640L - && pvrrc.fb_Y_CLIP.min == 0 - && lroundf((pvrrc.fb_Y_CLIP.max + 1) / scale_y) == 480L; + bool wide_screen_on = !is_rtt && settings.rend.WideScreen && !matrices.IsClipped(); //Color is cleared by the background plane @@ -1406,9 +1224,9 @@ bool RenderFrame() min_y += height; height = -height; } - if (ds2s_offs_x > 0) + if (matrices.GetSidebarWidth() > 0) { - float scaled_offs_x = ds2s_offs_x * screen_scaling; + float scaled_offs_x = matrices.GetSidebarWidth() * screen_scaling; glcache.ClearColor(0.f, 0.f, 0.f, 0.f); glcache.Enable(GL_SCISSOR_TEST); diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 2d7cfb869..38b8dd4f3 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -53,7 +53,6 @@ struct gl_ctx GLuint program; GLuint depth_scale; - GLuint extra_depth_scale; GLuint sp_ShaderColor; GLuint normal_matrix; diff --git a/core/rend/osd.cpp b/core/rend/osd.cpp index 2734e7f59..cb0ae10e9 100644 --- a/core/rend/osd.cpp +++ b/core/rend/osd.cpp @@ -1,5 +1,19 @@ -// Personal message to whoever wrote this code originally: please quit programming. Stop making other people's life miserable +/* + This file is part of reicast. + reicast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + reicast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with reicast. If not, see . + */ #include "osd.h" #include "types.h" #include "input/gamepad.h" diff --git a/core/rend/osd.h b/core/rend/osd.h index 00a201231..1fd823eb2 100644 --- a/core/rend/osd.h +++ b/core/rend/osd.h @@ -1,3 +1,19 @@ +/* + This file is part of reicast. + + reicast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + reicast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with reicast. If not, see . + */ #include #include "types.h" diff --git a/core/rend/transform_matrix.h b/core/rend/transform_matrix.h new file mode 100644 index 000000000..8dd43fa8e --- /dev/null +++ b/core/rend/transform_matrix.h @@ -0,0 +1,216 @@ +/* + Created on: Oct 22, 2019 + + Copyright 2019 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . +*/ +#include +#include +#include "hw/pvr/ta_ctx.h" + +extern float fb_scale_x, fb_scale_y; +extern int screen_width, screen_height; + +template +class TransformMatrix +{ +public: + TransformMatrix() = default; + TransformMatrix(const rend_context& renderingContext) + { + CalcMatrices(&renderingContext); + } + + bool IsClipped() const + { + return renderingContext->fb_X_CLIP.min != 0 + || lroundf((renderingContext->fb_X_CLIP.max + 1) / scale_x) != 640L + || renderingContext->fb_Y_CLIP.min != 0 + || lroundf((renderingContext->fb_Y_CLIP.max + 1) / scale_y) != 480L; + } + + const glm::mat4& GetNormalMatrix() const { + return normalMatrix; + } + const glm::mat4& GetScissorMatrix() const { + return scissorMatrix; + } + const glm::mat4& GetViewportMatrix() const { + return viewportMatrix; + } + + float GetSidebarWidth() const { + return sidebarWidth; + } + + glm::vec2 GetDreamcastViewport() const { + return dcViewport; + } + + void CalcMatrices(const rend_context *renderingContext) + { + this->renderingContext = renderingContext; + + GetFramebufferScaling(false, scale_x, scale_y); + + if (renderingContext->isRTT) + { + dcViewport.x = renderingContext->fb_X_CLIP.max - renderingContext->fb_X_CLIP.min + 1; + dcViewport.y = renderingContext->fb_Y_CLIP.max - renderingContext->fb_Y_CLIP.min + 1; + normalMatrix = glm::translate(glm::vec3(-1, -1, 0)) + * glm::scale(glm::vec3(2.0f / dcViewport.x, 2.0f / dcViewport.y, 1.f)); + scissorMatrix = normalMatrix; + sidebarWidth = 0; + } + else + { + dcViewport.x = 640.f * scale_x; + dcViewport.y = 480.f * scale_y; + + float startx = 0; + float starty = 0; + const bool vga = FB_R_CTRL.vclk_div == 1; + switch (SPG_LOAD.hcount) + { + case 857: // NTSC, VGA + startx = VO_STARTX.HStart - (vga ? 0xa8 : 0xa4); + break; + case 863: // PAL + startx = VO_STARTX.HStart - 0xae; + break; + default: + INFO_LOG(PVR, "unknown video mode: hcount %d", SPG_LOAD.hcount); + break; + } + switch (SPG_LOAD.vcount) + { + case 524: // NTSC, VGA + starty = VO_STARTY.VStart_field1 - (vga ? 0x28 : 0x12); + break; + case 262: // NTSC 240p + starty = VO_STARTY.VStart_field1 - 0x11; + break; + case 624: // PAL + starty = VO_STARTY.VStart_field1 - 0x2d; + break; + case 312: // PAL 240p + starty = VO_STARTY.VStart_field1 - 0x2e; + break; + default: + INFO_LOG(PVR, "unknown video mode: vcount %d", SPG_LOAD.vcount); + break; + } + // some heuristic... + startx *= 0.8; + starty *= 1.1; + normalMatrix = glm::translate(glm::vec3(startx, starty, 0)); + scissorMatrix = normalMatrix; + + const float screen_stretching = settings.rend.ScreenStretching / 100.f; + float scissoring_scale_x, scissoring_scale_y; + GetFramebufferScaling(true, scissoring_scale_x, scissoring_scale_y); + + if (settings.rend.Rotate90) + { + float dc2s_scale_h = screen_height / 640.0f; + sidebarWidth = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2; + float y_coef = -2.0f / (screen_width / dc2s_scale_h * scale_y) * screen_stretching; + float x_coef = -2.0f / dcViewport.x * (invertY ? -1 : 1); + glm::mat4 trans_rot = glm::rotate((float)M_PI_2, glm::vec3(0, 0, 1)) + * glm::translate(glm::vec3(invertY ? -1.f : 1.f, 1 - 2 * sidebarWidth / screen_width, 0)); + normalMatrix = trans_rot + * glm::scale(glm::vec3(x_coef, y_coef, 1.f)) + * normalMatrix; + scissorMatrix = trans_rot + * glm::scale(glm::vec3(x_coef / scale_x * scissoring_scale_x, y_coef / scale_y * scissoring_scale_y, 1.f)) + * scissorMatrix; + } + else + { + float dc2s_scale_h = screen_height / 480.0f; + sidebarWidth = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2; + float x_coef = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; + float y_coef = 2.0f / dcViewport.y * (invertY ? -1 : 1); + normalMatrix = glm::translate(glm::vec3(-1 + 2 * sidebarWidth / screen_width, invertY ? 1 : -1, 0)) + * glm::scale(glm::vec3(x_coef, y_coef, 1.f)) + * normalMatrix; + scissorMatrix = glm::translate(glm::vec3(-1 + 2 * sidebarWidth / screen_width, invertY ? 1 : -1, 0)) + * glm::scale(glm::vec3(x_coef / scale_x * scissoring_scale_x, y_coef / scale_y * scissoring_scale_y, 1.f)) + * scissorMatrix; + } + } + normalMatrix = glm::scale(glm::vec3(1, 1, 1 / settings.rend.ExtraDepthScale)) + * normalMatrix; + + glm::mat4 vp_trans = glm::translate(glm::vec3(1, 1, 0)); + if (renderingContext->isRTT) + { + vp_trans = glm::scale(glm::vec3(dcViewport.x / 2, dcViewport.y / 2, 1.f)) + * vp_trans; + } + else + { + float screen_scaling = settings.rend.ScreenScaling / 100.f; + vp_trans = glm::scale(glm::vec3(screen_width * screen_scaling / 2, screen_height * screen_scaling / 2, 1.f)) + * vp_trans; + } + viewportMatrix = vp_trans * normalMatrix; + scissorMatrix = vp_trans * scissorMatrix; + } + +private: + void GetFramebufferScaling(bool scissor, float& scale_x, float& scale_y) + { + scale_x = 1.f; + scale_y = 1.f; + + if (!renderingContext->isRTT && !renderingContext->isRenderFramebuffer) + { + scale_x = fb_scale_x; + scale_y = fb_scale_y; + if (SCALER_CTL.vscalefactor > 0x400) + { + // Interlace mode A (single framebuffer) + if (SCALER_CTL.interlace == 0 && !scissor) + scale_y *= roundf((float)SCALER_CTL.vscalefactor / 0x400); + else if (SCALER_CTL.interlace == 1 && scissor) + // Interlace mode B (alternating framebuffers) + scale_y *= roundf((float)SCALER_CTL.vscalefactor / 0x400); + } + + // VO pixel doubling is done after fb rendering/clipping + // so it should be used for scissoring as well + if (VO_CONTROL.pixel_double) + scale_x *= 0.5f; + + // the X Scaler halves the horizontal resolution but + // before clipping/scissoring + if (SCALER_CTL.hscale && !scissor) + scale_x *= 2.f; + } + } + + const rend_context *renderingContext = nullptr; + + glm::mat4 normalMatrix; + glm::mat4 scissorMatrix; + glm::mat4 viewportMatrix; + glm::vec2 dcViewport; + float scale_x = 0; + float scale_y = 0; + float sidebarWidth = 0; +}; diff --git a/core/rend/vulkan/drawer.cpp b/core/rend/vulkan/drawer.cpp index 9079b0c5d..0fcafe7a9 100644 --- a/core/rend/vulkan/drawer.cpp +++ b/core/rend/vulkan/drawer.cpp @@ -20,11 +20,8 @@ */ #include #include "drawer.h" -#include "../gui.h" #include "hw/pvr/pvr_mem.h" -extern float fb_scale_x, fb_scale_y; - void Drawer::SortTriangles() { sortedPolys.resize(pvrrc.render_passes.used()); @@ -84,33 +81,15 @@ TileClipping Drawer::SetTileClip(u32 val, vk::Rect2D& clipRect) { if (!pvrrc.isRTT) { - csx /= scale_x; - csy /= scale_y; - cex /= scale_x; - cey /= scale_y; - float dc2s_scale_h; - float ds2s_offs_x; - float screen_stretching = settings.rend.ScreenStretching / 100.f; + glm::vec4 clip_start(csx, csy, 0, 1); + glm::vec4 clip_end(cex, cey, 0, 1); + clip_start = matrices.GetViewportMatrix() * clip_start; + clip_end = matrices.GetViewportMatrix() * clip_end; - if (settings.rend.Rotate90) - { - float t = cex; - cex = cey; - cey = 640 - csx; - csx = csy; - csy = 640 - t; - dc2s_scale_h = screen_height / 640.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0 * screen_stretching) / 2; - } - else - { - dc2s_scale_h = screen_height / 480.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2; - } - csx = csx * dc2s_scale_h * screen_stretching + ds2s_offs_x; - cex = cex * dc2s_scale_h * screen_stretching + ds2s_offs_x; - csy = csy * dc2s_scale_h; - cey = cey * dc2s_scale_h; + csx = clip_start[0]; + csy = clip_start[1]; + cey = clip_end[1]; + cex = clip_end[0]; } else if (!settings.rend.RenderToTextureBuffer) { @@ -290,79 +269,8 @@ bool Drawer::Draw(const Texture *fogTexture) { extern bool fog_needs_update; - bool is_rtt = pvrrc.isRTT; - float dc_width = 640; - float dc_height = 480; - - if (is_rtt) - { - dc_width = pvrrc.fb_X_CLIP.max - pvrrc.fb_X_CLIP.min + 1; - dc_height = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1; - } - - scale_x = 1; - scissor_scale_x = 1; - scale_y = 1; - - if (!is_rtt && !pvrrc.isRenderFramebuffer) - { - scale_x = fb_scale_x; - scissor_scale_x = fb_scale_x; - scale_y = fb_scale_y; - if (SCALER_CTL.interlace == 0 && SCALER_CTL.vscalefactor > 0x400) - scale_y *= roundf((float)SCALER_CTL.vscalefactor / 0x400); - - //Pixel doubling is on VO, so it does not affect any pixel operations - if (VO_CONTROL.pixel_double) - { - scissor_scale_x *= 0.5f; - scale_x *= 0.5f; - } - - if (SCALER_CTL.hscale) - scale_x *= 2; - } - - dc_width *= scale_x; - dc_height *= scale_y; - - float screen_stretching = settings.rend.ScreenStretching / 100.f; - float screen_scaling = settings.rend.ScreenScaling / 100.f; - - float dc2s_scale_h; - float ds2s_offs_x; - VertexShaderUniforms vtxUniforms; - if (is_rtt) - { - vtxUniforms.scale[0] = 2.0f / dc_width; - vtxUniforms.scale[1] = 2.0f / dc_height; - vtxUniforms.scale[2] = 1; - vtxUniforms.scale[3] = 1; - } - else - { - if (settings.rend.Rotate90) - { - dc2s_scale_h = screen_height / 640.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2; - vtxUniforms.scale[0] = -2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; - vtxUniforms.scale[1] = 2.0f / dc_width; - vtxUniforms.scale[2] = 1 - 2 * ds2s_offs_x / screen_width; - vtxUniforms.scale[3] = 1; - } - else - { - dc2s_scale_h = screen_height / 480.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2; - vtxUniforms.scale[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; - vtxUniforms.scale[1] = 2.0f / dc_height; - vtxUniforms.scale[2] = 1 - 2 * ds2s_offs_x / screen_width; - vtxUniforms.scale[3] = 1; - } - //-1 -> too much to left - } - vtxUniforms.extra_depth_scale = settings.rend.ExtraDepthScale; + vtxUniforms.normal_matrix = matrices.GetNormalMatrix(); FragmentShaderUniforms fragUniforms; fragUniforms.extra_depth_scale = settings.rend.ExtraDepthScale; @@ -445,16 +353,16 @@ bool Drawer::Draw(const Texture *fogTexture) DrawList(cmdBuffer, ListType_Translucent, false, pvrrc.global_param_tr, previous_pass.tr_count, current_pass.tr_count - previous_pass.tr_count); previous_pass = current_pass; } - if (!is_rtt) - gui_display_osd(); - return !is_rtt; + return !pvrrc.isRTT; } vk::CommandBuffer TextureDrawer::BeginRenderPass() { DEBUG_LOG(RENDERER, "RenderToTexture packmode=%d stride=%d - %d,%d -> %d,%d", FB_W_CTRL.fb_packmode, FB_W_LINESTRIDE.stride * 8, FB_X_CLIP.min, FB_Y_CLIP.min, FB_X_CLIP.max, FB_Y_CLIP.max); + matrices.CalcMatrices(&pvrrc); + textureAddr = FB_W_SOF1 & VRAM_MASK; u32 origWidth = pvrrc.fb_X_CLIP.max - pvrrc.fb_X_CLIP.min + 1; u32 origHeight = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1; @@ -631,12 +539,12 @@ vk::CommandBuffer ScreenDrawer::BeginRenderPass() GetContext()->NewFrame(); GetContext()->BeginRenderPass(); vk::CommandBuffer commandBuffer = GetContext()->GetCurrentCommandBuffer(); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, (float) ((screen_width)), (float) ((screen_height)), 1.0f, 0.0f)); - bool wide_screen_on = settings.rend.WideScreen && !pvrrc.isRenderFramebuffer - && pvrrc.fb_X_CLIP.min == 0 - && lroundf((pvrrc.fb_X_CLIP.max + 1) / scissor_scale_x) == 640L - && pvrrc.fb_Y_CLIP.min == 0 - && lroundf((pvrrc.fb_Y_CLIP.max + 1) / scale_y) == 480L; + commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, (float)screen_width, (float)screen_height, 1.0f, 0.0f)); + + matrices.CalcMatrices(&pvrrc); + + bool wide_screen_on = settings.rend.WideScreen && !pvrrc.isRenderFramebuffer && !matrices.IsClipped(); + if (!wide_screen_on) { float width; @@ -653,45 +561,27 @@ vk::CommandBuffer ScreenDrawer::BeginRenderPass() } else { - width = (pvrrc.fb_X_CLIP.max - pvrrc.fb_X_CLIP.min + 1) / scissor_scale_x; - height = (pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1) / scale_y; - min_x = pvrrc.fb_X_CLIP.min / scissor_scale_x; - min_y = pvrrc.fb_Y_CLIP.min / scale_y; + glm::vec4 clip_min(pvrrc.fb_X_CLIP.min, pvrrc.fb_Y_CLIP.min, 0, 1); + glm::vec4 clip_dim(pvrrc.fb_X_CLIP.max - pvrrc.fb_X_CLIP.min + 1, + pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1, 0, 0); + clip_min = matrices.GetScissorMatrix() * clip_min; + clip_dim = matrices.GetScissorMatrix() * clip_dim; - if (SCALER_CTL.interlace && SCALER_CTL.vscalefactor > 0x400) + min_x = clip_min[0]; + min_y = clip_min[1]; + width = clip_dim[0]; + height = clip_dim[1]; + if (width < 0) { - // Clipping is done after scaling/filtering so account for that if enabled - height *= (float) SCALER_CTL.vscalefactor / 0x400; - min_y *= (float) SCALER_CTL.vscalefactor / 0x400; + min_x += width; + width = -width; + } + if (height < 0) + { + min_y += height; + height = -height; } } - if (settings.rend.Rotate90) - { - float t = width; - width = height; - height = t; - t = min_x; - min_x = min_y; - min_y = 640 - t - height; - } - const float screen_stretching = settings.rend.ScreenStretching / 100.f; - const float screen_scaling = settings.rend.ScreenScaling / 100.f; - float dc2s_scale_h, ds2s_offs_x; - if (settings.rend.Rotate90) - { - dc2s_scale_h = screen_height / 640.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2; - } - else - { - dc2s_scale_h = screen_height / 480.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2; - } - // Add x offset for aspect ratio > 4/3 - min_x = (min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x) * screen_scaling; - min_y = min_y * dc2s_scale_h * screen_scaling; - width *= dc2s_scale_h * screen_stretching * screen_scaling; - height *= dc2s_scale_h * screen_scaling; baseScissor = vk::Rect2D( vk::Offset2D((u32)std::max(lroundf(min_x), 0L), (u32)std::max(lroundf(min_y), 0L)), diff --git a/core/rend/vulkan/drawer.h b/core/rend/vulkan/drawer.h index 980b434c5..4aef89fce 100644 --- a/core/rend/vulkan/drawer.h +++ b/core/rend/vulkan/drawer.h @@ -21,6 +21,7 @@ #pragma once #include #include "rend/sorter.h" +#include "rend/transform_matrix.h" #include "vulkan.h" #include "buffer.h" #include "commandpool.h" @@ -68,10 +69,7 @@ protected: PipelineManager *pipelineManager = nullptr; vk::Rect2D baseScissor; - // temp stuff - float scale_x = 1.f; - float scissor_scale_x = 1.f; - float scale_y = 1.f; + TransformMatrix matrices; private: TileClipping SetTileClip(u32 val, vk::Rect2D& clipRect); diff --git a/core/rend/vulkan/pipeline.cpp b/core/rend/vulkan/pipeline.cpp index ac9f30814..acd6af538 100644 --- a/core/rend/vulkan/pipeline.cpp +++ b/core/rend/vulkan/pipeline.cpp @@ -319,7 +319,7 @@ void PipelineManager::CreatePipeline(u32 listType, bool sortTriangles, const Pol vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates); - vk::ShaderModule vertex_module = shaderManager->GetVertexShader(VertexShaderParams{ pp.pcw.Gouraud == 1, false }); // TODO rotate90 + vk::ShaderModule vertex_module = shaderManager->GetVertexShader(VertexShaderParams{ pp.pcw.Gouraud == 1 }); FragmentShaderParams params = {}; params.alphaTest = listType == ListType_Punch_Through; params.bumpmap = pp.tcw.PixelFmt == PixelBumpMap; diff --git a/core/rend/vulkan/pipeline.h b/core/rend/vulkan/pipeline.h index 56a5c7ab5..d5ef5ec79 100644 --- a/core/rend/vulkan/pipeline.h +++ b/core/rend/vulkan/pipeline.h @@ -195,7 +195,6 @@ private: | (pp->tsp.DstInstr << 17); hash |= (pp->isp.ZWriteDis << 20) | (pp->isp.CullMode << 21) | (pp->isp.DepthMode << 23); hash |= (u32)sortTriangles << 26; -// TODO hash |= (u32)rotate90 << 27; return hash; } diff --git a/core/rend/vulkan/shaders.cpp b/core/rend/vulkan/shaders.cpp index a2d447c90..3ed248201 100644 --- a/core/rend/vulkan/shaders.cpp +++ b/core/rend/vulkan/shaders.cpp @@ -28,7 +28,6 @@ static const char VertexShaderSource[] = R"( #extension GL_ARB_shading_language_420pack : enable #define pp_Gouraud %d -#define ROTATE_90 %d #if pp_Gouraud == 0 #define INTERPOLATION flat @@ -38,8 +37,7 @@ static const char VertexShaderSource[] = R"( layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms { - vec4 scale; - float extra_depth_scale; + mat4 normal_matrix; } uniformBuffer; layout (location = 0) in vec4 in_pos; @@ -62,13 +60,9 @@ void main() gl_Position = vec4(0.0, 0.0, 1.0, 1.0 / vpos.z); return; } - - vpos.w = uniformBuffer.extra_depth_scale / vpos.z; + vpos = uniformBuffer.normal_matrix * vpos; + vpos.w = 1.0 / vpos.z; vpos.z = vpos.w; -#if ROTATE_90 == 1 - vpos.xy = vec2(vpos.y, -vpos.x); -#endif - vpos.xy = vpos.xy * uniformBuffer.scale.xy - uniformBuffer.scale.zw; vpos.xy *= vpos.w; gl_Position = vpos; } @@ -252,8 +246,7 @@ static const char ModVolVertexShaderSource[] = R"( layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms { - vec4 scale; - float extra_depth_scale; + mat4 normal_matrix; } uniformBuffer; layout (location = 0) in vec4 in_pos; @@ -267,9 +260,9 @@ void main() return; } - vpos.w = uniformBuffer.extra_depth_scale / vpos.z; + vpos = uniformBuffer.normal_matrix * vpos; + vpos.w = 1.0 / vpos.z; vpos.z = vpos.w; - vpos.xy = vpos.xy * uniformBuffer.scale.xy - uniformBuffer.scale.zw; vpos.xy *= vpos.w; gl_Position = vpos; } @@ -542,7 +535,7 @@ vk::UniqueShaderModule ShaderManager::compileShader(const VertexShaderParams& pa { char buf[sizeof(VertexShaderSource) * 2]; - sprintf(buf, VertexShaderSource, (int)params.gouraud, (int)params.rotate90); + sprintf(buf, VertexShaderSource, (int)params.gouraud); return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eVertex, buf); } diff --git a/core/rend/vulkan/shaders.h b/core/rend/vulkan/shaders.h index 6e5deea10..50facbc68 100644 --- a/core/rend/vulkan/shaders.h +++ b/core/rend/vulkan/shaders.h @@ -19,15 +19,15 @@ along with Flycast. If not, see . */ #pragma once +#include #include "vulkan.h" #include "SPIRV/GlslangToSpv.h" struct VertexShaderParams { bool gouraud; - bool rotate90; - u32 hash() { return (((u32)gouraud) << 1) | rotate90; } + u32 hash() { return (u32)gouraud; } }; // alpha test, clip test, use alpha, texture, ignore alpha, shader instr, offset, fog, gouraud, bump, clamp, trilinear @@ -58,8 +58,7 @@ struct FragmentShaderParams // std140 alignment required struct VertexShaderUniforms { - float scale[4]; - float extra_depth_scale; + glm::mat4 normal_matrix; }; // std140 alignment required diff --git a/core/rend/vulkan/vulkan_renderer.cpp b/core/rend/vulkan/vulkan_renderer.cpp index b89135251..2f42d9726 100644 --- a/core/rend/vulkan/vulkan_renderer.cpp +++ b/core/rend/vulkan/vulkan_renderer.cpp @@ -142,17 +142,23 @@ public: curTexture->SetCommandBuffer(nullptr); texCommandPool.EndFrame(); - float screen_stretching = settings.rend.ScreenStretching / 100.f; - float dc2s_scale_h, ds2s_offs_x; - if (settings.rend.Rotate90) + TransformMatrix matrices(pvrrc); + glm::vec4 viewport_min = matrices.GetViewportMatrix() * glm::vec4(0, 0, 0, 1.f); + glm::vec4 viewport_dim = matrices.GetViewportMatrix() * glm::vec4(640.f, 480.f, 0, 0); + + float min_x = viewport_min[0]; + float min_y = viewport_min[1]; + width = viewport_dim[0]; + height = viewport_dim[1]; + if (width < 0) { - dc2s_scale_h = screen_height / 640.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2; + min_x += width; + width = -width; } - else + if (height < 0) { - dc2s_scale_h = screen_height / 480.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2; + min_y += height; + height = -height; } vk::CommandBuffer cmdBuffer = screenDrawer.BeginRenderPass(); @@ -165,9 +171,10 @@ public: float blendConstants[4] = { 1.0, 1.0, 1.0, 1.0 }; cmdBuffer.setBlendConstants(blendConstants); - // FIXME scaling, stretching... - vk::Viewport viewport(ds2s_offs_x, 0.f, screen_width - ds2s_offs_x * 2, (float)screen_height); + + vk::Viewport viewport(min_x, min_y, width, height); cmdBuffer.setViewport(0, 1, &viewport); + cmdBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(min_x, min_y), vk::Extent2D(width, height))); cmdBuffer.draw(3, 1, 0, 0); gui_display_osd(); @@ -211,6 +218,7 @@ public: void DrawOSD(bool clear_screen) override { + gui_display_osd(); if (!vjoyTexture) return; if (clear_screen) @@ -218,22 +226,13 @@ public: GetContext()->NewFrame(); GetContext()->BeginRenderPass(); } - const float screen_stretching = settings.rend.ScreenStretching / 100.f; - float dc2s_scale_h, ds2s_offs_x; - if (settings.rend.Rotate90) - { - dc2s_scale_h = screen_height / 640.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2; - } - else - { - dc2s_scale_h = screen_height / 480.0f; - ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2; - } + const float dc2s_scale_h = screen_height / 480.0f; + const float sidebarWidth = (screen_width - dc2s_scale_h * 640.0f) / 2; + std::vector osdVertices = GetOSDVertices(); - const float x1 = 2.0f / (screen_width / dc2s_scale_h /* FIXME * scale_x */) * screen_stretching; - const float y1 = 2.0f / 480 /* FIXME dc_height */; - const float x2 = 1 - 2 * ds2s_offs_x / screen_width; + const float x1 = 2.0f / (screen_width / dc2s_scale_h); + const float y1 = 2.0f / 480; + const float x2 = 1 - 2 * sidebarWidth / screen_width; const float y2 = 1; for (OSDVertex& vtx : osdVertices) {