Skip to content

Commit

Permalink
Merge pull request #15723 from hrydgard/d3d9-state-cache-cleanup
Browse files Browse the repository at this point in the history
D3D9 state cache cleanup
  • Loading branch information
hrydgard committed Jul 30, 2022
2 parents ab20315 + 62ded69 commit 512382c
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 169 deletions.
4 changes: 1 addition & 3 deletions Common/GPU/D3D9/D3D9StateCache.cpp
Expand Up @@ -50,9 +50,7 @@ void DirectXState::Restore() {
stencilTest.restore(); count++;
stencilOp.restore(); count++;
stencilFunc.restore(); count++;
stencilMask.restore(); count++;

dither.restore(); count++;
stencilWriteMask.restore(); count++;

texMinFilter.restore(); count++;
texMagFilter.restore(); count++;
Expand Down
102 changes: 6 additions & 96 deletions Common/GPU/D3D9/D3D9StateCache.h
Expand Up @@ -288,66 +288,6 @@ class DirectXState {
}
};

class SavedColorMask {
DWORD mask;
public:
SavedColorMask() {
mask = D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA;
DirectXState::state_count++;
}

inline void set(bool r, bool g, bool b, bool a) {
DWORD newmask = 0;
if (r) {
newmask |= D3DCOLORWRITEENABLE_RED;
}
if (g) {
newmask |= D3DCOLORWRITEENABLE_GREEN;
}
if (b) {
newmask |= D3DCOLORWRITEENABLE_BLUE;
}
if (a) {
newmask |= D3DCOLORWRITEENABLE_ALPHA;
}
if (mask != newmask) {
mask = newmask;
restore();
}
}
void force(bool r, bool g, bool b, bool a) {
DWORD old = mask;
set(r, g, b, a);
mask = old;
}
inline void restore() {
pD3Ddevice->SetRenderState(D3DRS_COLORWRITEENABLE, mask);
}
};


class BoolUnused {
public:
BoolUnused() {
DirectXState::state_count++;
}
inline void set(bool) {
// Nothing.
}
void force(bool) {
// Nothing.
}
inline void restore() {
// Nothing.
}
inline void enable() {
set(true);
}
inline void disable() {
set(false);
}
};

class StateVp {
D3DVIEWPORT9 viewport;
public:
Expand Down Expand Up @@ -404,36 +344,6 @@ class DirectXState {
}
};

class CullMode {
DWORD cull;
public:
CullMode() : cull (D3DCULL_NONE) {
}

inline void set(int wantcull, int cullmode) {
DWORD newcull;
if (!wantcull) {
// disable
newcull = D3DCULL_NONE;
} else {
// add front face ...
newcull = cullmode==0 ? D3DCULL_CW:D3DCULL_CCW;
}
if (cull != newcull) {
cull = newcull;
restore();
}
}
void force(int wantcull, int cullmode) {
DWORD old = cull;
set(wantcull, cullmode);
cull = old;
}
inline void restore() {
pD3Ddevice->SetRenderState(D3DRS_CULLMODE, cull);
}
};

bool initialized;

