implemented some render state caching for d3d

This commit is contained in:
aap 2016-02-27 13:35:20 +01:00
parent 3902ab328e
commit 0c77e505f0
6 changed files with 155 additions and 32 deletions

View File

@ -27,21 +27,19 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
if(inst->material->texture)
setTexture(inst->material->texture);
else
device->SetTexture(0, NULL);
setMaterial(inst->material);
device->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setTexture(0, inst->material->texture);
d3d::setMaterial(inst->material);
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
if(geo->geoflags & Geometry::PRELIT)
device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
device->SetFVF(inst->vertexShader);
device->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride);
device->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer);
uint32 numPrim = inst->primType == D3DPT_TRIANGLESTRIP ? inst->numIndices-2 : inst->numIndices/3;
d3d::flushCache();
device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex,
0, inst->numVertices, 0, numPrim);
inst++;

View File

@ -32,16 +32,14 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
if(inst->material->texture)
setTexture(inst->material->texture);
else
device->SetTexture(0, NULL);
setMaterial(inst->material);
device->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setTexture(0, inst->material->texture);
d3d::setMaterial(inst->material);
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
if(geo->geoflags & Geometry::PRELIT)
device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
d3d::flushCache();
device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex,
0, inst->numVertices,
inst->startIndex, inst->numPrimitives);

View File

