1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Emulate unsupported render target formats

Fixes Midtown Madness 2 rendering on NVIDIA. See issue #159.
This commit is contained in:
narzoul 2022-12-23 23:25:05 +01:00
parent b53678bfd4
commit 12c4f87cb6
6 changed files with 66 additions and 15 deletions

View File

@ -266,6 +266,26 @@ namespace D3dDdi
return supportedZBufferBitDepths;
}
bool Adapter::isEmulatedRenderTargetFormat(D3DDDIFORMAT format)
{
const auto& fi = getFormatInfo(format);
if (0 == fi.red.bitCount)
{
return false;
}
const auto& formatOps = getInfo().formatOps;
auto it = formatOps.find(format);
if (it == formatOps.end() || (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET))
{
return false;
}
auto replacementFormat = 0 != fi.alpha.bitCount ? D3DDDIFMT_A8R8G8B8 : D3DDDIFMT_X8R8G8B8;
it = formatOps.find(replacementFormat);
return it != formatOps.end() && (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET);
}
HRESULT Adapter::pfnCloseAdapter()
{
auto adapter = m_adapter;
@ -325,10 +345,16 @@ namespace D3dDdi
auto formatOp = static_cast<FORMATOP*>(pData->pData);
for (UINT i = 0; i < count; ++i)
{
if (isEmulatedRenderTargetFormat(formatOp[i].Format))
{
formatOp[i].Operations |= FORMATOP_OFFSCREEN_RENDERTARGET;
}
if (D3DDDIFMT_P8 == formatOp[i].Format && Config::palettizedTextures.get())
{
formatOp[i].Operations |= FORMATOP_TEXTURE | FORMATOP_CUBETEXTURE;
}
if (D3DDDIFMT_D24X4S4 == formatOp[i].Format || D3DDDIFMT_X4S4D24 == formatOp[i].Format)
{
// If these formats are reported as depth buffers, then EnumZBufferFormats returns only D16

View File

@ -40,6 +40,7 @@ namespace D3dDdi
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
SIZE getScaledSize(Int2 size) const;
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format);
HRESULT pfnCloseAdapter();
HRESULT pfnCreateDevice(D3DDDIARG_CREATEDEVICE* pCreateData);

View File

@ -587,7 +587,7 @@ namespace D3dDdi
void DeviceState::prepareTextures()
{
for (UINT stage = 0; stage < m_app.textures.size(); ++stage)
for (UINT stage = 0; stage < getVertexDecl().textureStageCount; ++stage)
{
auto resource = getTextureResource(stage);
if (resource)
@ -1045,7 +1045,13 @@ namespace D3dDdi
{
for (UINT stage = 0; stage <= m_maxChangedTextureStage; ++stage)
{
if (setTexture(stage, m_app.textures[stage]) ||
auto resource = getTextureResource(stage);
if (resource)
{
resource = &resource->prepareForGpuRead(0);
}
if (setTexture(stage, resource ? *resource : m_app.textures[stage]) ||
m_changedTextureStageStates[stage].test(D3DDDITSS_DISABLETEXTURECOLORKEY) ||
m_changedTextureStageStates[stage].test(D3DDDITSS_TEXTURECOLORKEYVAL))
{

View File

@ -35,6 +35,7 @@ namespace
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
RECT g_presentationRect = {};
bool g_enableConfig = true;
D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN;
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> g_msaaOverride = {};
@ -128,7 +129,7 @@ namespace D3dDdi
, m_paletteHandle(0)
, m_paletteColorKeyIndex(-1)
, m_isOversized(false)
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface())
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface() || !g_enableConfig)
, m_isClampable(true)
, m_isPrimary(false)
, m_isPalettizedTextureUpToDate(false)
@ -404,7 +405,7 @@ namespace D3dDdi
if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
(m_fixedData.Flags.ZBuffer && &dstRes == m_msaaSurface.resource && m_nullSurface.resource ||
m_fixedData.Flags.RenderTarget ||
dstRes.m_fixedData.Flags.RenderTarget ||
!m_fixedData.Flags.ZBuffer && (
data.Flags.SrcColorKey ||
data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown ||
@ -583,10 +584,12 @@ namespace D3dDdi
D3DDDI_RESOURCEFLAGS flags = {};
flags.Value = g_resourceTypeFlags;
flags.RenderTarget = 0;
flags.Texture = 0;
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool ||
m_isSurfaceRepoResource ||
0 == m_formatInfo.bytesPerPixel ||
0 != (m_fixedData.Flags.Value & flags.Value))
0 != (m_fixedData.Flags.Value & flags.Value) ||
m_fixedData.Flags.Texture && !m_origData.Flags.RenderTarget)
{
return;
}
@ -683,6 +686,11 @@ namespace D3dDdi
}
}
void Resource::enableConfig(bool enable)
{
g_enableConfig = enable;
}
void Resource::fixResourceData()
{
if (m_fixedData.Flags.MatchGdiPrimary)
@ -698,8 +706,7 @@ namespace D3dDdi
}
m_fixedData.Format = D3DDDIFMT_X8R8G8B8;
}
if (D3DDDIFMT_UNKNOWN != g_formatOverride)
else if (D3DDDIFMT_UNKNOWN != g_formatOverride)
{
m_fixedData.Format = g_formatOverride;
if (FOURCC_INTZ == g_formatOverride)
@ -707,6 +714,10 @@ namespace D3dDdi
m_fixedData.Flags.Texture = 1;
}
}
else if (m_fixedData.Flags.RenderTarget && m_device.getAdapter().isEmulatedRenderTargetFormat(m_fixedData.Format))
{
m_fixedData.Flags.RenderTarget = 0;
}
if (D3DDDIMULTISAMPLE_NONE != g_msaaOverride.first)
{
@ -736,6 +747,11 @@ namespace D3dDdi
D3DDDIFORMAT Resource::getFormatConfig()
{
if (m_origData.Flags.RenderTarget && !m_fixedData.Flags.RenderTarget)
{
return 0 != m_formatInfo.alpha.bitCount ? D3DDDIFMT_A8R8G8B8 : D3DDDIFMT_X8R8G8B8;
}
if (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)
{
switch (Config::renderColorDepth.get())
@ -775,8 +791,7 @@ namespace D3dDdi
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Resource::getMultisampleConfig()
{
if (!m_fixedData.Flags.Texture &&
(!m_isPrimary || m_fixedData.Flags.RenderTarget))
if (!m_isPrimary || m_origData.Flags.RenderTarget)
{
return m_device.getAdapter().getMultisampleConfig(m_fixedData.Format);
}
@ -803,7 +818,7 @@ namespace D3dDdi
SIZE Resource::getScaledSize()
{
SIZE size = { static_cast<LONG>(m_fixedData.pSurfList[0].Width), static_cast<LONG>(m_fixedData.pSurfList[0].Height) };
if (!m_fixedData.Flags.Texture)
if (m_origData.Flags.RenderTarget || m_fixedData.Flags.ZBuffer)
{
return m_device.getAdapter().getScaledSize(size);
}
@ -951,7 +966,7 @@ namespace D3dDdi
if (m_lockData[subResourceIndex].isMsaaUpToDate || m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
{
loadMsaaResolvedResource(subResourceIndex);
if (!m_fixedData.Flags.RenderTarget ||
if (!m_origData.Flags.RenderTarget ||
Config::Settings::ResolutionScaleFilter::POINT == Config::resolutionScaleFilter.get())
{
const bool isScaled = static_cast<LONG>(m_fixedData.pSurfList[0].Width) != m_scaledSize.cx ||
@ -1199,7 +1214,7 @@ namespace D3dDdi
if (srcResource->m_lockResource)
{
if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
!srcResource->m_fixedData.Flags.RenderTarget)
!srcResource->m_origData.Flags.RenderTarget)
{
srcResource->m_lockData[data.SrcSubResourceIndex].isVidMemUpToDate = false;
srcResource->m_lockData[data.SrcSubResourceIndex].isMsaaResolvedUpToDate = false;
@ -1515,7 +1530,7 @@ namespace D3dDdi
}
}
if (!m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer)
if (!dstResource.m_fixedData.Flags.RenderTarget && !dstResource.m_fixedData.Flags.ZBuffer)
{
LONG width = data.DstRect.right - data.DstRect.left;
LONG height = data.DstRect.bottom - data.DstRect.top;
@ -1563,7 +1578,7 @@ namespace D3dDdi
data.Flags.Linear ? D3DTEXF_LINEAR : D3DTEXF_POINT, data.Flags.SrcColorKey ? &ck : nullptr);
}
if (!m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer)
if (!dstResource.m_fixedData.Flags.RenderTarget && !dstResource.m_fixedData.Flags.ZBuffer)
{
HRESULT result = copySubResourceRegion(data.hDstResource, data.DstSubResourceIndex, data.DstRect,
*dstRes, dstIndex, dstRect);
@ -1617,7 +1632,7 @@ namespace D3dDdi
{
if (m_isSurfaceRepoResource || D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool || D3DDDIFMT_P8 == m_fixedData.Format ||
m_fixedData.Flags.MatchGdiPrimary ||
!m_isPrimary && !m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer ||
!m_isPrimary && !m_origData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer ||
!m_fixedData.Flags.ZBuffer && !m_lockResource)
{
return;

View File

@ -60,6 +60,7 @@ namespace D3dDdi
void updateConfig();
void updatePalettizedTexture(UINT stage);
static void enableConfig(bool enable);
static void setFormatOverride(D3DDDIFORMAT format);
private:

View File

@ -38,7 +38,9 @@ namespace DDraw
auto data = privateData.get();
data->m_palettizedSurface = palettizedSurface;
D3dDdi::Resource::enableConfig(false);
result = Surface::create(dd, desc, surface, std::move(privateData));
D3dDdi::Resource::enableConfig(true);
if (FAILED(result))
{
return LOG_RESULT(result);