From 0c77e505f0cc38ee684e56b2ddd7b6a511807a55 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 27 Feb 2016 13:35:20 +0100 Subject: [PATCH] implemented some render state caching for d3d --- src/d3d8render.cpp | 16 +++-- src/d3d9render.cpp | 16 +++-- src/d3ddriver.cpp | 143 +++++++++++++++++++++++++++++++++++++++++---- src/geometry.cpp | 1 + src/ps2.cpp | 4 +- src/rwd3d.h | 7 ++- 6 files changed, 155 insertions(+), 32 deletions(-) diff --git a/src/d3d8render.cpp b/src/d3d8render.cpp index 153d150..3f566e8 100644 --- a/src/d3d8render.cpp +++ b/src/d3d8render.cpp @@ -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++; diff --git a/src/d3d9render.cpp b/src/d3d9render.cpp index f2e0ea1..aa8be7d 100644 --- a/src/d3d9render.cpp +++ b/src/d3d9render.cpp @@ -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); diff --git a/src/d3ddriver.cpp b/src/d3ddriver.cpp index 12b2e0a..a0382fb 100644 --- a/src/d3ddriver.cpp +++ b/src/d3ddriver.cpp @@ -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; - device->SetMaterial(&mat9); + 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 diff --git a/src/geometry.cpp b/src/geometry.cpp index 25c3b1e..9a7428b 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -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++; diff --git a/src/ps2.cpp b/src/ps2.cpp index 288f2a3..fa2de18 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -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) diff --git a/src/rwd3d.h b/src/rwd3d.h index ad18b3b..d2d307e 100644 --- a/src/rwd3d.h +++ b/src/rwd3d.h @@ -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); }