mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-11 01:25:15 +02:00
108 lines
3.6 KiB
C++
108 lines
3.6 KiB
C++
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h"
|
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
|
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
|
|
|
LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, 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(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer)
|
|
{
|
|
NS_STACK_SCOPED MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
|
|
desc->setStorageMode(MTL::StorageModePrivate);
|
|
//desc->setCpuCacheMode(MTL::CPUCacheModeWriteCombined);
|
|
|
|
sint32 effectiveBaseWidth = width;
|
|
sint32 effectiveBaseHeight = height;
|
|
sint32 effectiveBaseDepth = depth;
|
|
if (overwriteInfo.hasResolutionOverwrite)
|
|
{
|
|
effectiveBaseWidth = overwriteInfo.width;
|
|
effectiveBaseHeight = overwriteInfo.height;
|
|
effectiveBaseDepth = overwriteInfo.depth;
|
|
}
|
|
effectiveBaseWidth = std::max(1, effectiveBaseWidth);
|
|
effectiveBaseHeight = std::max(1, effectiveBaseHeight);
|
|
effectiveBaseDepth = std::max(1, effectiveBaseDepth);
|
|
|
|
MTL::TextureType textureType;
|
|
switch (dim)
|
|
{
|
|
case Latte::E_DIM::DIM_1D:
|
|
textureType = MTL::TextureType1D;
|
|
effectiveBaseHeight = 1;
|
|
break;
|
|
case Latte::E_DIM::DIM_2D:
|
|
case Latte::E_DIM::DIM_2D_MSAA:
|
|
textureType = MTL::TextureType2D;
|
|
break;
|
|
case Latte::E_DIM::DIM_2D_ARRAY:
|
|
textureType = MTL::TextureType2DArray;
|
|
break;
|
|
case Latte::E_DIM::DIM_3D:
|
|
textureType = MTL::TextureType3D;
|
|
break;
|
|
case Latte::E_DIM::DIM_CUBEMAP:
|
|
cemu_assert_debug(effectiveBaseDepth % 6 == 0 && "cubemaps must have an array length multiple of 6");
|
|
|
|
textureType = MTL::TextureTypeCubeArray;
|
|
break;
|
|
default:
|
|
cemu_assert_unimplemented();
|
|
textureType = MTL::TextureType2D;
|
|
break;
|
|
}
|
|
desc->setTextureType(textureType);
|
|
|
|
// Clamp mip levels
|
|
mipLevels = std::min(mipLevels, (uint32)maxPossibleMipLevels);
|
|
mipLevels = std::max(mipLevels, (uint32)1);
|
|
|
|
desc->setWidth(effectiveBaseWidth);
|
|
desc->setHeight(effectiveBaseHeight);
|
|
desc->setMipmapLevelCount(mipLevels);
|
|
|
|
if (textureType == MTL::TextureType3D)
|
|
{
|
|
desc->setDepth(effectiveBaseDepth);
|
|
}
|
|
else if (textureType == MTL::TextureTypeCubeArray)
|
|
{
|
|
desc->setArrayLength(effectiveBaseDepth / 6);
|
|
}
|
|
else if (textureType == MTL::TextureType2DArray)
|
|
{
|
|
desc->setArrayLength(effectiveBaseDepth);
|
|
}
|
|
|
|
auto pixelFormat = GetMtlPixelFormat(format, isDepth);
|
|
desc->setPixelFormat(pixelFormat);
|
|
|
|
MTL::TextureUsage usage = MTL::TextureUsageShaderRead | MTL::TextureUsagePixelFormatView;
|
|
if (FormatIsRenderable(format))
|
|
usage |= MTL::TextureUsageRenderTarget;
|
|
desc->setUsage(usage);
|
|
|
|
m_texture = mtlRenderer->GetDevice()->newTexture(desc);
|
|
}
|
|
|
|
LatteTextureMtl::~LatteTextureMtl()
|
|
{
|
|
m_texture->release();
|
|
}
|
|
|
|
LatteTextureView* LatteTextureMtl::CreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
|
|
{
|
|
cemu_assert_debug(mipCount > 0);
|
|
cemu_assert_debug(sliceCount > 0);
|
|
cemu_assert_debug((firstMip + mipCount) <= this->mipLevels);
|
|
cemu_assert_debug((firstSlice + sliceCount) <= this->depth);
|
|
|
|
return new LatteTextureViewMtl(m_mtlr, this, dim, format, firstMip, mipCount, firstSlice, sliceCount);
|
|
}
|
|
|
|
// TODO: lazy allocation?
|
|
void LatteTextureMtl::AllocateOnHost()
|
|
{
|
|
// The texture is already allocated
|
|
}
|