mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-01 21:44:17 +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);
|
cemu_assert_debug(false);
|
||||||
outputCount = count + 1;
|
outputCount = count + 1;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
else if (primitiveMode == LattePrimitiveMode::TRIANGLE_FAN && g_renderer->GetType() == RendererAPI::Metal)
|
else if (primitiveMode == LattePrimitiveMode::TRIANGLE_FAN && g_renderer->GetType() == RendererAPI::Metal)
|
||||||
{
|
{
|
||||||
if (indexType == LatteIndexType::AUTO)
|
if (indexType == LatteIndexType::AUTO)
|
||||||
@ -722,6 +723,7 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|||||||
cemu_assert_debug(false);
|
cemu_assert_debug(false);
|
||||||
outputCount = count;
|
outputCount = count;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (indexType == LatteIndexType::U16_BE)
|
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;
|
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
|
// force linear or nearest neighbor filter
|
||||||
if(scaling_filter != kLinearFilter && scaling_filter != kNearestNeighborFilter)
|
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)
|
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)
|
: LatteTextureView(texture, firstMip, mipCount, firstSlice, sliceCount, dim, format), m_mtlr(mtlRenderer), m_baseTexture(texture)
|
||||||
{
|
{
|
||||||
|
m_rgbaView = CreateSwizzledView(RGBA_SWIZZLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
LatteTextureViewMtl::~LatteTextureViewMtl()
|
LatteTextureViewMtl::~LatteTextureViewMtl()
|
||||||
{
|
{
|
||||||
|
m_rgbaView->release();
|
||||||
for (sint32 i = 0; i < std::size(m_viewCache); i++)
|
for (sint32 i = 0; i < std::size(m_viewCache); i++)
|
||||||
{
|
{
|
||||||
if (m_viewCache[i].key != INVALID_SWIZZLE)
|
if (m_viewCache[i].key != INVALID_SWIZZLE)
|
||||||
@ -30,7 +32,7 @@ MTL::Texture* LatteTextureViewMtl::GetSwizzledView(uint32 gpuSamplerSwizzle)
|
|||||||
// RGBA swizzle == no swizzle
|
// RGBA swizzle == no swizzle
|
||||||
if (gpuSamplerSwizzle == RGBA_SWIZZLE)
|
if (gpuSamplerSwizzle == RGBA_SWIZZLE)
|
||||||
{
|
{
|
||||||
return m_baseTexture->GetTexture();
|
return m_rgbaView;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, try to find a view in the cache
|
// First, try to find a view in the cache
|
||||||
|
@ -26,6 +26,7 @@ private:
|
|||||||
|
|
||||||
class LatteTextureMtl* m_baseTexture;
|
class LatteTextureMtl* m_baseTexture;
|
||||||
|
|
||||||
|
MTL::Texture* m_rgbaView;
|
||||||
struct {
|
struct {
|
||||||
uint32 key;
|
uint32 key;
|
||||||
MTL::Texture* texture;
|
MTL::Texture* texture;
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||||
#include "Cemu/Logging/CemuDebugLogging.h"
|
#include "Cemu/Logging/CemuDebugLogging.h"
|
||||||
#include "Common/precompiled.h"
|
#include "Common/precompiled.h"
|
||||||
#include "Metal/MTLPixelFormat.hpp"
|
|
||||||
#include "gui/guiWrapper.h"
|
#include "gui/guiWrapper.h"
|
||||||
|
|
||||||
#define COMMIT_TRESHOLD 256
|
#define COMMIT_TRESHOLD 256
|
||||||
@ -32,6 +31,10 @@ MetalRenderer::MetalRenderer()
|
|||||||
|
|
||||||
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
|
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
|
||||||
m_nearestSampler = m_device->newSamplerState(samplerDescriptor);
|
m_nearestSampler = m_device->newSamplerState(samplerDescriptor);
|
||||||
|
|
||||||
|
samplerDescriptor->setMinFilter(MTL::SamplerMinMagFilterLinear);
|
||||||
|
samplerDescriptor->setMagFilter(MTL::SamplerMinMagFilterLinear);
|
||||||
|
m_linearSampler = m_device->newSamplerState(samplerDescriptor);
|
||||||
samplerDescriptor->release();
|
samplerDescriptor->release();
|
||||||
|
|
||||||
m_memoryManager = new MetalMemoryManager(this);
|
m_memoryManager = new MetalMemoryManager(this);
|
||||||
@ -109,6 +112,7 @@ MetalRenderer::~MetalRenderer()
|
|||||||
delete m_memoryManager;
|
delete m_memoryManager;
|
||||||
|
|
||||||
m_nearestSampler->release();
|
m_nearestSampler->release();
|
||||||
|
m_linearSampler->release();
|
||||||
|
|
||||||
m_readbackBuffer->release();
|
m_readbackBuffer->release();
|
||||||
|
|
||||||
@ -200,25 +204,26 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
|
|||||||
if (!AcquireNextDrawable(!padView))
|
if (!AcquireNextDrawable(!padView))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (clearBackground)
|
|
||||||
ClearColorbuffer(padView);
|
|
||||||
|
|
||||||
MTL::Texture* presentTexture = static_cast<LatteTextureViewMtl*>(texView)->GetRGBAView();
|
MTL::Texture* presentTexture = static_cast<LatteTextureViewMtl*>(texView)->GetRGBAView();
|
||||||
|
|
||||||
// Create render pass
|
// Create render pass
|
||||||
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
|
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};
|
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
||||||
colorRenderTargets[0] = m_drawable->texture();
|
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
|
// 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();
|
renderPassDescriptor->release();
|
||||||
|
|
||||||
// Draw to Metal layer
|
// Draw to Metal layer
|
||||||
renderCommandEncoder->setRenderPipelineState(m_state.m_usesSRGB ? m_presentPipelineSRGB : m_presentPipelineLinear);
|
renderCommandEncoder->setRenderPipelineState(m_state.m_usesSRGB ? m_presentPipelineSRGB : m_presentPipelineLinear);
|
||||||
renderCommandEncoder->setFragmentTexture(presentTexture, 0);
|
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));
|
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)
|
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);
|
uint32 offsetZ = 0;
|
||||||
size_t bytesPerImage = GetMtlTextureBytesPerImage(mtlTexture->GetFormat(), mtlTexture->IsDepth(), height, bytesPerRow);
|
if (textureMtl->Is3DTexture())
|
||||||
mtlTexture->GetTexture()->replaceRegion(MTL::Region(0, 0, width, height), mipIndex, sliceIndex, pixelData, bytesPerRow, bytesPerImage);
|
{
|
||||||
|
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)
|
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 copying whole textures, we can do a more efficient copy
|
||||||
if (effectiveSrcX == 0 && effectiveSrcY == 0 && effectiveDstX == 0 && effectiveDstY == 0 &&
|
if (effectiveSrcX == 0 && effectiveSrcY == 0 && effectiveDstX == 0 && effectiveDstY == 0 &&
|
||||||
effectiveCopyWidth == src->GetMipWidth(srcMip) && effectiveCopyHeight == src->GetMipHeight(srcMip) &&
|
srcOffsetZ == 0 && dstOffsetZ == 0 &&
|
||||||
effectiveCopyWidth == dst->GetMipWidth(dstMip) && effectiveCopyHeight == dst->GetMipHeight(dstMip) &&
|
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)
|
srcLayerCount == dstLayerCount)
|
||||||
{
|
{
|
||||||
blitCommandEncoder->copyFromTexture(mtlSrc, srcSlice, srcMip, mtlDst, dstSlice, dstMip, srcLayerCount, 1);
|
blitCommandEncoder->copyFromTexture(mtlSrc, srcBaseLayer, srcMip, mtlDst, dstBaseLayer, dstMip, srcLayerCount, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -421,7 +435,7 @@ void MetalRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, s
|
|||||||
{
|
{
|
||||||
for (uint32 i = 0; i < srcLayerCount; i++)
|
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
|
else
|
||||||
@ -438,7 +452,7 @@ void MetalRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, s
|
|||||||
else
|
else
|
||||||
dstSlice++;
|
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
|
// Basic
|
||||||
MTL::SamplerState* m_nearestSampler;
|
MTL::SamplerState* m_nearestSampler;
|
||||||
|
MTL::SamplerState* m_linearSampler;
|
||||||
|
|
||||||
// Texture readback
|
// Texture readback
|
||||||
MTL::Buffer* m_readbackBuffer;
|
MTL::Buffer* m_readbackBuffer;
|
||||||
|
Loading…
Reference in New Issue
Block a user