public:
Expand All @@ -451,9 +361,7 @@ class DirectXState {

BoolState<D3DRS_SCISSORTESTENABLE, false> scissorTest;

BoolUnused dither;

CullMode cullMode;
DxState1<D3DRS_CULLMODE, D3DCULL_NONE> cullMode;
DxState1<D3DRS_SHADEMODE, D3DSHADE_GOURAUD> shadeMode;

BoolState<D3DRS_ZENABLE, false> depthTest;
Expand All @@ -465,16 +373,18 @@ class DirectXState {
DxState1<D3DRS_ZFUNC, D3DCMP_LESSEQUAL> depthFunc;
DxState1<D3DRS_ZWRITEENABLE, TRUE> depthWrite;

SavedColorMask colorMask;
DxState1<D3DRS_COLORWRITEENABLE, 0xF> colorMask;

StateVp viewport;
StateScissor scissorRect;

BoolState<D3DRS_STENCILENABLE, false> stencilTest;

DxState3<D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP> stencilOp;
DxState3<D3DRS_STENCILFUNC, D3DCMP_ALWAYS, D3DRS_STENCILREF, 0, D3DRS_STENCILMASK, 0xFFFFFFFF> stencilFunc;
DxState1<D3DRS_STENCILWRITEMASK, 0xFFFFFFFF> stencilMask;
DxState1<D3DRS_STENCILFUNC, D3DCMP_ALWAYS> stencilFunc;
DxState1<D3DRS_STENCILREF, 0> stencilRef;
DxState1<D3DRS_STENCILWRITEMASK, 0xFFFFFFFF> stencilWriteMask;
DxState1<D3DRS_STENCILMASK, 0xFFFFFFFF> stencilCompareMask;

DxSampler0State1<D3DSAMP_MINFILTER, D3DTEXF_POINT> texMinFilter;
DxSampler0State1<D3DSAMP_MAGFILTER, D3DTEXF_POINT> texMagFilter;
Expand Down
85 changes: 44 additions & 41 deletions Common/GPU/D3D9/thin3d_d3d9.cpp
Expand Up @@ -162,33 +162,35 @@ class D3D9DepthStencilState : public DepthStencilState {
D3DSTENCILOP stencilZFail;
D3DSTENCILOP stencilPass;
D3DCMPFUNC stencilCompareOp;

uint8_t stencilCompareMask;
uint8_t stencilWriteMask;
void Apply(LPDIRECT3DDEVICE9 device) {
device->SetRenderState(D3DRS_ZENABLE, depthTestEnabled);
void Apply(LPDIRECT3DDEVICE9 device, uint8_t stencilRef) {
using namespace DX9;
dxstate.depthTest.set(depthTestEnabled);
if (depthTestEnabled) {
device->SetRenderState(D3DRS_ZWRITEENABLE, depthWriteEnabled);
device->SetRenderState(D3DRS_ZFUNC, depthCompare);
dxstate.depthWrite.set(depthWriteEnabled);
dxstate.depthFunc.set(depthCompare);
}
device->SetRenderState(D3DRS_STENCILENABLE, stencilEnabled);
dxstate.stencilTest.set(stencilEnabled);
if (stencilEnabled) {
device->SetRenderState(D3DRS_STENCILFAIL, stencilFail);
device->SetRenderState(D3DRS_STENCILZFAIL, stencilZFail);
device->SetRenderState(D3DRS_STENCILPASS, stencilPass);
device->SetRenderState(D3DRS_STENCILFUNC, stencilCompareOp);
device->SetRenderState(D3DRS_STENCILMASK, stencilCompareMask);
device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWriteMask);
dxstate.stencilOp.set(stencilFail, stencilZFail, stencilPass);
dxstate.stencilFunc.set(stencilCompareOp);
dxstate.stencilRef.set(stencilRef);
dxstate.stencilCompareMask.set(stencilCompareMask);
dxstate.stencilWriteMask.set(stencilWriteMask);
}
}
};

class D3D9RasterState : public RasterState {
public:
DWORD cullMode;
DWORD cullMode; // D3DCULL_*

void Apply(LPDIRECT3DDEVICE9 device) {
device->SetRenderState(D3DRS_CULLMODE, cullMode);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
using namespace DX9;
dxstate.cullMode.set(cullMode);
dxstate.scissorTest.enable();
}
};

Expand All @@ -197,19 +199,14 @@ class D3D9BlendState : public BlendState {
bool enabled;
D3DBLENDOP eqCol, eqAlpha;
D3DBLEND srcCol, srcAlpha, dstCol, dstAlpha;
uint32_t fixedColor;
uint32_t colorMask;

void Apply(LPDIRECT3DDEVICE9 device) {
device->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)enabled);
device->SetRenderState(D3DRS_BLENDOP, eqCol);
device->SetRenderState(D3DRS_BLENDOPALPHA, eqAlpha);
device->SetRenderState(D3DRS_SRCBLEND, srcCol);
device->SetRenderState(D3DRS_DESTBLEND, dstCol);
device->SetRenderState(D3DRS_SRCBLENDALPHA, srcAlpha);
device->SetRenderState(D3DRS_DESTBLENDALPHA, dstAlpha);
device->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
// device->SetRenderState(, fixedColor);
using namespace DX9;
dxstate.blend.set(enabled);
dxstate.blendFunc.set(srcCol, dstCol, srcAlpha, dstAlpha);
dxstate.blendEquation.set(eqCol, eqAlpha);
dxstate.colorMask.set(colorMask);
}
};

