Reading texture from PVR back into SH-4 RAM

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Just a quick question about textures in the PVR RAM. Do you know if it is possible to be able to read these back into SH-4 RAM and possibly untwiddle into a raw form for modification?

My thought behind this is to be able to perform a blurring effect to achieve a light bloom. I have had a look at the often cited (http://yam.20to4.net/dreamcast/index_old.html) and the author achieves a box filter effect amongst other post-processing effects which would help achieve this.

Without this to keep things in the PVR RAM (as an alternative) I have thought about rendering part of a scene to a small part of a texture and then just drawing this to a polygon scaled back up. However, the PVR only seems to be able to write to rounded screen size (1024 x 512) textures, which makes grabbing a precise section back rather tricky.

Any advice on this would be appreciated :)
Thanks,
Dave
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

Well, in KOS, pvr_ptr_t "objects" are simply pointers. So, if you have a pvr_ptr_t, you can read/write to/from it just like any other pointer (just potentially slower).

If you're using render-to-texture, it can be set up to do non-screen-sized output, but I just haven't ever gotten the chance to fix the code for that possibility. Also, the rendered "texture" should be non-twiddled and easily workable, simply as RGB565 pixels (unless you've changed the output format, of course).
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Thanks BlueCrab. I wasn't sure if the object at the end of the pvr_ptr_t was readable and manipulatable, so thanks for clarifying that for me.

I noticed on the Parallax tutorial 35 that there was an example of ortho rendering, which helps to deal with scaling down and texture then picking it out and scaling back up to create a blur so that issue has gone.

One last question that I have with KOS is regarding the blending source and destination flags. From what I understand the PVR2 only supports alpha blending, however, the flags imply that KOS somehow enables additive blending. I have had a play with different combinations, but they seem to lead to the same effect. Do you know if additive blending is possible with the hardware with a workaround?
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

For Opaque polygons, the only valid combination is PVR_BLEND_ONE for the source and PVR_BLEND_ZERO for the destination.
For Punch-thru polygons, the only valid combination is PVR_BLEND_SRCALPHA for the source and PVR_BLEND_INVSRCALPHA for the destination.
For translucent polygons, you should be able to use whatever blending modes you want for the source and destination, and they all should work as they would be expected to work.

The only blending modes available involve alpha blending.
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Thanks for the help. I seem to have more or less the effect that I was looking for by using alpha blending, however, when rendering to textures before blending I seem to have hit on either a bug in the hardware or something that I have misunderstood.

From what I can tell pvr_scene_begin_txr(...) can only be called once before a pvr_scene_begin() as a blank frame is passed to the screen itself when pvr_scene_begin_txr(...) is called again causing a flicker. Is this a known limitation with the hardware or should it be possible to call pvr_scene_begin_txr repeatedly to render to multiple textures then blend them together within the final pvr_scene_begin(). In this case I have ensured that pvr_wait_ready() is called before each frame is drawn.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

You shouldn't call pvr_scene_begin() when you do pvr_scene_begin_txr(). Only call one or the other. I'm not sure if you're calling both on the same scene, but what you wrote seems sort of like you are.

There is an example in the KOS tree of doing render-to-texture. Should be in examples/dreamcast/pvr/texture_render. Dunno if you've seen that or not.
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Apologies if that didn't come across too clear. I have looked through both the pvr render-to-texture and lesson35 examples which have given me enough information to put together an example to render a scene to a texture then to draw a cube with this texture on the sides. This seems to work fine.

The cut down code for what is causing the 'flashing black' is below. If I remove the second 'pvr_scene_begin_txr' then everything works fine, however, rendering more than one scene to a texture is causing the screen to blank.

pvr_wait_ready();
pvr_scene_begin_txr(TextureA.ptr, &tx_x, &tx_y);
... draw lists for first scene
pvr_scene_finish();

pvr_wait_ready();
pvr_scene_begin_txr(TextureB.ptr, &tx_x, &tx_y);
... draw lists for second scene
pvr_scene_finish();

pvr_wait_ready();
pvr_scene_begin();
... draw two cubes textured with TextureA and TextureB
pvr_scene_finish();

Thanks,
Dave
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

Ah... I've never actually tried rendering two frames in a row with render-to-texture... I'd guess the code is probably doing something slightly wrong, but I couldn't tell you what at the moment.
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Thanks for the advice anyways. I need to do a bit more testing to determine why this is happening. If it's something in KOS rather than my own code I'll see if I can fix it and make a patch.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

MisterDave wrote:Thanks for the advice anyways. I need to do a bit more testing to determine why this is happening. If it's something in KOS rather than my own code I'll see if I can fix it and make a patch.
When I said "in the code", I was referring to KOS itself. When I committed the patch years ago to re-enable the render-to-texture support that had been missing since the PVR API was re-done in like 1.1.7, I actually didn't quite have a grasp on everything that it was doing. I probably overlooked something back then. :wink:

EDIT: I think I may see the problem in the code, but I obviously want to test to see if this corrects it or not. Unfortunately, I have to walk out the door, so I can't quite test it at the moment.

EDIT x2: Well, I'm now 100% sure this is the code that is causing the problem. I have to rearrange a few things, because the way the code is set up now you cannot possibly do two render-to-texture passes without doing an intervening render-to-screen pass.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

So, I committed a fix for this problem to the repository tonight (commit da33c8).

There were a bunch of problems with the code, so I'll kinda briefly cover what was wrong... Basically, the main problem was that there was only one set of render-to-texture state, whereas every other bit of rendering state is duplicated. The reason the rendering state is duplicated is because you will always have one scene rendering while you're sending the data for the next. So, when you're submitting polygons, they obviously won't be drawn immediately -- basically, your standard double-buffer setup.

Since only one set of state variables for render-to-texture was stored, one of them represented whether texture rendering was enabled or not. This had three possible values -- 0: normal screen render, 1: you've called pvr_scene_begin_txr(), 2: you called pvr_scene_begin_txr() one frame ago, so the current render is going to a texture. You should already see the problem as to why this would (obviously) not work if you call pvr_scene_begin_txr() on two frames in a row... Basically, when you'd do that, you'd upset the state internally of the code and the framebuffer would get swapped (since it got swapped to the display in all states of that variable except it being 2).

So, now there's two sets of state for all the render-to-texture variables to take care of the issues involved with that... I didn't see any issues with doing two passes of render-to-texture in a row (I modified the example I mentioned before to do that). That said, I'm still not completely satisfied with how I'm doing things, even though it appears to work. Oh well... :roll:
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Thanks for looking into this so quickly BlueCrab and for creating a patch. Fingers crossed I should be able to get my bloom filter complete now. If this works as expected then I would be happy to share my code in the case that anyone else wants to reuse it as an example.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

MisterDave wrote:Thanks for looking into this so quickly BlueCrab and for creating a patch. Fingers crossed I should be able to get my bloom filter complete now. If this works as expected then I would be happy to share my code in the case that anyone else wants to reuse it as an example.
If you'd like, I could possibly add it to the repository as an example program. :wink:
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Cool, I'd be happy to do that. The effect works fairly well, I'm just wrestling with a bug that seems to make anything that moves behind the camera repeat in an endless corridor in front of the camera and trying to determine what is causing it.

It seems to be in the Parallax version of nehe lesson 10 (lesson 9 in the parallaxnehe naming convention) has that bug too. It runs fine on lxdream, but on the real hardware the problem happens. I'm just trying at the moment to determine if it is something wrong in that code (such as clipping being set wrong) or in KOS itself.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Reading texture from PVR back into SH-4 RAM

Post by BlueCrab »

MisterDave wrote:It seems to be in the Parallax version of nehe lesson 10 (lesson 9 in the parallaxnehe naming convention) has that bug too. It runs fine on lxdream, but on the real hardware the problem happens. I'm just trying at the moment to determine if it is something wrong in that code (such as clipping being set wrong) or in KOS itself.
That seems like a clipping bug or perhaps something odd with some matrix transforms.

Keep in mind that the PVR itself doesn't do any camera-related transforms or whatnot, so you do have to do a bit of manual work to deal with Z plane clipping and such.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Reading texture from PVR back into SH-4 RAM

Post by PH3NOM »

MisterDave wrote:I'm just wrestling with a bug that seems to make anything that moves behind the camera repeat in an endless corridor in front of the camera and trying to determine what is causing it.

It seems to be in the Parallax version of nehe lesson 10 (lesson 9 in the parallaxnehe naming convention) has that bug too. It runs fine on lxdream, but on the real hardware the problem happens. I'm just trying at the moment to determine if it is something wrong in that code (such as clipping being set wrong) or in KOS itself.
Yes BlueCrab beat me to it somehow ( my last post didnt submit? )

You will need to clip the vertices to the Near-Z Plane for use with the PVR, the results of not doing so, as you have experienced, can be quite bizarre indeed.

KGL includes a mechanism for Clipping on the Near-Z Plane, that might be sufficient for your project.
However, I noticed many deficiencies with the algorithm, so I decided to write my own implementation for my build of OpenGL.

My algorithm ( currently only written for clipping Triangle Strips, but will be easy to add support for triangles ) will break a Triangle Strip down into individual triangles, clipping them against the Near-Z plane, and output the results as an array of triangles.

It is not yet completed, as there are some cases where a strip will be clipped when it shouldn't, but I am not sure if the problem is in my clip code, or in the stage that clipping occurs in my pipeline( post transformation )

Any rate, here is my code, if you know of a better method I would like to hear about it.

Code: Select all

/*
** Gl-Clip.c (C) Josh PH3NOM Pearson 2013
** *Work In Progress
*/

#include <dc/pvr.h>

#define NONE   0x0000 /* Clip Codes */
#define FIRST  0x0001
#define SECOND 0x0010
#define THIRD  0x0100
#define ALL    0x0111
#define FIRST_TWO_OUT      0x0011
#define FIRST_AND_LAST_OUT 0x0101
#define LAST_TWO_OUT       0x0110

#define ALPHA 0xFF000000 /* Color Components using PVR's Packed 32bit int */
#define RED   0x00FF0000
#define GREEN 0x0000FF00
#define BLUE  0x000000FF

#define CLIP_ZNEAR 0.00001
#define CLIPZ 0xF

inline void VertexCopy( pvr_vertex_t *src, pvr_vertex_t *dst )
{
    *dst = *src;
}

inline void VertexClipZNear( pvr_vertex_t *v1, pvr_vertex_t *v2 )
{  
     float MAG = (CLIP_ZNEAR - v1->z)/(v2->z-v1->z); /* Displacement Mag */
     
     /* Linear interpolate the U/V data */
     v1->u = ((v2->u-v1->u)*MAG)+v1->u;
     v1->v = ((v2->v-v1->v)*MAG)+v1->v;
     
     /* Linear interpolate the Vertex data */
     v1->x = ((v2->x-v1->x)*MAG) + v1->x;
     v1->y = ((v2->y-v1->y)*MAG) + v1->y;
     v1->z = ((v2->z-v1->z)*MAG) + v1->z;
     
     /* Extract Color Components, Apply Linear Interpolation, then Pack it up */
     BYTE a1 = (v1->argb & ALPHA)>>24;
     BYTE r1 = (v1->argb & RED)>>16;
     BYTE g1 = (v1->argb & GREEN)>>8;
     BYTE b1 = (v1->argb & BLUE)>>0;
     BYTE a2 = (v2->argb & ALPHA)>>24;
     BYTE r2 = (v2->argb & RED)>>16;
     BYTE g2 = (v2->argb & GREEN)>>8;
     BYTE b2 = (v2->argb & BLUE)>>0;
     BYTE a  = ((a2-a1)*MAG)+ a1;
     BYTE r  = ((r2-r1)*MAG)+ r1;
     BYTE g  = ((g2-g1)*MAG)+ g1;
     BYTE b  = ((b2-b1)*MAG)+ b1;
     v1->argb = ( (a<<24) | (r<<16) | (g<<8) | (b<<0) );
}

/* Wowsers, what a run this has been. Initially forgot to modify vertex flags */
inline int ClipZNearTriStrip( pvr_vertex_t *in, pvr_vertex_t *out, unsigned int n )
{
    unsigned short int clip = 0, vertices_inside = 0;
    unsigned int v = 0, i;
    
    for( i=0; i<(n-2); i++ )
    {
        /* Compute clip codes for each vertex of triangle */ 
        ( in[i+0].z < CLIP_ZNEAR ) ? clip |= FIRST  : ++vertices_inside;
        ( in[i+1].z < CLIP_ZNEAR ) ? clip |= SECOND : ++vertices_inside;
        ( in[i+2].z < CLIP_ZNEAR ) ? clip |= THIRD  : ++vertices_inside;
        
        switch(vertices_inside)
        {
            case 0: /* All Vertices are outside of clip plane */
                 break;
                 
            case 3: /* All Vertices are inside of clip plane */
                 VertexCopy( &in[i+0], &out[v+0] );
                 VertexCopy( &in[i+1], &out[v+1] );
                 VertexCopy( &in[i+2], &out[v+2] );
                 out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;
                 out[v+2].flags = PVR_CMD_VERTEX_EOL;
                 v+=3;
                 
                 break;
                 
            case 1: /* 1 Vertex is inside of clip window, 2 are out */
                 VertexCopy( &in[i+0], &out[v+0] );
                 VertexCopy( &in[i+1], &out[v+1] );
                 VertexCopy( &in[i+2], &out[v+2] );
                 
                 switch(clip)
                 {
                     case FIRST_TWO_OUT:
                          VertexClipZNear( &out[v], &out[v+2] );
                          VertexClipZNear( &out[v+1], &out[v+2] );
                          
                          break;
                          
                     case FIRST_AND_LAST_OUT:
                          VertexClipZNear( &out[v], &out[v+1] );
                          VertexClipZNear( &out[v+2], &out[v+1] );
                          
                          break;
                     
                     case LAST_TWO_OUT:    
                          VertexClipZNear( &out[v+1], &out[v] );
                          VertexClipZNear( &out[v+2], &out[v] );
                          
                          break;       
                 }
                 out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;
                 out[v+2].flags = PVR_CMD_VERTEX_EOL;
                 v+=3;
                                  
                 break;   
                              
            case 2: /* 2 Vertices are inside of clip window, 1 is out */
                 switch(clip)
                 {
                     case FIRST:
                          VertexCopy( &in[i+0], &out[v+0] );
                          VertexCopy( &in[i+1], &out[v+1] );
                          VertexClipZNear( &out[v+0], &out[v+1] );
                          out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;
                          v+=2;
                          
                          VertexCopy( &in[i+0], &out[v+0] );
                          VertexCopy( &in[i+2], &out[v+1] );
                          VertexClipZNear( &out[v+0], &out[v+1] );
                          out[v+0].flags = PVR_CMD_VERTEX_EOL;
                          ++v; 
                                                   
                          VertexCopy( &out[v-2], &out[v+0] );
                          VertexCopy( &out[v-1], &out[v+1] );                          
                          VertexCopy( &in[i+2] , &out[v+2] ); 
                          out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;                     
                          out[v+2].flags = PVR_CMD_VERTEX_EOL;
                          v+=3;
                          
                          break;
                     
                     case SECOND:
                          VertexCopy( &in[i+0], &out[v+0] );
                          VertexCopy( &in[i+1], &out[v+1] );
                          VertexClipZNear( &out[v+1], &out[v+0] );
                          out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;
                          v+=2;

                          VertexCopy( &in[i+2], &out[v+0] );
                          out[v+0].flags = PVR_CMD_VERTEX_EOL;
                          ++v; 

                          VertexCopy( &out[v-2], &out[v+0] );
                          VertexCopy( &out[v-1], &out[v+1] );                          
                          VertexCopy( &in[i+1] , &out[v+2] );                      
                          VertexClipZNear( &out[v+2], &out[v+1] );
                          out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;
                          out[v+2].flags = PVR_CMD_VERTEX_EOL;
                          v+=3;
                                                    
                          break;
                          
                     case THIRD:
                          VertexCopy( &in[i+0], &out[v+0] );
                          VertexCopy( &in[i+1], &out[v+1] );
                          VertexCopy( &in[i+2], &out[v+1] );
                          VertexClipZNear( &out[v+2], &out[v+1] );
                          out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;
                          out[v+2].flags = PVR_CMD_VERTEX_EOL;
                          v+=3;
                          
                          VertexCopy( &out[v-3], &out[v+0] );
                          VertexCopy( &out[v-1], &out[v+1] );
                          out[v+0].flags = out[v+1].flags = PVR_CMD_VERTEX;
                          v+=2; 

                          VertexCopy( &in[i+2], &out[v] );
                          VertexClipZNear( &out[v+0], &out[v-2] );
                          out[v+0].flags = PVR_CMD_VERTEX_EOL;
                          ++v;
                                                    
                          break;
                 }                 
                 break;                            
        }
        vertices_inside = clip = 0;       
    }
    //printf("clip in/out: %i / %i\n", n, v);
    
    return v;
}
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Reading texture from PVR back into SH-4 RAM

Post by PH3NOM »

One last thought on that subject, sometimes it is not appropriate to clip every triangle of a mesh, for example high-poly models that exist within a small volume.

In that case, it is best to define a "bounding box" that defines the volume of that mesh, and cull against the bounding box, rather than clipping every triangle of the mesh.

I use the dot product of the camera->camera-destination vector and the bounding box position to determine if the mesh is behind the camera:

Code: Select all

/* DOT for a 3 float vector = FIPR with W components set to 1 */
#define dot(x1, y1, z1, x2, y2, z2) ({ \
	register float __x __asm__("fr0") = (x1); \
	register float __y __asm__("fr1") = (y1); \
	register float __z __asm__("fr2") = (z1); \
	register float __w __asm__("fr3"); \
	register float __a __asm__("fr4") = (x2); \
	register float __b __asm__("fr5") = (y2); \
	register float __c __asm__("fr6") = (z2); \
	register float __d __asm__("fr7"); \
	__asm__ __volatile__( \
		"fldi1 fr3\n" \
		"fldi1 fr7\n" \
		"fipr	fv4,fv0" \
		: "+f" (__w) \
		: "f" (__x), "f" (__y), "f" (__z), "f" (__w), \
		  "f" (__a), "f" (__b), "f" (__c), "f" (__d) \
		); \
		__w; })

