Render to texture single pass implemented

This commit is contained in:
Marcel Szewczyk 2018-10-28 20:16:45 +01:00
parent ddacfd4e7a
commit f309a59fac
5 changed files with 101 additions and 48 deletions

View File

@ -146,14 +146,15 @@ bool QueueRender(TA_context* ctx)
bool too_fast = (cycle_span / time_span) > (SH4_MAIN_CLOCK * 1.2);
if (rqueue && too_fast && settings.pvr.SynchronousRender) {
if ((rqueue && too_fast && settings.pvr.SynchronousRender) ||
(rqueue && ctx->rend.isRTT)) {
//wait for a frame if
// we have another one queue'd and
// sh4 run at > 120% on the last slice
// and SynchronousRendering is enabled
frame_finished.Wait();
verify(!rqueue);
}
}
if (rqueue) {
tactx_Recycle(ctx);

View File

@ -146,15 +146,18 @@ s32 SetTileClip(u32 val, bool set)
return 0;
if (set && clip_mode) {
csy = 480 - csy;
cey = 480 - cey;
float dc2s_scale_h = screen_height / 480.0f;
float ds2s_offs_x = (screen_width - dc2s_scale_h * 640) / 2;
csx = csx * dc2s_scale_h + ds2s_offs_x;
cex = cex * dc2s_scale_h + ds2s_offs_x;
csy = csy * dc2s_scale_h;
cey = cey * dc2s_scale_h;
glUniform4f(CurrentShader->pp_ClipTest, csx, cey, cex, csy);
if (!pvrrc.isRTT) {
float t = cey;
cey = 480 - csy;
csy = 480 - t;
float dc2s_scale_h = screen_height / 480.0f;
float ds2s_offs_x = (screen_width - dc2s_scale_h * 640) / 2;
csx = csx * dc2s_scale_h + ds2s_offs_x;
cex = cex * dc2s_scale_h + ds2s_offs_x;
csy = csy * dc2s_scale_h;
cey = cey * dc2s_scale_h;
}
glUniform4f(CurrentShader->pp_ClipTest, csx, csy, cex, cey);
}
return clip_mode;

View File

@ -172,10 +172,10 @@ const char* VertexShaderSource =
#endif
//0 - not in use
//1 - in use since the last frame
//2 - not anymore in use (e.g. exit to menu)
u8 rttInUse = 0;
/*
@ -1447,10 +1447,6 @@ void OSD_DRAW()
bool ProcessFrame(TA_context* ctx)
{
//disable RTTs for now ..
if (ctx->rend.isRTT)
return false;
ctx->rend_inuse.Lock();
ctx->MarkRend();
@ -1580,14 +1576,10 @@ bool RenderFrame()
//For some reason this produces wrong results
//so for now its hacked based like on the d3d code
/*
dc_width=FB_X_CLIP.max-FB_X_CLIP.min+1;
dc_height=FB_Y_CLIP.max-FB_Y_CLIP.min+1;
u32 pvr_stride=(FB_W_LINESTRIDE.stride)*8;
*/
dc_width=640;
dc_height=480;
dc_width = FB_X_CLIP.max - FB_X_CLIP.min + 1;
dc_height = FB_Y_CLIP.max - FB_Y_CLIP.min + 1;
//u32 pvr_stride=(FB_W_LINESTRIDE.stride)*8;
}
float scale_x=1, scale_y=1;
@ -1646,8 +1638,9 @@ bool RenderFrame()
/*
Handle Dc to screen scaling
*/
float dc2s_scale_h=screen_height/480.0f;
float ds2s_offs_x=(screen_width-dc2s_scale_h*640)/2;
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0) / 2);
//-1 -> too much to left
ShaderUniforms.scale_coefs[0]=2.0f/(screen_width/dc2s_scale_h*scale_x);
@ -1703,7 +1696,6 @@ bool RenderFrame()
glUniform4fv( gl.modvol_shader.scale, 1, ShaderUniforms.scale_coefs);
glUniform4fv( gl.modvol_shader.depth_scale, 1, ShaderUniforms.depth_coefs);
GLfloat td[4]={0.5,0,0,0};
glUseProgram(gl.OSD_SHADER.program);
@ -1768,12 +1760,22 @@ bool RenderFrame()
break;
}
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);
rttInUse = 1;
}
else
{
#if HOST_OS != OS_DARWIN
//Fix this in a proper way
if (rttInUse == 1) {
ReadRTT();
rttInUse = 2;
}
else if (rttInUse == 2) {
FreeRTTBuffers();
rttInUse = 0;
}
glBindFramebuffer(GL_FRAMEBUFFER,0);
glViewport(0, 0, screen_width, screen_height);
#endif
}

