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

Update only changed pixels when scaled render target is unlocked

This commit is contained in:
narzoul 2022-05-21 12:11:19 +02:00
parent 0bc2694cce
commit 6463cc84aa
9 changed files with 151 additions and 38 deletions

View File

@ -164,11 +164,12 @@ namespace D3dDdi
HRESULT Device::pfnClear(const D3DDDIARG_CLEAR* data, UINT numRect, const RECT* rect)
{
flushPrimitives();
m_state.flush();
if (data->Flags & D3DCLEAR_TARGET)
{
setRenderTarget(m_state.getAppState().renderTarget);
prepareForGpuWrite();
}
m_state.flush();
if (m_renderTarget && rect)
{

View File

@ -475,6 +475,8 @@ namespace D3dDdi
{
state.setSpriteMode(false);
}
m_device.setRenderTarget(state.getAppState().renderTarget);
m_device.prepareForGpuWrite();
state.flush();
}
@ -531,6 +533,8 @@ namespace D3dDdi
{
state.setSpriteMode(false);
}
m_device.setRenderTarget(state.getAppState().renderTarget);
m_device.prepareForGpuWrite();
state.flush();
}

View File

@ -111,6 +111,7 @@ namespace D3dDdi
, m_fixedData(data)
, m_lockBuffer(nullptr, &heapFree)
, m_lockResource(nullptr, ResourceDeleter(device, device.getOrigVtable().pfnDestroyResource))
, m_lockRefSurface{}
, m_msaaSurface{}
, m_msaaResolvedSurface{}
, m_formatConfig(D3DDDIFMT_UNKNOWN)
@ -184,11 +185,12 @@ namespace D3dDdi
Gdi::Cursor::setMonitorClipRect({});
}
if (m_msaaSurface.surface || m_msaaResolvedSurface.surface)
if (m_msaaSurface.surface || m_msaaResolvedSurface.surface || m_lockRefSurface.surface)
{
auto& repo = SurfaceRepository::get(m_device.getAdapter());
repo.release(m_msaaSurface);
repo.release(m_msaaResolvedSurface);
repo.release(m_lockRefSurface);
}
}
@ -593,6 +595,7 @@ namespace D3dDdi
m_lockData[i].isVidMemUpToDate = true;
m_lockData[i].isMsaaUpToDate = m_msaaSurface.resource;
m_lockData[i].isMsaaResolvedUpToDate = m_msaaResolvedSurface.resource;
m_lockData[i].isRefLocked = false;
}
}
@ -747,6 +750,38 @@ namespace D3dDdi
rect.bottom <= static_cast<LONG>(m_fixedData.pSurfList[subResourceIndex].Height);
}
void Resource::loadFromLockRefResource(UINT subResourceIndex)
{
if (m_lockData[subResourceIndex].isRefLocked)
{
m_lockData[subResourceIndex].isRefLocked = false;
loadVidMemResource(subResourceIndex);
auto srcResource = this;
auto srcIndex = subResourceIndex;
auto& si = m_fixedData.pSurfList[subResourceIndex];
const RECT srcRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
if (!m_fixedData.Flags.Texture)
{
auto& repo = SurfaceRepository::get(m_device.getAdapter());
auto& texture = repo.getTempTexture(si.Width, si.Height, getPixelFormat(m_fixedData.Format));
if (!texture.resource)
{
return;
}
srcResource = texture.resource;
srcIndex = 0;
copySubResourceRegion(*srcResource, 0, srcRect, m_handle, subResourceIndex, srcRect);
}
const RECT dstRect = { 0, 0, static_cast<LONG>(m_msaaResolvedSurface.width),
static_cast<LONG>(m_msaaResolvedSurface.height) };
m_device.getShaderBlitter().lockRefBlt(*m_msaaResolvedSurface.resource, subResourceIndex, dstRect,
*srcResource, srcIndex, srcRect, *m_lockRefSurface.resource);
m_lockData[subResourceIndex].isMsaaResolvedUpToDate = true;
}
}
void Resource::loadMsaaResource(UINT subResourceIndex)
{
if (!m_lockData[subResourceIndex].isMsaaUpToDate)
@ -767,6 +802,7 @@ namespace D3dDdi
void Resource::loadMsaaResolvedResource(UINT subResourceIndex)
{
loadFromLockRefResource(subResourceIndex);
if (!m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
{
if (m_lockData[subResourceIndex].isMsaaUpToDate)
@ -799,20 +835,14 @@ namespace D3dDdi
{
if (m_lockData[subResourceIndex].isMsaaUpToDate || m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
{
if (m_msaaResolvedSurface.resource)
{
loadMsaaResolvedResource(subResourceIndex);
copySubResource(*this, *m_msaaResolvedSurface.resource, subResourceIndex);
}
else
{
copySubResource(*this, *m_msaaSurface.resource, subResourceIndex);
}
loadMsaaResolvedResource(subResourceIndex);
copySubResource(*this, *m_msaaResolvedSurface.resource, subResourceIndex);
}
else
{
copySubResource(*this, m_lockResource.get(), subResourceIndex);
notifyLock(subResourceIndex);
m_lockData[subResourceIndex].isRefLocked = false;
}
m_lockData[subResourceIndex].isVidMemUpToDate = true;
}
@ -883,6 +913,7 @@ namespace D3dDdi
{
if (m_lockResource)
{
loadFromLockRefResource(subResourceIndex);
if (m_lockData[subResourceIndex].isMsaaUpToDate)
{
resource = *m_msaaSurface.resource;
@ -921,6 +952,14 @@ namespace D3dDdi
{
if (m_lockResource)
{
if (m_lockRefSurface.resource &&
(m_lockData[subResourceIndex].isMsaaResolvedUpToDate || m_lockData[subResourceIndex].isMsaaUpToDate))
{
loadVidMemResource(subResourceIndex);
copySubResource(*m_lockRefSurface.resource, m_handle, subResourceIndex);
m_lockData[subResourceIndex].isRefLocked = true;
}
loadSysMemResource(subResourceIndex);
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isSysMemUpToDate = true;
@ -1270,7 +1309,8 @@ 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_fixedData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer ||
!m_fixedData.Flags.ZBuffer && !m_lockResource)
{
return;
}
@ -1297,11 +1337,13 @@ namespace D3dDdi
}
m_lockData[i].isMsaaUpToDate = false;
m_lockData[i].isMsaaResolvedUpToDate = false;
m_lockData[i].isRefLocked = false;
}
}
m_msaaSurface = {};
m_msaaResolvedSurface = {};
m_lockRefSurface = {};
if (D3DDDIMULTISAMPLE_NONE != msaa.first || m_fixedData.Format != formatConfig ||
static_cast<LONG>(m_fixedData.pSurfList[0].Width) != m_scaledSize.cx ||
@ -1344,6 +1386,13 @@ namespace D3dDdi
scaledSize.cx, scaledSize.cy, getPixelFormat(formatConfig),
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
}
if (m_msaaResolvedSurface.resource)
{
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_lockRefSurface,
m_fixedData.pSurfList[0].Width, m_fixedData.pSurfList[0].Height, getPixelFormat(m_fixedData.Format),
DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
}
}
}
}

View File

@ -75,6 +75,7 @@ namespace D3dDdi
bool isVidMemUpToDate;
bool isMsaaUpToDate;
bool isMsaaResolvedUpToDate;
bool isRefLocked;
};
HRESULT bltLock(D3DDDIARG_LOCK& data);
@ -97,6 +98,7 @@ namespace D3dDdi
RECT getRect(UINT subResourceIndex);
SIZE getScaledSize();
bool isValidRect(UINT subResourceIndex, const RECT& rect);
void loadFromLockRefResource(UINT subResourceIndex);
void loadMsaaResource(UINT subResourceIndex);
void loadMsaaResolvedResource(UINT subResourceIndex);
void loadSysMemResource(UINT subResourceIndex);
@ -114,6 +116,7 @@ namespace D3dDdi
std::unique_ptr<void, void(*)(void*)> m_lockBuffer;
std::vector<LockData> m_lockData;
std::unique_ptr<void, ResourceDeleter> m_lockResource;
SurfaceRepository::Surface m_lockRefSurface;
SurfaceRepository::Surface m_msaaSurface;
SurfaceRepository::Surface m_msaaResolvedSurface;
D3DDDIFORMAT m_formatConfig;

View File

@ -9,6 +9,7 @@
#include <Shaders/DrawCursor.h>
#include <Shaders/Gamma.h>
#include <Shaders/GenBilinear.h>
#include <Shaders/LockRef.h>
#include <Shaders/PaletteLookup.h>
#include <Shaders/TextureSampler.h>
@ -38,10 +39,16 @@ namespace D3dDdi
, m_psDrawCursor(createPixelShader(g_psDrawCursor))
, m_psGamma(createPixelShader(g_psGamma))
, m_psGenBilinear(createPixelShader(g_psGenBilinear))
, m_psLockRef(createPixelShader(g_psLockRef))
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup))
, m_psTextureSampler(createPixelShader(g_psTextureSampler))
, m_vertexShaderDecl(createVertexShaderDecl())
, m_vertices{}
{
for (std::size_t i = 0; i < m_vertices.size(); ++i)
{
m_vertices[i].rhw = 1;
}
}
void ShaderBlitter::blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
@ -104,15 +111,11 @@ namespace D3dDdi
state.setTempRenderState({ D3DDDIRS_BLENDFACTOR, blendFactor });
}
setTempTextureStage(0, srcResource, filter, srcColorKey);
setTempTextureStage(0, srcResource, srcRect, filter, srcColorKey);
state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, srgb });
const float srcWidth = static_cast<float>(srcSurface.Width);
const float srcHeight = static_cast<float>(srcSurface.Height);
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, m_vertices.data());
Vertex vertices[4] = {};
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, vertices);
DeviceState::TempStateLock lock(state);
if (srcRgn)
@ -122,12 +125,12 @@ namespace D3dDdi
{
RectF dr = Rect::toRectF(sr);
Rect::transform(dr, srcRect, dstRect);
drawRect(vertices, sr, dr, srcWidth, srcHeight);
drawRect(sr, dr, srcSurface.Width, srcSurface.Height);
}
}
else
{
drawRect(vertices, srcRect, Rect::toRectF(dstRect), srcWidth, srcHeight);
drawRect(srcRect, Rect::toRectF(dstRect), srcSurface.Width, srcSurface.Height);
}
m_device.flushPrimitives();
@ -154,7 +157,10 @@ namespace D3dDdi
const D3DDDIVERTEXELEMENT vertexElements[] = {
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
{ 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }
{ 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
{ 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
{ 0, 40, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 }
};
D3DDDIARG_CREATEVERTEXSHADERDECL data = {};
@ -202,19 +208,21 @@ namespace D3dDdi
data.DstRect = clippedSrcRect;
m_device.getOrigVtable().pfnBlt(m_device, &data);
setTempTextureStage(1, *cur.maskTexture, D3DTEXF_POINT);
setTempTextureStage(2, *cur.colorTexture, D3DTEXF_POINT);
setTempTextureStage(3, *xorTexture, D3DTEXF_POINT);
setTempTextureStage(1, *cur.maskTexture, clippedSrcRect, D3DTEXF_POINT);
setTempTextureStage(2, *cur.colorTexture, clippedSrcRect, D3DTEXF_POINT);
setTempTextureStage(3, *xorTexture, clippedSrcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, 0, clippedSrcRect,
m_psDrawCursor.get(), D3DTEXF_POINT);
}
void ShaderBlitter::drawRect(Vertex(&vertices)[4], const RECT& srcRect, const RectF& dstRect, float srcWidth, float srcHeight)
void ShaderBlitter::drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight)
{
vertices[0] = { dstRect.left - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.top / srcHeight };
vertices[1] = { dstRect.right - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.top / srcHeight };
vertices[2] = { dstRect.left - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.bottom / srcHeight };
vertices[3] = { dstRect.right - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.bottom / srcHeight };
m_vertices[0].xy = { dstRect.left - 0.5f, dstRect.top - 0.5f };
m_vertices[1].xy = { dstRect.right - 0.5f, dstRect.top - 0.5f };
m_vertices[2].xy = { dstRect.left - 0.5f, dstRect.bottom - 0.5f };
m_vertices[3].xy = { dstRect.right - 0.5f, dstRect.bottom - 0.5f };
setTextureCoords(0, srcRect, srcWidth, srcHeight);
D3DDDIARG_DRAWPRIMITIVE dp = {};
dp.PrimitiveType = D3DPT_TRIANGLESTRIP;
@ -257,7 +265,7 @@ namespace D3dDdi
g_isGammaRampInvalidated = false;
}
setTempTextureStage(1, *gammaRampTexture, D3DTEXF_POINT);
setTempTextureStage(1, *gammaRampTexture, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psGamma.get(), D3DTEXF_POINT);
}
@ -295,6 +303,19 @@ namespace D3dDdi
return g_isGammaRampDefault;
}
void ShaderBlitter::lockRefBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
const Resource& lockRefResource)
{
LOG_FUNC("ShaderBlitter::lockRefBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
static_cast<HANDLE>(lockRefResource));
setTempTextureStage(1, lockRefResource, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
m_psLockRef.get(), D3DTEXF_POINT);
}
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, RGBQUAD palette[256])
{
@ -322,7 +343,7 @@ namespace D3dDdi
unlock.hResource = *paletteTexture;
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
setTempTextureStage(1, *paletteTexture, D3DTEXF_POINT);
setTempTextureStage(1, *paletteTexture, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT);
}
@ -344,16 +365,31 @@ namespace D3dDdi
g_isGammaRampInvalidated = !g_isGammaRampDefault;
}
void ShaderBlitter::setTempTextureStage(UINT stage, HANDLE texture, UINT filter, const UINT* srcColorKey)
void ShaderBlitter::setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter,
const UINT* srcColorKey)
{
auto& state = m_device.getState();
state.setTempTexture(stage, texture, srcColorKey);
state.setTempTextureStageState({ stage, D3DDDITSS_TEXCOORDINDEX, stage });
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, D3DTADDRESS_CLAMP });
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, D3DTADDRESS_CLAMP });
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, filter });
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, filter });
state.setTempTextureStageState({ stage, D3DDDITSS_MIPFILTER, D3DTEXF_NONE });
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
auto& si = texture.getFixedDesc().pSurfList[0];
setTextureCoords(stage, rect, si.Width, si.Height);
}
void ShaderBlitter::setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height)
{
const float w = static_cast<float>(width);
const float h = static_cast<float>(height);
m_vertices[0].tc[stage] = { rect.left / w, rect.top / h };
m_vertices[1].tc[stage] = { rect.right / w, rect.top / h };
m_vertices[2].tc[stage] = { rect.left / w, rect.bottom / h };
m_vertices[3].tc[stage] = { rect.right / w, rect.bottom / h };
}
void ShaderBlitter::textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,