// Camera to Camera Destination ( camera from / to ) vector
vector3f cp = {campos[0]-camdst[0], campos[1]-camdst[1], campos[2]-camdst[2] };
// Dot product of Camera From-To Vector to Vertex Position
float dc = dot( cp[0], cp[1], cp[2], 
                     campos[0]-vpos1[0], campos[1]-vpos1[1],campos[2]-vpos1[2]);
if(dc<0)
    //Vertex "vpos1" is behind camera z plane
else
    // Vertex "vpos1" is in front of camera z plane

User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Thanks guys. Ah .. I should have checked the Parallax documentation more closely as I had assumed that it handled the Z clipping just like KGL. Thanks for the code sample - I had taken this for granted in KGL.
TapamN
DC Developer
DC Developer
Posts: 105
Joined: Sun Oct 04, 2009 11:13 am
Has thanked: 2 times
Been thanked: 90 times

Re: Reading texture from PVR back into SH-4 RAM

Post by TapamN »

I have an old video of bloom on the Dreamcast (which I've never bothered to link to before) with my own modified version of the PVR driver (which is too messy to release at the moment, although I plan to at some point).

One thing that needs to be changed in the vanilla PVR driver for good render-to-texture support is changing how the driver starts renders. In the normal driver (I haven't looked at BlueCrab's changes), it only starts a render on a vblank, so each render-to-texture will wait until vblank and costs a multiple of one frame of time.

One trick to applying fullscreen bilinear render-to-texture results to the main framebuffer on the PVR is having the PVR twiddle the texture. Untwiddled textures, like a render-to-texture result, have half speed bilinear filtering, so there's a big difference in fillrate consumed if you first twiddle the texture. It's possible to have the PVR twiddle the texture by taking advantage of the fact that the process to untwiddle a texture (which the PVR does when drawing from a twiddled texture) can generate the twiddled version of the texture if you repeat it 3 times. With this trick, I was able to get my bloom demo to reach 60 FPS.
User avatar
MisterDave
DCEmu Freak
DCEmu Freak
Posts: 58
Joined: Mon Apr 08, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: Reading texture from PVR back into SH-4 RAM

Post by MisterDave »

Just a quick screenshot of what I have working so far. I'm looking at putting together a small demo of a player walking in and out of dark environments into a brightly lit area fairly soon and make the code public.

Image

TapamN, thanks for the advice on the optimisations. So far the effect runs fairly quick with simple geometry, however, once I start ramping up the number of polys in the scene every millisecond is going to count so optimisation is something to bring in soon :)
Post Reply