Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[d3d9] Several Wine device test fixes #4492

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
8 changes: 2 additions & 6 deletions src/d3d8/d3d8_d3d9_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,9 @@ namespace dxvk {
& ~D3DPRASTERCAPS_DEPTHBIAS
& ~D3DPRASTERCAPS_MULTISAMPLE_TOGGLE;

pCaps8->SrcBlendCaps &= ~D3DPBLENDCAPS_BLENDFACTOR
& ~D3DPBLENDCAPS_INVSRCCOLOR2
& ~D3DPBLENDCAPS_SRCCOLOR2;
pCaps8->SrcBlendCaps &= ~D3DPBLENDCAPS_BLENDFACTOR;

pCaps8->DestBlendCaps &= ~D3DPBLENDCAPS_BLENDFACTOR
& ~D3DPBLENDCAPS_INVSRCCOLOR2
& ~D3DPBLENDCAPS_SRCCOLOR2;
pCaps8->DestBlendCaps &= ~D3DPBLENDCAPS_BLENDFACTOR;

pCaps8->LineCaps &= ~D3DLINECAPS_ANTIALIAS;

Expand Down
4 changes: 2 additions & 2 deletions src/d3d9/d3d9_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,8 @@ namespace dxvk {
| D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
| D3DPBLENDCAPS_BLENDFACTOR
| D3DPBLENDCAPS_INVSRCCOLOR2
| D3DPBLENDCAPS_SRCCOLOR2;
| D3DPBLENDCAPS_SRCCOLOR2
| D3DPBLENDCAPS_INVSRCCOLOR2;
// Destination Blend Caps
pCaps->DestBlendCaps = pCaps->SrcBlendCaps;
// Alpha Comparison Caps
Expand Down
48 changes: 32 additions & 16 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ namespace dxvk {

// When in SWVP mode, 256 matrices can be used for indexed vertex blending
pCaps->MaxVertexBlendMatrixIndex = m_isSWVP ? 255 : 8;
// Only 9Ex devices advertise D3DPBLENDCAPS_SRCCOLOR2 and D3DPBLENDCAPS_INVSRCCOLOR2
if (!IsExtended()) {
pCaps->SrcBlendCaps &= ~D3DPBLENDCAPS_SRCCOLOR2
& ~D3DPBLENDCAPS_INVSRCCOLOR2;

pCaps->DestBlendCaps &= ~D3DPBLENDCAPS_SRCCOLOR2
& ~D3DPBLENDCAPS_INVSRCCOLOR2;
}

return D3D_OK;
}
Expand Down Expand Up @@ -514,7 +522,8 @@ namespace dxvk {
if (unlikely(m_losableResourceCounter.load() != 0 && !IsExtended() && m_d3d9Options.countLosableResources)) {
Logger::warn(str::format("Device reset failed because device still has alive losable resources: Device not reset. Remaining resources: ", m_losableResourceCounter.load()));
m_deviceLostState = D3D9DeviceLostState::NotReset;
return D3DERR_DEVICELOST;
// D3D8 expects a D3DERR_DEVICELOST error code
return m_isD3D8Compatible ? D3DERR_DEVICELOST : D3DERR_INVALIDCALL;
}

hr = ResetSwapChain(pPresentationParameters, nullptr);
Expand Down Expand Up @@ -2025,10 +2034,6 @@ namespace dxvk {

const uint32_t idx = GetTransformIndex(TransformState);

// D3D8 state blocks ignore capturing calls to MultiplyTransform().
if (unlikely(!m_isD3D8Compatible && ShouldRecord()))
return m_recorder->MultiplyStateTransform(idx, pMatrix);

m_state.transforms[idx] = m_state.transforms[idx] * ConvertMatrix(pMatrix);

m_flags.set(D3D9DeviceFlag::DirtyFFVertexData);
Expand Down Expand Up @@ -2191,9 +2196,13 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetClipPlane(DWORD Index, const float* pPlane) {
D3D9DeviceLock lock = LockDevice();

if (unlikely(Index >= caps::MaxClipPlanes || !pPlane))
if (unlikely(!pPlane))
return D3DERR_INVALIDCALL;

// Higher indexes will be capped to the last valid index
if (unlikely(Index >= caps::MaxClipPlanes))
Index = caps::MaxClipPlanes - 1;

if (unlikely(ShouldRecord()))
return m_recorder->SetClipPlane(Index, pPlane);

Expand All @@ -2217,9 +2226,13 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetClipPlane(DWORD Index, float* pPlane) {
D3D9DeviceLock lock = LockDevice();

if (unlikely(Index >= caps::MaxClipPlanes || !pPlane))
if (unlikely(!pPlane))
return D3DERR_INVALIDCALL;

// Higher indexes will be capped to the last valid index
if (unlikely(Index >= caps::MaxClipPlanes))
Index = caps::MaxClipPlanes - 1;

for (uint32_t i = 0; i < 4; i++)
pPlane[i] = m_state.clipPlanes[Index].coeff[i];

Expand Down Expand Up @@ -2586,6 +2599,10 @@ namespace dxvk {
IDirect3DStateBlock9** ppSB) {
D3D9DeviceLock lock = LockDevice();

// A state block can not be created while another is being recorded.
if (unlikely(ShouldRecord()))
return D3DERR_INVALIDCALL;

InitReturnPtr(ppSB);

if (unlikely(ppSB == nullptr))
Expand All @@ -2609,7 +2626,8 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::BeginStateBlock() {
D3D9DeviceLock lock = LockDevice();

if (unlikely(m_recorder != nullptr))
// Only one state block can be recorded at a given time.
if (unlikely(ShouldRecord()))
return D3DERR_INVALIDCALL;

m_recorder = new D3D9StateBlock(this, D3D9StateBlockType::None);
Expand All @@ -2621,11 +2639,12 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::EndStateBlock(IDirect3DStateBlock9** ppSB) {
D3D9DeviceLock lock = LockDevice();

InitReturnPtr(ppSB);

if (unlikely(ppSB == nullptr || m_recorder == nullptr))
// Recording a state block can't end if recording hasn't been started.
if (unlikely(ppSB == nullptr || !ShouldRecord()))
return D3DERR_INVALIDCALL;

InitReturnPtr(ppSB);

*ppSB = m_recorder.ref();
if (!m_isD3D8Compatible)
m_losableResourceCounter++;
Expand Down Expand Up @@ -4626,21 +4645,18 @@ namespace dxvk {
}


inline bool D3D9DeviceEx::ShouldRecord() {
return m_recorder != nullptr && !m_recorder->IsApplying();
}


D3D9_VK_FORMAT_MAPPING D3D9DeviceEx::LookupFormat(
D3D9Format Format) const {
return m_adapter->GetFormatMapping(Format);
}


const DxvkFormatInfo* D3D9DeviceEx::UnsupportedFormatInfo(
D3D9Format Format) const {
return m_adapter->GetUnsupportedFormatInfo(Format);
}


bool D3D9DeviceEx::WaitForResource(
const DxvkPagedResource& Resource,
uint64_t SequenceNumber,
Expand Down
12 changes: 7 additions & 5 deletions src/d3d9/d3d9_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,13 @@ namespace dxvk {
*/
void RemoveMappedTexture(D3D9CommonTexture* pTexture);

/**
* \brief Returns whether the device is currently recording a StateBlock
*/
bool ShouldRecord() const {
return m_recorder != nullptr;
}

bool IsD3D8Compatible() const {
return m_isD3D8Compatible;
}
Expand Down Expand Up @@ -1160,11 +1167,6 @@ namespace dxvk {
*/
void WaitStagingBuffer();

/**
* \brief Returns whether the device is currently recording a StateBlock
*/
inline bool ShouldRecord();

HRESULT CreateShaderModule(
D3D9CommonShader* pShaderModule,
uint32_t* pLength,
Expand Down
4 changes: 4 additions & 0 deletions src/d3d9/d3d9_device_child.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ namespace dxvk {
}

ULONG STDMETHODCALLTYPE Release() {
// ignore Release calls on objects with 0 refCount
if(unlikely(!this->m_refCount))
return this->m_refCount;

uint32_t refCount = --this->m_refCount;
if (unlikely(!refCount)) {
auto* pDevice = GetDevice();
Expand Down
12 changes: 12 additions & 0 deletions src/d3d9/d3d9_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,16 @@ namespace dxvk {
|| format == D3D9Format::DXT5;
}

// D3D9 documentation says: IDirect3DSurface9::GetDC is valid on the following formats only:
// D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_R8G8B8, and D3DFMT_X8R8G8B8. However,
// the equivalent formats of D3DFMT_A1R5G5B5 and D3DFMT_A8R8G8B8 are also supported.
inline bool IsSurfaceGetDCCompatibleFormat(D3D9Format format) {
return format == D3D9Format::R5G6B5
|| format == D3D9Format::X1R5G5B5
|| format == D3D9Format::A1R5G5B5
|| format == D3D9Format::R8G8B8
|| format == D3D9Format::X8R8G8B8
|| format == D3D9Format::A8R8G8B8;
}

}
17 changes: 14 additions & 3 deletions src/d3d9/d3d9_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,20 @@ namespace dxvk {
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DCAPS9* pCaps) {
if (auto* adapter = GetAdapter(Adapter))
return adapter->GetDeviceCaps(
DeviceType, pCaps);
if (auto* adapter = GetAdapter(Adapter)) {
adapter->GetDeviceCaps(DeviceType, pCaps);

// Only 9Ex interfaces advertise D3DPBLENDCAPS_SRCCOLOR2 and D3DPBLENDCAPS_INVSRCCOLOR2
if (!m_extended) {
pCaps->SrcBlendCaps &= ~D3DPBLENDCAPS_SRCCOLOR2
& ~D3DPBLENDCAPS_INVSRCCOLOR2;

pCaps->DestBlendCaps &= ~D3DPBLENDCAPS_SRCCOLOR2
& ~D3DPBLENDCAPS_INVSRCCOLOR2;
}

return D3D_OK;
}

return D3DERR_INVALIDCALL;
}
Expand Down
18 changes: 7 additions & 11 deletions src/d3d9/d3d9_stateblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ namespace dxvk {


HRESULT STDMETHODCALLTYPE D3D9StateBlock::Capture() {
// A state block can't capture state while another is being recorded.
if (unlikely(m_parent->ShouldRecord()))
return D3DERR_INVALIDCALL;

if (m_captures.flags.test(D3D9CapturedStateFlag::VertexDecl))
SetVertexDeclaration(m_deviceState->vertexDecl.ptr());

Expand All @@ -56,13 +60,14 @@ namespace dxvk {


HRESULT STDMETHODCALLTYPE D3D9StateBlock::Apply() {
m_applying = true;
// A state block can't be applied while another is being recorded.
if (unlikely(m_parent->ShouldRecord()))
return D3DERR_INVALIDCALL;

if (m_captures.flags.test(D3D9CapturedStateFlag::VertexDecl) && m_state.vertexDecl != nullptr)
m_parent->SetVertexDeclaration(m_state.vertexDecl.ptr());

ApplyOrCapture<D3D9StateFunction::Apply, false>();
m_applying = false;

return D3D_OK;
}
Expand Down Expand Up @@ -243,15 +248,6 @@ namespace dxvk {
}


HRESULT D3D9StateBlock::MultiplyStateTransform(uint32_t idx, const D3DMATRIX* pMatrix) {
m_state.transforms[idx] = m_state.transforms[idx] * ConvertMatrix(pMatrix);

m_captures.flags.set(D3D9CapturedStateFlag::Transforms);
m_captures.transforms.set(idx, true);
return D3D_OK;
}


HRESULT D3D9StateBlock::SetViewport(const D3DVIEWPORT9* pViewport) {
m_state.viewport = *pViewport;

Expand Down
10 changes: 1 addition & 9 deletions src/d3d9/d3d9_stateblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ namespace dxvk {
D3D9TextureStageStateTypes Type,
DWORD Value);

HRESULT MultiplyStateTransform(uint32_t idx, const D3DMATRIX* pMatrix);

HRESULT SetViewport(const D3DVIEWPORT9* pViewport);

HRESULT SetScissorRect(const RECT* pRect);
Expand Down Expand Up @@ -390,10 +388,6 @@ namespace dxvk {
HRESULT SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits);
HRESULT SetPixelBoolBitfield (uint32_t idx, uint32_t mask, uint32_t bits);

inline bool IsApplying() {
return m_applying;
}

private:

void CapturePixelRenderStates();
Expand All @@ -409,9 +403,7 @@ namespace dxvk {
D3D9CapturableState m_state;
D3D9StateCaptures m_captures;

D3D9DeviceState* m_deviceState;

bool m_applying = false;
D3D9DeviceState* m_deviceState;

};

Expand Down
11 changes: 7 additions & 4 deletions src/d3d9/d3d9_surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ namespace dxvk {
}

HRESULT STDMETHODCALLTYPE D3D9Surface::QueryInterface(REFIID riid, void** ppvObject) {
if (ppvObject == nullptr)
if (unlikely(ppvObject == nullptr))
return E_POINTER;

*ppvObject = nullptr;
Expand Down Expand Up @@ -101,7 +101,7 @@ namespace dxvk {
}

HRESULT STDMETHODCALLTYPE D3D9Surface::GetDesc(D3DSURFACE_DESC *pDesc) {
if (pDesc == nullptr)
if (unlikely(pDesc == nullptr))
return D3DERR_INVALIDCALL;

auto& desc = *(m_texture->Desc());
Expand Down Expand Up @@ -190,11 +190,14 @@ namespace dxvk {
}

HRESULT STDMETHODCALLTYPE D3D9Surface::GetDC(HDC *phDC) {
if (phDC == nullptr)
if (unlikely(phDC == nullptr))
return D3DERR_INVALIDCALL;

const D3D9_COMMON_TEXTURE_DESC& desc = *m_texture->Desc();

if (unlikely(!IsSurfaceGetDCCompatibleFormat(desc.Format)))
return D3DERR_INVALIDCALL;

D3DLOCKED_RECT lockedRect;
HRESULT hr = LockRect(&lockedRect, nullptr, 0);
if (FAILED(hr))
Expand Down Expand Up @@ -228,7 +231,7 @@ namespace dxvk {
}

HRESULT STDMETHODCALLTYPE D3D9Surface::ReleaseDC(HDC hDC) {
if (m_dcDesc.hDC == nullptr || m_dcDesc.hDC != hDC)
if (unlikely(m_dcDesc.hDC == nullptr || m_dcDesc.hDC != hDC))
return D3DERR_INVALIDCALL;

D3DKMTDestroyDCFromMemory(&m_dcDesc);
Expand Down