mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 20:44:18 +01:00
fix: 3D texture copies & fix: present filter
This commit is contained in:
parent
3f52f3acfe
commit
4b7c01ee2a
@ -699,6 +699,7 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
||||
cemu_assert_debug(false);
|
||||
outputCount = count + 1;
|
||||
}
|
||||
/*
|
||||
else if (primitiveMode == LattePrimitiveMode::TRIANGLE_FAN && g_renderer->GetType() == RendererAPI::Metal)
|
||||
{
|
||||
if (indexType == LatteIndexType::AUTO)
|
||||
@ -722,6 +723,7 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
||||
cemu_assert_debug(false);
|
||||
outputCount = count;
|
||||
}
|
||||
*/
|
||||
else
|
||||
{
|
||||
if (indexType == LatteIndexType::U16_BE)
|
||||
|
@ -934,7 +934,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
|
||||
{
|
||||
sint32 scaling_filter = downscaling ? GetConfig().downscale_filter : GetConfig().upscale_filter;
|
||||
|
||||
if (g_renderer->GetType() == RendererAPI::Vulkan)
|
||||
if (g_renderer->GetType() == RendererAPI::Vulkan || g_renderer->GetType() == RendererAPI::Metal)
|
||||
{
|
||||
// force linear or nearest neighbor filter
|
||||
if(scaling_filter != kLinearFilter && scaling_filter != kNearestNeighborFilter)
|
||||
|
@ -6,10 +6,12 @@
|
||||
LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextureMtl* texture, Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
|
||||
: LatteTextureView(texture, firstMip, mipCount, firstSlice, sliceCount, dim, format), m_mtlr(mtlRenderer), m_baseTexture(texture)
|
||||
{
|
||||
m_rgbaView = CreateSwizzledView(RGBA_SWIZZLE);
|
||||
}
|
||||
|
||||
LatteTextureViewMtl::~LatteTextureViewMtl()
|
||||
{
|
||||
m_rgbaView->release();
|
||||
for (sint32 i = 0; i < std::size(m_viewCache); i++)
|
||||
{
|
||||
if (m_viewCache[i].key != INVALID_SWIZZLE)
|
||||
@ -30,7 +32,7 @@ MTL::Texture* LatteTextureViewMtl::GetSwizzledView(uint32 gpuSamplerSwizzle)
|
||||
// RGBA swizzle == no swizzle
|
||||
if (gpuSamplerSwizzle == RGBA_SWIZZLE)
|
||||
{
|
||||
return m_baseTexture->GetTexture();
|
||||
return m_rgbaView;
|
||||
}
|
||||
|
||||
// First, try to find a view in the cache
|
||||
|
@ -26,6 +26,7 @@ private:
|
||||
|
||||
class LatteTextureMtl* m_baseTexture;
|
||||
|
||||
MTL::Texture* m_rgbaView;
|
||||
struct {
|
||||
uint32 key;
|
||||
MTL::Texture* texture;
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||
#include "Cemu/Logging/CemuDebugLogging.h"
|
||||
#include "Common/precompiled.h"
|
||||
#include "Metal/MTLPixelFormat.hpp"
|
||||
#include "gui/guiWrapper.h"
|
||||
|
||||
#define COMMIT_TRESHOLD 256
|
||||
@ -32,6 +31,10 @@ MetalRenderer::MetalRenderer()
|
||||
|
||||
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
|
||||
m_nearestSampler = m_device->newSamplerState(samplerDescriptor);
|
||||
|
||||
samplerDescriptor->setMinFilter(MTL::SamplerMinMagFilterLinear);
|
||||
samplerDescriptor->setMagFilter(MTL::SamplerMinMagFilterLinear);
|
||||
m_linearSampler = m_device->newSamplerState(samplerDescriptor);
|
||||
samplerDescriptor->release();
|
||||
|
||||
m_memoryManager = new MetalMemoryManager(this);
|
||||
@ -109,6 +112,7 @@ MetalRenderer::~MetalRenderer()
|
||||
delete m_memoryManager;
|
||||
|
||||
m_nearestSampler->release();
|
||||
m_linearSampler->release();
|
||||
|
||||
m_readbackBuffer->release();
|
||||
|
||||
@ -200,25 +204,26 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
|
||||
if (!AcquireNextDrawable(!padView))
|
||||
return;
|
||||
|
||||
if (clearBackground)
|
||||
ClearColorbuffer(padView);
|
||||
|
||||
MTL::Texture* presentTexture = static_cast<LatteTextureViewMtl*>(texView)->GetRGBAView();
|
||||
|
||||
// Create render pass
|
||||
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
|
||||
renderPassDescriptor->colorAttachments()->object(0)->setTexture(m_drawable->texture());
|
||||
auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
|
||||
colorAttachment->setTexture(m_drawable->texture());
|
||||
// TODO: shouldn't it be LoadActionLoad when not clearing?
|
||||
colorAttachment->setLoadAction(clearBackground ? MTL::LoadActionClear : MTL::LoadActionDontCare);
|
||||
colorAttachment->setStoreAction(MTL::StoreActionStore);
|
||||
|
||||
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
||||
colorRenderTargets[0] = m_drawable->texture();
|
||||
// If there was already an encoder with these attachment, we should set the viewport and scissor to default, but that shouldn't happen
|
||||
auto renderCommandEncoder = GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, nullptr, false, false);
|
||||
auto renderCommandEncoder = GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, nullptr, clearBackground, false);
|
||||
renderPassDescriptor->release();
|
||||
|
||||
// Draw to Metal layer
|
||||
renderCommandEncoder->setRenderPipelineState(m_state.m_usesSRGB ? m_presentPipelineSRGB : m_presentPipelineLinear);
|
||||
renderCommandEncoder->setFragmentTexture(presentTexture, 0);
|
||||
renderCommandEncoder->setFragmentSamplerState(m_nearestSampler, 0);
|
||||
renderCommandEncoder->setFragmentSamplerState((useLinearTexFilter ? m_linearSampler : m_nearestSampler), 0);
|
||||
|
||||
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
|
||||
}
|
||||
@ -314,11 +319,19 @@ void MetalRenderer::texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIn
|
||||
|
||||
void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize)
|
||||
{
|
||||
auto mtlTexture = (LatteTextureMtl*)hostTexture;
|
||||
auto textureMtl = (LatteTextureMtl*)hostTexture;
|
||||
|
||||
size_t bytesPerRow = GetMtlTextureBytesPerRow(mtlTexture->GetFormat(), mtlTexture->IsDepth(), width);
|
||||
size_t bytesPerImage = GetMtlTextureBytesPerImage(mtlTexture->GetFormat(), mtlTexture->IsDepth(), height, bytesPerRow);
|
||||
mtlTexture->GetTexture()->replaceRegion(MTL::Region(0, 0, width, height), mipIndex, sliceIndex, pixelData, bytesPerRow, bytesPerImage);
|
||||
uint32 offsetZ = 0;
|
||||
if (textureMtl->Is3DTexture())
|
||||
{
|
||||
offsetZ = sliceIndex;
|
||||
sliceIndex = 0;
|
||||
}
|
||||
|
||||
size_t bytesPerRow = GetMtlTextureBytesPerRow(textureMtl->GetFormat(), textureMtl->IsDepth(), width);
|
||||
// No need to calculate bytesPerImage for 3D textures, since we always load just one slice
|
||||
//size_t bytesPerImage = GetMtlTextureBytesPerImage(textureMtl->GetFormat(), textureMtl->IsDepth(), height, bytesPerRow);
|
||||
textureMtl->GetTexture()->replaceRegion(MTL::Region(0, 0, offsetZ, width, height, 1), mipIndex, sliceIndex, pixelData, bytesPerRow, 0);
|
||||
}
|
||||
|
||||
void MetalRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a)
|
||||
@ -409,11 +422,12 @@ void MetalRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, s
|
||||
|
||||
// If copying whole textures, we can do a more efficient copy
|
||||
if (effectiveSrcX == 0 && effectiveSrcY == 0 && effectiveDstX == 0 && effectiveDstY == 0 &&
|
||||
effectiveCopyWidth == src->GetMipWidth(srcMip) && effectiveCopyHeight == src->GetMipHeight(srcMip) &&
|
||||
effectiveCopyWidth == dst->GetMipWidth(dstMip) && effectiveCopyHeight == dst->GetMipHeight(dstMip) &&
|
||||
srcOffsetZ == 0 && dstOffsetZ == 0 &&
|
||||
effectiveCopyWidth == src->GetMipWidth(srcMip) && effectiveCopyHeight == src->GetMipHeight(srcMip) && srcDepth == src->GetMipDepth(srcMip) &&
|
||||
effectiveCopyWidth == dst->GetMipWidth(dstMip) && effectiveCopyHeight == dst->GetMipHeight(dstMip) && dstDepth == dst->GetMipDepth(dstMip) &&
|
||||
srcLayerCount == dstLayerCount)
|
||||
{
|
||||
blitCommandEncoder->copyFromTexture(mtlSrc, srcSlice, srcMip, mtlDst, dstSlice, dstMip, srcLayerCount, 1);
|
||||
blitCommandEncoder->copyFromTexture(mtlSrc, srcBaseLayer, srcMip, mtlDst, dstBaseLayer, dstMip, srcLayerCount, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -421,7 +435,7 @@ void MetalRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, s
|
||||
{
|
||||
for (uint32 i = 0; i < srcLayerCount; i++)
|
||||
{
|
||||
blitCommandEncoder->copyFromTexture(mtlSrc, srcSlice + i, srcMip, MTL::Origin(effectiveSrcX, effectiveSrcY, srcOffsetZ), MTL::Size(effectiveCopyWidth, effectiveCopyHeight, 1), mtlDst, dstSlice + i, dstMip, MTL::Origin(effectiveDstX, effectiveDstY, dstOffsetZ));
|
||||
blitCommandEncoder->copyFromTexture(mtlSrc, srcBaseLayer + i, srcMip, MTL::Origin(effectiveSrcX, effectiveSrcY, srcOffsetZ), MTL::Size(effectiveCopyWidth, effectiveCopyHeight, srcDepth), mtlDst, dstBaseLayer + i, dstMip, MTL::Origin(effectiveDstX, effectiveDstY, dstOffsetZ));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -438,7 +452,7 @@ void MetalRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, s
|
||||
else
|
||||
dstSlice++;
|
||||
|
||||
blitCommandEncoder->copyFromTexture(mtlSrc, srcSlice, srcMip, MTL::Origin(effectiveSrcX, effectiveSrcY, srcOffsetZ), MTL::Size(effectiveCopyWidth, effectiveCopyHeight, 1), mtlDst, dstSlice, dstMip, MTL::Origin(effectiveDstX, effectiveDstY, dstOffsetZ));
|
||||
blitCommandEncoder->copyFromTexture(mtlSrc, srcBaseLayer, srcMip, MTL::Origin(effectiveSrcX, effectiveSrcY, srcOffsetZ), MTL::Size(effectiveCopyWidth, effectiveCopyHeight, 1), mtlDst, dstBaseLayer, dstMip, MTL::Origin(effectiveDstX, effectiveDstY, dstOffsetZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -288,6 +288,7 @@ private:
|
||||
|
||||
// Basic
|
||||
MTL::SamplerState* m_nearestSampler;
|
||||
MTL::SamplerState* m_linearSampler;
|
||||
|
||||
// Texture readback
|
||||
MTL::Buffer* m_readbackBuffer;
|
||||
|
Loading…
Reference in New Issue
Block a user