mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-19 04:37:05 +00:00
don't bind textures and buffers which are already bound
This commit is contained in:
parent
ed7354fa1b
commit
9a215e064f
5 changed files with 119 additions and 60 deletions
|
|
@ -16,6 +16,7 @@
|
|||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||
#include "Cemu/Logging/CemuDebugLogging.h"
|
||||
#include "Common/precompiled.h"
|
||||
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||
#include "Metal/MTLRenderPass.hpp"
|
||||
#include "gui/guiWrapper.h"
|
||||
|
||||
|
|
@ -49,12 +50,10 @@ MetalRenderer::MetalRenderer()
|
|||
m_xfbRingBuffer = m_device->newBuffer(LatteStreamout_GetRingBufferSize(), MTL::StorageModeShared);
|
||||
|
||||
// Initialize state
|
||||
for (uint32 i = 0; i < (uint32)LatteConst::ShaderType::TotalCount; i++)
|
||||
for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++)
|
||||
{
|
||||
for (uint32 j = 0; j < MAX_MTL_BUFFERS; j++)
|
||||
{
|
||||
m_state.m_uniformBufferOffsets[i][j] = INVALID_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
// Utility shader library
|
||||
|
|
@ -63,7 +62,7 @@ MetalRenderer::MetalRenderer()
|
|||
std::string processedUtilityShaderSource = utilityShaderSource;
|
||||
processedUtilityShaderSource.pop_back();
|
||||
processedUtilityShaderSource.erase(processedUtilityShaderSource.begin());
|
||||
processedUtilityShaderSource = "#include <metal_stdlib>\n" + processedUtilityShaderSource;
|
||||
processedUtilityShaderSource = "#include <metal_stdlib>\nusing namespace metal;\n#define GET_BUFFER_BINDING(index) (27 + index)\n#define GET_TEXTURE_BINDING(index) (29 + index)\n#define GET_SAMPLER_BINDING(index) (14 + index)\n" + processedUtilityShaderSource;
|
||||
|
||||
// Create the library
|
||||
NS::Error* error = nullptr;
|
||||
|
|
@ -233,8 +232,8 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
|
|||
|
||||
// Draw to Metal layer
|
||||
renderCommandEncoder->setRenderPipelineState(m_state.m_usesSRGB ? m_presentPipelineSRGB : m_presentPipelineLinear);
|
||||
renderCommandEncoder->setFragmentTexture(presentTexture, 0);
|
||||
renderCommandEncoder->setFragmentSamplerState((useLinearTexFilter ? m_linearSampler : m_nearestSampler), 0);
|
||||
renderCommandEncoder->setFragmentTexture(presentTexture, GET_HELPER_TEXTURE_BINDING(0));
|
||||
renderCommandEncoder->setFragmentSamplerState((useLinearTexFilter ? m_linearSampler : m_nearestSampler), GET_HELPER_SAMPLER_BINDING(0));
|
||||
|
||||
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
|
||||
|
||||
|
|
@ -540,8 +539,8 @@ void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* so
|
|||
renderCommandEncoder->setViewport(MTL::Viewport{0.0, 0.0, (double)effectiveCopyWidth, (double)effectiveCopyHeight, 0.0, 1.0});
|
||||
renderCommandEncoder->setScissorRect(MTL::ScissorRect{0, 0, (uint32)effectiveCopyWidth, (uint32)effectiveCopyHeight});
|
||||
|
||||
renderCommandEncoder->setVertexTextures(textures, NS::Range(0, 2));
|
||||
renderCommandEncoder->setVertexBytes(¶ms, sizeof(params), 0);
|
||||
renderCommandEncoder->setVertexTextures(textures, NS::Range(GET_HELPER_BUFFER_BINDING(0), 2));
|
||||
renderCommandEncoder->setVertexBytes(¶ms, sizeof(params), GET_HELPER_BUFFER_BINDING(0));
|
||||
|
||||
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
|
||||
}
|
||||
|
|
@ -596,7 +595,7 @@ void MetalRenderer::buffer_bindVertexBuffer(uint32 bufferIndex, uint32 offset, u
|
|||
|
||||
void MetalRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size)
|
||||
{
|
||||
m_state.m_uniformBufferOffsets[(uint32)shaderType][bufferIndex] = offset;
|
||||
m_state.m_uniformBufferOffsets[GetMtlShaderType(shaderType)][bufferIndex] = offset;
|
||||
}
|
||||
|
||||
RendererShader* MetalRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader)
|
||||
|
|
@ -962,6 +961,8 @@ MTL::RenderCommandEncoder* MetalRenderer::GetRenderCommandEncoder(bool forceRecr
|
|||
m_commandEncoder = renderCommandEncoder;
|
||||
m_encoderType = MetalEncoderType::Render;
|
||||
|
||||
ResetEncoderState();
|
||||
|
||||
if (rebindStateIfNewEncoder)
|
||||
{
|
||||
// Rebind all the render state
|
||||
|
|
@ -989,6 +990,8 @@ MTL::ComputeCommandEncoder* MetalRenderer::GetComputeCommandEncoder()
|
|||
m_commandEncoder = computeCommandEncoder;
|
||||
m_encoderType = MetalEncoderType::Compute;
|
||||
|
||||
ResetEncoderState();
|
||||
|
||||
return computeCommandEncoder;
|
||||
}
|
||||
|
||||
|
|
@ -1010,6 +1013,8 @@ MTL::BlitCommandEncoder* MetalRenderer::GetBlitCommandEncoder()
|
|||
m_commandEncoder = blitCommandEncoder;
|
||||
m_encoderType = MetalEncoderType::Blit;
|
||||
|
||||
ResetEncoderState();
|
||||
|
||||
return blitCommandEncoder;
|
||||
}
|
||||
|
||||
|
|
@ -1075,8 +1080,9 @@ bool MetalRenderer::AcquireNextDrawable(bool mainWindow)
|
|||
|
||||
void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandEncoder, LatteDecompilerShader* shader)
|
||||
{
|
||||
sint32 textureCount = shader->resourceMapping.getTextureCount();
|
||||
auto mtlShaderType = GetMtlShaderType(shader->shaderType);
|
||||
|
||||
sint32 textureCount = shader->resourceMapping.getTextureCount();
|
||||
for (int i = 0; i < textureCount; ++i)
|
||||
{
|
||||
const auto relative_textureUnit = shader->resourceMapping.getTextureUnitFromBindingPoint(i);
|
||||
|
|
@ -1108,24 +1114,16 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||
continue;
|
||||
}
|
||||
|
||||
LatteTexture* baseTexture = textureView->baseTexture;
|
||||
// get texture register word 0
|
||||
uint32 word4 = LatteGPUState.contextRegister[texUnitRegIndex + 4];
|
||||
|
||||
// TODO: wht
|
||||
//auto imageViewObj = textureView->GetSamplerView(word4);
|
||||
//info.imageView = imageViewObj->m_textureImageView;
|
||||
|
||||
// TODO: uncomment
|
||||
uint32 binding = shader->resourceMapping.getTextureBaseBindingPoint() + i;//shader->resourceMapping.textureUnitToBindingPoint[hostTextureUnit];
|
||||
//uint32 textureBinding = binding % MAX_MTL_TEXTURES;
|
||||
//uint32 samplerBinding = binding % MAX_MTL_SAMPLERS;
|
||||
if (binding >= MAX_MTL_TEXTURES)
|
||||
{
|
||||
debug_printf("invalid texture binding %u\n", binding);
|
||||
continue;
|
||||
}
|
||||
|
||||
LatteTexture* baseTexture = textureView->baseTexture;
|
||||
|
||||
uint32 stageSamplerIndex = shader->textureUnitSamplerAssignment[relative_textureUnit];
|
||||
if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE)
|
||||
{
|
||||
|
|
@ -1249,6 +1247,14 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||
sampler->release();
|
||||
}
|
||||
|
||||
// get texture register word 0
|
||||
uint32 word4 = LatteGPUState.contextRegister[texUnitRegIndex + 4];
|
||||
auto& boundTexture = m_state.m_encoderState.m_textures[mtlShaderType][binding];
|
||||
if (textureView == boundTexture.m_textureView && word4 == boundTexture.m_word4)
|
||||
continue;
|
||||
|
||||
boundTexture = {textureView, word4};
|
||||
|
||||
MTL::Texture* mtlTexture = textureView->GetSwizzledView(word4);
|
||||
switch (shader->shaderType)
|
||||
{
|
||||
|
|
@ -1376,28 +1382,36 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||
uint32 binding = shader->resourceMapping.uniformBuffersBindingPoint[i];
|
||||
if (binding >= MAX_MTL_BUFFERS)
|
||||
{
|
||||
debug_printf("too big buffer index (%u), skipping binding\n", binding);
|
||||
debug_printf("invalid buffer binding%u\n", binding);
|
||||
continue;
|
||||
}
|
||||
size_t offset = m_state.m_uniformBufferOffsets[(uint32)shader->shaderType][i];
|
||||
if (offset != INVALID_OFFSET)
|
||||
{
|
||||
switch (shader->shaderType)
|
||||
{
|
||||
case LatteConst::ShaderType::Vertex:
|
||||
{
|
||||
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
break;
|
||||
}
|
||||
case LatteConst::ShaderType::Pixel:
|
||||
{
|
||||
renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
size_t offset = m_state.m_uniformBufferOffsets[mtlShaderType][i];
|
||||
if (offset == INVALID_OFFSET)
|
||||
continue;
|
||||
|
||||
auto& boundOffset = m_state.m_encoderState.m_uniformBufferOffsets[mtlShaderType][binding];
|
||||
if (offset == boundOffset)
|
||||
continue;
|
||||
|
||||
boundOffset = offset;
|
||||
|
||||
// TODO: only set the offset if already bound
|
||||
switch (shader->shaderType)
|
||||
{
|
||||
case LatteConst::ShaderType::Vertex:
|
||||
{
|
||||
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
break;
|
||||
}
|
||||
case LatteConst::ShaderType::Pixel:
|
||||
{
|
||||
renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue