1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-01 16:24:12 +01:00

Compare commits

...

8 Commits

Author SHA1 Message Date
WinterSnowfall
2ab24880e7
Merge e2c20a39ef into b8ce414820 2024-11-27 20:40:46 +00:00
WinterSnowfall
e2c20a39ef
[d3d9] Only validate buffer count on non-Ex devices 2024-11-27 22:33:13 +02:00
WinterSnowfall
b8ce414820 [util] Enable deferSurfaceCreation for the Codename Panzer series 2024-11-27 16:51:54 +01:00
WinterSnowfall
db0ed011d3
[d3d9] Fixes for state block specific behavior 2024-11-27 15:00:29 +02:00
WinterSnowfall
fe8cebb125
[d3d9] Adjust device reset failure error codes 2024-11-27 15:00:29 +02:00
WinterSnowfall
79bae3960e
[d3d9] Validate supported formats in D3D9Surface::GetDC 2024-11-27 15:00:29 +02:00
WinterSnowfall
09bb3e773a
[d3d9] Adjust out of bounds clip plane index handling 2024-11-27 15:00:29 +02:00
WinterSnowfall
e5052ba17d
[d3d9] Skip recording MultiplyTransform calls in state blocks 2024-11-27 15:00:19 +02:00
8 changed files with 58 additions and 48 deletions

View File

@ -522,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);
@ -2033,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);
@ -2199,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);
@ -2225,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];
@ -2594,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))
@ -2617,7 +2626,7 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::BeginStateBlock() {
D3D9DeviceLock lock = LockDevice();
if (unlikely(m_recorder != nullptr))
if (unlikely(ShouldRecord()))
return D3DERR_INVALIDCALL;
m_recorder = new D3D9StateBlock(this, D3D9StateBlockType::None);
@ -2629,11 +2638,11 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::EndStateBlock(IDirect3DStateBlock9** ppSB) {
D3D9DeviceLock lock = LockDevice();
InitReturnPtr(ppSB);
if (unlikely(ppSB == nullptr || m_recorder == nullptr))
if (unlikely(ppSB == nullptr || !ShouldRecord()))
return D3DERR_INVALIDCALL;
InitReturnPtr(ppSB);
*ppSB = m_recorder.ref();
if (!m_isD3D8Compatible)
m_losableResourceCounter++;
@ -4634,21 +4643,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,

View File

@ -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;
}
@ -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,

View File

@ -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;
}
}

View File

@ -449,8 +449,8 @@ namespace dxvk {
&& pPresentationParameters->BackBufferCount > 1))
return D3DERR_INVALIDCALL;
// 3 is the highest supported back buffer count.
if (unlikely(pPresentationParameters->BackBufferCount > 3))
// 3 is the highest supported back buffer count for non-Ex devices.
if (unlikely(!m_extended && pPresentationParameters->BackBufferCount > 3))
return D3DERR_INVALIDCALL;
// Valid fullscreen presentation intervals must be known values.

View File

@ -46,6 +46,9 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9StateBlock::Capture() {
if (unlikely(m_parent->ShouldRecord()))
return D3DERR_INVALIDCALL;
if (m_captures.flags.test(D3D9CapturedStateFlag::VertexDecl))
SetVertexDeclaration(m_deviceState->vertexDecl.ptr());
@ -56,13 +59,13 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9StateBlock::Apply() {
m_applying = true;
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;
}
@ -243,15 +246,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;

View File

@ -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);
@ -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();
@ -409,9 +403,7 @@ namespace dxvk {
D3D9CapturableState m_state;
D3D9StateCaptures m_captures;
D3D9DeviceState* m_deviceState;
bool m_applying = false;
D3D9DeviceState* m_deviceState;
};

View File

@ -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;
@ -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());
@ -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))
@ -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);

View File

@ -822,7 +822,8 @@ namespace dxvk {
* Main menu won't render after intros *
* and CPU bound performance */
{ R"(\\(PANZERS|PANZERS_Phase_2)\.exe$)", {{
{ "d3d9.cachedDynamicBuffers", "True" },
{ "d3d9.deferSurfaceCreation", "True" },
{ "d3d9.cachedDynamicBuffers", "True" },
}} },
/* DC Universe Online *
* Freezes after alt tabbing */