gl/gl4: simplify clipping. share code with vulkan

This commit is contained in:
Flyinghead 2020-05-11 15:50:16 +02:00
parent 9df8e83ef0
commit fec79624df
15 changed files with 313 additions and 226 deletions

View File

@ -431,7 +431,7 @@ void DrawTranslucentModVols(int first, int count)
u32 mv_mode = param.isp.DepthMode;
verify(param.first >= 0 && param.first + param.count <= pvrrc.modtrig.used());
verify(param.first >= 0 && param.first + param.count <= (u32)pvrrc.modtrig.used());
if (mod_base == -1)
mod_base = param.first;

View File

@ -10,22 +10,30 @@ struct gl4PipelineShader
{
GLuint program;
GLuint pp_ClipTest,cp_AlphaTestValue;
GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY;
GLuint shade_scale_factor;
GLuint pp_Number;
GLuint blend_mode;
GLuint use_alpha;
GLuint ignore_tex_alpha;
GLuint shading_instr;
GLuint fog_control;
GLuint trilinear_alpha;
GLuint fog_clamp_min, fog_clamp_max;
GLuint normal_matrix;
GLint pp_ClipTest;
GLint cp_AlphaTestValue;
GLint sp_FOG_COL_RAM;
GLint sp_FOG_COL_VERT;
GLint sp_FOG_DENSITY;
GLint shade_scale_factor;
GLint pp_Number;
GLint blend_mode;
GLint use_alpha;
GLint ignore_tex_alpha;
GLint shading_instr;
GLint fog_control;
GLint trilinear_alpha;
GLint fog_clamp_min, fog_clamp_max;
GLint normal_matrix;
u32 cp_AlphaTest;
s32 pp_ClipTestMode;
u32 pp_Texture, pp_UseAlpha, pp_IgnoreTexA, pp_ShadInstr, pp_Offset, pp_FogCtrl;
bool cp_AlphaTest;
bool pp_InsideClipping;
bool pp_Texture;
bool pp_UseAlpha;
bool pp_IgnoreTexA;
u32 pp_ShadInstr;
bool pp_Offset;
u32 pp_FogCtrl;
Pass pass;
bool pp_TwoVolumes;
bool pp_Gouraud;
@ -240,8 +248,15 @@ extern struct gl4ShaderUniforms_t
float fog_clamp_min[4];
float fog_clamp_max[4];
glm::mat4 normal_mat;
struct {
bool enabled;
int x;
int y;
int width;
int height;
} base_clipping;
void setUniformArray(GLuint location, int v0, int v1)
void setUniformArray(GLint location, int v0, int v1)
{
int array[] = { v0, v1 };
glUniform1iv(location, 2, array);

View File

@ -1,5 +1,6 @@
#include "gl4.h"
#include "rend/gles/glcache.h"
#include "rend/tileclip.h"
/*
@ -21,22 +22,22 @@ GLuint texSamplers[2];
GLuint depth_fbo;
GLuint depthSaveTexId;
static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, s32 pp_ClipTestMode,
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
static gl4PipelineShader *gl4GetProgram(bool cp_AlphaTest, bool pp_InsideClipping,
bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr, bool pp_Offset,
u32 pp_FogCtrl, bool pp_TwoVolumes, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, Pass pass)
{
u32 rv=0;
rv |= (pp_ClipTestMode + 1);
rv<<=1; rv|=cp_AlphaTest;
rv<<=1; rv|=pp_Texture;
rv<<=1; rv|=pp_UseAlpha;
rv<<=1; rv|=pp_IgnoreTexA;
rv<<=2; rv|=pp_ShadInstr;
rv<<=1; rv|=pp_Offset;
rv<<=2; rv|=pp_FogCtrl;
rv <<= 1; rv |= (int)pp_TwoVolumes;
rv <<= 1; rv |= (int)pp_Gouraud;
rv |= pp_InsideClipping;
rv <<= 1; rv |= cp_AlphaTest;
rv <<= 1; rv |= pp_Texture;
rv <<= 1; rv |= pp_UseAlpha;
rv <<= 1; rv |= pp_IgnoreTexA;
rv <<= 2; rv |= pp_ShadInstr;
rv <<= 1; rv |= pp_Offset;
rv <<= 2; rv |= pp_FogCtrl;
rv <<= 1; rv |= pp_TwoVolumes;
rv <<= 1; rv |= pp_Gouraud;
rv <<= 1; rv |= pp_BumpMap;
rv <<= 1; rv |= fog_clamping;
rv <<= 2; rv |= (int)pass;
@ -45,7 +46,7 @@ static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, s32 pp_ClipTestMode,
if (shader->program == 0)
{
shader->cp_AlphaTest = cp_AlphaTest;
shader->pp_ClipTestMode = pp_ClipTestMode;
shader->pp_InsideClipping = pp_InsideClipping;
shader->pp_Texture = pp_Texture;
shader->pp_UseAlpha = pp_UseAlpha;
shader->pp_IgnoreTexA = pp_IgnoreTexA;
@ -71,6 +72,17 @@ static void SetTextureRepeatMode(int index, GLuint dir, u32 clamp, u32 mirror)
glSamplerParameteri(texSamplers[index], dir, mirror ? GL_MIRRORED_REPEAT : GL_REPEAT);
}
static void SetBaseClipping()
{
if (gl4ShaderUniforms.base_clipping.enabled)
{
glcache.Enable(GL_SCISSOR_TEST);
glcache.Scissor(gl4ShaderUniforms.base_clipping.x, gl4ShaderUniforms.base_clipping.y, gl4ShaderUniforms.base_clipping.width, gl4ShaderUniforms.base_clipping.height);
}
else
glcache.Disable(GL_SCISSOR_TEST);
}
template <u32 Type, bool SortingEnabled, Pass pass>
static void SetGPState(const PolyParam* gp)
{
@ -85,12 +97,13 @@ static void SetGPState(const PolyParam* gp)
else
gl4ShaderUniforms.trilinear_alpha = 1.0;
s32 clipping = SetTileClip(gp->tileclip, -1);
int clip_rect[4] = {};
TileClipping clipmode = GetTileClip(gp->tileclip, ViewportMatrix, clip_rect);
if (pass == Pass::Depth)
{
CurrentShader = gl4GetProgram(Type == ListType_Punch_Through ? 1 : 0,
clipping,
clipmode == TileClipping::Inside,
Type == ListType_Punch_Through ? gp->pcw.Texture : 0,
1,
gp->tsp.IgnoreTexA,
@ -106,13 +119,13 @@ static void SetGPState(const PolyParam* gp)
else
{
// Two volumes mode only supported for OP and PT
bool two_volumes_mode = (gp->tsp1.full != -1) && Type != ListType_Translucent;
bool two_volumes_mode = (gp->tsp1.full != (u32)-1) && Type != ListType_Translucent;
bool color_clamp = gp->tsp.ColorClamp && (pvrrc.fog_clamp_min != 0 || pvrrc.fog_clamp_max != 0xffffffff);
int fog_ctrl = settings.rend.Fog ? gp->tsp.FogCtrl : 2;
CurrentShader = gl4GetProgram(Type == ListType_Punch_Through ? 1 : 0,
clipping,
clipmode == TileClipping::Inside,
gp->pcw.Texture,
gp->tsp.UseAlpha,
gp->tsp.IgnoreTexA,
@ -141,7 +154,15 @@ static void SetGPState(const PolyParam* gp)
else
glcache.Disable(GL_BLEND);
SetTileClip(gp->tileclip, CurrentShader->pp_ClipTest);
if (clipmode == TileClipping::Inside)
glUniform4f(CurrentShader->pp_ClipTest, clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3]);
if (clipmode == TileClipping::Outside)
{
glcache.Enable(GL_SCISSOR_TEST);
glcache.Scissor(clip_rect[0], clip_rect[1], clip_rect[2], clip_rect[3]);
}
else
SetBaseClipping();
// This bit controls which pixels are affected by modvols
const u32 stencil = gp->pcw.Shadow != 0 ? 0x80 : 0x0;
@ -155,12 +176,11 @@ static void SetGPState(const PolyParam* gp)
glActiveTexture(GL_TEXTURE0 + i);
GLuint texid = (GLuint)(i == 0 ? gp->texid : gp->texid1);
glBindTexture(GL_TEXTURE_2D, texid == -1 ? 0 : texid);
glBindTexture(GL_TEXTURE_2D, texid == (GLuint)-1 ? 0 : texid);
if (texid != -1)
if (texid != (GLuint)-1)
{
TSP tsp = i == 0 ? gp->tsp : gp->tsp1;
TCW tcw = i == 0 ? gp->tcw : gp->tcw1;
glBindSampler(i, texSamplers[i]);
SetTextureRepeatMode(i, GL_TEXTURE_WRAP_S, tsp.ClampU, tsp.FlipU);
@ -298,6 +318,7 @@ static void DrawModVols(int first, int count)
glBindVertexArray(gl4.vbo.modvol_vao);
glcache.Disable(GL_BLEND);
SetBaseClipping();
glcache.UseProgram(gl4.modvol_shader.program);
@ -639,7 +660,7 @@ static void gl4_draw_quad_texture(GLuint texture, float w, float h)
gl4ShaderUniforms.trilinear_alpha = 1.0;
CurrentShader = gl4GetProgram(0,
0,
false,
1,
0,
1,

View File

@ -51,7 +51,7 @@ void main()
const char* gl4PixelPipelineShader = SHADER_HEADER
R"(
#define cp_AlphaTest %d
#define pp_ClipTestMode %d
#define pp_ClipInside %d
#define pp_UseAlpha %d
#define pp_Texture %d
#define pp_IgnoreTexA %d
@ -146,14 +146,8 @@ void main()
discard;
#endif
// Clip outside the box
#if pp_ClipTestMode==1
if (gl_FragCoord.x < pp_ClipTest.x || gl_FragCoord.x > pp_ClipTest.z
|| gl_FragCoord.y < pp_ClipTest.y || gl_FragCoord.y > pp_ClipTest.w)
discard;
#endif
// Clip inside the box
#if pp_ClipTestMode==-1
#if pp_ClipInside == 1
if (gl_FragCoord.x >= pp_ClipTest.x && gl_FragCoord.x <= pp_ClipTest.z
&& gl_FragCoord.y >= pp_ClipTest.y && gl_FragCoord.y <= pp_ClipTest.w)
discard;
@ -374,8 +368,9 @@ bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *pixel_source /*
char pshader[16384];
sprintf(pshader, pixel_source,
s->cp_AlphaTest,s->pp_ClipTestMode,s->pp_UseAlpha,
s->pp_Texture,s->pp_IgnoreTexA,s->pp_ShadInstr,s->pp_Offset,s->pp_FogCtrl, s->pp_TwoVolumes, s->pp_Gouraud, s->pp_BumpMap, s->fog_clamping, (int)s->pass);
s->cp_AlphaTest, s->pp_InsideClipping, s->pp_UseAlpha,
s->pp_Texture, s->pp_IgnoreTexA, s->pp_ShadInstr, s->pp_Offset, s->pp_FogCtrl,
s->pp_TwoVolumes, s->pp_Gouraud, s->pp_BumpMap, s->fog_clamping, (int)s->pass);
s->program = gl_CompileAndLink(vshader, pshader);
@ -705,7 +700,7 @@ static bool RenderFrame()
case 7: //7 invalid
die("7 is not valid");
break;
return false;
}
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);
@ -785,9 +780,9 @@ static bool RenderFrame()
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
glcache.Enable(GL_SCISSOR_TEST);
glScissor(0, 0, (GLsizei)lroundf(scaled_offs_x), rendering_height);
glcache.Scissor(0, 0, (GLsizei)lroundf(scaled_offs_x), rendering_height);
glClear(GL_COLOR_BUFFER_BIT);
glScissor((GLint)lroundf(screen_width * screen_scaling - scaled_offs_x), 0, (GLsizei)lroundf(scaled_offs_x) + 1, rendering_height);
glcache.Scissor((GLint)lroundf(screen_width * screen_scaling - scaled_offs_x), 0, (GLsizei)lroundf(scaled_offs_x) + 1, rendering_height);
glClear(GL_COLOR_BUFFER_BIT);
}
}
@ -805,9 +800,19 @@ static bool RenderFrame()
height *= settings.rend.RenderToTextureUpscale;
}
}
glScissor((GLint)lroundf(min_x), (GLint)lroundf(min_y), (GLsizei)lroundf(width), (GLsizei)lroundf(height));
gl4ShaderUniforms.base_clipping.enabled = true;
gl4ShaderUniforms.base_clipping.x = (int)lroundf(min_x);
gl4ShaderUniforms.base_clipping.y = (int)lroundf(min_y);
gl4ShaderUniforms.base_clipping.width = (int)lroundf(width);
gl4ShaderUniforms.base_clipping.height = (int)lroundf(height);
glcache.Scissor(gl4ShaderUniforms.base_clipping.x, gl4ShaderUniforms.base_clipping.y,
gl4ShaderUniforms.base_clipping.width, gl4ShaderUniforms.base_clipping.height);
glcache.Enable(GL_SCISSOR_TEST);
}
else
{
gl4ShaderUniforms.base_clipping.enabled = false;
}
gl4DrawStrips(output_fbo, rendering_width, rendering_height);
}
@ -822,8 +827,6 @@ static bool RenderFrame()
gl4DrawFramebuffer(640.f, 480.f);
}
eglCheck();
if (is_rtt)
ReadRTTBuffer();
else if (settings.rend.ScreenScaling != 100 || !theGLContext.IsSwapBufferPreserved())

View File

@ -9,10 +9,10 @@ GLuint gl4BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
gl.rtt.TexAddr=addy>>3;
// Find the smallest power of two texture that fits the viewport
int fbh2 = 8;
u32 fbh2 = 8;
while (fbh2 < fbh)
fbh2 *= 2;
int fbw2 = 8;
u32 fbw2 = 8;
while (fbw2 < fbw)
fbw2 *= 2;

View File

@ -110,6 +110,18 @@ public:
}
}
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
if (x != _scissor.x || y != _scissor.y || width != _scissor.width || height != _scissor.height || _disable_cache)
{
_scissor.x = x;
_scissor.y = y;
_scissor.width = width;
_scissor.height = height;
glScissor(x, y, width, height);
}
}
void TexParameteri(GLenum target, GLenum pname, GLint param)
{
if (target == GL_TEXTURE_2D && !_disable_cache)
@ -117,22 +129,22 @@ public:
TextureParameters &cur_params = _texture_params[_texture];
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
if (cur_params._min_filter == param)
if (cur_params._min_filter == (GLenum)param)
return;
cur_params._min_filter = param;
break;
case GL_TEXTURE_MAG_FILTER:
if (cur_params._mag_filter == param)
if (cur_params._mag_filter == (GLenum)param)
return;
cur_params._mag_filter = param;
break;
case GL_TEXTURE_WRAP_S:
if (cur_params._wrap_s == param)
if (cur_params._wrap_s == (GLenum)param)
return;
cur_params._wrap_s = param;
break;
case GL_TEXTURE_WRAP_T:
if (cur_params._wrap_t == param)
if (cur_params._wrap_t == (GLenum)param)
return;
cur_params._wrap_t = param;
break;
@ -190,6 +202,10 @@ public:
_stencil_dpfail = 0xFFFFFFFFu;
_stencil_dppass = 0xFFFFFFFFu;
_stencil_mask = 0;
_scissor.x = -1;
_scissor.y = -1;
_scissor.width = -1;
_scissor.height = -1;
if (_texture_cache_size > 0)
{
glDeleteTextures(_texture_cache_size, _texture_ids);
@ -274,6 +290,12 @@ private:
GLenum _stencil_dpfail;
GLenum _stencil_dppass;
GLuint _stencil_mask;
struct {
GLint x;
GLint y;
GLsizei width;
GLsizei height;
} _scissor;
GLuint _texture_ids[TEXTURE_ID_CACHE_SIZE];
GLuint _texture_cache_size;
std::map<GLuint, TextureParameters> _texture_params;

View File

@ -1,6 +1,7 @@
#include "glcache.h"
#include "gles.h"
#include "rend/sorter.h"
#include "rend/tileclip.h"
/*
@ -70,59 +71,6 @@ extern int screen_height;
PipelineShader* CurrentShader;
u32 gcflip;
s32 SetTileClip(u32 val, GLint uniform)
{
if (!settings.rend.Clipping)
return 0;
u32 clipmode = val >> 28;
s32 clip_mode;
if (clipmode < 2)
clip_mode = 0; //always passes
else if (clipmode & 1)
clip_mode = -1; //render stuff outside the region
else
clip_mode = 1; //render stuff inside the region
float csx = val & 63;
float cex = (val >> 6) & 63;
float csy = (val >> 12) & 31;
float cey = (val >> 17) & 31;
csx = csx * 32;
cex = cex * 32 + 32;
csy = csy * 32;
cey = cey * 32 + 32;
if (csx <= 0 && csy <= 0 && cex >= 640 && cey >= 480)
return 0;
if (uniform >= 0 && clip_mode)
{
if (!pvrrc.isRTT)
{
glm::vec4 clip_start(csx, csy, 0, 1);
glm::vec4 clip_end(cex, cey, 0, 1);
clip_start = ViewportMatrix * clip_start;
clip_end = ViewportMatrix * clip_end;
csx = clip_start[0];
csy = clip_start[1];
cey = clip_end[1];
cex = clip_end[0];
}
else if (!settings.rend.RenderToTextureBuffer)
{
csx *= settings.rend.RenderToTextureUpscale;
csy *= settings.rend.RenderToTextureUpscale;
cex *= settings.rend.RenderToTextureUpscale;
cey *= settings.rend.RenderToTextureUpscale;
}
glUniform4f(uniform, std::min(csx, cex), std::min(csy, cey), std::max(csx, cex), std::max(csy, cey));
}
return clip_mode;
}
void SetCull(u32 CulliMode)
{
if (CullMode[CulliMode]==GL_NONE)
@ -142,6 +90,17 @@ static void SetTextureRepeatMode(GLuint dir, u32 clamp, u32 mirror)
glcache.TexParameteri(GL_TEXTURE_2D, dir, mirror ? GL_MIRRORED_REPEAT : GL_REPEAT);
}
static void SetBaseClipping()
{
if (ShaderUniforms.base_clipping.enabled)
{
glcache.Enable(GL_SCISSOR_TEST);
glcache.Scissor(ShaderUniforms.base_clipping.x, ShaderUniforms.base_clipping.y, ShaderUniforms.base_clipping.width, ShaderUniforms.base_clipping.height);
}
else
glcache.Disable(GL_SCISSOR_TEST);
}
template <u32 Type, bool SortingEnabled>
__forceinline
void SetGPState(const PolyParam* gp,u32 cflip=0)
@ -159,8 +118,11 @@ __forceinline
bool color_clamp = gp->tsp.ColorClamp && (pvrrc.fog_clamp_min != 0 || pvrrc.fog_clamp_max != 0xffffffff);
int fog_ctrl = settings.rend.Fog ? gp->tsp.FogCtrl : 2;
int clip_rect[4] = {};
TileClipping clipmode = GetTileClip(gp->tileclip, ViewportMatrix, clip_rect);
CurrentShader = GetProgram(Type == ListType_Punch_Through ? 1 : 0,
SetTileClip(gp->tileclip, -1) + 1,
clipmode == TileClipping::Inside,
gp->pcw.Texture,
gp->tsp.UseAlpha,
gp->tsp.IgnoreTexA,
@ -176,7 +138,15 @@ __forceinline
if (CurrentShader->trilinear_alpha != -1)
glUniform1f(CurrentShader->trilinear_alpha, ShaderUniforms.trilinear_alpha);
SetTileClip(gp->tileclip, CurrentShader->pp_ClipTest);
if (clipmode == TileClipping::Inside)
glUniform4f(CurrentShader->pp_ClipTest, clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3]);
if (clipmode == TileClipping::Outside)
{
glcache.Enable(GL_SCISSOR_TEST);
glcache.Scissor(clip_rect[0], clip_rect[1], clip_rect[2], clip_rect[3]);
}
else
SetBaseClipping();
//This bit control which pixels are affected
//by modvols
@ -184,7 +154,7 @@ __forceinline
glcache.StencilFunc(GL_ALWAYS,stencil,stencil);
glcache.BindTexture(GL_TEXTURE_2D, gp->texid == -1 ? 0 : (GLuint)gp->texid);
glcache.BindTexture(GL_TEXTURE_2D, gp->texid == (u64)-1 ? 0 : (GLuint)gp->texid);
SetTextureRepeatMode(GL_TEXTURE_WRAP_S, gp->tsp.ClampU, gp->tsp.FlipU);
SetTextureRepeatMode(GL_TEXTURE_WRAP_T, gp->tsp.ClampV, gp->tsp.FlipV);
@ -533,6 +503,7 @@ void DrawModVols(int first, int count)
SetupModvolVBO();
glcache.Disable(GL_BLEND);
SetBaseClipping();
glcache.UseProgram(gl.modvol_shader.program);
glUniform1f(gl.modvol_shader.sp_ShaderColor, 1 - FPU_SHAD_SCALE.scale_factor / 256.f);
@ -672,7 +643,7 @@ static void DrawQuad(GLuint texId, float x, float y, float w, float h, float u0,
ShaderUniforms.trilinear_alpha = 1.0;
PipelineShader *shader = GetProgram(0, 1, 1, 0, 1, 0, 0, 2, false, false, false, false);
PipelineShader *shader = GetProgram(0, false, 1, 0, 1, 0, 0, 2, false, false, false, false);
glcache.UseProgram(shader->program);
glActiveTexture(GL_TEXTURE0);

View File

@ -95,7 +95,7 @@ R"(%s
#define TARGET_GL %s
#define cp_AlphaTest %d
#define pp_ClipTestMode %d
#define pp_ClipInside %d
#define pp_UseAlpha %d
#define pp_Texture %d
#define pp_IgnoreTexA %d
@ -185,14 +185,8 @@ highp vec4 fog_clamp(lowp vec4 col)
void main()
{
// Clip outside the box
#if pp_ClipTestMode==1
if (gl_FragCoord.x < pp_ClipTest.x || gl_FragCoord.x > pp_ClipTest.z
|| gl_FragCoord.y < pp_ClipTest.y || gl_FragCoord.y > pp_ClipTest.w)
discard;
#endif
// Clip inside the box
#if pp_ClipTestMode==-1
#if pp_ClipInside == 1
if (gl_FragCoord.x >= pp_ClipTest.x && gl_FragCoord.x <= pp_ClipTest.z
&& gl_FragCoord.y >= pp_ClipTest.y && gl_FragCoord.y <= pp_ClipTest.w)
discard;
@ -599,13 +593,13 @@ GLuint gl_CompileAndLink(const char* VertexShader, const char* FragmentShader)
return program;
}
PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear)
PipelineShader *GetProgram(bool cp_AlphaTest, bool pp_InsideClipping,
bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr, bool pp_Offset,
u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear)
{
u32 rv=0;
rv|=pp_ClipTestMode;
rv |= pp_InsideClipping;
rv<<=1; rv|=cp_AlphaTest;
rv<<=1; rv|=pp_Texture;
rv<<=1; rv|=pp_UseAlpha;
@ -622,7 +616,7 @@ PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
if (shader->program == 0)
{
shader->cp_AlphaTest = cp_AlphaTest;
shader->pp_ClipTestMode = pp_ClipTestMode-1;
shader->pp_InsideClipping = pp_InsideClipping;
shader->pp_Texture = pp_Texture;
shader->pp_UseAlpha = pp_UseAlpha;
shader->pp_IgnoreTexA = pp_IgnoreTexA;
@ -644,21 +638,21 @@ bool CompilePipelineShader( PipelineShader* s)
char vshader[8192];
int rc = sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud);
verify(rc + 1 <= sizeof(vshader));
verify(rc + 1 <= (int)sizeof(vshader));
char pshader[8192];
rc = sprintf(pshader,PixelPipelineShader, gl.glsl_version_header, gl.gl_version,
s->cp_AlphaTest,s->pp_ClipTestMode,s->pp_UseAlpha,
s->cp_AlphaTest,s->pp_InsideClipping,s->pp_UseAlpha,
s->pp_Texture,s->pp_IgnoreTexA,s->pp_ShadInstr,s->pp_Offset,s->pp_FogCtrl, s->pp_Gouraud, s->pp_BumpMap,
s->fog_clamping, s->trilinear);
verify(rc + 1 <= sizeof(pshader));
verify(rc + 1 <= (int)sizeof(pshader));
s->program=gl_CompileAndLink(vshader, pshader);
//setup texture 0 as the input for the shader
GLuint gu=glGetUniformLocation(s->program, "tex");
GLint gu = glGetUniformLocation(s->program, "tex");
if (s->pp_Texture==1)
glUniform1i(gu,0);
@ -1118,7 +1112,7 @@ bool RenderFrame()
case 7: //7 invalid
die("7 is not valid");
break;
return false;
}
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);
@ -1205,9 +1199,9 @@ bool RenderFrame()
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
glcache.Enable(GL_SCISSOR_TEST);
glScissor(0, 0, (GLsizei)lroundf(scaled_offs_x), (GLsizei)lroundf(screen_height * screen_scaling));
glcache.Scissor(0, 0, (GLsizei)lroundf(scaled_offs_x), (GLsizei)lroundf(screen_height * screen_scaling));
glClear(GL_COLOR_BUFFER_BIT);
glScissor(screen_width * screen_scaling - scaled_offs_x, 0, (GLsizei)lroundf(scaled_offs_x + 1.f), (GLsizei)lroundf(screen_height * screen_scaling));
glcache.Scissor(screen_width * screen_scaling - scaled_offs_x, 0, (GLsizei)lroundf(scaled_offs_x + 1.f), (GLsizei)lroundf(screen_height * screen_scaling));
glClear(GL_COLOR_BUFFER_BIT);
}
}
@ -1225,9 +1219,18 @@ bool RenderFrame()
height *= settings.rend.RenderToTextureUpscale;
}
}
glScissor((GLint)lroundf(min_x), (GLint)lroundf(min_y), (GLsizei)lroundf(width), (GLsizei)lroundf(height));
ShaderUniforms.base_clipping.enabled = true;
ShaderUniforms.base_clipping.x = (int)lroundf(min_x);
ShaderUniforms.base_clipping.y = (int)lroundf(min_y);
ShaderUniforms.base_clipping.width = (int)lroundf(width);
ShaderUniforms.base_clipping.height = (int)lroundf(height);
glcache.Scissor(ShaderUniforms.base_clipping.x, ShaderUniforms.base_clipping.y, ShaderUniforms.base_clipping.width, ShaderUniforms.base_clipping.height);
glcache.Enable(GL_SCISSOR_TEST);
}
else
{
ShaderUniforms.base_clipping.enabled = false;
}
DrawStrips();
}
@ -1238,8 +1241,6 @@ bool RenderFrame()
DrawFramebuffer();
}
eglCheck();
if (is_rtt)
ReadRTTBuffer();
else if (settings.rend.ScreenScaling != 100 || !theGLContext.IsSwapBufferPreserved())

View File

@ -8,7 +8,6 @@
#include <glm/glm.hpp>
#define glCheck() do { if (unlikely(settings.validate.OpenGlChecks)) { verify(glGetError()==GL_NO_ERROR); } } while(0)
#define eglCheck() false
#define VERTEX_POS_ARRAY 0
#define VERTEX_COL_BASE_ARRAY 1
@ -30,17 +29,27 @@ struct PipelineShader
{
GLuint program;
GLuint depth_scale;
GLuint pp_ClipTest,cp_AlphaTestValue;
GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY;
GLuint trilinear_alpha;
GLuint fog_clamp_min, fog_clamp_max;
GLuint normal_matrix;
GLint depth_scale;
GLint pp_ClipTest;
GLint cp_AlphaTestValue;
GLint sp_FOG_COL_RAM;
GLint sp_FOG_COL_VERT;
GLint sp_FOG_DENSITY;
GLint trilinear_alpha;
GLint fog_clamp_min, fog_clamp_max;
GLint normal_matrix;
//
u32 cp_AlphaTest; s32 pp_ClipTestMode;
u32 pp_Texture, pp_UseAlpha, pp_IgnoreTexA, pp_ShadInstr, pp_Offset, pp_FogCtrl;
bool pp_Gouraud, pp_BumpMap;
bool cp_AlphaTest;
bool pp_InsideClipping;
bool pp_Texture;
bool pp_UseAlpha;
bool pp_IgnoreTexA;
u32 pp_ShadInstr;
bool pp_Offset;
u32 pp_FogCtrl;
bool pp_Gouraud;
bool pp_BumpMap;
bool fog_clamping;
bool trilinear;
};
@ -52,9 +61,9 @@ struct gl_ctx
{
GLuint program;
GLuint depth_scale;
GLuint sp_ShaderColor;
GLuint normal_matrix;
GLint depth_scale;
GLint sp_ShaderColor;
GLint normal_matrix;
} modvol_shader;
@ -63,7 +72,7 @@ struct gl_ctx
struct
{
GLuint program;
GLuint scale;
GLint scale;
GLuint vao;
GLuint geometry;
GLuint osd_tex;
@ -146,9 +155,9 @@ void free_output_framebuffer();
void HideOSD();
void OSD_DRAW(bool clear_screen);
PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear);
PipelineShader *GetProgram(bool cp_AlphaTest, bool pp_InsideClipping,
bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr, bool pp_Offset,
u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear);
GLuint gl_CompileShader(const char* shader, GLuint type);
GLuint gl_CompileAndLink(const char* VertexShader, const char* FragmentShader);
@ -165,6 +174,13 @@ extern struct ShaderUniforms_t
float fog_clamp_min[4];
float fog_clamp_max[4];
glm::mat4 normal_mat;
struct {
bool enabled;
int x;
int y;
int width;
int height;
} base_clipping;
void Set(const PipelineShader* s)
{

View File

@ -241,9 +241,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
{
// Apply scissor/clipping rectangle
if (clip_origin_lower_left)
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
glcache.Scissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
else
glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
glcache.Scissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
// Bind texture, Draw
glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);

84
core/rend/tileclip.h Normal file
View File

@ -0,0 +1,84 @@
/*
Copyright 2020 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/>.
*/
#pragma once
#include <glm/glm.hpp>
#include "types.h"
#include "hw/pvr/Renderer_if.h"
enum class TileClipping {
Inside, // Render stuff outside the region
Off, // Always passes
Outside // Render stuff inside the region
};
// clip_rect[] will contain x, y, width, height
static inline TileClipping GetTileClip(u32 val, const glm::mat4& viewport, int *clip_rect)
{
if (!settings.rend.Clipping)
return TileClipping::Off;
u32 clipmode = val >> 28;
if (clipmode < 2)
return TileClipping::Off; //always passes
TileClipping tileClippingMode;
if (clipmode & 1)
tileClippingMode = TileClipping::Inside; //render stuff outside the region
else
tileClippingMode = TileClipping::Outside; //render stuff inside the region
float csx = (float)(val & 63);
float cex = (float)((val >> 6) & 63);
float csy = (float)((val >> 12) & 31);
float cey = (float)((val >> 17) & 31);
csx = csx * 32;
cex = cex * 32 + 32;
csy = csy * 32;
cey = cey * 32 + 32;
if (csx <= 0 && csy <= 0 && cex >= 640 && cey >= 480)
return TileClipping::Off;
if (!pvrrc.isRTT)
{
glm::vec4 clip_start(csx, csy, 0, 1);
glm::vec4 clip_end(cex, cey, 0, 1);
clip_start = viewport * clip_start;
clip_end = viewport * clip_end;
csx = clip_start[0];
csy = clip_start[1];
cey = clip_end[1];
cex = clip_end[0];
}
else if (!settings.rend.RenderToTextureBuffer)
{
csx *= settings.rend.RenderToTextureUpscale;
csy *= settings.rend.RenderToTextureUpscale;
cex *= settings.rend.RenderToTextureUpscale;
cey *= settings.rend.RenderToTextureUpscale;
}
clip_rect[0] = std::max(0, (int)lroundf(csx));
clip_rect[1] = std::max(0, (int)lroundf(std::min(csy, cey)));
clip_rect[2] = std::max(0, (int)lroundf(cex - csx));
clip_rect[3] = std::max(0, (int)lroundf(std::abs(cey - csy)));
return tileClippingMode;
}

View File

@ -45,57 +45,16 @@ void Drawer::SortTriangles()
}
}
// FIXME Code dup
TileClipping BaseDrawer::SetTileClip(u32 val, vk::Rect2D& clipRect)
{
if (!settings.rend.Clipping)
return TileClipping::Off;
int rect[4] = {};
TileClipping clipmode = ::GetTileClip(val, matrices.GetViewportMatrix(), rect);
clipRect.offset.x = rect[0];
clipRect.offset.y = rect[1];
clipRect.extent.width = rect[2];
clipRect.extent.height = rect[3];
u32 clipmode = val >> 28;
if (clipmode < 2)
return TileClipping::Off; //always passes
TileClipping tileClippingMode;
if (clipmode & 1)
tileClippingMode = TileClipping::Inside; //render stuff outside the region
else
tileClippingMode = TileClipping::Outside; //render stuff inside the region
float csx = (float)(val & 63);
float cex = (float)((val >> 6) & 63);
float csy = (float)((val >> 12) & 31);
float cey = (float)((val >> 17) & 31);
csx = csx * 32;
cex = cex * 32 + 32;
csy = csy * 32;
cey = cey * 32 + 32;
if (csx <= 0 && csy <= 0 && cex >= 640 && cey >= 480)
return TileClipping::Off;
if (!pvrrc.isRTT)
{
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;
csx = clip_start[0];
csy = clip_start[1];
cey = clip_end[1];
cex = clip_end[0];
}
else if (!settings.rend.RenderToTextureBuffer)
{
csx *= settings.rend.RenderToTextureUpscale;
csy *= settings.rend.RenderToTextureUpscale;
cex *= settings.rend.RenderToTextureUpscale;
cey *= settings.rend.RenderToTextureUpscale;
}
clipRect = vk::Rect2D(vk::Offset2D(std::max(0, (int)lroundf(csx)), std::max(0, (int)lroundf(csy))),
vk::Extent2D(std::max(0, (int)lroundf(cex - csx)), std::max(0, (int)lroundf(cey - csy))));
return tileClippingMode;
return clipmode;
}
void BaseDrawer::SetBaseScissor()
@ -432,10 +391,10 @@ vk::CommandBuffer TextureDrawer::BeginRenderPass()
u32 origHeight = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1;
u32 upscaledWidth = origWidth;
u32 upscaledHeight = origHeight;
int heightPow2 = 8;
u32 heightPow2 = 8;
while (heightPow2 < upscaledHeight)
heightPow2 *= 2;
int widthPow2 = 8;
u32 widthPow2 = 8;
while (widthPow2 < upscaledWidth)
widthPow2 *= 2;
@ -486,8 +445,8 @@ vk::CommandBuffer TextureDrawer::BeginRenderPass()
}
TSP tsp = { 0 };
for (tsp.TexU = 0; tsp.TexU <= 7 && (8 << tsp.TexU) < origWidth; tsp.TexU++);
for (tsp.TexV = 0; tsp.TexV <= 7 && (8 << tsp.TexV) < origHeight; tsp.TexV++);
for (tsp.TexU = 0; tsp.TexU <= 7 && (8u << tsp.TexU) < origWidth; tsp.TexU++);
for (tsp.TexV = 0; tsp.TexV <= 7 && (8u << tsp.TexV) < origHeight; tsp.TexV++);
texture = textureCache->getTextureCacheData(tsp, tcw);
if (texture->IsNew())

