refactor xform matrix out of gles. use xform matrix in vulkan

This commit is contained in:
Flyinghead 2019-10-23 18:13:28 +02:00
parent 2f363a7355
commit 07958f08ae
15 changed files with 349 additions and 440 deletions

View File

@ -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)

View File

@ -40,7 +40,6 @@ struct gl4_ctx
{
GLuint program;
GLuint extra_depth_scale;
GLuint normal_matrix;
} modvol_shader;

View File

@ -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<true> 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
{

View File

@ -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 <glm/gtx/transform.hpp>
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<true> 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);

View File

@ -53,7 +53,6 @@ struct gl_ctx
GLuint program;
GLuint depth_scale;
GLuint extra_depth_scale;
GLuint sp_ShaderColor;
GLuint normal_matrix;

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include "osd.h"
#include "types.h"
#include "input/gamepad.h"

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <vector>
#include "types.h"

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include "hw/pvr/ta_ctx.h"
extern float fb_scale_x, fb_scale_y;
extern int screen_width, screen_height;
template<bool invertY>
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;
};

View File

@ -20,11 +20,8 @@
*/
#include <math.h>
#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)),

View File

@ -21,6 +21,7 @@
#pragma once
#include <memory>
#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<false> matrices;
private:
TileClipping SetTileClip(u32 val, vk::Rect2D& clipRect);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -19,15 +19,15 @@
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glm/glm.hpp>
#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

View File

@ -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<false> 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<OSDVertex> 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)
{