From a29bcef4d7bd6557264dc5bf6621fa88b7ffc961 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 10 Aug 2020 08:34:39 +0200 Subject: [PATCH] custom rendertarget support for d3d9 --- src/d3d/d3d.cpp | 70 ++++++++++++++++----- src/d3d/d3ddevice.cpp | 141 +++++++++++++++++++++++++++++++++++++++--- src/d3d/rwd3dimpl.h | 5 +- 3 files changed, 188 insertions(+), 28 deletions(-) diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index a5e65a6..684878e 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -493,6 +493,7 @@ rasterSetFormat(Raster *raster) #ifdef RW_D3D9 case Raster::ZBUFFER: + // TODO: allow other formats raster->format = findFormatInfoD3D(d3d9Globals.present.AutoDepthStencilFormat)->rwFormat; // can this even happen? just do something... if(raster->format == 0) @@ -586,7 +587,6 @@ static Raster* rasterCreateCamera(Raster *raster) { D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); - raster->flags |= Raster::DONTALLOCATE; raster->originalWidth = raster->width; raster->originalHeight = raster->height; raster->stride = 0; @@ -594,6 +594,8 @@ rasterCreateCamera(Raster *raster) natras->format = d3d9Globals.present.BackBufferFormat; raster->depth = findFormatDepth(natras->format); + + natras->texture = nil; // global default render target return raster; } @@ -601,14 +603,34 @@ static Raster* rasterCreateZbuffer(Raster *raster) { D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); - raster->flags |= Raster::DONTALLOCATE; raster->originalWidth = raster->width; raster->originalHeight = raster->height; raster->stride = 0; raster->pixels = nil; + // TODO: allow other formats natras->format = d3d9Globals.present.AutoDepthStencilFormat; raster->depth = findFormatDepth(natras->format); + + RECT rect; + GetClientRect(d3d9Globals.window, &rect); + // This check is done by RW but it's rather strange... + if(rect.right == raster->width && rect.bottom == raster->height) + natras->texture = d3d9Globals.defaultDepthSurf; + else{ + IDirect3DSurface9 *surf = nil; + d3ddevice->CreateDepthStencilSurface(raster->width, raster->height, (D3DFORMAT)natras->format, + d3d9Globals.present.MultiSampleType, d3d9Globals.present.MultiSampleQuality, + FALSE, &surf, nil); + assert(natras->texture == nil); + natras->texture = surf; + if(natras->texture == nil){ + RWERROR((ERR_NOTEXTURE)); + return nil; + } + } + addVidmemRaster(raster); + return raster; } #endif @@ -620,27 +642,22 @@ rasterCreate(Raster *raster) rasterSetFormat(raster); + if(raster->width == 0 || raster->height == 0){ + raster->flags |= Raster::DONTALLOCATE; + raster->stride = 0; + return raster; + } + if(raster->flags & Raster::DONTALLOCATE) + return raster; + switch(raster->type){ case Raster::NORMAL: case Raster::TEXTURE: - // Dummy to use as subraster - // ^ what did i do there? - if(raster->width == 0 || raster->height == 0){ - raster->flags |= Raster::DONTALLOCATE; - raster->stride = 0; - return raster; - } - - if(raster->flags & Raster::DONTALLOCATE) - return raster; return rasterCreateTexture(raster); #ifdef RW_D3D9 case Raster::CAMERATEXTURE: - if(raster->flags & Raster::DONTALLOCATE) - return raster; return rasterCreateCameraTexture(raster); - case Raster::ZBUFFER: return rasterCreateZbuffer(raster); case Raster::CAMERA: @@ -1007,9 +1024,28 @@ destroyNativeRaster(void *object, int32 offset, int32) Raster *raster = (Raster*)object; D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, offset); #ifdef RW_D3D9 - destroyD3D9Raster(raster); + removeVidmemRaster(raster); + evictD3D9Raster(raster); #endif - destroyTexture(natras->texture); + switch(raster->type){ + case Raster::NORMAL: + case Raster::TEXTURE: + case Raster::CAMERATEXTURE: + destroyTexture(natras->texture); + break; + + case Raster::ZBUFFER: +#ifdef RW_D3D9 + if(raster->flags & Raster::DONTALLOCATE) + break; + if(natras->texture != d3d9Globals.defaultDepthSurf) + ((IDirect3DSurface9*)natras->texture)->Release(); + natras->texture = nil; +#endif + break; + case Raster::CAMERA: + break; + } rwFree(natras->palette); return object; } diff --git a/src/d3d/d3ddevice.cpp b/src/d3d/d3ddevice.cpp index c1f0730..99ff0b5 100644 --- a/src/d3d/d3ddevice.cpp +++ b/src/d3d/d3ddevice.cpp @@ -96,6 +96,7 @@ D3dShaderState d3dShaderState; #define MAXNUMTEXSTATES (D3DTSS_CONSTANT+1) #define MAXNUMSAMPLERSTATES (D3DSAMP_DMAPOFFSET+1) #define MAXNUMSTREAMS (3) +#define MAXNUMRENDERTARGETS (4) static int32 numDirtyStates; static uint32 dirtyStates[MAXNUMSTATES]; @@ -116,6 +117,8 @@ struct D3dDeviceCache { uint32 offset; uint32 stride; } vertexStreams[MAXNUMSTREAMS]; + IDirect3DSurface9 *renderTargets[MAXNUMRENDERTARGETS]; + IDirect3DSurface9 *depthSurface; }; static D3dDeviceCache deviceCache; @@ -198,6 +201,24 @@ getRenderState(uint32 state, uint32 *value) *value = stateCache[state].value; } +void +setRenderTarget(int n, void *surf) +{ + if(surf != deviceCache.renderTargets[n]){ + deviceCache.renderTargets[n] = (IDirect3DSurface9*)surf; + d3ddevice->SetRenderTarget(n, deviceCache.renderTargets[n]); + } +} + +void +setDepthSurface(void *surf) +{ + if(surf != deviceCache.depthSurface){ + deviceCache.depthSurface = (IDirect3DSurface9*)surf; + d3ddevice->SetDepthStencilSurface(deviceCache.depthSurface); + } +} + void setTextureStageState(uint32 stage, uint32 type, uint32 value) { @@ -267,6 +288,7 @@ restoreD3d9Device(void) { int32 i; uint32 s, t; + for(i = 0; i < MAXNUMSTAGES; i++){ Raster *raster = rwStateCache.texstage[i].raster; if(raster){ @@ -300,15 +322,28 @@ restoreD3d9Device(void) } void -destroyD3D9Raster(Raster *raster) +evictD3D9Raster(Raster *raster) { int i; - if(raster->type == Raster::CAMERATEXTURE) - removeVidmemRaster(raster); // Make sure we're not still referencing this raster - for(i = 0; i < MAXNUMSTAGES; i++) - if(rwStateCache.texstage[i].raster == raster) - rwStateCache.texstage[i].raster = nil; + D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + switch(raster->type){ + case Raster::CAMERATEXTURE: + for(i = 0; i < MAXNUMRENDERTARGETS; i++) + if(deviceCache.renderTargets[i] == natras->texture) + setRenderTarget(i, i == 0 ? d3d9Globals.defaultRenderTarget : nil); + // fall through + case Raster::NORMAL: + case Raster::TEXTURE: + for(i = 0; i < MAXNUMSTAGES; i++) + if(rwStateCache.texstage[i].raster == raster) + rwStateCache.texstage[i].raster = nil; + break; + case Raster::ZBUFFER: + if(natras->texture == deviceCache.depthSurface) + setDepthSurface(d3d9Globals.defaultDepthSurf); + break; + } } // RW render state @@ -722,6 +757,35 @@ destroyPixelShader(void *shader) // Camera +static void +setRenderSurfaces(Camera *cam) +{ + Raster *fbuf = cam->frameBuffer; + assert(fbuf); + { + D3dRaster *natras = PLUGINOFFSET(D3dRaster, fbuf, nativeRasterOffset); + assert(fbuf->type == Raster::CAMERA || fbuf->type == Raster::CAMERATEXTURE); + if(natras->texture == nil) + setRenderTarget(0, d3d9Globals.defaultRenderTarget); + else{ + assert(fbuf->type == Raster::CAMERATEXTURE); + IDirect3DSurface9 *surf; + ((IDirect3DTexture9*)natras->texture)->GetSurfaceLevel(0, &surf); + setRenderTarget(0, surf); + surf->Release(); + } + } + + Raster *zbuf = cam->zBuffer; + if(zbuf){ + D3dRaster *natras = PLUGINOFFSET(D3dRaster, zbuf, nativeRasterOffset); + assert(zbuf->type == Raster::ZBUFFER); + setDepthSurface(natras->texture); + }else + setDepthSurface(nil); + +} + static void beginUpdate(Camera *cam) { @@ -749,7 +813,7 @@ beginUpdate(Camera *cam) view[14] = inv.pos.z; view[15] = 1.0f; memcpy(&cam->devView, view, sizeof(RawMatrix)); - d3ddevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view); +// d3ddevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view); // Projection Matrix float32 invwx = 1.0f/cam->viewWindow.x; @@ -783,7 +847,7 @@ beginUpdate(Camera *cam) } proj[14] = -cam->nearPlane*proj[10]; memcpy(&cam->devProj, proj, sizeof(RawMatrix)); - d3ddevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj); +// d3ddevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj); // TODO: figure out where this is really done // setRenderState(D3DRS_FOGSTART, *(uint32*)&cam->fogPlane); @@ -798,6 +862,8 @@ beginUpdate(Camera *cam) d3dShaderState.fogDisable.range = 0.0f; d3dShaderState.fogDisable.disable = 1.0f; + setRenderSurfaces(cam); + D3DVIEWPORT9 vp; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; @@ -852,9 +918,19 @@ releaseVidmemRasters(void) for(vmr = vidmemRasters; vmr; vmr = vmr->next){ raster = vmr->raster; natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); - if(raster->type == Raster::CAMERATEXTURE){ + switch(raster->type){ + case Raster::CAMERATEXTURE: destroyTexture(natras->texture); natras->texture = nil; + break; + + case Raster::ZBUFFER: + // we'll leave the default surface dangling so we can tell the difference + if(natras->texture != d3d9Globals.defaultDepthSurf){ + ((IDirect3DSurface9*)natras->texture)->Release(); + natras->texture = nil; + } + break; } } } @@ -868,7 +944,8 @@ recreateVidmemRasters(void) for(vmr = vidmemRasters; vmr; vmr = vmr->next){ raster = vmr->raster; natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); - if(raster->type == Raster::CAMERATEXTURE){ + switch(raster->type){ + case Raster::CAMERATEXTURE: { int32 levels = Raster::calculateNumLevels(raster->width, raster->height); IDirect3DTexture9 *tex; d3ddevice->CreateTexture(raster->width, raster->height, @@ -878,6 +955,26 @@ recreateVidmemRasters(void) natras->texture = tex; if(natras->texture) d3d9Globals.numTextures++; + break; + } + + case Raster::ZBUFFER: + if(natras->texture){ + RECT rect; + GetClientRect(d3d9Globals.window, &rect); + raster->width = rect.right; + raster->height = rect.bottom; + natras->texture = d3d9Globals.defaultDepthSurf; + natras->format = d3d9Globals.present.AutoDepthStencilFormat; + raster->depth = findFormatDepth(natras->format); + }else{ + IDirect3DSurface9 *surf = nil; + d3ddevice->CreateDepthStencilSurface(raster->width, raster->height, (D3DFORMAT)natras->format, + d3d9Globals.present.MultiSampleType, d3d9Globals.present.MultiSampleQuality, + FALSE, &surf, nil); + natras->texture = surf; + } + break; } } } @@ -991,6 +1088,11 @@ releaseVideoMemory(void) for(i = 0; i < MAXNUMSTREAMS; i++) d3ddevice->SetStreamSource(0, nil, 0, 0); + setRenderTarget(0, d3d9Globals.defaultRenderTarget); + for(i = 1; i < MAXNUMRENDERTARGETS; i++) + setRenderTarget(i, nil); + setDepthSurface(d3d9Globals.defaultDepthSurf); + releaseVidmemRasters(); releaseDynamicVBs(); releaseDynamicIBs(); @@ -999,6 +1101,14 @@ releaseVideoMemory(void) static void restoreVideoMemory(void) { + // Have to get these back before recreating rasters + d3ddevice->GetRenderTarget(0, &d3d9Globals.defaultRenderTarget); + d3d9Globals.defaultRenderTarget->Release(); // refcount increased by Get + deviceCache.renderTargets[0] = d3d9Globals.defaultRenderTarget; + d3ddevice->GetDepthStencilSurface(&d3d9Globals.defaultDepthSurf); + d3d9Globals.defaultDepthSurf->Release(); // refcount increased by Get + deviceCache.depthSurface = d3d9Globals.defaultDepthSurf; + recreateDynamicIBs(); recreateDynamicVBs(); // important that we get all raster back before restoring state @@ -1032,6 +1142,8 @@ clearCamera(Camera *cam, RGBA *col, uint32 mode) restoreVideoMemory(); } + setRenderSurfaces(cam); + d3ddevice->Clear(0, 0, mode, c, 1.0f, 0); } @@ -1131,7 +1243,9 @@ findFormatDepth(uint32 format) case D3DFMT_L8: return 8; case D3DFMT_D16: return 16; + case D3DFMT_D24S8: return 32; case D3DFMT_D24X8: return 32; + case D3DFMT_D24X4S4: return 32; case D3DFMT_D32: return 32; default: return 0; @@ -1324,6 +1438,13 @@ initD3D(void) { int32 s, t; + d3ddevice->GetRenderTarget(0, &d3d9Globals.defaultRenderTarget); + d3d9Globals.defaultRenderTarget->Release(); // refcount increased by Get + deviceCache.renderTargets[0] = d3d9Globals.defaultRenderTarget; + d3ddevice->GetDepthStencilSurface(&d3d9Globals.defaultDepthSurf); + d3d9Globals.defaultDepthSurf->Release(); // refcount increased by Get + deviceCache.depthSurface = d3d9Globals.defaultDepthSurf; + d3d9Globals.numTextures = 0; d3d9Globals.numVertexShaders = 0; d3d9Globals.numPixelShaders = 0; diff --git a/src/d3d/rwd3dimpl.h b/src/d3d/rwd3dimpl.h index adefe8c..caa6fc1 100644 --- a/src/d3d/rwd3dimpl.h +++ b/src/d3d/rwd3dimpl.h @@ -38,6 +38,9 @@ struct D3d9Globals D3DPRESENT_PARAMETERS present; + IDirect3DSurface9 *defaultRenderTarget; + IDirect3DSurface9 *defaultDepthSurf; + int numTextures; int numVertexShaders; int numPixelShaders; @@ -59,7 +62,7 @@ void removeDynamicIB(IDirect3DIndexBuffer9 **buf); int findFormatDepth(uint32 format); -void destroyD3D9Raster(Raster *raster); +void evictD3D9Raster(Raster *raster); #endif