diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 48dfa97db1..fd0098bf84 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -128,11 +128,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float)); FlipProjMatrix(flippedMatrix); - ConvertProjMatrixToZeroToOneDepth(flippedMatrix); - if (!useBufferedRendering && g_display.rotation != DisplayRotation::ROTATE_0) { - flippedMatrix = flippedMatrix * g_display.rot_matrix; - } CopyMatrix4x4(ub->proj, flippedMatrix.getReadPtr()); ub->rotation = useBufferedRendering ? 0 : (float)g_display.rotation; @@ -141,9 +137,6 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView if (dirtyUniforms & DIRTY_PROJTHROUGHMATRIX) { Matrix4x4 proj_through; proj_through.setOrthoVulkan(0.0f, gstate_c.curRTWidth, 0, gstate_c.curRTHeight, 0, 1); - if (!useBufferedRendering && g_display.rotation != DisplayRotation::ROTATE_0) { - proj_through = proj_through * g_display.rot_matrix; - } // Negative RT offsets come from split framebuffers (Killzone) if (gstate_c.curRTOffsetX < 0 || gstate_c.curRTOffsetY < 0) { @@ -152,6 +145,8 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView } CopyMatrix4x4(ub->proj_through, proj_through.getReadPtr()); + + ub->rotation = useBufferedRendering ? 0 : (float)g_display.rotation; } // Transform diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 77c8ebc8de..2f8c1513cd 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -17,7 +17,7 @@ enum : uint64_t { DIRTY_MATDIFFUSE | DIRTY_MATSPECULAR | DIRTY_MATEMISSIVE | DIRTY_AMBIENT, }; -// Currently 496 bytes. +// Currently 480 bytes. // Every line here is a 4-float. struct alignas(16) UB_VS_FS_Base { float proj[16]; @@ -43,6 +43,7 @@ struct alignas(16) UB_VS_FS_Base { // VR stuff is to go here, later. For normal drawing, we can then get away // with just uploading the first 448 bytes of the struct (up to and including fogCoef). }; +static_assert(sizeof(UB_VS_FS_Base) == 480, "UB_VS_FS_Base should be 496 bytes"); static const char * const ub_baseStr = R"( mat4 u_proj; @@ -84,6 +85,7 @@ struct alignas(16) UB_VS_Lights { float lightDiffuse[4][4]; float lightSpecular[4][4]; }; +static_assert(sizeof(UB_VS_Lights) == 512); // it's ok to optimize this, it's just an assumption check. static const char * const ub_vs_lightsStr = R"( vec4 u_ambient; @@ -105,6 +107,7 @@ R"( vec4 u_ambient; struct alignas(16) UB_VS_Bones { float bones[8][12]; }; +static_assert(sizeof(UB_VS_Bones) == 384); // No way to optimize this further. static const char * const ub_vs_bonesStr = R"( mat3x4 u_bone0; mat3x4 u_bone1; mat3x4 u_bone2; mat3x4 u_bone3; mat3x4 u_bone4; mat3x4 u_bone5; mat3x4 u_bone6; mat3x4 u_bone7; mat3x4 u_bone8; diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index f3591c626f..db32cc44de 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -363,6 +363,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } WRITE(p, "};\n"); } else { + // Non-Vulkan GLSL. if (enableBones) { const char * const * boneWeightDecl = boneWeightAttrDecl; if (!strcmp(compat.attribute, "in")) { @@ -479,8 +480,6 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, "uniform lowp vec3 u_matemissive;\n"); *uniformMask |= DIRTY_MATSPECULAR | DIRTY_MATEMISSIVE; } - } else { - WRITE(p, "uniform lowp float u_rotation;\n"); } if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { @@ -749,24 +748,11 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag // The proj_through matrix already has the rotation, if needed. WRITE(p, " vec4 outPos = mul(u_proj_through, vec4(position.xyz, 1.0));\n"); } else { - if (compat.shaderLanguage == GLSL_VULKAN) { - // Apply rotation from the uniform. - WRITE(p, " mat2 displayRotation = mat2(\n"); - WRITE(p, " u_rotation == 0.0 ? 1.0 : (u_rotation == 2.0 ? -1.0 : 0.0), u_rotation == 1.0 ? 1.0 : (u_rotation == 3.0 ? -1.0 : 0.0),\n"); - WRITE(p, " u_rotation == 3.0 ? 1.0 : (u_rotation == 1.0 ? -1.0 : 0.0), u_rotation == 0.0 ? 1.0 : (u_rotation == 2.0 ? -1.0 : 0.0)\n"); - WRITE(p, " );\n"); - - WRITE(p, " vec4 pos = position;\n"); - WRITE(p, " pos.xy = mul(displayRotation, pos.xy);\n"); - } else { - WRITE(p, " vec4 pos = position;\n"); - } - // The viewport is used in this case, so need to compensate for that. if (gstate_c.Use(GPU_ROUND_DEPTH_TO_16BIT)) { - WRITE(p, " vec4 outPos = depthRoundZVP(pos);\n"); + WRITE(p, " vec4 outPos = depthRoundZVP(position);\n"); } else { - WRITE(p, " vec4 outPos = pos;\n"); + WRITE(p, " vec4 outPos = position;\n"); } } } else { @@ -1276,6 +1262,16 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } } + if (compat.shaderLanguage == GLSL_VULKAN) { + // Apply rotation from the uniform. + WRITE(p, " mat2 displayRotation = mat2(\n"); + WRITE(p, " u_rotation == 0.0 ? 1.0 : (u_rotation == 2.0 ? -1.0 : 0.0), u_rotation == 1.0 ? 1.0 : (u_rotation == 3.0 ? -1.0 : 0.0),\n"); + WRITE(p, " u_rotation == 3.0 ? 1.0 : (u_rotation == 1.0 ? -1.0 : 0.0), u_rotation == 0.0 ? 1.0 : (u_rotation == 2.0 ? -1.0 : 0.0)\n"); + WRITE(p, " );\n"); + + WRITE(p, " outPos.xy = mul(displayRotation, outPos.xy);\n"); + } + bool flipY = strlen(compat.viewportYSign) > 0; if (gstate_c.Use(GPU_USE_NONBUFFERED_FLIP)) { flipY = !flipY; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index ec610ec6d4..6f8678675c 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -129,7 +129,6 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, queries.push_back({ &u_depthRange, "u_depthRange" }); queries.push_back({ &u_cullRangeMin, "u_cullRangeMin" }); queries.push_back({ &u_cullRangeMax, "u_cullRangeMax" }); - queries.push_back({ &u_rotation, "u_rotation" }); // These two are only used for VR, but let's always query them for simplicity. queries.push_back({ &u_scaleX, "u_scaleX" }); @@ -442,7 +441,6 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin ConvertProjMatrixToGL(flippedMatrix); render_->SetUniformM4x4(&u_proj, flippedMatrix.m); - render_->SetUniformF1(&u_rotation, useBufferedRendering ? 0 : (float)g_display.rotation); } if (dirty & DIRTY_PROJTHROUGHMATRIX) { Matrix4x4 proj_through; diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 5ea181bd29..35fc2054e8 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -68,7 +68,6 @@ public: int u_depthRange; // x,y = viewport xscale/xcenter. z,w=clipping minz/maxz (?) int u_cullRangeMin; int u_cullRangeMax; - int u_rotation; int u_mipBias; int u_scaleX; int u_scaleY; diff --git a/UI/SystemInfoScreen.cpp b/UI/SystemInfoScreen.cpp index 5822469c0f..b9f8f22e57 100644 --- a/UI/SystemInfoScreen.cpp +++ b/UI/SystemInfoScreen.cpp @@ -504,10 +504,15 @@ void SystemInfoScreen::CreateVulkanExtsTab(UI::LinearLayout *gpuExtensions) { auto si = GetI18NCategory(I18NCat::SYSINFO); auto di = GetI18NCategory(I18NCat::DIALOG); + auto gr = GetI18NCategory(I18NCat::GRAPHICS); Draw::DrawContext *draw = screenManager()->getDrawContext(); CollapsibleSection *vulkanFeatures = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Features"))); + + // TODO: This one belongs under its own header. And this is Vulkan "pre-rotation" really. + vulkanFeatures->Add(new InfoItem(gr->T("Display rotation"), StringFromFormat("%d°", (int)g_display.rotation * 90))); + std::vector features = draw->GetFeatureList(); for (const auto &feature : features) { vulkanFeatures->Add(new TextView(feature, FLAG_DYNAMIC_ASCII, true, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);