View File

@ -20,6 +20,7 @@
*/
#pragma once
#include "rend/sorter.h"
#include "rend/tileclip.h"
#include "rend/transform_matrix.h"
#include "vulkan.h"
#include "buffer.h"

View File

@ -42,7 +42,7 @@ void OITDrawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool
trilinearAlpha = 1.0 - trilinearAlpha;
}
bool twoVolumes = poly.tsp1.full != -1 || poly.tcw1.full != -1;
bool twoVolumes = poly.tsp1.full != (u32)-1 || poly.tcw1.full != (u32)-1;
OITDescriptorSets::PushConstants pushConstants = {
{
@ -114,7 +114,7 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs
u32 mv_mode = param.isp.DepthMode;
verify(param.first >= 0 && param.first + param.count <= pvrrc.modtrig.used());
verify(param.first >= 0 && param.first + param.count <= (u32)pvrrc.modtrig.used());
if (mod_base == -1)
mod_base = param.first;
@ -469,10 +469,10 @@ vk::CommandBuffer OITTextureDrawer::NewFrame()
u32 origHeight = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1;
u32 upscaledWidth = origWidth;
u32 upscaledHeight = origHeight;
int heightPow2 = 8;
u32 heightPow2 = 8;
while (heightPow2 < upscaledHeight)
heightPow2 *= 2;
int widthPow2 = 8;
u32 widthPow2 = 8;
while (widthPow2 < upscaledWidth)
widthPow2 *= 2;
@ -514,8 +514,8 @@ vk::CommandBuffer OITTextureDrawer::NewFrame()
}
TSP tsp = {};
for (tsp.TexU = 0; tsp.TexU <= 7 && (8 << tsp.TexU) < origWidth; tsp.TexU++);
for (tsp.TexV = 0; tsp.TexV <= 7 && (8 << tsp.TexV) < origHeight; tsp.TexV++);
for (tsp.TexU = 0; tsp.TexU <= 7 && (8u << tsp.TexU) < origWidth; tsp.TexU++);
for (tsp.TexV = 0; tsp.TexV <= 7 && (8u << tsp.TexV) < origHeight; tsp.TexV++);
texture = textureCache->getTextureCacheData(tsp, tcw);
if (texture->IsNew())

View File

@ -23,12 +23,6 @@
enum class ModVolMode { Xor, Or, Inclusion, Exclusion, Final };
enum class TileClipping {
Inside, // render stuff outside the region
Off,
Outside // render stuff inside the region
};
static const vk::CompareOp depthOps[] =
{
vk::CompareOp::eNever, //0 Never
@ -41,7 +35,7 @@ static const vk::CompareOp depthOps[] =
vk::CompareOp::eAlways, //7 Always
};
static vk::BlendFactor getBlendFactor(u32 instr, bool src)
static inline vk::BlendFactor getBlendFactor(u32 instr, bool src)
{
switch (instr) {
case 0: // zero
@ -78,6 +72,6 @@ static inline u32 findMemoryType(vk::PhysicalDeviceMemoryProperties const& memor
}
typeBits >>= 1;
}
verify(typeIndex != ~0);
verify(typeIndex != u32(~0));
return typeIndex;
}