mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 12:34:17 +01:00
Latte+Vulkan: Code cleanup
Besides a general cleanup: - Remove deprecated resource destruction queues - Move functionality from renderer into Latte base classes to deduplicate code
This commit is contained in:
parent
bc04662525
commit
193767e6cc
@ -98,7 +98,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
|
|||||||
void LatteRenderTarget_GetCurrentVirtualViewportSize(sint32* viewportWidth, sint32* viewportHeight);
|
void LatteRenderTarget_GetCurrentVirtualViewportSize(sint32* viewportWidth, sint32* viewportHeight);
|
||||||
|
|
||||||
void LatteRenderTarget_itHLESwapScanBuffer();
|
void LatteRenderTarget_itHLESwapScanBuffer();
|
||||||
void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorBufferMPTR, MPTR colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice, MPTR depthBufferMPTR, MPTR depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice, float r, float g, float b, float a, float clearDepth, uint32 clearStencil);
|
void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorBufferMPTR, Latte::E_GX2SURFFMT colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice, MPTR depthBufferMPTR, Latte::E_GX2SURFFMT depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice, float r, float g, float b, float a, float clearDepth, uint32 clearStencil);
|
||||||
void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferSliceIndex, uint32 colorBufferFormat, uint32 colorBufferPitch, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferSwizzle, uint32 renderTarget);
|
void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferSliceIndex, uint32 colorBufferFormat, uint32 colorBufferPitch, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferSwizzle, uint32 renderTarget);
|
||||||
|
|
||||||
void LatteRenderTarget_unloadAll();
|
void LatteRenderTarget_unloadAll();
|
||||||
|
@ -864,8 +864,8 @@ LatteCMDPtr LatteCP_itHLEClearColorDepthStencil(LatteCMDPtr cmd, uint32 nWords)
|
|||||||
cemu_assert_debug(nWords == 23);
|
cemu_assert_debug(nWords == 23);
|
||||||
uint32 clearMask = LatteReadCMD(); // color (1), depth (2), stencil (4)
|
uint32 clearMask = LatteReadCMD(); // color (1), depth (2), stencil (4)
|
||||||
// color buffer
|
// color buffer
|
||||||
MPTR colorBufferMPTR = LatteReadCMD(); // MPTR for color buffer (physical address)
|
MPTR colorBufferMPTR = LatteReadCMD(); // physical address for color buffer
|
||||||
MPTR colorBufferFormat = LatteReadCMD(); // format for color buffer
|
Latte::E_GX2SURFFMT colorBufferFormat = (Latte::E_GX2SURFFMT)LatteReadCMD();
|
||||||
Latte::E_HWTILEMODE colorBufferTilemode = (Latte::E_HWTILEMODE)LatteReadCMD();
|
Latte::E_HWTILEMODE colorBufferTilemode = (Latte::E_HWTILEMODE)LatteReadCMD();
|
||||||
uint32 colorBufferWidth = LatteReadCMD();
|
uint32 colorBufferWidth = LatteReadCMD();
|
||||||
uint32 colorBufferHeight = LatteReadCMD();
|
uint32 colorBufferHeight = LatteReadCMD();
|
||||||
@ -873,8 +873,8 @@ LatteCMDPtr LatteCP_itHLEClearColorDepthStencil(LatteCMDPtr cmd, uint32 nWords)
|
|||||||
uint32 colorBufferViewFirstSlice = LatteReadCMD();
|
uint32 colorBufferViewFirstSlice = LatteReadCMD();
|
||||||
uint32 colorBufferViewNumSlice = LatteReadCMD();
|
uint32 colorBufferViewNumSlice = LatteReadCMD();
|
||||||
// depth buffer
|
// depth buffer
|
||||||
MPTR depthBufferMPTR = LatteReadCMD(); // MPTR for depth buffer (physical address)
|
MPTR depthBufferMPTR = LatteReadCMD(); // physical address for depth buffer
|
||||||
MPTR depthBufferFormat = LatteReadCMD(); // format for depth buffer
|
Latte::E_GX2SURFFMT depthBufferFormat = (Latte::E_GX2SURFFMT)LatteReadCMD();
|
||||||
Latte::E_HWTILEMODE depthBufferTileMode = (Latte::E_HWTILEMODE)LatteReadCMD();
|
Latte::E_HWTILEMODE depthBufferTileMode = (Latte::E_HWTILEMODE)LatteReadCMD();
|
||||||
uint32 depthBufferWidth = LatteReadCMD();
|
uint32 depthBufferWidth = LatteReadCMD();
|
||||||
uint32 depthBufferHeight = LatteReadCMD();
|
uint32 depthBufferHeight = LatteReadCMD();
|
||||||
|
@ -221,35 +221,9 @@ void LatteMRT::BindDepthBufferOnly(LatteTextureView* view)
|
|||||||
ApplyCurrentState();
|
ApplyCurrentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************/
|
|
||||||
|
|
||||||
LatteTextureView* LatteMRT_FindColorBufferForClearing(MPTR colorBufferPtr, sint32 colorBufferWidth, sint32 colorBufferHeight, sint32 colorBufferPitch, uint32 format, sint32 sliceIndex, sint32* searchIndex)
|
|
||||||
{
|
|
||||||
LatteTextureView* view = LatteTC_LookupTextureByData(colorBufferPtr, colorBufferWidth, colorBufferHeight, colorBufferPitch, 0, 1, sliceIndex, 1, searchIndex);
|
|
||||||
if (view == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
LatteTextureView* LatteMRT_CreateColorBuffer(MPTR colorBufferPhysMem, uint32 width, uint32 height, uint32 pitch, Latte::E_GX2SURFFMT format, Latte::E_HWTILEMODE tileMode, uint32 swizzle, uint32 viewSlice)
|
|
||||||
{
|
|
||||||
cemu_assert_debug(colorBufferPhysMem != MPTR_NULL);
|
|
||||||
LatteTextureView* textureView;
|
|
||||||
if(viewSlice != 0)
|
|
||||||
textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, false);
|
|
||||||
else
|
|
||||||
textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, 1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
|
|
||||||
return textureView;
|
|
||||||
}
|
|
||||||
|
|
||||||
LatteTextureView* LatteMRT_CreateDepthBuffer(MPTR depthBufferPhysMem, uint32 width, uint32 height, uint32 pitch, Latte::E_HWTILEMODE tileMode, Latte::E_GX2SURFFMT format, uint32 swizzle, sint32 viewSlice)
|
LatteTextureView* LatteMRT_CreateDepthBuffer(MPTR depthBufferPhysMem, uint32 width, uint32 height, uint32 pitch, Latte::E_HWTILEMODE tileMode, Latte::E_GX2SURFFMT format, uint32 swizzle, sint32 viewSlice)
|
||||||
{
|
{
|
||||||
LatteTextureView* textureView;
|
LatteTextureView* textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, viewSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
|
||||||
if(viewSlice == 0)
|
|
||||||
textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, 1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
|
|
||||||
else
|
|
||||||
textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, true);
|
|
||||||
|
|
||||||
LatteMRT::SetDepthAndStencilAttachment(textureView, textureView->baseTexture->hasStencil);
|
LatteMRT::SetDepthAndStencilAttachment(textureView, textureView->baseTexture->hasStencil);
|
||||||
return textureView;
|
return textureView;
|
||||||
}
|
}
|
||||||
@ -605,7 +579,7 @@ bool LatteMRT::UpdateCurrentFBO()
|
|||||||
if (depthBufferPhysMem != MPTR_NULL)
|
if (depthBufferPhysMem != MPTR_NULL)
|
||||||
{
|
{
|
||||||
LatteTextureView* depthBufferView = LatteTextureViewLookupCache::lookupSliceEx(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, depthBufferViewFirstSlice, depthBufferFormat, true);
|
LatteTextureView* depthBufferView = LatteTextureViewLookupCache::lookupSliceEx(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, depthBufferViewFirstSlice, depthBufferFormat, true);
|
||||||
if (depthBufferView == nullptr)
|
if (!depthBufferView)
|
||||||
{
|
{
|
||||||
// create new depth buffer view and if it doesn't exist then also create the texture
|
// create new depth buffer view and if it doesn't exist then also create the texture
|
||||||
depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
|
depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
|
||||||
@ -768,7 +742,10 @@ void LatteRenderTarget_applyTextureDepthClear(LatteTexture* texture, uint32 slic
|
|||||||
LatteTexture_MarkDynamicTextureAsChanged(texture->baseView, sliceIndex, mipIndex, eventCounter);
|
LatteTexture_MarkDynamicTextureAsChanged(texture->baseView, sliceIndex, mipIndex, eventCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorBufferMPTR, MPTR colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice, MPTR depthBufferMPTR, MPTR depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice, float r, float g, float b, float a, float clearDepth, uint32 clearStencil)
|
void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask,
|
||||||
|
MPTR colorBufferMPTR, Latte::E_GX2SURFFMT colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice,
|
||||||
|
MPTR depthBufferMPTR, Latte::E_GX2SURFFMT depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice,
|
||||||
|
float r, float g, float b, float a, float clearDepth, uint32 clearStencil)
|
||||||
{
|
{
|
||||||
uint32 depthBufferMipIndex = 0; // todo
|
uint32 depthBufferMipIndex = 0; // todo
|
||||||
uint32 colorBufferMipIndex = 0; // todo
|
uint32 colorBufferMipIndex = 0; // todo
|
||||||
@ -803,13 +780,11 @@ void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorB
|
|||||||
bool targetFound = false;
|
bool targetFound = false;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
LatteTextureView* colorView = LatteMRT_FindColorBufferForClearing(colorBufferMPTR, colorBufferWidth, colorBufferHeight, colorBufferPitch, colorBufferFormat, colorBufferViewFirstSlice, &searchIndex);
|
LatteTextureView* colorView = LatteTC_LookupTextureByData(colorBufferMPTR, colorBufferWidth, colorBufferHeight, colorBufferPitch, 0, 1, colorBufferViewFirstSlice, 1, &searchIndex);
|
||||||
if (!colorView)
|
if (!colorView)
|
||||||
break;
|
break;
|
||||||
if (Latte::GetFormatBits((Latte::E_GX2SURFFMT)colorBufferFormat) != Latte::GetFormatBits(colorView->baseTexture->format))
|
if (Latte::GetFormatBits(colorBufferFormat) != Latte::GetFormatBits(colorView->baseTexture->format))
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (colorView->baseTexture->pitch == colorBufferPitch && colorView->baseTexture->height == colorBufferHeight)
|
if (colorView->baseTexture->pitch == colorBufferPitch && colorView->baseTexture->height == colorBufferHeight)
|
||||||
targetFound = true;
|
targetFound = true;
|
||||||
@ -821,7 +796,7 @@ void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorB
|
|||||||
{
|
{
|
||||||
// create new texture with matching format
|
// create new texture with matching format
|
||||||
cemu_assert_debug(colorBufferViewNumSlice <= 1);
|
cemu_assert_debug(colorBufferViewNumSlice <= 1);
|
||||||
LatteTextureView* newColorView = LatteMRT_CreateColorBuffer(colorBufferMPTR, colorBufferWidth, colorBufferHeight, colorBufferPitch, (Latte::E_GX2SURFFMT)colorBufferFormat, colorBufferTilemode, colorBufferSwizzle, colorBufferViewFirstSlice);
|
LatteTextureView* newColorView = LatteTexture_CreateMapping(colorBufferMPTR, MPTR_NULL, colorBufferWidth, colorBufferHeight, colorBufferViewFirstSlice+1, colorBufferPitch, colorBufferTilemode, colorBufferSwizzle, 0, 1, colorBufferViewFirstSlice, 1, colorBufferFormat, colorBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
|
||||||
LatteRenderTarget_applyTextureColorClear(newColorView->baseTexture, colorBufferViewFirstSlice, colorBufferMipIndex, r, g, b, a, eventCounter);
|
LatteRenderTarget_applyTextureColorClear(newColorView->baseTexture, colorBufferViewFirstSlice, colorBufferMipIndex, r, g, b, a, eventCounter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1199,6 +1199,15 @@ std::vector<LatteTexture*>& LatteTexture::GetAllTextures()
|
|||||||
return sAllTextures;
|
return sAllTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LatteTexture_GX2FormatHasStencil(bool isDepth, Latte::E_GX2SURFFMT format)
|
||||||
|
{
|
||||||
|
if (!isDepth)
|
||||||
|
return false;
|
||||||
|
return format == Latte::E_GX2SURFFMT::D24_S8_UNORM ||
|
||||||
|
format == Latte::E_GX2SURFFMT::D24_S8_FLOAT ||
|
||||||
|
format == Latte::E_GX2SURFFMT::D32_S8_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
|
LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
|
||||||
Latte::E_HWTILEMODE tileMode, bool isDepth)
|
Latte::E_HWTILEMODE tileMode, bool isDepth)
|
||||||
{
|
{
|
||||||
@ -1217,6 +1226,7 @@ LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddre
|
|||||||
this->mipLevels = mipLevels;
|
this->mipLevels = mipLevels;
|
||||||
this->tileMode = tileMode;
|
this->tileMode = tileMode;
|
||||||
this->isDepth = isDepth;
|
this->isDepth = isDepth;
|
||||||
|
this->hasStencil = LatteTexture_GX2FormatHasStencil(isDepth, format);
|
||||||
this->physMipAddress = physMipAddress;
|
this->physMipAddress = physMipAddress;
|
||||||
this->lastUpdateEventCounter = LatteTexture_getNextUpdateEventCounter();
|
this->lastUpdateEventCounter = LatteTexture_getNextUpdateEventCounter();
|
||||||
this->lastWriteEventCounter = LatteTexture_getNextUpdateEventCounter();
|
this->lastWriteEventCounter = LatteTexture_getNextUpdateEventCounter();
|
||||||
|
@ -27,6 +27,8 @@ public:
|
|||||||
LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
|
LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
|
||||||
virtual ~LatteTexture();
|
virtual ~LatteTexture();
|
||||||
|
|
||||||
|
virtual void AllocateOnHost() = 0;
|
||||||
|
|
||||||
LatteTextureView* GetOrCreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
|
LatteTextureView* GetOrCreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
|
||||||
{
|
{
|
||||||
for (auto& itr : views)
|
for (auto& itr : views)
|
||||||
|
@ -316,7 +316,7 @@ void LatteTexture_Delete(LatteTexture* texture)
|
|||||||
delete[] texture->sliceMipInfo;
|
delete[] texture->sliceMipInfo;
|
||||||
texture->sliceMipInfo = nullptr;
|
texture->sliceMipInfo = nullptr;
|
||||||
}
|
}
|
||||||
g_renderer->texture_destroy(texture);
|
delete texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -621,7 +621,7 @@ void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, uint32 sliceIn
|
|||||||
|
|
||||||
if (tex->isDataDefined == false)
|
if (tex->isDataDefined == false)
|
||||||
{
|
{
|
||||||
g_renderer->texture_reserveTextureOnGPU(tex);
|
tex->AllocateOnHost();
|
||||||
tex->isDataDefined = true;
|
tex->isDataDefined = true;
|
||||||
// if decoder is not set then clear texture
|
// if decoder is not set then clear texture
|
||||||
// on Vulkan this is used to make sure the texture is no longer in UNDEFINED layout
|
// on Vulkan this is used to make sure the texture is no longer in UNDEFINED layout
|
||||||
|
@ -5,20 +5,6 @@
|
|||||||
|
|
||||||
#include "config/LaunchSettings.h"
|
#include "config/LaunchSettings.h"
|
||||||
|
|
||||||
GLuint texIdPool[64];
|
|
||||||
sint32 texIdPoolIndex = 64;
|
|
||||||
|
|
||||||
static GLuint _genTextureHandleGL()
|
|
||||||
{
|
|
||||||
if (texIdPoolIndex == 64)
|
|
||||||
{
|
|
||||||
glGenTextures(64, texIdPool);
|
|
||||||
texIdPoolIndex = 0;
|
|
||||||
}
|
|
||||||
texIdPoolIndex++;
|
|
||||||
return texIdPool[texIdPoolIndex - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
|
LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
|
||||||
Latte::E_HWTILEMODE tileMode, bool isDepth)
|
Latte::E_HWTILEMODE tileMode, bool isDepth)
|
||||||
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth)
|
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth)
|
||||||
@ -29,7 +15,6 @@ LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipA
|
|||||||
GetOpenGLFormatInfo(isDepth, overwriteInfo.hasFormatOverwrite ? (Latte::E_GX2SURFFMT)overwriteInfo.format : format, dim, &glFormatInfo);
|
GetOpenGLFormatInfo(isDepth, overwriteInfo.hasFormatOverwrite ? (Latte::E_GX2SURFFMT)overwriteInfo.format : format, dim, &glFormatInfo);
|
||||||
this->glInternalFormat = glFormatInfo.glInternalFormat;
|
this->glInternalFormat = glFormatInfo.glInternalFormat;
|
||||||
this->isAlternativeFormat = glFormatInfo.isUsingAlternativeFormat;
|
this->isAlternativeFormat = glFormatInfo.isUsingAlternativeFormat;
|
||||||
this->hasStencil = glFormatInfo.hasStencil; // todo - should get this from the GX2 format?
|
|
||||||
// set debug name
|
// set debug name
|
||||||
bool useGLDebugNames = false;
|
bool useGLDebugNames = false;
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
@ -88,34 +73,34 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
|
|||||||
{
|
{
|
||||||
if (format == Latte::E_GX2SURFFMT::D24_S8_UNORM)
|
if (format == Latte::E_GX2SURFFMT::D24_S8_UNORM)
|
||||||
{
|
{
|
||||||
formatInfoOut->setDepthFormat(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, true);
|
formatInfoOut->setFormat(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (format == Latte::E_GX2SURFFMT::D24_S8_FLOAT)
|
else if (format == Latte::E_GX2SURFFMT::D24_S8_FLOAT)
|
||||||
{
|
{
|
||||||
formatInfoOut->setDepthFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, true);
|
formatInfoOut->setFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
|
||||||
formatInfoOut->markAsAlternativeFormat();
|
formatInfoOut->markAsAlternativeFormat();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (format == Latte::E_GX2SURFFMT::D32_S8_FLOAT)
|
else if (format == Latte::E_GX2SURFFMT::D32_S8_FLOAT)
|
||||||
{
|
{
|
||||||
formatInfoOut->setDepthFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, true);
|
formatInfoOut->setFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (format == Latte::E_GX2SURFFMT::D32_FLOAT)
|
else if (format == Latte::E_GX2SURFFMT::D32_FLOAT)
|
||||||
{
|
{
|
||||||
formatInfoOut->setDepthFormat(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false);
|
formatInfoOut->setFormat(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (format == Latte::E_GX2SURFFMT::D16_UNORM)
|
else if (format == Latte::E_GX2SURFFMT::D16_UNORM)
|
||||||
{
|
{
|
||||||
formatInfoOut->setDepthFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false);
|
formatInfoOut->setFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// unsupported depth format
|
// unsupported depth format
|
||||||
cemuLog_log(LogType::Force, "OpenGL: Unsupported texture depth format 0x{:04x}", (uint32)format);
|
cemuLog_log(LogType::Force, "OpenGL: Unsupported texture depth format 0x{:04x}", (uint32)format);
|
||||||
// use placeholder format
|
// use placeholder format
|
||||||
formatInfoOut->setDepthFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false);
|
formatInfoOut->setFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
|
||||||
formatInfoOut->markAsAlternativeFormat();
|
formatInfoOut->markAsAlternativeFormat();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -496,3 +481,49 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
|
|||||||
formatInfoOut->glIsCompressed = glIsCompressed;
|
formatInfoOut->glIsCompressed = glIsCompressed;
|
||||||
formatInfoOut->isUsingAlternativeFormat = isUsingAlternativeFormat;
|
formatInfoOut->isUsingAlternativeFormat = isUsingAlternativeFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LatteTextureGL::AllocateOnHost()
|
||||||
|
{
|
||||||
|
auto hostTexture = this;
|
||||||
|
cemu_assert_debug(hostTexture->isDataDefined == false);
|
||||||
|
sint32 effectiveBaseWidth = hostTexture->width;
|
||||||
|
sint32 effectiveBaseHeight = hostTexture->height;
|
||||||
|
sint32 effectiveBaseDepth = hostTexture->depth;
|
||||||
|
if (hostTexture->overwriteInfo.hasResolutionOverwrite)
|
||||||
|
{
|
||||||
|
effectiveBaseWidth = hostTexture->overwriteInfo.width;
|
||||||
|
effectiveBaseHeight = hostTexture->overwriteInfo.height;
|
||||||
|
effectiveBaseDepth = hostTexture->overwriteInfo.depth;
|
||||||
|
}
|
||||||
|
// calculate mip count
|
||||||
|
sint32 mipLevels = std::min(hostTexture->mipLevels, hostTexture->maxPossibleMipLevels);
|
||||||
|
mipLevels = std::max(mipLevels, 1);
|
||||||
|
// create immutable storage
|
||||||
|
if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
|
||||||
|
{
|
||||||
|
cemu_assert_debug(effectiveBaseDepth == 1);
|
||||||
|
glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
|
||||||
|
}
|
||||||
|
else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
|
||||||
|
{
|
||||||
|
cemu_assert_debug(effectiveBaseHeight == 1);
|
||||||
|
cemu_assert_debug(effectiveBaseDepth == 1);
|
||||||
|
glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth);
|
||||||
|
}
|
||||||
|
else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
|
||||||
|
{
|
||||||
|
glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
|
||||||
|
}
|
||||||
|
else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
|
||||||
|
{
|
||||||
|
glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
|
||||||
|
}
|
||||||
|
else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
|
||||||
|
{
|
||||||
|
glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cemu_assert_unimplemented();
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,8 @@ public:
|
|||||||
|
|
||||||
~LatteTextureGL();
|
~LatteTextureGL();
|
||||||
|
|
||||||
|
void AllocateOnHost() override;
|
||||||
|
|
||||||
static void GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget, bool createForTargetType);
|
static void GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget, bool createForTargetType);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -23,7 +25,6 @@ public:
|
|||||||
sint32 glSuppliedFormat;
|
sint32 glSuppliedFormat;
|
||||||
sint32 glSuppliedFormatType;
|
sint32 glSuppliedFormatType;
|
||||||
bool glIsCompressed;
|
bool glIsCompressed;
|
||||||
bool hasStencil{};
|
|
||||||
bool isUsingAlternativeFormat{};
|
bool isUsingAlternativeFormat{};
|
||||||
|
|
||||||
void setFormat(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType)
|
void setFormat(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType)
|
||||||
@ -34,15 +35,6 @@ public:
|
|||||||
this->glIsCompressed = false;
|
this->glIsCompressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDepthFormat(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType, bool hasStencil)
|
|
||||||
{
|
|
||||||
this->glInternalFormat = glInternalFormat;
|
|
||||||
this->glSuppliedFormat = glSuppliedFormat;
|
|
||||||
this->glSuppliedFormatType = glSuppliedFormatType;
|
|
||||||
this->glIsCompressed = false;
|
|
||||||
this->hasStencil = hasStencil;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCompressed(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType)
|
void setCompressed(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType)
|
||||||
{
|
{
|
||||||
setFormat(glInternalFormat, glSuppliedFormat, glSuppliedFormatType);
|
setFormat(glInternalFormat, glSuppliedFormat, glSuppliedFormatType);
|
||||||
|
@ -1002,57 +1002,6 @@ TextureDecoder* OpenGLRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT
|
|||||||
return texDecoder;
|
return texDecoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::texture_destroy(LatteTexture* hostTexture)
|
|
||||||
{
|
|
||||||
delete hostTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTextureGeneric)
|
|
||||||
{
|
|
||||||
auto hostTexture = (LatteTextureGL*)hostTextureGeneric;
|
|
||||||
cemu_assert_debug(hostTexture->isDataDefined == false);
|
|
||||||
sint32 effectiveBaseWidth = hostTexture->width;
|
|
||||||
sint32 effectiveBaseHeight = hostTexture->height;
|
|
||||||
sint32 effectiveBaseDepth = hostTexture->depth;
|
|
||||||
if (hostTexture->overwriteInfo.hasResolutionOverwrite)
|
|
||||||
{
|
|
||||||
effectiveBaseWidth = hostTexture->overwriteInfo.width;
|
|
||||||
effectiveBaseHeight = hostTexture->overwriteInfo.height;
|
|
||||||
effectiveBaseDepth = hostTexture->overwriteInfo.depth;
|
|
||||||
}
|
|
||||||
// calculate mip count
|
|
||||||
sint32 mipLevels = std::min(hostTexture->mipLevels, hostTexture->maxPossibleMipLevels);
|
|
||||||
mipLevels = std::max(mipLevels, 1);
|
|
||||||
// create immutable storage
|
|
||||||
if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
|
|
||||||
{
|
|
||||||
cemu_assert_debug(effectiveBaseDepth == 1);
|
|
||||||
glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
|
|
||||||
}
|
|
||||||
else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
|
|
||||||
{
|
|
||||||
cemu_assert_debug(effectiveBaseHeight == 1);
|
|
||||||
cemu_assert_debug(effectiveBaseDepth == 1);
|
|
||||||
glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth);
|
|
||||||
}
|
|
||||||
else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
|
|
||||||
{
|
|
||||||
glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
|
|
||||||
}
|
|
||||||
else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
|
|
||||||
{
|
|
||||||
glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
|
|
||||||
}
|
|
||||||
else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
|
|
||||||
{
|
|
||||||
glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cemu_assert_unimplemented();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use standard API to upload texture data
|
// use standard API to upload texture data
|
||||||
void OpenGLRenderer_texture_loadSlice_normal(LatteTexture* hostTextureGeneric, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 imageSize)
|
void OpenGLRenderer_texture_loadSlice_normal(LatteTexture* hostTextureGeneric, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 imageSize)
|
||||||
{
|
{
|
||||||
|
@ -66,14 +66,11 @@ public:
|
|||||||
void renderstate_updateTextureSettingsGL(LatteDecompilerShader* shaderContext, LatteTextureView* _hostTextureView, uint32 hostTextureUnit, const Latte::LATTE_SQ_TEX_RESOURCE_WORD4_N texUnitWord4, uint32 texUnitIndex, bool isDepthSampler);
|
void renderstate_updateTextureSettingsGL(LatteDecompilerShader* shaderContext, LatteTextureView* _hostTextureView, uint32 hostTextureUnit, const Latte::LATTE_SQ_TEX_RESOURCE_WORD4_N texUnitWord4, uint32 texUnitIndex, bool isDepthSampler);
|
||||||
|
|
||||||
// texture functions
|
// texture functions
|
||||||
void texture_destroy(LatteTexture* hostTexture) override;
|
|
||||||
|
|
||||||
void* texture_acquireTextureUploadBuffer(uint32 size) override;
|
void* texture_acquireTextureUploadBuffer(uint32 size) override;
|
||||||
void texture_releaseTextureUploadBuffer(uint8* mem) override;
|
void texture_releaseTextureUploadBuffer(uint8* mem) override;
|
||||||
|
|
||||||
TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) override;
|
TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) override;
|
||||||
|
|
||||||
void texture_reserveTextureOnGPU(LatteTexture* hostTexture) override;
|
|
||||||
void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) override;
|
void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) override;
|
||||||
void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) override;
|
void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) override;
|
||||||
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
|
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
|
||||||
|
@ -97,14 +97,11 @@ public:
|
|||||||
virtual void rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo) = 0;
|
virtual void rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo) = 0;
|
||||||
|
|
||||||
// texture functions
|
// texture functions
|
||||||
virtual void texture_destroy(LatteTexture* hostTexture) = 0;
|
|
||||||
|
|
||||||
virtual void* texture_acquireTextureUploadBuffer(uint32 size) = 0;
|
virtual void* texture_acquireTextureUploadBuffer(uint32 size) = 0;
|
||||||
virtual void texture_releaseTextureUploadBuffer(uint8* mem) = 0;
|
virtual void texture_releaseTextureUploadBuffer(uint8* mem) = 0;
|
||||||
|
|
||||||
virtual TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) = 0;
|
virtual TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) = 0;
|
||||||
|
|
||||||
virtual void texture_reserveTextureOnGPU(LatteTexture* hostTexture) = 0;
|
|
||||||
virtual void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) = 0;
|
virtual void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) = 0;
|
||||||
virtual void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) = 0;
|
virtual void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) = 0;
|
||||||
virtual void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) = 0;
|
virtual void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) = 0;
|
||||||
|
@ -44,9 +44,9 @@ CachedFBOVk::~CachedFBOVk()
|
|||||||
while (!m_usedByPipelines.empty())
|
while (!m_usedByPipelines.empty())
|
||||||
delete m_usedByPipelines[0];
|
delete m_usedByPipelines[0];
|
||||||
auto vkr = VulkanRenderer::GetInstance();
|
auto vkr = VulkanRenderer::GetInstance();
|
||||||
vkr->releaseDestructibleObject(m_vkrObjFramebuffer);
|
vkr->ReleaseDestructibleObject(m_vkrObjFramebuffer);
|
||||||
m_vkrObjFramebuffer = nullptr;
|
m_vkrObjFramebuffer = nullptr;
|
||||||
vkr->releaseDestructibleObject(m_vkrObjRenderPass);
|
vkr->ReleaseDestructibleObject(m_vkrObjRenderPass);
|
||||||
m_vkrObjRenderPass = nullptr;
|
m_vkrObjRenderPass = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,14 +79,14 @@ LatteTextureViewVk::~LatteTextureViewVk()
|
|||||||
delete list_descriptorSets[0];
|
delete list_descriptorSets[0];
|
||||||
|
|
||||||
if (m_smallCacheView0)
|
if (m_smallCacheView0)
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(m_smallCacheView0);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_smallCacheView0);
|
||||||
if (m_smallCacheView1)
|
if (m_smallCacheView1)
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(m_smallCacheView1);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_smallCacheView1);
|
||||||
|
|
||||||
if (m_fallbackCache)
|
if (m_fallbackCache)
|
||||||
{
|
{
|
||||||
for (auto& itr : *m_fallbackCache)
|
for (auto& itr : *m_fallbackCache)
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(itr.second);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(itr.second);
|
||||||
delete m_fallbackCache;
|
delete m_fallbackCache;
|
||||||
m_fallbackCache = nullptr;
|
m_fallbackCache = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ LatteTextureVk::LatteTextureVk(class VulkanRenderer* vkRenderer, Latte::E_DIM di
|
|||||||
|
|
||||||
VulkanRenderer::FormatInfoVK texFormatInfo;
|
VulkanRenderer::FormatInfoVK texFormatInfo;
|
||||||
vkRenderer->GetTextureFormatInfoVK(format, isDepth, dim, effectiveBaseWidth, effectiveBaseHeight, &texFormatInfo);
|
vkRenderer->GetTextureFormatInfoVK(format, isDepth, dim, effectiveBaseWidth, effectiveBaseHeight, &texFormatInfo);
|
||||||
hasStencil = (texFormatInfo.vkImageAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
|
cemu_assert_debug(hasStencil == ((texFormatInfo.vkImageAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0));
|
||||||
imageInfo.format = texFormatInfo.vkImageFormat;
|
imageInfo.format = texFormatInfo.vkImageFormat;
|
||||||
vkObjTex->m_imageAspect = texFormatInfo.vkImageAspect;
|
vkObjTex->m_imageAspect = texFormatInfo.vkImageAspect;
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ LatteTextureVk::~LatteTextureVk()
|
|||||||
|
|
||||||
m_vkr->surfaceCopy_notifyTextureRelease(this);
|
m_vkr->surfaceCopy_notifyTextureRelease(this);
|
||||||
|
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(vkObjTex);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(vkObjTex);
|
||||||
vkObjTex = nullptr;
|
vkObjTex = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,12 +130,8 @@ LatteTextureView* LatteTextureVk::CreateView(Latte::E_DIM dim, Latte::E_GX2SURFF
|
|||||||
return new LatteTextureViewVk(m_vkr->GetLogicalDevice(), this, dim, format, firstMip, mipCount, firstSlice, sliceCount);
|
return new LatteTextureViewVk(m_vkr->GetLogicalDevice(), this, dim, format, firstMip, mipCount, firstSlice, sliceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LatteTextureVk::setAllocation(struct VkImageMemAllocation* memAllocation)
|
void LatteTextureVk::AllocateOnHost()
|
||||||
{
|
{
|
||||||
vkObjTex->m_allocation = memAllocation;
|
auto allocationInfo = VulkanRenderer::GetInstance()->GetMemoryManager()->imageMemoryAllocate(GetImageObj()->m_image);
|
||||||
}
|
vkObjTex->m_allocation = allocationInfo;
|
||||||
|
|
||||||
struct VkImageMemAllocation* LatteTextureVk::getAllocation() const
|
|
||||||
{
|
|
||||||
return vkObjTex->m_allocation;
|
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,13 @@ public:
|
|||||||
|
|
||||||
~LatteTextureVk();
|
~LatteTextureVk();
|
||||||
|
|
||||||
|
void AllocateOnHost() override;
|
||||||
|
|
||||||
VKRObjectTexture* GetImageObj() const { return vkObjTex; };
|
VKRObjectTexture* GetImageObj() const { return vkObjTex; };
|
||||||
|
|
||||||
VkFormat GetFormat() const { return vkObjTex->m_format; }
|
VkFormat GetFormat() const { return vkObjTex->m_format; }
|
||||||
VkImageAspectFlags GetImageAspect() const { return vkObjTex->m_imageAspect; }
|
VkImageAspectFlags GetImageAspect() const { return vkObjTex->m_imageAspect; }
|
||||||
|
|
||||||
void setAllocation(struct VkImageMemAllocation* memAllocation);
|
|
||||||
struct VkImageMemAllocation* getAllocation() const;
|
|
||||||
|
|
||||||
VkImageLayout GetImageLayout(VkImageSubresource& subresource)
|
VkImageLayout GetImageLayout(VkImageSubresource& subresource)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(subresource.mipLevel < m_layoutsMips);
|
cemu_assert_debug(subresource.mipLevel < m_layoutsMips);
|
||||||
|
@ -207,7 +207,8 @@ RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxH
|
|||||||
|
|
||||||
RendererShaderVk::~RendererShaderVk()
|
RendererShaderVk::~RendererShaderVk()
|
||||||
{
|
{
|
||||||
VulkanRenderer::GetInstance()->destroyShader(this);
|
while (!list_pipelineInfo.empty())
|
||||||
|
delete list_pipelineInfo[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererShaderVk::Init()
|
void RendererShaderVk::Init()
|
||||||
|
@ -84,7 +84,7 @@ PipelineInfo::~PipelineInfo()
|
|||||||
// queue pipeline for destruction
|
// queue pipeline for destruction
|
||||||
if (m_vkrObjPipeline)
|
if (m_vkrObjPipeline)
|
||||||
{
|
{
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(m_vkrObjPipeline);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_vkrObjPipeline);
|
||||||
m_vkrObjPipeline = nullptr;
|
m_vkrObjPipeline = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ void VulkanPipelineStableCache::LoadPipelineFromCache(std::span<uint8> fileData)
|
|||||||
delete pipelineInfo;
|
delete pipelineInfo;
|
||||||
delete lcr;
|
delete lcr;
|
||||||
delete cachedPipeline;
|
delete cachedPipeline;
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(renderPass);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(renderPass);
|
||||||
s_spinlockSharedInternal.unlock();
|
s_spinlockSharedInternal.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1803,44 +1803,6 @@ void VulkanRenderer::PreparePresentationFrame(bool mainWindow)
|
|||||||
AcquireNextSwapchainImage(mainWindow);
|
AcquireNextSwapchainImage(mainWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::ProcessDestructionQueues(size_t commandBufferIndex)
|
|
||||||
{
|
|
||||||
auto& current_descriptor_cache = m_destructionQueues.m_cmd_descriptor_set_objects[commandBufferIndex];
|
|
||||||
if (!current_descriptor_cache.empty())
|
|
||||||
{
|
|
||||||
assert_dbg();
|
|
||||||
//for (const auto& descriptor : current_descriptor_cache)
|
|
||||||
//{
|
|
||||||
// vkFreeDescriptorSets(m_logicalDevice, m_descriptorPool, 1, &descriptor);
|
|
||||||
// performanceMonitor.vk.numDescriptorSets.decrement();
|
|
||||||
//}
|
|
||||||
|
|
||||||
current_descriptor_cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// destroy buffers
|
|
||||||
for (auto& itr : m_destructionQueues.m_buffers[commandBufferIndex])
|
|
||||||
vkDestroyBuffer(m_logicalDevice, itr, nullptr);
|
|
||||||
m_destructionQueues.m_buffers[commandBufferIndex].clear();
|
|
||||||
|
|
||||||
// destroy device memory objects
|
|
||||||
for (auto& itr : m_destructionQueues.m_memory[commandBufferIndex])
|
|
||||||
vkFreeMemory(m_logicalDevice, itr, nullptr);
|
|
||||||
m_destructionQueues.m_memory[commandBufferIndex].clear();
|
|
||||||
|
|
||||||
// destroy image views
|
|
||||||
for (auto& itr : m_destructionQueues.m_cmd_image_views[commandBufferIndex])
|
|
||||||
vkDestroyImageView(m_logicalDevice, itr, nullptr);
|
|
||||||
m_destructionQueues.m_cmd_image_views[commandBufferIndex].clear();
|
|
||||||
|
|
||||||
// destroy host textures
|
|
||||||
for (auto itr : m_destructionQueues.m_host_textures[commandBufferIndex])
|
|
||||||
delete itr;
|
|
||||||
m_destructionQueues.m_host_textures[commandBufferIndex].clear();
|
|
||||||
|
|
||||||
ProcessDestructionQueue2();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::InitFirstCommandBuffer()
|
void VulkanRenderer::InitFirstCommandBuffer()
|
||||||
{
|
{
|
||||||
cemu_assert_debug(m_state.currentCommandBuffer == nullptr);
|
cemu_assert_debug(m_state.currentCommandBuffer == nullptr);
|
||||||
@ -1869,7 +1831,7 @@ void VulkanRenderer::ProcessFinishedCommandBuffers()
|
|||||||
VkResult fenceStatus = vkGetFenceStatus(m_logicalDevice, m_cmd_buffer_fences[m_commandBufferSyncIndex]);
|
VkResult fenceStatus = vkGetFenceStatus(m_logicalDevice, m_cmd_buffer_fences[m_commandBufferSyncIndex]);
|
||||||
if (fenceStatus == VK_SUCCESS)
|
if (fenceStatus == VK_SUCCESS)
|
||||||
{
|
{
|
||||||
ProcessDestructionQueues(m_commandBufferSyncIndex);
|
ProcessDestructionQueue();
|
||||||
m_commandBufferSyncIndex = (m_commandBufferSyncIndex + 1) % m_commandBuffers.size();
|
m_commandBufferSyncIndex = (m_commandBufferSyncIndex + 1) % m_commandBuffers.size();
|
||||||
memoryManager->cleanupBuffers(m_countCommandBufferFinished);
|
memoryManager->cleanupBuffers(m_countCommandBufferFinished);
|
||||||
m_countCommandBufferFinished++;
|
m_countCommandBufferFinished++;
|
||||||
@ -3035,48 +2997,7 @@ TextureDecoder* VulkanRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT
|
|||||||
return texFormatInfo.decoder;
|
return texFormatInfo.decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
|
void VulkanRenderer::ReleaseDestructibleObject(VKRDestructibleObject* destructibleObject)
|
||||||
{
|
|
||||||
LatteTextureVk* vkTexture = (LatteTextureVk*)hostTexture;
|
|
||||||
auto allocationInfo = memoryManager->imageMemoryAllocate(vkTexture->GetImageObj()->m_image);
|
|
||||||
vkTexture->setAllocation(allocationInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::texture_destroy(LatteTexture* hostTexture)
|
|
||||||
{
|
|
||||||
LatteTextureVk* texVk = (LatteTextureVk*)hostTexture;
|
|
||||||
delete texVk;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::destroyViewDepr(VkImageView imageView)
|
|
||||||
{
|
|
||||||
cemu_assert_debug(false);
|
|
||||||
|
|
||||||
m_destructionQueues.m_cmd_image_views[m_commandBufferIndex].emplace_back(imageView);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::destroyBuffer(VkBuffer buffer)
|
|
||||||
{
|
|
||||||
m_destructionQueues.m_buffers[m_commandBufferIndex].emplace_back(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::destroyDeviceMemory(VkDeviceMemory mem)
|
|
||||||
{
|
|
||||||
m_destructionQueues.m_memory[m_commandBufferIndex].emplace_back(mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::destroyPipelineInfo(PipelineInfo* pipelineInfo)
|
|
||||||
{
|
|
||||||
cemu_assert_debug(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::destroyShader(RendererShaderVk* shader)
|
|
||||||
{
|
|
||||||
while (!shader->list_pipelineInfo.empty())
|
|
||||||
delete shader->list_pipelineInfo[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::releaseDestructibleObject(VKRDestructibleObject* destructibleObject)
|
|
||||||
{
|
{
|
||||||
// destroy immediately if possible
|
// destroy immediately if possible
|
||||||
if (destructibleObject->canDestroy())
|
if (destructibleObject->canDestroy())
|
||||||
@ -3090,7 +3011,7 @@ void VulkanRenderer::releaseDestructibleObject(VKRDestructibleObject* destructib
|
|||||||
m_spinlockDestructionQueue.unlock();
|
m_spinlockDestructionQueue.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::ProcessDestructionQueue2()
|
void VulkanRenderer::ProcessDestructionQueue()
|
||||||
{
|
{
|
||||||
m_spinlockDestructionQueue.lock();
|
m_spinlockDestructionQueue.lock();
|
||||||
for (auto it = m_destructionQueue.begin(); it != m_destructionQueue.end();)
|
for (auto it = m_destructionQueue.begin(); it != m_destructionQueue.end();)
|
||||||
@ -3139,7 +3060,7 @@ VkDescriptorSetInfo::~VkDescriptorSetInfo()
|
|||||||
performanceMonitor.vk.numDescriptorDynUniformBuffers.decrement(statsNumDynUniformBuffers);
|
performanceMonitor.vk.numDescriptorDynUniformBuffers.decrement(statsNumDynUniformBuffers);
|
||||||
performanceMonitor.vk.numDescriptorStorageBuffers.decrement(statsNumStorageBuffers);
|
performanceMonitor.vk.numDescriptorStorageBuffers.decrement(statsNumStorageBuffers);
|
||||||
|
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(m_vkObjDescriptorSet);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_vkObjDescriptorSet);
|
||||||
m_vkObjDescriptorSet = nullptr;
|
m_vkObjDescriptorSet = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,6 @@ public:
|
|||||||
void DrawEmptyFrame(bool mainWindow) override;
|
void DrawEmptyFrame(bool mainWindow) override;
|
||||||
void PreparePresentationFrame(bool mainWindow);
|
void PreparePresentationFrame(bool mainWindow);
|
||||||
|
|
||||||
void ProcessDestructionQueues(size_t commandBufferIndex);
|
|
||||||
void InitFirstCommandBuffer();
|
void InitFirstCommandBuffer();
|
||||||
void ProcessFinishedCommandBuffers();
|
void ProcessFinishedCommandBuffers();
|
||||||
void WaitForNextFinishedCommandBuffer();
|
void WaitForNextFinishedCommandBuffer();
|
||||||
@ -244,15 +243,9 @@ public:
|
|||||||
bool HasCommandBufferFinished(uint64 commandBufferId) const;
|
bool HasCommandBufferFinished(uint64 commandBufferId) const;
|
||||||
void WaitCommandBufferFinished(uint64 commandBufferId);
|
void WaitCommandBufferFinished(uint64 commandBufferId);
|
||||||
|
|
||||||
// clean up (deprecated)
|
// resource destruction queue
|
||||||
void destroyViewDepr(VkImageView imageView);
|
void ReleaseDestructibleObject(VKRDestructibleObject* destructibleObject);
|
||||||
void destroyBuffer(VkBuffer buffer);
|
void ProcessDestructionQueue();
|
||||||
void destroyDeviceMemory(VkDeviceMemory mem);
|
|
||||||
void destroyPipelineInfo(PipelineInfo* pipelineInfo);
|
|
||||||
void destroyShader(RendererShaderVk* shader);
|
|
||||||
// clean up (new)
|
|
||||||
void releaseDestructibleObject(VKRDestructibleObject* destructibleObject);
|
|
||||||
void ProcessDestructionQueue2();
|
|
||||||
|
|
||||||
FSpinlock m_spinlockDestructionQueue;
|
FSpinlock m_spinlockDestructionQueue;
|
||||||
std::vector<VKRDestructibleObject*> m_destructionQueue;
|
std::vector<VKRDestructibleObject*> m_destructionQueue;
|
||||||
@ -290,9 +283,6 @@ public:
|
|||||||
|
|
||||||
TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) override;
|
TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) override;
|
||||||
|
|
||||||
void texture_reserveTextureOnGPU(LatteTexture* hostTexture) override;
|
|
||||||
void texture_destroy(LatteTexture* hostTexture) override;
|
|
||||||
|
|
||||||
void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) override;
|
void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) override;
|
||||||
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
|
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
|
||||||
void texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) override;
|
void texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) override;
|
||||||
@ -634,15 +624,6 @@ private:
|
|||||||
// command buffer, garbage collection, synchronization
|
// command buffer, garbage collection, synchronization
|
||||||
static constexpr uint32 kCommandBufferPoolSize = 128;
|
static constexpr uint32 kCommandBufferPoolSize = 128;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
std::array<std::vector<VkDescriptorSet>, kCommandBufferPoolSize> m_cmd_descriptor_set_objects;
|
|
||||||
std::array<std::vector<VkImageView>, kCommandBufferPoolSize> m_cmd_image_views;
|
|
||||||
std::array<std::vector<LatteTextureVk*>, kCommandBufferPoolSize> m_host_textures;
|
|
||||||
std::array<std::vector<VkBuffer>, kCommandBufferPoolSize> m_buffers;
|
|
||||||
std::array<std::vector<VkDeviceMemory>, kCommandBufferPoolSize> m_memory;
|
|
||||||
}m_destructionQueues;
|
|
||||||
|
|
||||||
size_t m_commandBufferIndex = 0; // current buffer being filled
|
size_t m_commandBufferIndex = 0; // current buffer being filled
|
||||||
size_t m_commandBufferSyncIndex = 0; // latest buffer that finished execution (updated on submit)
|
size_t m_commandBufferSyncIndex = 0; // latest buffer that finished execution (updated on submit)
|
||||||
std::array<VkFence, kCommandBufferPoolSize> m_cmd_buffer_fences;
|
std::array<VkFence, kCommandBufferPoolSize> m_cmd_buffer_fences;
|
||||||
|
@ -813,9 +813,9 @@ void VulkanRenderer::surfaceCopy_notifyTextureRelease(LatteTextureVk* hostTextur
|
|||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjDescriptorSet);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjDescriptorSet);
|
||||||
p->vkObjDescriptorSet = nullptr;
|
p->vkObjDescriptorSet = nullptr;
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjImageView);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjImageView);
|
||||||
p->vkObjImageView = nullptr;
|
p->vkObjImageView = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -829,9 +829,9 @@ void VulkanRenderer::surfaceCopy_notifyTextureRelease(LatteTextureVk* hostTextur
|
|||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjFramebuffer);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjFramebuffer);
|
||||||
p->vkObjFramebuffer = nullptr;
|
p->vkObjFramebuffer = nullptr;
|
||||||
VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjImageView);
|
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjImageView);
|
||||||
p->vkObjImageView = nullptr;
|
p->vkObjImageView = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,18 +245,13 @@ static void check_vk_result(VkResult err)
|
|||||||
|
|
||||||
static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
|
static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
|
||||||
{
|
{
|
||||||
VulkanRenderer* vkRenderer = VulkanRenderer::GetInstance();
|
|
||||||
|
|
||||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||||
|
vkDeviceWaitIdle(v->Device); // make sure previously created buffer is not in use anymore
|
||||||
VkResult err;
|
VkResult err;
|
||||||
if (buffer != VK_NULL_HANDLE)
|
if (buffer != VK_NULL_HANDLE)
|
||||||
{
|
vkDestroyBuffer(v->Device, buffer, v->Allocator);
|
||||||
vkRenderer->destroyBuffer(buffer);
|
|
||||||
}
|
|
||||||
if (buffer_memory != VK_NULL_HANDLE)
|
if (buffer_memory != VK_NULL_HANDLE)
|
||||||
{
|
vkFreeMemory(v->Device, buffer_memory, v->Allocator);
|
||||||
vkRenderer->destroyDeviceMemory(buffer_memory);
|
|
||||||
}
|
|
||||||
VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment;
|
VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment;
|
||||||
VkBufferCreateInfo buffer_info = {};
|
VkBufferCreateInfo buffer_info = {};
|
||||||
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
Loading…
Reference in New Issue
Block a user