per-pixel renderer: RTT might need bigger buffers than screen

This commit is contained in:
Flyinghead 2019-06-27 22:41:16 +02:00
parent e6b8c46557
commit 99778a7715
6 changed files with 101 additions and 102 deletions

View File

@ -280,9 +280,6 @@ void main(void) \n\
void initABuffer()
{
g_imageWidth = (int)roundf(screen_width * settings.rend.ScreenScaling / 100.f);
g_imageHeight = (int)roundf(screen_height * settings.rend.ScreenScaling / 100.f);
if (g_imageWidth > 0 && g_imageHeight > 0)
{
if (pixels_pointers == 0)
@ -384,7 +381,7 @@ void initABuffer()
glcache.UseProgram(g_abuffer_clear_shader.program);
gl4ShaderUniforms.Set(&g_abuffer_clear_shader);
abufferDrawQuad();
abufferDrawQuad(g_imageWidth, g_imageHeight);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glCheck();
@ -432,39 +429,34 @@ void termABuffer()
void reshapeABuffer(int w, int h)
{
w = (int)roundf(w * settings.rend.ScreenScaling / 100.f);
h = (int)roundf(h * settings.rend.ScreenScaling / 100.f);
if (w != g_imageWidth || h != g_imageHeight) {
if (pixels_pointers != 0)
{
glcache.DeleteTextures(1, &pixels_pointers);
pixels_pointers = 0;
}
g_imageWidth = w;
g_imageHeight = h;
initABuffer();
}
}
void abufferDrawQuad(bool upsideDown, float x, float y, float w, float h)
void abufferDrawQuad(float w, float h)
{
if (w == 0 || h == 0)
{
float scl = 480.f / screen_height;
float tx = (screen_width * scl - 640.f) / 2;
float scl = 480.f / h;
float tx = (w * scl - 640.f) / 2;
x = -tx;
y = 0.f;
w = 640.f + tx * 2;
h = 480.f;
}
float x = -tx;
float y = 0.f;
w = 640.f + tx * 2;
h = 480.f;
glBindVertexArray(g_quadVertexArray);
struct Vertex vertices[] = {
{ x, y + h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, upsideDown ? 0.f : 1.f },
{ x, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, upsideDown ? 1.f : 0.f },
{ x + w, y + h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, upsideDown ? 0.f : 1.f },
{ x + w, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, upsideDown ? 1.f : 0.f },
{ x, y + h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, 1.f },
{ x, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, 0.f },
{ x + w, y + h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, 1.f },
{ x + w, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, 0.f },
};
GLushort indices[] = { 0, 1, 2, 1, 3 };
@ -574,15 +566,15 @@ void checkOverflowAndReset()
glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0 , sizeof(GLuint), &max_pixel_index);
}
void renderABuffer(bool sortFragments)
void renderABuffer(bool sortFragments, int width, int height)
{
// Reset scale params to a standard 640x480 dc screen
float scale_h = screen_height / 480.f;
float offs_x = (screen_width - scale_h * 640.f) / 2.f;
gl4ShaderUniforms.scale_coefs[0] = 2.f / (screen_width / scale_h);
gl4ShaderUniforms.scale_coefs[1]= -2.f / 480.f;
gl4ShaderUniforms.scale_coefs[2]= 1.f - 2.f * offs_x / screen_width;
gl4ShaderUniforms.scale_coefs[3]= -1.f;
float scale_h = height / 480.f;
float offs_x = (width - scale_h * 640.f) / 2.f;
gl4ShaderUniforms.scale_coefs[0] = 2.f / (width / scale_h);
gl4ShaderUniforms.scale_coefs[1] = -2.f / 480.f;
gl4ShaderUniforms.scale_coefs[2] = 1.f - 2.f * offs_x / width;
gl4ShaderUniforms.scale_coefs[3] = -1.f;
// Render to output FBO
glcache.UseProgram(sortFragments ? g_abuffer_final_shader.program : g_abuffer_final_nosort_shader.program);
@ -592,7 +584,7 @@ void renderABuffer(bool sortFragments)
glcache.Disable(GL_CULL_FACE);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT);
abufferDrawQuad();
abufferDrawQuad(width, height);
glCheck();
@ -601,7 +593,7 @@ void renderABuffer(bool sortFragments)
gl4ShaderUniforms.Set(&g_abuffer_clear_shader);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
abufferDrawQuad();
abufferDrawQuad(width, height);
glActiveTexture(GL_TEXTURE0);

View File

@ -2,7 +2,7 @@
#include "rend/gles/gles.h"
#include <unordered_map>
void gl4DrawStrips(GLuint output_fbo);
void gl4DrawStrips(GLuint output_fbo, int width, int height);
struct gl4PipelineShader
{
@ -64,7 +64,7 @@ extern int screen_height;
GLuint gl4BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt);
void gl4DrawFramebuffer(float w, float h);
bool gl4_render_output_framebuffer();
void abufferDrawQuad(bool upsideDown = false, float x = 0.f, float y = 0.f, float w = 0.f, float h = 0.f);
void abufferDrawQuad(float w, float h);
extern const char *gl4PixelPipelineShader;
bool gl4CompilePipelineShader(gl4PipelineShader* s, bool rotate_90, const char *source = gl4PixelPipelineShader);

View File

@ -386,7 +386,7 @@ static void DrawModVols(int first, int count)
glcache.DepthMask(GL_TRUE);
}
void renderABuffer(bool sortFragments);
void renderABuffer(bool sortFragments, int width, int height);
void DrawTranslucentModVols(int first, int count);
void checkOverflowAndReset();
@ -403,8 +403,14 @@ static GLuint CreateColorFBOTexture(int width, int height)
return texId;
}
static void CreateTextures(int width, int height)
void gl4CreateTextures(int width, int height)
{
if (geom_fbo == 0)
{
glGenFramebuffers(1, &geom_fbo);
}
glBindFramebuffer(GL_FRAMEBUFFER, geom_fbo);
stencilTexId = glcache.GenTexture();
glBindTexture(GL_TEXTURE_2D, stencilTexId); glCheck();
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); // OpenGL >= 4.3
@ -425,31 +431,16 @@ static void CreateTextures(int width, int height)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCheck();
GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
verify(uStatus == GL_FRAMEBUFFER_COMPLETE);
}
void gl4DrawStrips(GLuint output_fbo)
void gl4DrawStrips(GLuint output_fbo, int width, int height)
{
checkOverflowAndReset();
int scaled_width = (int)roundf(screen_width * settings.rend.ScreenScaling / 100.f);
int scaled_height = (int)roundf(screen_height * settings.rend.ScreenScaling / 100.f);
if (geom_fbo == 0)
{
glGenFramebuffers(1, &geom_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, geom_fbo);
CreateTextures(scaled_width, scaled_height);
GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
verify(uStatus == GL_FRAMEBUFFER_COMPLETE);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, geom_fbo);
if (stencilTexId == 0)
CreateTextures(scaled_width, scaled_height);
}
glBindFramebuffer(GL_FRAMEBUFFER, geom_fbo);
if (texSamplers[0] == 0)
glGenSamplers(2, texSamplers);
@ -514,14 +505,14 @@ void gl4DrawStrips(GLuint output_fbo)
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, scaled_width, scaled_height, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); glCheck();
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); glCheck();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthSaveTexId, 0); glCheck();
}
GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
verify(uStatus == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_READ_FRAMEBUFFER, geom_fbo);
glBlitFramebuffer(0, 0, scaled_width, scaled_height, 0, 0, scaled_width, scaled_height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glCheck();
glBindFramebuffer(GL_FRAMEBUFFER, geom_fbo);
@ -553,7 +544,7 @@ void gl4DrawStrips(GLuint output_fbo)
// FIXME This is pretty slow apparently (CS)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, geom_fbo);
glBindFramebuffer(GL_READ_FRAMEBUFFER, depth_fbo);
glBlitFramebuffer(0, 0, scaled_width, scaled_height, 0, 0, scaled_width, scaled_height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glCheck();
glBindFramebuffer(GL_FRAMEBUFFER, geom_fbo);
}
@ -621,7 +612,7 @@ void gl4DrawStrips(GLuint output_fbo)
//
// PASS 3c: Render a-buffer to temporary texture
//
GLuint texId = CreateColorFBOTexture(scaled_width, scaled_height);
GLuint texId = CreateColorFBOTexture(width, height);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -629,7 +620,7 @@ void gl4DrawStrips(GLuint output_fbo)
glBindSampler(0, 0);
glBindTexture(GL_TEXTURE_2D, opaqueTexId);
renderABuffer(current_pass.autosort);
renderABuffer(current_pass.autosort, width, height);
glcache.DeleteTextures(1, &opaqueTexId);
opaqueTexId = texId;
@ -657,10 +648,10 @@ void gl4DrawStrips(GLuint output_fbo)
glActiveTexture(GL_TEXTURE0);
glBindSampler(0, 0);
glBindTexture(GL_TEXTURE_2D, opaqueTexId);
renderABuffer(previous_pass.autosort);
renderABuffer(previous_pass.autosort, width, height);
}
static void gl4_draw_quad_texture(GLuint texture, bool upsideDown, float x = 0.f, float y = 0.f, float w = 0.f, float h = 0.f)
static void gl4_draw_quad_texture(GLuint texture, float w, float h)
{
glcache.Disable(GL_SCISSOR_TEST);
glcache.Disable(GL_DEPTH_TEST);
@ -690,12 +681,12 @@ static void gl4_draw_quad_texture(GLuint texture, bool upsideDown, float x = 0.f
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
abufferDrawQuad(upsideDown, x, y, w, h);
abufferDrawQuad(w, h);
}
void gl4DrawFramebuffer(float w, float h)
{
gl4_draw_quad_texture(fbTextureId, false, 0, 0, w, h);
gl4_draw_quad_texture(fbTextureId, w, h);
glcache.DeleteTextures(1, &fbTextureId);
fbTextureId = 0;
}

View File

@ -561,6 +561,8 @@ static bool gl_create_resources()
//setup
extern void initABuffer();
void reshapeABuffer(int width, int height);
extern void gl4CreateTextures(int width, int height);
static bool gles_init()
{
@ -610,15 +612,41 @@ static bool gles_init()
return true;
}
static void resize(int w, int h)
{
static int cur_width, cur_height;
if (w > cur_width || h > cur_height || stencilTexId == 0)
{
cur_width = w;
cur_height = h;
if (stencilTexId != 0)
{
glcache.DeleteTextures(1, &stencilTexId);
stencilTexId = 0;
}
if (depthTexId != 0)
{
glcache.DeleteTextures(1, &depthTexId);
depthTexId = 0;
}
if (opaqueTexId != 0)
{
glcache.DeleteTextures(1, &opaqueTexId);
opaqueTexId = 0;
}
if (depthSaveTexId != 0)
{
glcache.DeleteTextures(1, &depthSaveTexId);
depthSaveTexId = 0;
}
gl4CreateTextures(w, h);
reshapeABuffer(w, h);
}
}
static bool RenderFrame()
{
static int old_screen_width, old_screen_height, old_screen_scaling;
if (screen_width != old_screen_width || screen_height != old_screen_height || settings.rend.ScreenScaling != old_screen_scaling) {
rend_resize(screen_width, screen_height);
old_screen_width = screen_width;
old_screen_height = screen_height;
old_screen_scaling = settings.rend.ScreenScaling;
}
DoCleanup();
create_modvol_shader();
@ -687,12 +715,17 @@ static bool RenderFrame()
float dc2s_scale_h;
float ds2s_offs_x;
int rendering_width;
int rendering_height;
if (is_rtt)
{
gl4ShaderUniforms.scale_coefs[0] = 2.0f / dc_width;
gl4ShaderUniforms.scale_coefs[1] = 2.0f / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
gl4ShaderUniforms.scale_coefs[2] = 1;
gl4ShaderUniforms.scale_coefs[3] = 1;
int scaling = settings.rend.RenderToTextureBuffer ? 1 : settings.rend.RenderToTextureUpscale;
rendering_width = dc_width * scaling;
rendering_height = dc_height * scaling;
}
else
{
@ -715,7 +748,10 @@ static bool RenderFrame()
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
gl4ShaderUniforms.scale_coefs[3] = -1;
}
rendering_width = screen_width * screen_scaling + 0.5f;
rendering_height = screen_height * screen_scaling + 0.5f;
}
resize(rendering_width, rendering_height);
gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale;
@ -808,7 +844,7 @@ static bool RenderFrame()
{
if (settings.rend.ScreenScaling != 100 || gl.swap_buffer_not_preserved)
{
output_fbo = init_output_framebuffer(screen_width * screen_scaling + 0.5f, screen_height * screen_scaling + 0.5f);
output_fbo = init_output_framebuffer(rendering_width, rendering_width);
}
else
{
@ -820,9 +856,9 @@ static bool RenderFrame()
bool wide_screen_on = !is_rtt && settings.rend.WideScreen
&& pvrrc.fb_X_CLIP.min == 0
&& (pvrrc.fb_X_CLIP.max + 1) / scale_x == 640
&& int((pvrrc.fb_X_CLIP.max + 1) / scale_x + 0.5f) == 640
&& pvrrc.fb_Y_CLIP.min == 0
&& (pvrrc.fb_Y_CLIP.max + 1) / scale_y == 480;
&& int((pvrrc.fb_Y_CLIP.max + 1) / scale_y + 0.5f) == 480;
//Color is cleared by the background plane
@ -898,9 +934,9 @@ static bool RenderFrame()
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
glcache.Enable(GL_SCISSOR_TEST);
glScissor(0, 0, scaled_offs_x + 0.5f, screen_height * screen_scaling + 0.5f);
glScissor(0, 0, scaled_offs_x + 0.5f, rendering_height);
glClear(GL_COLOR_BUFFER_BIT);
glScissor(screen_width * screen_scaling - scaled_offs_x + 0.5f, 0, scaled_offs_x + 1.f, screen_height * screen_scaling + 0.5f);
glScissor(screen_width * screen_scaling - scaled_offs_x + 0.5f, 0, scaled_offs_x + 1.f, rendering_height);
glClear(GL_COLOR_BUFFER_BIT);
}
}
@ -918,7 +954,7 @@ static bool RenderFrame()
//restore scale_x
scale_x /= scissoring_scale_x;
gl4DrawStrips(output_fbo);
gl4DrawStrips(output_fbo, rendering_width, rendering_height);
}
else
{
@ -952,27 +988,7 @@ struct gl4rend : Renderer
{
screen_width=w;
screen_height=h;
if (stencilTexId != 0)
{
glcache.DeleteTextures(1, &stencilTexId);
stencilTexId = 0;
}
if (depthTexId != 0)
{
glcache.DeleteTextures(1, &depthTexId);
depthTexId = 0;
}
if (opaqueTexId != 0)
{
glcache.DeleteTextures(1, &opaqueTexId);
opaqueTexId = 0;
}
if (depthSaveTexId != 0)
{
glcache.DeleteTextures(1, &depthSaveTexId);
depthSaveTexId = 0;
}
reshapeABuffer(w, h);
resize(w * settings.rend.ScreenScaling / 100.f + 0.5f, h * settings.rend.ScreenScaling / 100.f + 0.5f);
}
void Term()
{

View File

@ -1924,9 +1924,9 @@ bool RenderFrame()
bool wide_screen_on = !is_rtt && settings.rend.WideScreen
&& pvrrc.fb_X_CLIP.min == 0
&& (pvrrc.fb_X_CLIP.max + 1) / scale_x == 640
&& int((pvrrc.fb_X_CLIP.max + 1) / scale_x + 0.5f) == 640
&& pvrrc.fb_Y_CLIP.min == 0
&& (pvrrc.fb_Y_CLIP.max + 1) / scale_y == 480;
&& int((pvrrc.fb_Y_CLIP.max + 1) / scale_y + 0.5f) == 480;
//Color is cleared by the background plane

View File

@ -482,7 +482,7 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
gl.rtt.TexAddr=addy>>3;
// Find the smallest power of two texture that fits into the viewport
// Find the smallest power of two texture that fits the viewport
int fbh2 = 2;
while (fbh2 < fbh)
fbh2 *= 2;