View File

@ -117,6 +117,8 @@ void DoCleanup();
void SortPParams();
void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt);
void ReadRTT();
void FreeRTTBuffers();
int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
u32 pp_FogCtrl);

View File

@ -20,6 +20,8 @@ Compression
look into it, but afaik PVRC is not realtime doable
*/
u16 buf[1024*1024];
#if FEAT_HAS_SOFTREND
#include <xmmintrin.h>
#endif
@ -384,11 +386,6 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
{
FBT& rv=fb_rtt;
if (rv.fbo) glDeleteFramebuffers(1,&rv.fbo);
if (rv.tex) glDeleteTextures(1,&rv.tex);
if (rv.depthb) glDeleteRenderbuffers(1,&rv.depthb);
if (rv.stencilb) glDeleteRenderbuffers(1,&rv.stencilb);
rv.TexAddr=addy>>3;
// Find the largest square power of two texture that fits into the viewport
@ -397,7 +394,8 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
//glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo);
// Generate and bind a render buffer which will become a depth buffer shared between our two FBOs
glGenRenderbuffers(1, &rv.depthb);
if (!rv.depthb)
glGenRenderbuffers(1, &rv.depthb);
glBindRenderbuffer(GL_RENDERBUFFER, rv.depthb);
/*
@ -412,23 +410,25 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, fbw, fbh);
#endif
glGenRenderbuffers(1, &rv.stencilb);
if (!rv.stencilb)
glGenRenderbuffers(1, &rv.stencilb);
glBindRenderbuffer(GL_RENDERBUFFER, rv.stencilb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fbw, fbh);
// Create a texture for rendering to
glGenTextures(1, &rv.tex);
if (!rv.tex)
glGenTextures(1, &rv.tex);
glBindTexture(GL_TEXTURE_2D, rv.tex);
glTexImage2D(GL_TEXTURE_2D, 0, channels, fbw, fbh, 0, channels, fmt, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_OES);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_OES);
// Create the object that will allow us to render to the aforementioned texture
glGenFramebuffers(1, &rv.fbo);
if (!rv.fbo)
glGenFramebuffers(1, &rv.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo);
// Attach the texture to the FBO
@ -441,6 +441,51 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
verify(uStatus == GL_FRAMEBUFFER_COMPLETE);
glViewport(0, 0, fbw, fbh);
}
void ReadRTT() {
FBT& rv=fb_rtt;
//get viewport width and height from rtt framebuffer
GLint dimensions[4] = {0};
glGetIntegerv(GL_VIEWPORT, dimensions);
GLint w = dimensions[2];
GLint h = dimensions[3];
//bind texture to which we have rendered in the last rtt pass
glBindTexture(GL_TEXTURE_2D, rv.tex);
switch(FB_W_CTRL.fb_packmode)
{
//currently RGB 565 is supported only
case 1: //0x1 565 RGB 16 bit
{
u16 *dataPointer = temp_tex_buffer;
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, temp_tex_buffer);
for (u32 i = 0; i < w * h; i++) {
buf[i] = ((*dataPointer & 0xF000) >> 12) | ((*dataPointer & 0x0FFF) << 4);
*dataPointer++;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, buf);
break;
}
default:
//clear unsupported texture to avoid artifacts
memset(buf, '\0', w * h);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, buf);
break;
}
}
void FreeRTTBuffers() {
if (fb_rtt.fbo) { glDeleteFramebuffers(1,&fb_rtt.fbo); fb_rtt.fbo = 0; }
if (fb_rtt.tex) { glDeleteTextures(1,&fb_rtt.tex); fb_rtt.tex = 0; }
if (fb_rtt.depthb) { glDeleteRenderbuffers(1,&fb_rtt.depthb); fb_rtt.depthb = 0; }
if (fb_rtt.stencilb) { glDeleteRenderbuffers(1,&fb_rtt.stencilb); fb_rtt.stencilb = 0; }
}
GLuint gl_GetTexture(TSP tsp, TCW tcw)
@ -523,12 +568,12 @@ text_info raw_GetTexture(TSP tsp, TCW tcw)
//return gl texture
rv.height = tf->h;
rv.width = tf->w;
rv.pdata = tf->pData;
rv.textype = tf->tex_type;
return rv;
rv.width = tf->w;
rv.pdata = tf->pData;
rv.textype = tf->tex_type;
return rv;
}
void CollectCleanup() {