View File

@ -1,5 +1,6 @@
#pragma once
#include <array>
#include <memory>
#include <Windows.h>
@ -29,6 +30,9 @@ namespace D3dDdi
const Resource& srcResource, const RECT& srcRect);
void genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, UINT blurPercent);
void lockRefBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
const Resource& lockRefResource);
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, RGBQUAD palette[256]);
void textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
@ -43,12 +47,10 @@ namespace D3dDdi
private:
struct Vertex
{
float x;
float y;
std::array<float, 2> xy;
float z;
float rhw;
float tu;
float tv;
std::array<float, 2> tc[4];
};
void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
@ -64,15 +66,19 @@ namespace D3dDdi
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
void drawRect(Vertex(&vertices)[4], const RECT& srcRect, const RectF& dstRect, float srcWidth, float srcHeight);
void setTempTextureStage(UINT stage, HANDLE texture, UINT filter, const UINT* srcColorKey = nullptr);
void drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight);
void setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter,
const UINT* srcColorKey = nullptr);
void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height);
Device& m_device;
std::unique_ptr<void, ResourceDeleter> m_psDrawCursor;
std::unique_ptr<void, ResourceDeleter> m_psGamma;
std::unique_ptr<void, ResourceDeleter> m_psGenBilinear;
std::unique_ptr<void, ResourceDeleter> m_psLockRef;
std::unique_ptr<void, ResourceDeleter> m_psPaletteLookup;
std::unique_ptr<void, ResourceDeleter> m_psTextureSampler;
std::unique_ptr<void, ResourceDeleter> m_vertexShaderDecl;
std::array<Vertex, 4> m_vertices;
};
}

View File

@ -466,6 +466,7 @@
<FxCompile Include="Shaders\DrawCursor.hlsl" />
<FxCompile Include="Shaders\Gamma.hlsl" />
<FxCompile Include="Shaders\GenBilinear.hlsl" />
<FxCompile Include="Shaders\LockRef.hlsl" />
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
<FxCompile Include="Shaders\TextureSampler.hlsl" />
<FxCompile Include="Shaders\VertexFixup.hlsl">

View File

@ -920,6 +920,9 @@
<FxCompile Include="Shaders\Gamma.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\LockRef.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<Image Include="arrow.bmp">

View File

@ -0,0 +1,10 @@
sampler2D s_texture : register(s0);
sampler2D s_lockRef : register(s1);
float4 main(float2 texCoord : TEXCOORD0, float2 refCoord : TEXCOORD1) : COLOR0
{
float4 texColor = tex2D(s_texture, texCoord);
float4 refColor = tex2D(s_lockRef, refCoord);
clip(all(texColor == refColor) ? -1 : 1);
return texColor;
}