Latte: Simplify and fix texture copy

This commit is contained in:
Exzap 2023-11-20 22:18:17 +01:00
parent f6bb666abf
commit 9398c0ca6b
2 changed files with 19 additions and 25 deletions

View File

@ -46,9 +46,7 @@ void LatteSurfaceCopy_copySurfaceNew(MPTR srcPhysAddr, MPTR srcMipAddr, uint32 s
// mark source and destination texture as still in use // mark source and destination texture as still in use
LatteTC_MarkTextureStillInUse(destinationTexture); LatteTC_MarkTextureStillInUse(destinationTexture);
LatteTC_MarkTextureStillInUse(sourceTexture); LatteTC_MarkTextureStillInUse(sourceTexture);
// determine GL slice indices
sint32 realSrcSlice = srcSlice; sint32 realSrcSlice = srcSlice;
sint32 realDstSlice = dstSlice;
if (LatteTexture_doesEffectiveRescaleRatioMatch(sourceTexture, sourceView->firstMip, destinationTexture, destinationView->firstMip)) if (LatteTexture_doesEffectiveRescaleRatioMatch(sourceTexture, sourceView->firstMip, destinationTexture, destinationView->firstMip))
{ {
// adjust copy size // adjust copy size
@ -62,29 +60,11 @@ void LatteSurfaceCopy_copySurfaceNew(MPTR srcPhysAddr, MPTR srcMipAddr, uint32 s
LatteTexture_scaleToEffectiveSize(sourceTexture, &effectiveCopyWidth, &effectiveCopyHeight, 0); LatteTexture_scaleToEffectiveSize(sourceTexture, &effectiveCopyWidth, &effectiveCopyHeight, 0);
// copy slice // copy slice
if (sourceView->baseTexture->isDepth != destinationView->baseTexture->isDepth) if (sourceView->baseTexture->isDepth != destinationView->baseTexture->isDepth)
{
g_renderer->surfaceCopy_copySurfaceWithFormatConversion(sourceTexture, sourceView->firstMip, sourceView->firstSlice, destinationTexture, destinationView->firstMip, destinationView->firstSlice, copyWidth, copyHeight); g_renderer->surfaceCopy_copySurfaceWithFormatConversion(sourceTexture, sourceView->firstMip, sourceView->firstSlice, destinationTexture, destinationView->firstMip, destinationView->firstSlice, copyWidth, copyHeight);
uint64 eventCounter = LatteTexture_getNextUpdateEventCounter();
LatteTexture_MarkDynamicTextureAsChanged(destinationTexture->baseView, destinationView->firstSlice, destinationView->firstMip, eventCounter);
}
else else
{ g_renderer->texture_copyImageSubData(sourceTexture, sourceView->firstMip, 0, 0, realSrcSlice, destinationTexture, destinationView->firstMip, 0, 0, destinationView->firstSlice, effectiveCopyWidth, effectiveCopyHeight, 1);
// calculate mip levels relative to texture base const uint64 eventCounter = LatteTexture_getNextUpdateEventCounter();
sint32 texDstMipLevel; LatteTexture_MarkDynamicTextureAsChanged(destinationTexture->baseView, destinationView->firstSlice, destinationView->firstMip, eventCounter);
if (destinationTexture->physAddress == dstPhysAddr)
{
texDstMipLevel = dstLevel;
}
else
{
// todo - handle mip addresses properly
texDstMipLevel = dstLevel - destinationView->firstMip;
}
g_renderer->texture_copyImageSubData(sourceTexture, sourceView->firstMip, 0, 0, realSrcSlice, destinationTexture, texDstMipLevel, 0, 0, realDstSlice, effectiveCopyWidth, effectiveCopyHeight, 1);
uint64 eventCounter = LatteTexture_getNextUpdateEventCounter();
LatteTexture_MarkDynamicTextureAsChanged(destinationTexture->baseView, destinationView->firstSlice, texDstMipLevel, eventCounter);
}
} }
else else
{ {

View File

@ -836,6 +836,11 @@ bool IsDimensionCompatibleForView(Latte::E_DIM baseDim, Latte::E_DIM viewDim)
// not compatible // not compatible
incompatibleDim = true; incompatibleDim = true;
} }
else if (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_3D)
{
// incompatible by default, but may be compatible if the view matches the depth of the base texture and starts at mip/slice 0
incompatibleDim = true;
}
else if ((baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_CUBEMAP) || else if ((baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_CUBEMAP) ||
(baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_2D)) (baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_2D))
{ {
@ -872,7 +877,9 @@ VIEWCOMPATIBILITY LatteTexture_CanTextureBeRepresentedAsView(LatteTexture* baseT
return VIEW_NOT_COMPATIBLE; // depth and non-depth formats are never compatible (on OpenGL) return VIEW_NOT_COMPATIBLE; // depth and non-depth formats are never compatible (on OpenGL)
if (!LatteTexture_IsTexelSizeCompatibleFormat(baseTexture->format, format) || baseTexture->width != width || baseTexture->height != height) if (!LatteTexture_IsTexelSizeCompatibleFormat(baseTexture->format, format) || baseTexture->width != width || baseTexture->height != height)
return VIEW_NOT_COMPATIBLE; return VIEW_NOT_COMPATIBLE;
if (!IsDimensionCompatibleForView(baseTexture->dim, dimView)) // 3D views are only compatible on Vulkan if they match the base texture in regards to mip and slice count
bool isCompatible3DView = dimView == Latte::E_DIM::DIM_3D && baseTexture->dim == dimView && firstSlice == 0 && firstMip == 0 && baseTexture->mipLevels == numMip && baseTexture->depth == numSlice;
if (!isCompatible3DView && !IsDimensionCompatibleForView(baseTexture->dim, dimView))
return VIEW_NOT_COMPATIBLE; return VIEW_NOT_COMPATIBLE;
if (baseTexture->isDepth && baseTexture->format != format) if (baseTexture->isDepth && baseTexture->format != format)
{ {
@ -999,6 +1006,7 @@ void LatteTexture_RecreateTextureWithDifferentMipSliceCount(LatteTexture* textur
// create new texture representation // create new texture representation
// if allowCreateNewDataTexture is true, a new texture will be created if necessary. If it is false, only existing textures may be used, except if a data-compatible version of the requested texture already exists and it's not view compatible // if allowCreateNewDataTexture is true, a new texture will be created if necessary. If it is false, only existing textures may be used, except if a data-compatible version of the requested texture already exists and it's not view compatible
// the returned view will map to the provided mip and slice range within the created texture, this is to match the behavior of lookupSliceEx
LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dimBase, Latte::E_DIM dimView, bool isDepth, bool allowCreateNewDataTexture) LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dimBase, Latte::E_DIM dimView, bool isDepth, bool allowCreateNewDataTexture)
{ {
if (format == Latte::E_GX2SURFFMT::INVALID_FORMAT) if (format == Latte::E_GX2SURFFMT::INVALID_FORMAT)
@ -1105,11 +1113,17 @@ LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, si
if (allowCreateNewDataTexture == false) if (allowCreateNewDataTexture == false)
return nullptr; return nullptr;
LatteTextureView* view = LatteTexture_CreateTexture(0, dimBase, physAddr, physMipAddr, format, width, height, depth, pitch, firstMip + numMip, swizzle, tileMode, isDepth); LatteTextureView* view = LatteTexture_CreateTexture(0, dimBase, physAddr, physMipAddr, format, width, height, depth, pitch, firstMip + numMip, swizzle, tileMode, isDepth);
LatteTexture* newTexture = view->baseTexture;
LatteTexture_GatherTextureRelations(view->baseTexture); LatteTexture_GatherTextureRelations(view->baseTexture);
LatteTexture_UpdateTextureFromDynamicChanges(view->baseTexture); LatteTexture_UpdateTextureFromDynamicChanges(view->baseTexture);
// delete any individual smaller slices/mips that have become redundant // delete any individual smaller slices/mips that have become redundant
LatteTexture_DeleteAbsorbedSubtextures(view->baseTexture); LatteTexture_DeleteAbsorbedSubtextures(view->baseTexture);
return view; // create view
sint32 relativeMipIndex;
sint32 relativeSliceIndex;
VIEWCOMPATIBILITY viewCompatibility = LatteTexture_CanTextureBeRepresentedAsView(newTexture, physAddr, width, height, pitch, dimView, format, isDepth, firstMip, numMip, firstSlice, numSlice, relativeMipIndex, relativeSliceIndex);
cemu_assert(viewCompatibility == VIEW_COMPATIBLE);
return view->baseTexture->GetOrCreateView(dimView, format, relativeMipIndex + firstMip, numMip, relativeSliceIndex + firstSlice, numSlice);
} }
LatteTextureView* LatteTC_LookupTextureByData(MPTR physAddr, sint32 width, sint32 height, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, sint32* searchIndex) LatteTextureView* LatteTC_LookupTextureByData(MPTR physAddr, sint32 width, sint32 height, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, sint32* searchIndex)