mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-12 13:54:14 +01:00
[d3d8] Implement SCRATCH pool copies with CopyRects
This commit is contained in:
parent
7482e45534
commit
753c11d144
@ -542,7 +542,6 @@ namespace dxvk {
|
|||||||
if (unlikely(ppSurface == nullptr))
|
if (unlikely(ppSurface == nullptr))
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
// FIXME: Handle D3DPOOL_SCRATCH in CopyRects
|
|
||||||
D3DPOOL pool = isUnsupportedSurfaceFormat(Format) ? D3DPOOL_SCRATCH : D3DPOOL_SYSTEMMEM;
|
D3DPOOL pool = isUnsupportedSurfaceFormat(Format) ? D3DPOOL_SCRATCH : D3DPOOL_SYSTEMMEM;
|
||||||
|
|
||||||
Com<d3d9::IDirect3DSurface9> pSurf = nullptr;
|
Com<d3d9::IDirect3DSurface9> pSurf = nullptr;
|
||||||
@ -646,14 +645,14 @@ namespace dxvk {
|
|||||||
* The following table shows the possible combinations of source
|
* The following table shows the possible combinations of source
|
||||||
* and destination surface pools, and how we handle each of them.
|
* and destination surface pools, and how we handle each of them.
|
||||||
*
|
*
|
||||||
* ┌────────────┬───────────────────────────┬───────────────────────┬───────────────────────┬──────────┐
|
* ┌────────────┬───────────────────────────┬───────────────────────┬───────────────────────┬──────────────────────┐
|
||||||
* │ Src/Dst │ DEFAULT │ MANAGED │ SYSTEMMEM │ SCRATCH │
|
* │ Src/Dst │ DEFAULT │ MANAGED │ SYSTEMMEM │ SCRATCH │
|
||||||
* ├────────────┼───────────────────────────┼───────────────────────┼───────────────────────┼──────────┤
|
* ├────────────┼───────────────────────────┼───────────────────────┼───────────────────────┼──────────────────────┤
|
||||||
* │ DEFAULT │ StretchRect │ GetRenderTargetData │ GetRenderTargetData │ - │
|
* │ DEFAULT │ StretchRect │ GetRenderTargetData │ GetRenderTargetData │ GetRenderTargetData │
|
||||||
* │ MANAGED │ UpdateTextureFromBuffer │ memcpy │ memcpy │ - │
|
* │ MANAGED │ UpdateTextureFromBuffer │ memcpy │ memcpy │ memcpy │
|
||||||
* │ SYSTEMMEM │ UpdateSurface │ memcpy │ memcpy │ - │
|
* │ SYSTEMMEM │ UpdateSurface │ memcpy │ memcpy │ memcpy │
|
||||||
* │ SCRATCH │ - │ - │ - │ - │
|
* │ SCRATCH │ memcpy + UpdateSurface │ memcpy │ memcpy │ memcpy │
|
||||||
* └────────────┴───────────────────────────┴───────────────────────┴───────────────────────┴──────────┘
|
* └────────────┴───────────────────────────┴───────────────────────┴───────────────────────┴──────────────────────┘
|
||||||
*/
|
*/
|
||||||
HRESULT STDMETHODCALLTYPE D3D8Device::CopyRects(
|
HRESULT STDMETHODCALLTYPE D3D8Device::CopyRects(
|
||||||
IDirect3DSurface8* pSourceSurface,
|
IDirect3DSurface8* pSourceSurface,
|
||||||
@ -735,8 +734,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
POINT dstPt = { dstRect.left, dstRect.top };
|
POINT dstPt = { dstRect.left, dstRect.top };
|
||||||
|
|
||||||
auto unhandled = [&] {
|
auto unsupported = [&] {
|
||||||
Logger::warn(str::format("D3D8Device::CopyRects: Unhandled case from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool));
|
Logger::err(str::format("D3D8Device::CopyRects: Unsupported case from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool));
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -782,10 +781,44 @@ namespace dxvk {
|
|||||||
&dstPt
|
&dstPt
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
case d3d9::D3DPOOL_SCRATCH:
|
case d3d9::D3DPOOL_SCRATCH: {
|
||||||
|
// SCRATCH -> DEFAULT: memcpy to a SYSTEMMEM temporary buffer and use UpdateSurface
|
||||||
|
|
||||||
|
// UpdateSurface will not work on surface formats unsupported by D3DPOOL_DEFAULT
|
||||||
|
if (unlikely(isUnsupportedSurfaceFormat(D3DFORMAT(srcDesc.Format)))) {
|
||||||
|
return logError(D3DERR_INVALIDCALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Com<IDirect3DSurface8> pTempImageSurface;
|
||||||
|
// The temporary image surface is guaranteed to end up in SYSTEMMEM for supported formats
|
||||||
|
HRESULT res = CreateImageSurface(
|
||||||
|
srcDesc.Width,
|
||||||
|
srcDesc.Height,
|
||||||
|
D3DFORMAT(srcDesc.Format),
|
||||||
|
&pTempImageSurface
|
||||||
|
);
|
||||||
|
|
||||||
|
if (FAILED(res)) {
|
||||||
|
return logError(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
Com<D3D8Surface> pBlitImage = static_cast<D3D8Surface*>(pTempImageSurface.ptr());
|
||||||
|
// Temporary image surface dimensions are identical, so we can reuse srcDesc/Rect
|
||||||
|
res = copyTextureBuffers(src.ptr(), pBlitImage.ptr(), srcDesc, srcDesc, srcRect, srcRect);
|
||||||
|
|
||||||
|
if (FAILED(res)) {
|
||||||
|
return logError(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return logError(GetD3D9()->UpdateSurface(
|
||||||
|
pBlitImage->GetD3D9(),
|
||||||
|
&srcRect,
|
||||||
|
dst->GetD3D9(),
|
||||||
|
&dstPt
|
||||||
|
));
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
return unsupported();
|
||||||
return unhandled();
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -813,8 +846,9 @@ namespace dxvk {
|
|||||||
return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()));
|
return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()));
|
||||||
}
|
}
|
||||||
case d3d9::D3DPOOL_MANAGED:
|
case d3d9::D3DPOOL_MANAGED:
|
||||||
case d3d9::D3DPOOL_SYSTEMMEM: {
|
case d3d9::D3DPOOL_SYSTEMMEM:
|
||||||
// SYSTEMMEM -> MANAGED: LockRect / memcpy
|
case d3d9::D3DPOOL_SCRATCH: {
|
||||||
|
// MANAGED/SYSMEM/SCRATCH -> MANAGED: LockRect / memcpy
|
||||||
|
|
||||||
if (stretch) {
|
if (stretch) {
|
||||||
return logError(D3DERR_INVALIDCALL);
|
return logError(D3DERR_INVALIDCALL);
|
||||||
@ -822,10 +856,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect));
|
return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect));
|
||||||
}
|
}
|
||||||
case d3d9::D3DPOOL_SCRATCH:
|
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
return unsupported();
|
||||||
return unhandled();
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -857,6 +889,7 @@ namespace dxvk {
|
|||||||
pBlitImage.ptr(),
|
pBlitImage.ptr(),
|
||||||
&dstRect,
|
&dstRect,
|
||||||
d3d9::D3DTEXF_NONE);
|
d3d9::D3DTEXF_NONE);
|
||||||
|
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
return logError(res);
|
return logError(res);
|
||||||
}
|
}
|
||||||
@ -864,29 +897,75 @@ namespace dxvk {
|
|||||||
// Now sync the rendertarget data into main memory.
|
// Now sync the rendertarget data into main memory.
|
||||||
return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()));
|
return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()));
|
||||||
}
|
}
|
||||||
|
// MANAGED/SYSMEM/SCRATCH -> SYSMEM: LockRect / memcpy
|
||||||
// SYSMEM/MANAGED -> SYSMEM: LockRect / memcpy
|
|
||||||
case d3d9::D3DPOOL_MANAGED:
|
case d3d9::D3DPOOL_MANAGED:
|
||||||
case d3d9::D3DPOOL_SYSTEMMEM: {
|
case d3d9::D3DPOOL_SYSTEMMEM:
|
||||||
|
case d3d9::D3DPOOL_SCRATCH: {
|
||||||
if (stretch) {
|
if (stretch) {
|
||||||
return logError(D3DERR_INVALIDCALL);
|
return logError(D3DERR_INVALIDCALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect));
|
return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect));
|
||||||
}
|
}
|
||||||
case d3d9::D3DPOOL_SCRATCH:
|
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
return unsupported();
|
||||||
return unhandled();
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEST: SCRATCH
|
// DEST: SCRATCH
|
||||||
case d3d9::D3DPOOL_SCRATCH:
|
case d3d9::D3DPOOL_SCRATCH: {
|
||||||
|
|
||||||
|
// RT (DEFAULT) -> SCRATCH: Use GetRenderTargetData as fast path if possible
|
||||||
|
if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget == src.ptr())) {
|
||||||
|
|
||||||
|
// GetRenderTargetData works if the formats and sizes match
|
||||||
|
if (srcDesc.MultiSampleType == d3d9::D3DMULTISAMPLE_NONE
|
||||||
|
&& srcDesc.Width == dstDesc.Width
|
||||||
|
&& srcDesc.Height == dstDesc.Height
|
||||||
|
&& srcDesc.Format == dstDesc.Format
|
||||||
|
&& !asymmetric) {
|
||||||
|
return logError(GetD3D9()->GetRenderTargetData(src->GetD3D9(), dst->GetD3D9()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (srcDesc.Pool) {
|
||||||
|
case d3d9::D3DPOOL_DEFAULT: {
|
||||||
|
// Get temporary off-screen surface for stretching.
|
||||||
|
Com<d3d9::IDirect3DSurface9> pBlitImage = dst->GetBlitImage();
|
||||||
|
|
||||||
|
// Stretch the source RT to the temporary surface.
|
||||||
|
HRESULT res = GetD3D9()->StretchRect(
|
||||||
|
src->GetD3D9(),
|
||||||
|
&srcRect,
|
||||||
|
pBlitImage.ptr(),
|
||||||
|
&dstRect,
|
||||||
|
d3d9::D3DTEXF_NONE);
|
||||||
|
|
||||||
|
if (FAILED(res)) {
|
||||||
|
return logError(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now sync the rendertarget data into main memory.
|
||||||
|
return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()));
|
||||||
|
}
|
||||||
|
// MANAGED/SYSMEM/SCRATCH -> SCRATCH: LockRect / memcpy
|
||||||
|
case d3d9::D3DPOOL_MANAGED:
|
||||||
|
case d3d9::D3DPOOL_SYSTEMMEM:
|
||||||
|
case d3d9::D3DPOOL_SCRATCH: {
|
||||||
|
if (stretch) {
|
||||||
|
return logError(D3DERR_INVALIDCALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect));
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
return unsupported();
|
||||||
return unhandled();
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return unsupported();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user