Expand All @@ -219,11 +216,12 @@ class D3D9SamplerState : public SamplerState {
D3DTEXTUREFILTERTYPE magFilt, minFilt, mipFilt;

void Apply(LPDIRECT3DDEVICE9 device, int index) {
device->SetSamplerState(index, D3DSAMP_ADDRESSU, wrapS);
device->SetSamplerState(index, D3DSAMP_ADDRESSV, wrapT);
device->SetSamplerState(index, D3DSAMP_MAGFILTER, magFilt);
device->SetSamplerState(index, D3DSAMP_MINFILTER, minFilt);
device->SetSamplerState(index, D3DSAMP_MIPFILTER, mipFilt);
using namespace DX9;
dxstate.texAddressU.set(wrapS);
dxstate.texAddressV.set(wrapT);
dxstate.texMagFilter.set(magFilt);
dxstate.texMinFilter.set(minFilt);
dxstate.texMipFilter.set(mipFilt);
}
};

Expand Down Expand Up @@ -291,7 +289,7 @@ class D3D9Pipeline : public Pipeline {
AutoRef<D3D9RasterState> raster;
UniformBufferDesc dynamicUniforms;

void Apply(LPDIRECT3DDEVICE9 device);
void Apply(LPDIRECT3DDEVICE9 device, uint8_t stencilRef);
};

class D3D9Texture : public Texture {
Expand Down Expand Up @@ -558,7 +556,9 @@ class D3D9Context : public DrawContext {
void SetScissorRect(int left, int top, int width, int height) override;
void SetViewports(int count, Viewport *viewports) override;
void SetBlendFactor(float color[4]) override;
void SetStencilRef(uint8_t ref) override;
void SetStencilRef(uint8_t ref) override {
stencilRef_ = ref;
}

void Draw(int vertexCount, int offset) override;
void DrawIndexed(int vertexCount, int offset) override;
Expand Down Expand Up @@ -622,6 +622,9 @@ class D3D9Context : public DrawContext {
LPDIRECT3DSURFACE9 deviceRTsurf = 0;
LPDIRECT3DSURFACE9 deviceDSsurf = 0;
bool supportsINTZ = false;

// Dynamic state
uint8_t stencilRef_ = 0;
};

void D3D9Context::InvalidateCachedState() {
Expand Down Expand Up @@ -674,6 +677,8 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
}

shaderLanguageDesc_.Init(HLSL_D3D9);

DX9::dxstate.Restore();
}

D3D9Context::~D3D9Context() {
Expand Down Expand Up @@ -951,31 +956,31 @@ void D3D9Context::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offse
}
}

