Render to texture single pass implemented
This commit is contained in:
parent
ddacfd4e7a
commit
f309a59fac
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue