diff --git a/src/d3d8/d3d8_buffer.h b/src/d3d8/d3d8_buffer.h index 0823277e7..be5ca8451 100644 --- a/src/d3d8/d3d8_buffer.h +++ b/src/d3d8/d3d8_buffer.h @@ -18,6 +18,7 @@ namespace dxvk { : D3D8Resource (pDevice, std::move(pBuffer)) , m_pool (Pool) , m_usage (Usage) { + m_options = this->GetParent()->GetOptions(); } HRESULT STDMETHODCALLTYPE Lock( @@ -25,6 +26,13 @@ namespace dxvk { UINT SizeToLock, BYTE** ppbData, DWORD Flags) { + + if (m_options->forceLegacyDiscard && + (Flags & D3DLOCK_DISCARD) && + !((m_usage & D3DUSAGE_DYNAMIC) && + (m_usage & D3DUSAGE_WRITEONLY))) + Flags &= ~D3DLOCK_DISCARD; + return this->GetD3D9()->Lock( OffsetToLock, SizeToLock, @@ -41,8 +49,9 @@ namespace dxvk { } protected: - const D3DPOOL m_pool; - const DWORD m_usage; + const D3D8Options* m_options; + const D3DPOOL m_pool; + const DWORD m_usage; }; diff --git a/src/d3d8/d3d8_device.h b/src/d3d8/d3d8_device.h index 878e84409..51c3fa2dd 100644 --- a/src/d3d8/d3d8_device.h +++ b/src/d3d8/d3d8_device.h @@ -358,6 +358,10 @@ namespace dxvk { public: // Internal Methods // + const D3D8Options* GetOptions() const { + return &m_d3d8Options; + } + inline bool ShouldRecord() { return m_recorder != nullptr; } inline bool ShouldBatch() { return m_batcher != nullptr; } diff --git a/src/d3d8/d3d8_options.h b/src/d3d8/d3d8_options.h index 67bdf3592..2b5047617 100644 --- a/src/d3d8/d3d8_options.h +++ b/src/d3d8/d3d8_options.h @@ -34,11 +34,19 @@ namespace dxvk { /// and above. Most likely ATI/AMD drivers never supported P8 in the first place. bool placeP8InScratch = false; + /// Rayman 3 relies on D3DLOCK_DISCARD being ignored for everything except D3DUSAGE_DYNAMIC + + /// D3DUSAGE_WRITEONLY buffers, however this approach incurs a performance penalty. + /// + /// Some titles might abuse this early D3D8 quirk, however at some point in its history + /// it was brought in line with standard D3D9 behavior. + bool forceLegacyDiscard = false; + D3D8Options() {} D3D8Options(const Config& config) { auto forceVsDeclStr = config.getOption("d3d8.forceVsDecl", ""); batching = config.getOption ("d3d8.batching", batching); placeP8InScratch = config.getOption ("d3d8.placeP8InScratch", placeP8InScratch); + forceLegacyDiscard = config.getOption ("d3d8.forceLegacyDiscard", forceLegacyDiscard); parseVsDecl(forceVsDeclStr); }