diff --git a/DDrawCompat/Config/Config.cpp b/DDrawCompat/Config/Config.cpp index 248f74d..16c956f 100644 --- a/DDrawCompat/Config/Config.cpp +++ b/DDrawCompat/Config/Config.cpp @@ -8,6 +8,7 @@ namespace Config Settings::DesktopColorDepth desktopColorDepth; Settings::DisplayFilter displayFilter; Settings::DisplayResolution displayResolution; + Settings::RenderColorDepth renderColorDepth; Settings::SupportedResolutions supportedResolutions; Settings::TextureFilter textureFilter; Settings::ThreadPriorityBoost threadPriorityBoost; diff --git a/DDrawCompat/Config/Config.h b/DDrawCompat/Config/Config.h index 41192ab..1b39fe0 100644 --- a/DDrawCompat/Config/Config.h +++ b/DDrawCompat/Config/Config.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ namespace Config extern Settings::DesktopColorDepth desktopColorDepth; extern Settings::DisplayFilter displayFilter; extern Settings::DisplayResolution displayResolution; + extern Settings::RenderColorDepth renderColorDepth; extern Settings::SupportedResolutions supportedResolutions; extern Settings::TextureFilter textureFilter; extern Settings::ThreadPriorityBoost threadPriorityBoost; diff --git a/DDrawCompat/Config/Settings/RenderColorDepth.h b/DDrawCompat/Config/Settings/RenderColorDepth.h new file mode 100644 index 0000000..ebb0b13 --- /dev/null +++ b/DDrawCompat/Config/Settings/RenderColorDepth.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace Config +{ + namespace Settings + { + class RenderColorDepth : public MappedSetting + { + public: + RenderColorDepth() + : MappedSetting("RenderColorDepth", "app", { {"app", 0}, {"16", 16}, {"32", 32} }) + { + } + }; + } +} diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index 09ea596..3cc7a09 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -86,29 +86,11 @@ namespace D3dDdi return it != m_resources.end() ? it->second.get() : nullptr; } - void Device::prepareForBlt(HANDLE resource, UINT subResourceIndex, bool isReadOnly) - { - auto it = m_resources.find(resource); - if (it != m_resources.end()) - { - it->second->prepareForBlt(subResourceIndex, isReadOnly); - } - } - - void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex) - { - auto it = m_resources.find(resource); - if (it != m_resources.end()) - { - it->second->prepareForRendering(subResourceIndex); - } - } - - void Device::prepareForRendering() + void Device::prepareForGpuWrite() { if (m_renderTarget) { - m_renderTarget->prepareForRendering(m_renderTargetSubResourceIndex); + m_renderTarget->prepareForGpuWrite(m_renderTargetSubResourceIndex); } } @@ -152,7 +134,12 @@ namespace D3dDdi { return it->second->blt(*data); } - prepareForBlt(data->hSrcResource, data->SrcSubResourceIndex, true); + + it = m_resources.find(data->hSrcResource); + if (it != m_resources.end()) + { + it->second->prepareForBltSrc(*data); + } return m_origVtable.pfnBlt(m_device, data); } @@ -162,7 +149,7 @@ namespace D3dDdi m_state.flush(); if (data->Flags & D3DCLEAR_TARGET) { - prepareForRendering(); + prepareForGpuWrite(); } return m_origVtable.pfnClear(m_device, data, numRect, rect); } @@ -258,13 +245,11 @@ namespace D3dDdi HRESULT Device::pfnDrawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2* data, UINT /*indicesSize*/, const void* indexBuffer, const UINT* flagBuffer) { - prepareForRendering(); return m_drawPrimitive.drawIndexed(*data, static_cast(indexBuffer), flagBuffer); } HRESULT Device::pfnDrawPrimitive(const D3DDDIARG_DRAWPRIMITIVE* data, const UINT* flagBuffer) { - prepareForRendering(); return m_drawPrimitive.draw(*data, flagBuffer); } @@ -312,16 +297,27 @@ namespace D3dDdi HRESULT Device::pfnPresent(const D3DDDIARG_PRESENT* data) { flushPrimitives(); - prepareForBlt(data->hSrcResource, data->SrcSubResourceIndex, true); - return m_origVtable.pfnPresent(m_device, data); + auto d = *data; + auto resource = getResource(data->hSrcResource); + if (resource) + { + d.hSrcResource = resource->prepareForGpuRead(data->SrcSubResourceIndex); + } + return m_origVtable.pfnPresent(m_device, &d); } HRESULT Device::pfnPresent1(D3DDDIARG_PRESENT1* data) { flushPrimitives(); + std::vector srcResources(data->phSrcResources, data->phSrcResources + data->SrcResources); + data->phSrcResources = srcResources.data(); for (UINT i = 0; i < data->SrcResources; ++i) { - prepareForBlt(data->phSrcResources[i].hResource, data->phSrcResources[i].SubResourceIndex, true); + auto resource = getResource(srcResources[i].hResource); + if (resource) + { + srcResources[i].hResource = resource->prepareForGpuRead(srcResources[i].SubResourceIndex); + } } return m_origVtable.pfnPresent1(m_device, data); } diff --git a/DDrawCompat/D3dDdi/Device.h b/DDrawCompat/D3dDdi/Device.h index 2db86bd..ee8a377 100644 --- a/DDrawCompat/D3dDdi/Device.h +++ b/DDrawCompat/D3dDdi/Device.h @@ -55,9 +55,7 @@ namespace D3dDdi HRESULT createPrivateResource(D3DDDIARG_CREATERESOURCE2& data); void flushPrimitives() { m_drawPrimitive.flushPrimitives(); } - void prepareForBlt(HANDLE resource, UINT subResourceIndex, bool isReadOnly); - void prepareForRendering(HANDLE resource, UINT subResourceIndex); - void prepareForRendering(); + void prepareForGpuWrite(); void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data); void updateConfig(); diff --git a/DDrawCompat/D3dDdi/DeviceState.cpp b/DDrawCompat/D3dDdi/DeviceState.cpp index f241735..73a1c7a 100644 --- a/DDrawCompat/D3dDdi/DeviceState.cpp +++ b/DDrawCompat/D3dDdi/DeviceState.cpp @@ -354,7 +354,6 @@ namespace D3dDdi { m_app.renderTarget = *data; m_changedStates |= CS_RENDER_TARGET; - m_device.setRenderTarget(*data); return S_OK; } @@ -509,6 +508,7 @@ namespace D3dDdi { if (setData(renderTarget, m_current.renderTarget, m_device.getOrigVtable().pfnSetRenderTarget)) { + m_device.setRenderTarget(m_app.renderTarget); LOG_DS << renderTarget; } } diff --git a/DDrawCompat/D3dDdi/DrawPrimitive.cpp b/DDrawCompat/D3dDdi/DrawPrimitive.cpp index 6c912f9..86e735b 100644 --- a/DDrawCompat/D3dDdi/DrawPrimitive.cpp +++ b/DDrawCompat/D3dDdi/DrawPrimitive.cpp @@ -597,6 +597,7 @@ namespace D3dDdi } LOG_DEBUG << "Flushing " << m_batched.primitiveCount << " primitives of type " << m_batched.primitiveType; + m_device.prepareForGpuWrite(); return m_batched.indices.empty() ? flush(flagBuffer) : flushIndexed(flagBuffer); } diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index bd1ab3f..2b3d34d 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -25,7 +25,9 @@ namespace const UINT g_resourceTypeFlags = getResourceTypeFlags().Value; RECT g_presentationRect = {}; RECT g_primaryRect = {}; + D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN; + std::pair g_msaaOverride = {}; RECT calculatePresentationRect() { @@ -106,7 +108,9 @@ namespace D3dDdi , m_fixedData(data) , m_lockBuffer(nullptr, &heapFree) , m_lockResource(nullptr, ResourceDeleter(device, device.getOrigVtable().pfnDestroyResource)) - , m_customSurface{} + , m_msaaSurface{} + , m_msaaResolvedSurface{} + , m_formatConfig(D3DDDIFMT_UNKNOWN) , m_multiSampleConfig{ D3DDDIMULTISAMPLE_NONE, 0 } , m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface()) { @@ -133,6 +137,7 @@ namespace D3dDdi fixResourceData(); m_formatInfo = getFormatInfo(m_fixedData.Format); + m_formatConfig = m_fixedData.Format; HRESULT result = m_device.createPrivateResource(m_fixedData); if (FAILED(result)) @@ -195,31 +200,33 @@ namespace D3dDdi { if (srcResource) { - srcResource->prepareForBlt(data.SrcSubResourceIndex, true); + srcResource->prepareForBltSrc(data); } - HRESULT result = splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect); - notifyLock(data.DstSubResourceIndex); - return result; + return splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect); } - else if (srcResource) + + if (srcResource) { if (srcResource->isOversized()) { - prepareForBlt(data.DstSubResourceIndex, false); - HRESULT result = srcResource->splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect); - srcResource->notifyLock(data.SrcSubResourceIndex); - return result; + if (m_lockResource) + { + loadVidMemResource(data.DstSubResourceIndex); + clearUpToDateFlags(data.DstSubResourceIndex); + m_lockData[data.DstSubResourceIndex].isVidMemUpToDate = true; + } + return srcResource->splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect); } - else if (m_fixedData.Flags.Primary) + + if (m_fixedData.Flags.Primary) { return presentationBlt(data, srcResource); } - else - { - return sysMemPreferredBlt(data, *srcResource); - } + + return sysMemPreferredBlt(data, *srcResource); } - prepareForBlt(data.DstSubResourceIndex, false); + + prepareForBltDst(data); return m_device.getOrigVtable().pfnBlt(m_device, &data); } @@ -227,14 +234,15 @@ namespace D3dDdi { LOG_FUNC("Resource::bltLock", data); + loadSysMemResource(data.SubResourceIndex); + auto& lockData = m_lockData[data.SubResourceIndex]; - if (!lockData.isSysMemUpToDate) - { - copyToSysMem(data.SubResourceIndex); - } - lockData.isVidMemUpToDate &= data.Flags.ReadOnly; - lockData.isCustomUpToDate &= data.Flags.ReadOnly; lockData.qpcLastForcedLock = Time::queryPerformanceCounter(); + if (!data.Flags.ReadOnly) + { + clearUpToDateFlags(data.SubResourceIndex); + lockData.isSysMemUpToDate = true; + } unsigned char* ptr = static_cast(lockData.data); if (data.Flags.AreaValid) @@ -244,18 +252,15 @@ namespace D3dDdi data.pSurfData = ptr; data.Pitch = lockData.pitch; - ++lockData.lockCount; return LOG_RESULT(S_OK); } - HRESULT Resource::bltUnlock(const D3DDDIARG_UNLOCK& data) + void Resource::clearUpToDateFlags(UINT subResourceIndex) { - LOG_FUNC("Resource::bltUnlock", data); - if (0 != m_lockData[data.SubResourceIndex].lockCount) - { - --m_lockData[data.SubResourceIndex].lockCount; - } - return LOG_RESULT(S_OK); + m_lockData[subResourceIndex].isMsaaUpToDate = false; + m_lockData[subResourceIndex].isMsaaResolvedUpToDate = false; + m_lockData[subResourceIndex].isVidMemUpToDate = false; + m_lockData[subResourceIndex].isSysMemUpToDate = false; } void Resource::clipRect(UINT subResourceIndex, RECT& rect) @@ -278,6 +283,24 @@ namespace D3dDdi if (m_lockResource) { auto& lockData = m_lockData[data.SubResourceIndex]; + + if (lockData.isVidMemUpToDate) + { + m_device.getOrigVtable().pfnColorFill(m_device, &data); + } + + if (lockData.isMsaaUpToDate) + { + data.hResource = *m_msaaSurface.resource; + m_device.getOrigVtable().pfnColorFill(m_device, &data); + } + + if (lockData.isMsaaResolvedUpToDate) + { + data.hResource = *m_msaaResolvedSurface.resource; + m_device.getOrigVtable().pfnColorFill(m_device, &data); + } + if (lockData.isSysMemUpToDate) { auto dstBuf = static_cast(lockData.data) + @@ -286,13 +309,11 @@ namespace D3dDdi DDraw::Blitter::colorFill(dstBuf, lockData.pitch, data.DstRect.right - data.DstRect.left, data.DstRect.bottom - data.DstRect.top, m_formatInfo.bytesPerPixel, colorConvert(m_formatInfo, data.Color)); - - m_lockData[data.SubResourceIndex].isVidMemUpToDate = false; - m_lockData[data.SubResourceIndex].isCustomUpToDate = false; - return LOG_RESULT(S_OK); } + + return LOG_RESULT(S_OK); } - prepareForBlt(data.SubResourceIndex, false); + return LOG_RESULT(m_device.getOrigVtable().pfnColorFill(m_device, &data)); } @@ -319,32 +340,6 @@ namespace D3dDdi return LOG_RESULT(result); } - void Resource::copyToSysMem(UINT subResourceIndex) - { - if (!m_lockData[subResourceIndex].isVidMemUpToDate) - { - copySubResource(m_handle, m_customSurface.resource->m_handle, subResourceIndex); - m_lockData[subResourceIndex].isVidMemUpToDate = true; - } - copySubResource(m_lockResource.get(), m_handle, subResourceIndex); - notifyLock(subResourceIndex); - m_lockData[subResourceIndex].isSysMemUpToDate = true; - } - - void Resource::copyToVidMem(UINT subResourceIndex) - { - if (m_lockData[subResourceIndex].isCustomUpToDate) - { - copySubResource(m_handle, m_customSurface.resource->m_handle, subResourceIndex); - } - else - { - copySubResource(m_handle, m_lockResource.get(), subResourceIndex); - notifyLock(subResourceIndex); - } - m_lockData[subResourceIndex].isVidMemUpToDate = true; - } - void Resource::createGdiLockResource() { auto gdiSurfaceDesc(Gdi::VirtualScreen::getSurfaceDesc(DDraw::PrimarySurface::getMonitorRect())); @@ -363,8 +358,8 @@ namespace D3dDdi createSysMemResource({ surfaceInfo }); if (m_lockResource) { - m_lockData[0].isVidMemUpToDate = false; - m_lockData[0].isCustomUpToDate = false; + clearUpToDateFlags(0); + m_lockData[0].isSysMemUpToDate = true; } else { @@ -444,7 +439,8 @@ namespace D3dDdi m_lockData[i].qpcLastForcedLock = qpcLastForcedLock; m_lockData[i].isSysMemUpToDate = true; m_lockData[i].isVidMemUpToDate = true; - m_lockData[i].isCustomUpToDate = m_customSurface.resource; + m_lockData[i].isMsaaUpToDate = m_msaaSurface.resource; + m_lockData[i].isMsaaResolvedUpToDate = m_msaaResolvedSurface.resource; } } @@ -472,9 +468,12 @@ namespace D3dDdi if (D3DDDIFMT_UNKNOWN != g_formatOverride) { m_fixedData.Format = g_formatOverride; - auto msaa = getMultisampleConfig(); - m_fixedData.MultisampleType = msaa.first; - m_fixedData.MultisampleQuality = msaa.second; + } + + if (D3DDDIMULTISAMPLE_NONE != g_msaaOverride.first) + { + m_fixedData.MultisampleType = g_msaaOverride.first; + m_fixedData.MultisampleQuality = g_msaaOverride.second; } const bool isOffScreenPlain = 0 == (m_fixedData.Flags.Value & g_resourceTypeFlags); @@ -499,6 +498,20 @@ namespace D3dDdi return m_lockData.empty() ? nullptr : m_lockData[subResourceIndex].data; } + D3DDDIFORMAT Resource::getFormatConfig() + { + if (m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Primary && D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool && + (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)) + { + switch (Config::renderColorDepth.get()) + { + case 16: return D3DDDIFMT_R5G6B5; + case 32: return D3DDDIFMT_X8R8G8B8; + } + } + return m_fixedData.Format; + } + std::pair Resource::getMultisampleConfig() { if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.Primary || @@ -522,6 +535,77 @@ namespace D3dDdi rect.bottom <= static_cast(m_fixedData.pSurfList[subResourceIndex].Height); } + void Resource::loadMsaaResource(UINT subResourceIndex) + { + if (!m_lockData[subResourceIndex].isMsaaUpToDate) + { + if (m_msaaResolvedSurface.resource) + { + loadMsaaResolvedResource(subResourceIndex); + copySubResource(*m_msaaSurface.resource, *m_msaaResolvedSurface.resource, subResourceIndex); + } + else + { + loadVidMemResource(subResourceIndex); + copySubResource(*m_msaaSurface.resource, m_handle, subResourceIndex); + } + m_lockData[subResourceIndex].isMsaaUpToDate = true; + } + } + + void Resource::loadMsaaResolvedResource(UINT subResourceIndex) + { + if (!m_lockData[subResourceIndex].isMsaaResolvedUpToDate) + { + if (m_lockData[subResourceIndex].isMsaaUpToDate) + { + copySubResource(*m_msaaResolvedSurface.resource, *m_msaaSurface.resource, subResourceIndex); + } + else + { + loadVidMemResource(subResourceIndex); + copySubResource(*m_msaaResolvedSurface.resource, m_handle, subResourceIndex); + } + m_lockData[subResourceIndex].isMsaaResolvedUpToDate = true; + } + } + + void Resource::loadSysMemResource(UINT subResourceIndex) + { + if (!m_lockData[subResourceIndex].isSysMemUpToDate) + { + loadVidMemResource(subResourceIndex); + copySubResource(m_lockResource.get(), m_handle, subResourceIndex); + notifyLock(subResourceIndex); + m_lockData[subResourceIndex].isSysMemUpToDate = true; + } + } + + void Resource::loadVidMemResource(UINT subResourceIndex) + { + if (!m_lockData[subResourceIndex].isVidMemUpToDate) + { + if (m_lockData[subResourceIndex].isMsaaUpToDate || m_lockData[subResourceIndex].isMsaaResolvedUpToDate) + { + if (m_msaaResolvedSurface.resource) + { + loadMsaaResolvedResource(subResourceIndex); + copySubResource(m_handle, *m_msaaResolvedSurface.resource, subResourceIndex); + } + else + { + copySubResource(m_handle, *m_msaaSurface.resource, subResourceIndex); + } + } + else + { + copySubResource(m_handle, m_lockResource.get(), subResourceIndex); + notifyLock(subResourceIndex); + } + m_lockData[subResourceIndex].isVidMemUpToDate = true; + } + } + HRESULT Resource::lock(D3DDDIARG_LOCK& data) { if (isOversized()) @@ -558,69 +642,110 @@ namespace D3dDdi m_device.getOrigVtable().pfnUnlock(m_device, &unlock); } - void Resource::prepareForBlt(UINT subResourceIndex, bool isReadOnly) + void Resource::prepareForBltSrc(const D3DDDIARG_BLT& data) { - if (m_lockResource && 0 == m_lockData[subResourceIndex].lockCount) + if (m_lockResource) { - if (!m_lockData[subResourceIndex].isVidMemUpToDate) - { - copyToVidMem(subResourceIndex); - } - m_lockData[subResourceIndex].isCustomUpToDate &= isReadOnly; - m_lockData[subResourceIndex].isSysMemUpToDate &= isReadOnly; + loadVidMemResource(data.SrcSubResourceIndex); } } - void Resource::prepareForGdiRendering(bool isReadOnly) + void Resource::prepareForBltDst(D3DDDIARG_BLT& data) { - if (!m_lockResource) + if (m_lockResource) { - return; + if (m_lockData[data.DstSubResourceIndex].isMsaaUpToDate) + { + data.hDstResource = *m_msaaSurface.resource; + clearUpToDateFlags(data.DstSubResourceIndex); + m_lockData[data.DstSubResourceIndex].isMsaaUpToDate = true; + } + else if (m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate) + { + data.hDstResource = *m_msaaResolvedSurface.resource; + clearUpToDateFlags(data.DstSubResourceIndex); + m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate = true; + } + else + { + loadVidMemResource(data.DstSubResourceIndex); + clearUpToDateFlags(data.DstSubResourceIndex); + m_lockData[data.DstSubResourceIndex].isVidMemUpToDate = true; + } } - - if (!m_lockData[0].isSysMemUpToDate) - { - copyToSysMem(0); - } - m_lockData[0].isVidMemUpToDate &= isReadOnly; - m_lockData[0].isCustomUpToDate &= isReadOnly; - m_lockData[0].qpcLastForcedLock = Time::queryPerformanceCounter(); } - void Resource::prepareForRendering(UINT subResourceIndex) + void Resource::prepareForCpuRead(UINT subResourceIndex) { - if (m_lockResource && 0 == m_lockData[subResourceIndex].lockCount) + if (m_lockResource) { - if (m_customSurface.resource) + loadSysMemResource(subResourceIndex); + } + } + + void Resource::prepareForCpuWrite(UINT subResourceIndex) + { + if (m_lockResource) + { + loadSysMemResource(subResourceIndex); + clearUpToDateFlags(subResourceIndex); + m_lockData[subResourceIndex].isSysMemUpToDate = true; + } + } + + Resource& Resource::prepareForGpuRead(UINT subResourceIndex) + { + if (m_lockResource) + { + if (m_msaaResolvedSurface.resource) { - if (!m_lockData[subResourceIndex].isCustomUpToDate) - { - if (!m_lockData[subResourceIndex].isVidMemUpToDate) - { - copyToVidMem(subResourceIndex); - } - copySubResource(m_customSurface.resource->m_handle, m_handle, subResourceIndex); - m_lockData[subResourceIndex].isCustomUpToDate = true; - } - m_lockData[subResourceIndex].isVidMemUpToDate = false; + loadMsaaResolvedResource(subResourceIndex); + return *m_msaaResolvedSurface.resource; } - else if (!m_lockData[subResourceIndex].isVidMemUpToDate) + else { - copyToVidMem(subResourceIndex); + loadVidMemResource(subResourceIndex); + } + } + return *this; + } + + void Resource::prepareForGpuWrite(UINT subResourceIndex) + { + if (m_lockResource) + { + if (m_msaaSurface.resource) + { + loadMsaaResource(subResourceIndex); + clearUpToDateFlags(subResourceIndex); + m_lockData[subResourceIndex].isMsaaUpToDate = true; + } + else if (m_msaaResolvedSurface.resource) + { + loadMsaaResolvedResource(subResourceIndex); + clearUpToDateFlags(subResourceIndex); + m_lockData[subResourceIndex].isMsaaResolvedUpToDate = true; + } + else + { + loadVidMemResource(subResourceIndex); + clearUpToDateFlags(subResourceIndex); + m_lockData[subResourceIndex].isVidMemUpToDate = true; } - m_lockData[subResourceIndex].isSysMemUpToDate = false; } } HRESULT Resource::presentationBlt(D3DDDIARG_BLT data, Resource* srcResource) { - if (srcResource->m_lockResource && - srcResource->m_lockData[0].isSysMemUpToDate && - !srcResource->m_fixedData.Flags.RenderTarget) + if (srcResource->m_lockResource) { - srcResource->m_lockData[0].isVidMemUpToDate = false; + if (srcResource->m_lockData[0].isSysMemUpToDate && + !srcResource->m_fixedData.Flags.RenderTarget) + { + srcResource->m_lockData[0].isVidMemUpToDate = false; + } + data.hSrcResource = srcResource->prepareForGpuRead(0); } - srcResource->prepareForBlt(0, true); const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format; @@ -768,6 +893,7 @@ namespace D3dDdi ++tilePos.x; tileRect.left += caps.dwMaxTextureWidth; tileRect.right += caps.dwMaxTextureWidth; + notifyLock(subResourceIndex); } ++tilePos.y; @@ -803,7 +929,7 @@ namespace D3dDdi m_fixedData.Flags.Texture = 0; } - HRESULT Resource::sysMemPreferredBlt(const D3DDDIARG_BLT& data, Resource& srcResource) + HRESULT Resource::sysMemPreferredBlt(D3DDDIARG_BLT& data, Resource& srcResource) { if (m_fixedData.Format == srcResource.m_fixedData.Format && !m_lockData.empty() && @@ -831,17 +957,8 @@ namespace D3dDdi if (isSysMemBltPreferred) { - if (!dstLockData.isSysMemUpToDate) - { - copyToSysMem(data.DstSubResourceIndex); - } - dstLockData.isVidMemUpToDate = false; - dstLockData.isCustomUpToDate = false; - - if (!srcLockData.isSysMemUpToDate) - { - srcResource.copyToSysMem(data.SrcSubResourceIndex); - } + prepareForCpuWrite(data.DstSubResourceIndex); + srcResource.prepareForCpuRead(data.SrcSubResourceIndex); auto dstBuf = static_cast(dstLockData.data) + data.DstRect.top * dstLockData.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel; @@ -866,8 +983,9 @@ namespace D3dDdi } } - prepareForBlt(data.DstSubResourceIndex, false); - srcResource.prepareForBlt(data.SrcSubResourceIndex, true); + srcResource.prepareForBltSrc(data); + prepareForBltDst(data); + HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data); if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) { @@ -908,10 +1026,6 @@ namespace D3dDdi } return splitLock(data, m_device.getOrigVtable().pfnUnlock); } - else if (m_lockResource) - { - return bltUnlock(data); - } return m_device.getOrigVtable().pfnUnlock(m_device, &data); } @@ -924,30 +1038,35 @@ namespace D3dDdi } const auto msaa = getMultisampleConfig(); - if (m_multiSampleConfig == msaa) + const auto formatConfig = getFormatConfig(); + if (m_multiSampleConfig == msaa && m_formatConfig == formatConfig) { return; } m_multiSampleConfig = msaa; + m_formatConfig = formatConfig; - if (m_customSurface.resource && m_fixedData.Flags.RenderTarget) + if (m_fixedData.Flags.RenderTarget && + (m_msaaSurface.resource || m_msaaResolvedSurface.resource)) { for (UINT i = 0; i < m_lockData.size(); ++i) { - if (m_lockData[i].isCustomUpToDate && !m_lockData[i].isVidMemUpToDate) + if (m_lockData[i].isMsaaUpToDate || m_lockData[i].isMsaaResolvedUpToDate) { - copyToVidMem(i); + loadVidMemResource(i); } - m_lockData[i].isCustomUpToDate = false; + m_lockData[i].isMsaaUpToDate = false; + m_lockData[i].isMsaaResolvedUpToDate = false; } } auto& surfaceRepo(SurfaceRepository::get(m_device.getAdapter())); - surfaceRepo.release(m_customSurface); + surfaceRepo.release(m_msaaSurface); + surfaceRepo.release(m_msaaResolvedSurface); - if (D3DDDIMULTISAMPLE_NONE != msaa.first) + if (D3DDDIMULTISAMPLE_NONE != msaa.first || m_fixedData.Format != formatConfig) { - g_formatOverride = m_fixedData.Format; + g_formatOverride = formatConfig; if (m_fixedData.Flags.ZBuffer) { DDPIXELFORMAT pf = {}; @@ -956,13 +1075,25 @@ namespace D3dDdi pf.dwZBufferBitDepth = 16; pf.dwZBitMask = 0xFFFF; - SurfaceRepository::get(m_device.getAdapter()).getSurface(m_customSurface, + g_msaaOverride = msaa; + SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaSurface, m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, pf, DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount); + g_msaaOverride = {}; } else { - SurfaceRepository::get(m_device.getAdapter()).getSurface(m_customSurface, + if (D3DDDIMULTISAMPLE_NONE != msaa.first) + { + g_msaaOverride = msaa; + SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaSurface, + m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, + DDraw::DirectDraw::getRgbPixelFormat(32), + DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY); + g_msaaOverride = {}; + } + + SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface, m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, DDraw::DirectDraw::getRgbPixelFormat(32), DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY); diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index 16de953..942edf2 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -26,7 +26,7 @@ namespace D3dDdi ~Resource(); operator HANDLE() const { return m_handle; } - const Resource* getCustomResource() { return m_customSurface.resource; } + const Resource* getCustomResource() { return m_msaaSurface.resource ? m_msaaSurface.resource : m_msaaResolvedSurface.resource; } const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; } const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; } @@ -34,9 +34,12 @@ namespace D3dDdi HRESULT colorFill(D3DDDIARG_COLORFILL data); void* getLockPtr(UINT subResourceIndex); HRESULT lock(D3DDDIARG_LOCK& data); - void prepareForBlt(UINT subResourceIndex, bool isReadOnly); - void prepareForGdiRendering(bool isReadOnly); - void prepareForRendering(UINT subResourceIndex); + void prepareForBltSrc(const D3DDDIARG_BLT& data); + void prepareForBltDst(D3DDDIARG_BLT& data); + void prepareForCpuRead(UINT subResourceIndex); + void prepareForCpuWrite(UINT subResourceIndex); + Resource& prepareForGpuRead(UINT subResourceIndex); + void prepareForGpuWrite(UINT subResourceIndex); void setAsGdiResource(bool isGdiResource); HRESULT unlock(const D3DDDIARG_UNLOCK& data); void updateConfig(); @@ -63,22 +66,26 @@ namespace D3dDdi long long qpcLastForcedLock; bool isSysMemUpToDate; bool isVidMemUpToDate; - bool isCustomUpToDate; + bool isMsaaUpToDate; + bool isMsaaResolvedUpToDate; }; HRESULT bltLock(D3DDDIARG_LOCK& data); - HRESULT bltUnlock(const D3DDDIARG_UNLOCK& data); + void clearUpToDateFlags(UINT subResourceIndex); void clipRect(UINT subResourceIndex, RECT& rect); HRESULT copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex); - void copyToSysMem(UINT subResourceIndex); - void copyToVidMem(UINT subResourceIndex); void createGdiLockResource(); void createLockResource(); void createSysMemResource(const std::vector& surfaceInfo); void fixResourceData(); + D3DDDIFORMAT getFormatConfig(); std::pair getMultisampleConfig(); bool isOversized() const; bool isValidRect(UINT subResourceIndex, const RECT& rect); + void loadMsaaResource(UINT subResourceIndex); + void loadMsaaResolvedResource(UINT subResourceIndex); + void loadSysMemResource(UINT subResourceIndex); + void loadVidMemResource(UINT subResourceIndex); void notifyLock(UINT subResourceIndex); HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource); HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect); @@ -87,7 +94,7 @@ namespace D3dDdi HRESULT splitLock(Arg& data, HRESULT(APIENTRY *lockFunc)(HANDLE, Arg*)); void splitToTiles(UINT tileWidth, UINT tileHeight); - HRESULT sysMemPreferredBlt(const D3DDDIARG_BLT& data, Resource& srcResource); + HRESULT sysMemPreferredBlt(D3DDDIARG_BLT& data, Resource& srcResource); Device& m_device; HANDLE m_handle; @@ -97,7 +104,9 @@ namespace D3dDdi std::unique_ptr m_lockBuffer; std::vector m_lockData; std::unique_ptr m_lockResource; - SurfaceRepository::Surface m_customSurface; + SurfaceRepository::Surface m_msaaSurface; + SurfaceRepository::Surface m_msaaResolvedSurface; + D3DDDIFORMAT m_formatConfig; std::pair m_multiSampleConfig; bool m_isSurfaceRepoResource; }; diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.cpp b/DDrawCompat/D3dDdi/SurfaceRepository.cpp index 04311c1..7d0cf2f 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.cpp +++ b/DDrawCompat/D3dDdi/SurfaceRepository.cpp @@ -148,8 +148,8 @@ namespace D3dDdi } DeleteObject(iconInfo.hbmMask); - m_cursorMaskTexture.resource->prepareForBlt(0, true); - m_cursorColorTexture.resource->prepareForBlt(0, true); + m_cursorMaskTexture.resource->prepareForGpuRead(0); + m_cursorColorTexture.resource->prepareForGpuRead(0); m_cursorSize.cx = rect.right - rect.left; m_cursorSize.cy = rect.bottom - rect.top; @@ -203,7 +203,7 @@ namespace D3dDdi initFunc(desc); surface.surface->Unlock(surface.surface, nullptr); - surface.resource->prepareForBlt(0, true); + surface.resource->prepareForGpuRead(0); return surface.resource; } diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 1b7d140..3cccc30 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -220,6 +220,7 @@ + @@ -440,4 +441,4 @@ - \ No newline at end of file + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index e1230e9..d12d692 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -501,6 +501,9 @@ Header Files\D3dDdi + + Header Files\Config\Settings + diff --git a/DDrawCompat/Gdi/CompatDc.cpp b/DDrawCompat/Gdi/CompatDc.cpp index be8e34e..25567aa 100644 --- a/DDrawCompat/Gdi/CompatDc.cpp +++ b/DDrawCompat/Gdi/CompatDc.cpp @@ -19,7 +19,14 @@ namespace Gdi auto gdiResource = D3dDdi::Device::getGdiResource(); if (gdiResource) { - gdiResource->prepareForGdiRendering(isReadOnly); + if (isReadOnly) + { + gdiResource->prepareForCpuRead(0); + } + else + { + gdiResource->prepareForCpuWrite(0); + } } } else diff --git a/DDrawCompat/Overlay/ConfigWindow.cpp b/DDrawCompat/Overlay/ConfigWindow.cpp index fb5fce0..9ce3346 100644 --- a/DDrawCompat/Overlay/ConfigWindow.cpp +++ b/DDrawCompat/Overlay/ConfigWindow.cpp @@ -11,6 +11,7 @@ namespace Overlay addControl(Config::alternatePixelCenter); addControl(Config::antialiasing); addControl(Config::displayFilter); + addControl(Config::renderColorDepth); addControl(Config::textureFilter); } diff --git a/DDrawCompat/Overlay/SettingControl.cpp b/DDrawCompat/Overlay/SettingControl.cpp index 86f4cad..e956974 100644 --- a/DDrawCompat/Overlay/SettingControl.cpp +++ b/DDrawCompat/Overlay/SettingControl.cpp @@ -39,6 +39,7 @@ namespace Overlay } if (&Config::antialiasing == &m_setting || + &Config::renderColorDepth == &m_setting || &Config::textureFilter == &m_setting) { D3dDdi::Device::updateAllConfig();