void D3D9Pipeline::Apply(LPDIRECT3DDEVICE9 device) {
void D3D9Pipeline::Apply(LPDIRECT3DDEVICE9 device, uint8_t stencilRef) {
vshader->Apply(device);
pshader->Apply(device);
blend->Apply(device);
depthStencil->Apply(device);
depthStencil->Apply(device, stencilRef);
raster->Apply(device);
}

void D3D9Context::Draw(int vertexCount, int offset) {
device_->SetStreamSource(0, curVBuffers_[0]->vbuffer_, curVBufferOffsets_[0], curPipeline_->inputLayout->GetStride(0));
curPipeline_->Apply(device_);
curPipeline_->Apply(device_, stencilRef_);
curPipeline_->inputLayout->Apply(device_);
device_->DrawPrimitive(curPipeline_->prim, offset, vertexCount / 3);
}

void D3D9Context::DrawIndexed(int vertexCount, int offset) {
curPipeline_->Apply(device_);
curPipeline_->Apply(device_, stencilRef_);
curPipeline_->inputLayout->Apply(device_);
device_->SetStreamSource(0, curVBuffers_[0]->vbuffer_, curVBufferOffsets_[0], curPipeline_->inputLayout->GetStride(0));
device_->SetIndices(curIBuffer_->ibuffer_);
device_->DrawIndexedPrimitive(curPipeline_->prim, 0, 0, vertexCount, offset, vertexCount / curPipeline_->primDivisor);
}

void D3D9Context::DrawUP(const void *vdata, int vertexCount) {
curPipeline_->Apply(device_);
curPipeline_->Apply(device_, stencilRef_);
curPipeline_->inputLayout->Apply(device_);
device_->DrawPrimitiveUP(curPipeline_->prim, vertexCount / 3, vdata, curPipeline_->inputLayout->GetStride(0));
}
Expand All @@ -998,6 +1003,7 @@ void D3D9Context::SetScissorRect(int left, int top, int width, int height) {
using namespace DX9;

dxstate.scissorRect.set(left, top, left + width, top + height);
dxstate.scissorTest.set(true);
}

void D3D9Context::SetViewports(int count, Viewport *viewports) {
Expand All @@ -1015,11 +1021,8 @@ void D3D9Context::SetBlendFactor(float color[4]) {
uint32_t g = (uint32_t)(color[1] * 255.0f);
uint32_t b = (uint32_t)(color[2] * 255.0f);
uint32_t a = (uint32_t)(color[3] * 255.0f);
device_->SetRenderState(D3DRS_BLENDFACTOR, r | (g << 8) | (b << 16) | (a << 24));
}

void D3D9Context::SetStencilRef(uint8_t ref) {
device_->SetRenderState(D3DRS_STENCILREF, (DWORD)ref);
using namespace DX9;
dxstate.blendColor.set(color);
}

bool D3D9ShaderModule::Compile(LPDIRECT3DDEVICE9 device, const uint8_t *data, size_t size) {
Expand Down
4 changes: 3 additions & 1 deletion GPU/Directx9/DrawEngineDX9.cpp
Expand Up @@ -598,7 +598,9 @@ void DrawEngineDX9::DoFlush() {

if (result.action == SW_DRAW_PRIMITIVES) {
if (result.setStencil) {
dxstate.stencilFunc.set(D3DCMP_ALWAYS, result.stencilValue, 255);
dxstate.stencilFunc.set(D3DCMP_ALWAYS);
dxstate.stencilRef.set(result.stencilValue);
dxstate.stencilCompareMask.set(255);
}

// TODO: Add a post-transform cache here for multi-RECTANGLES only.
Expand Down
6 changes: 3 additions & 3 deletions GPU/Directx9/FramebufferManagerDX9.cpp
Expand Up @@ -200,12 +200,12 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
dxstate.texMipLodBias.set(0.0f);
dxstate.texMaxMipLevel.set(0);
dxstate.blend.disable();
dxstate.cullMode.set(false, false);
dxstate.cullMode.set(D3DCULL_NONE);
dxstate.depthTest.disable();
dxstate.scissorTest.disable();
dxstate.stencilTest.disable();
dxstate.colorMask.set(true, true, true, true);
dxstate.stencilMask.set(0xFF);
dxstate.colorMask.set(0xF);
dxstate.stencilWriteMask.set(0xFF);
HRESULT hr = device_->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coord, 5 * sizeof(float));
if (FAILED(hr)) {
ERROR_LOG_REPORT(G3D, "DrawActiveTexture() failed: %08x", (uint32_t)hr);
Expand Down
4 changes: 2 additions & 2 deletions GPU/Directx9/GPU_DX9.cpp
Expand Up @@ -256,7 +256,7 @@ void GPU_DX9::DeviceRestore() {
void GPU_DX9::InitClear() {
if (!framebufferManager_->UseBufferedRendering()) {
dxstate.depthWrite.set(true);
dxstate.colorMask.set(true, true, true, true);
dxstate.colorMask.set(0xF);
device_->Clear(0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0);
}
}
Expand Down Expand Up @@ -298,7 +298,7 @@ void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for

void GPU_DX9::CopyDisplayToOutput(bool reallyDirty) {
dxstate.depthWrite.set(true);
dxstate.colorMask.set(true, true, true, true);
dxstate.colorMask.set(0xF);

drawEngine_.Flush();

Expand Down

0 comments on commit 512382c

Please sign in to comment.