@ -11,10 +11,118 @@
namespace rw {
namespace d3d {
#ifdef RW_D3D9
#define MAXNUMSTATES D3DRS_BLENDOPALPHA
#define MAXNUMSTAGES 8
#define MAXNUMTEXSTATES D3DTSS_CONSTANT
#define MAXNUMSAMPLERSTATES D3DSAMP_DMAPOFFSET
static int32 numDirtyStates;
static uint32 dirtyStates[MAXNUMSTATES];
static struct {
uint32 value;
bool32 dirty;
} stateCache[MAXNUMSTATES];
static uint32 d3dStates[MAXNUMSTATES];
static int32 numDirtyTextureStageStates;
static struct {
uint32 stage;
uint32 type;
} dirtyTextureStageStates[MAXNUMTEXSTATES*MAXNUMSTAGES];
static struct {
uint32 value;
bool32 dirty;
} textureStageStateCache[MAXNUMSTATES][MAXNUMSTAGES];
static uint32 d3dTextureStageStates[MAXNUMSTATES][MAXNUMSTAGES];
static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES];
static Raster *d3dRaster[MAXNUMSTAGES];
static D3DMATERIAL9 d3dmaterial;
void
setTexture(Texture *tex)
setRenderState(uint32 state, uint32 value)
{
if(stateCache[state].value != value){
stateCache[state].value = value;
if(!stateCache[state].dirty){
stateCache[state].dirty = 1;
dirtyStates[numDirtyStates++] = state;
}
}
}
void
setTextureStageState(uint32 stage, uint32 type, uint32 value)
{
if(textureStageStateCache[type][stage].value != value){
textureStageStateCache[type][stage].value = value;
if(!textureStageStateCache[type][stage].dirty){
textureStageStateCache[type][stage].dirty = 1;
dirtyTextureStageStates[numDirtyTextureStageStates].stage = stage;
dirtyTextureStageStates[numDirtyTextureStageStates].type = type;
numDirtyTextureStageStates++;
}
}
}
void
flushCache(void)
{
uint32 s, t;
uint32 v;
for(int32 i = 0; i < numDirtyStates; i++){
s = dirtyStates[i];
v = stateCache[s].value;
stateCache[s].dirty = 0;
if(d3dStates[s] != v){
device->SetRenderState((D3DRENDERSTATETYPE)s, v);
d3dStates[s] = v;
}
}
numDirtyStates = 0;
for(int32 i = 0; i < numDirtyTextureStageStates; i++){
s = dirtyTextureStageStates[i].stage;
t = dirtyTextureStageStates[i].type;
v = textureStageStateCache[t][s].value;
textureStageStateCache[t][s].dirty = 0;
if(d3dTextureStageStates[t][s] != v){
device->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v);
d3dTextureStageStates[t][s] = v;
}
}
numDirtyTextureStageStates = 0;
}
void
setSamplerState(uint32 stage, uint32 type, uint32 value)
{
if(d3dSamplerStates[type][stage] != value){
device->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value);
d3dSamplerStates[type][stage] = value;
}
}
void
setRasterStage(uint32 stage, Raster *raster)
{
D3dRaster *d3draster = NULL;
if(raster != d3dRaster[stage]){
d3dRaster[stage] = raster;
if(raster){
d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
device->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture);
}else
device->SetTexture(stage, NULL);
}
}
void
setTexture(uint32 stage, Texture *tex)
{
static DWORD filternomip[] = {
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
@ -25,16 +133,17 @@ setTexture(Texture *tex)
0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
};
D3dRaster *raster = PLUGINOFFSET(D3dRaster, tex->raster, nativeRasterOffset);
if(tex->raster && raster->texture){
device->SetTexture(0, (IDirect3DTexture9*)raster->texture);
device->SetSamplerState(0, D3DSAMP_MAGFILTER, filternomip[tex->filterAddressing & 0xFF]);
device->SetSamplerState(0, D3DSAMP_MINFILTER, filternomip[tex->filterAddressing & 0xFF]);
device->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap[(tex->filterAddressing >> 8) & 0xF]);
device->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap[(tex->filterAddressing >> 12) & 0xF]);
}else
device->SetTexture(0, NULL);
if(tex == NULL){
setRasterStage(stage, NULL);
return;
}
if(tex->raster){
setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->filterAddressing & 0xFF]);
setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->filterAddressing & 0xFF]);
setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[(tex->filterAddressing >> 8) & 0xF]);
setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[(tex->filterAddressing >> 12) & 0xF]);
}
setRasterStage(stage, tex->raster);
}
void
@ -55,7 +164,17 @@ setMaterial(Material *mat)
mat9.Power = 0.0f;
mat9.Emissive = black;
mat9.Specular = black;
if(d3dmaterial.Diffuse.r != mat9.Diffuse.r ||
d3dmaterial.Diffuse.g != mat9.Diffuse.g ||
d3dmaterial.Diffuse.b != mat9.Diffuse.b ||
d3dmaterial.Diffuse.a != mat9.Diffuse.a ||
d3dmaterial.Ambient.r != mat9.Ambient.r ||
d3dmaterial.Ambient.g != mat9.Ambient.g ||
d3dmaterial.Ambient.b != mat9.Ambient.b ||
d3dmaterial.Ambient.a != mat9.Ambient.a){
device->SetMaterial(&mat9);
d3dmaterial = mat9;
}
}
#endif

View File

@ -400,6 +400,7 @@ Geometry::generateTriangles(int8 *adc)
tri->v[1] = m->indices[j+1];
tri->v[2] = m->indices[j+2];
tri->matId = matid;
tri++;
}
adcbits += m->numIndices;
m++;

View File

@ -910,8 +910,10 @@ defaultUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh
v.n[1] = norms[1]/127.0f;
v.n[2] = norms[2]/127.0f;
}
if(mask & 0x100)
if(mask & 0x100){
memcpy(&v.c, colors, 4);
//v.c[3] = 0xFF;
}
if(mask & 0x1000)
memcpy(&v.t, texcoords, 8);
if(mask & 0x2000)

View File

@ -99,7 +99,12 @@ void registerNativeRaster(void);
// Rendering
void setTexture(Texture *tex);
void setRenderState(uint32 state, uint32 value);
void setTextureStageState(uint32 stage, uint32 type, uint32 value);
void flushCache(void);
void setSamplerState(uint32 stage, uint32 type, uint32 value);
void setTexture(uint32 stage, Texture *tex);
void setMaterial(Material *mat);
}