mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-01 21:44:17 +01:00
fix: viewport and scissor
This commit is contained in:
parent
1fbd6ad376
commit
d4564c18f2
@ -80,6 +80,11 @@ void MetalMemoryManager::InitBufferCache(size_t size)
|
|||||||
|
|
||||||
void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, size_t size)
|
void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, size_t size)
|
||||||
{
|
{
|
||||||
|
if ((offset + size) > m_bufferCache->length())
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::to_string(offset) + " + " + std::to_string(size) + " > " + std::to_string(m_bufferCache->length()));
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_bufferCache)
|
if (!m_bufferCache)
|
||||||
{
|
{
|
||||||
printf("MetalMemoryManager::UploadToBufferCache: buffer cache not initialized\n");
|
printf("MetalMemoryManager::UploadToBufferCache: buffer cache not initialized\n");
|
||||||
|
@ -29,6 +29,15 @@ MetalRenderer::MetalRenderer()
|
|||||||
m_nearestSampler = m_device->newSamplerState(samplerDescriptor);
|
m_nearestSampler = m_device->newSamplerState(samplerDescriptor);
|
||||||
|
|
||||||
m_memoryManager = new MetalMemoryManager(this);
|
m_memoryManager = new MetalMemoryManager(this);
|
||||||
|
|
||||||
|
// Initialize state
|
||||||
|
for (uint32 i = 0; i < (uint32)LatteConst::ShaderType::TotalCount; i++)
|
||||||
|
{
|
||||||
|
for (uint32 j = 0; j < MAX_MTL_BUFFERS; j++)
|
||||||
|
{
|
||||||
|
m_state.uniformBufferOffsets[i][j] = INVALID_OFFSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalRenderer::~MetalRenderer()
|
MetalRenderer::~MetalRenderer()
|
||||||
@ -149,7 +158,8 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
|
|||||||
|
|
||||||
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
||||||
colorRenderTargets[0] = m_drawable->texture();
|
colorRenderTargets[0] = m_drawable->texture();
|
||||||
auto renderCommandEncoder = GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, nullptr);
|
// 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);
|
||||||
|
|
||||||
// Draw to Metal layer
|
// Draw to Metal layer
|
||||||
renderCommandEncoder->setRenderPipelineState(m_presentPipeline);
|
renderCommandEncoder->setRenderPipelineState(m_presentPipeline);
|
||||||
@ -435,7 +445,7 @@ void MetalRenderer::buffer_bindVertexBuffer(uint32 bufferIndex, uint32 offset, u
|
|||||||
|
|
||||||
void MetalRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size)
|
void MetalRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size)
|
||||||
{
|
{
|
||||||
printf("MetalRenderer::buffer_bindUniformBuffer not implemented\n");
|
m_state.uniformBufferOffsets[(uint32)shaderType][bufferIndex] = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererShader* MetalRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader)
|
RendererShader* MetalRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader)
|
||||||
@ -872,22 +882,29 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||||||
if (shader->resourceMapping.uniformBuffersBindingPoint[i] >= 0)
|
if (shader->resourceMapping.uniformBuffersBindingPoint[i] >= 0)
|
||||||
{
|
{
|
||||||
uint32 binding = shader->resourceMapping.uniformBuffersBindingPoint[i];
|
uint32 binding = shader->resourceMapping.uniformBuffersBindingPoint[i];
|
||||||
// TODO: don't hardcode
|
if (binding >= MAX_MTL_BUFFERS)
|
||||||
size_t offset = 0;
|
|
||||||
switch (shader->shaderType)
|
|
||||||
{
|
{
|
||||||
case LatteConst::ShaderType::Vertex:
|
printf("too big buffer index (%u), skipping binding\n", binding);
|
||||||
{
|
continue;
|
||||||
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case LatteConst::ShaderType::Pixel:
|
size_t offset = m_state.uniformBufferOffsets[(uint32)shader->shaderType][binding];
|
||||||
|
if (offset != INVALID_OFFSET)
|
||||||
{
|
{
|
||||||
renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
switch (shader->shaderType)
|
||||||
break;
|
{
|
||||||
}
|
case LatteConst::ShaderType::Vertex:
|
||||||
default:
|
{
|
||||||
UNREACHABLE;
|
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LatteConst::ShaderType::Pixel:
|
||||||
|
{
|
||||||
|
renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
UNREACHABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -896,10 +913,10 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||||||
void MetalRenderer::RebindRenderState(MTL::RenderCommandEncoder* renderCommandEncoder)
|
void MetalRenderer::RebindRenderState(MTL::RenderCommandEncoder* renderCommandEncoder)
|
||||||
{
|
{
|
||||||
// Viewport
|
// Viewport
|
||||||
if (m_state.viewport.width != 0.0)
|
//if (m_state.viewport.width != 0.0)
|
||||||
{
|
//{
|
||||||
printf("setting previous viewport X: %f Y: %f width: %f height %f\n", m_state.viewport.originX, m_state.viewport.originY, m_state.viewport.width, m_state.viewport.height);
|
renderCommandEncoder->setViewport(m_state.viewport);
|
||||||
renderCommandEncoder->setViewport(m_state.viewport);
|
/*
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -919,26 +936,27 @@ void MetalRenderer::RebindRenderState(MTL::RenderCommandEncoder* renderCommandEn
|
|||||||
{
|
{
|
||||||
framebufferWidth = texture->baseTexture->width;
|
framebufferWidth = texture->baseTexture->width;
|
||||||
framebufferHeight = texture->baseTexture->height;
|
framebufferHeight = texture->baseTexture->height;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MTL::Viewport viewport{0, (double)framebufferHeight, (double)framebufferWidth, -(double)framebufferHeight, 0.0, 1.0};
|
MTL::Viewport viewport{0, (double)framebufferHeight, (double)framebufferWidth, -(double)framebufferHeight, 0.0, 1.0};
|
||||||
printf("setting default viewport X: %f Y: %f width: %f height %f\n", viewport.originX, viewport.originY, viewport.width, viewport.height);
|
|
||||||
renderCommandEncoder->setViewport(viewport);
|
renderCommandEncoder->setViewport(viewport);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Scissor
|
// Scissor
|
||||||
if (m_state.scissor.width != 0)
|
//if (m_state.scissor.width != 0)
|
||||||
{
|
//{
|
||||||
renderCommandEncoder->setScissorRect(m_state.scissor);
|
renderCommandEncoder->setScissorRect(m_state.scissor);
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Vertex buffers
|
// Vertex buffers
|
||||||
for (uint8 i = 0; i < MAX_MTL_BUFFERS; i++)
|
for (uint8 i = 0; i < MAX_MTL_BUFFERS; i++)
|
||||||
{
|
{
|
||||||
auto& vertexBufferRange = m_state.vertexBuffers[i];
|
auto& vertexBufferRange = m_state.vertexBuffers[i];
|
||||||
if (vertexBufferRange.offset != -1)
|
if (vertexBufferRange.offset != INVALID_OFFSET)
|
||||||
{
|
{
|
||||||
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), vertexBufferRange.offset, GET_MTL_VERTEX_BUFFER_INDEX(i));
|
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), vertexBufferRange.offset, GET_MTL_VERTEX_BUFFER_INDEX(i));
|
||||||
vertexBufferRange.needsRebind = false;
|
vertexBufferRange.needsRebind = false;
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
|
|
||||||
#define MAX_MTL_TEXTURES 31
|
#define MAX_MTL_TEXTURES 31
|
||||||
|
|
||||||
|
constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
struct MetalBoundBuffer
|
struct MetalBoundBuffer
|
||||||
{
|
{
|
||||||
bool needsRebind = false;
|
bool needsRebind = false;
|
||||||
sint32 offset = -1;
|
size_t offset = INVALID_OFFSET;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MetalState
|
struct MetalState
|
||||||
@ -30,6 +32,7 @@ struct MetalState
|
|||||||
class CachedFBOMtl* activeFBO = nullptr;
|
class CachedFBOMtl* activeFBO = nullptr;
|
||||||
MetalBoundBuffer vertexBuffers[MAX_MTL_BUFFERS] = {{}};
|
MetalBoundBuffer vertexBuffers[MAX_MTL_BUFFERS] = {{}};
|
||||||
class LatteTextureViewMtl* textures[MAX_MTL_TEXTURES] = {nullptr};
|
class LatteTextureViewMtl* textures[MAX_MTL_TEXTURES] = {nullptr};
|
||||||
|
size_t uniformBufferOffsets[(uint32)LatteConst::ShaderType::TotalCount][MAX_MTL_BUFFERS];
|
||||||
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
||||||
MTL::Texture* depthRenderTarget = nullptr;
|
MTL::Texture* depthRenderTarget = nullptr;
|
||||||
MTL::Viewport viewport = {0, 0, 0, 0, 0, 0};
|
MTL::Viewport viewport = {0, 0, 0, 0, 0, 0};
|
||||||
@ -210,7 +213,7 @@ private:
|
|||||||
MTL::CommandBuffer* m_commandBuffer = nullptr;
|
MTL::CommandBuffer* m_commandBuffer = nullptr;
|
||||||
MetalEncoderType m_encoderType = MetalEncoderType::None;
|
MetalEncoderType m_encoderType = MetalEncoderType::None;
|
||||||
MTL::CommandEncoder* m_commandEncoder = nullptr;
|
MTL::CommandEncoder* m_commandEncoder = nullptr;
|
||||||
CA::MetalDrawable* m_drawable;
|
CA::MetalDrawable* m_drawable = nullptr;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
MetalState m_state;
|
MetalState m_state;
|
||||||
@ -227,7 +230,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MTL::RenderCommandEncoder* GetRenderCommandEncoder(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* colorRenderTargets[8], MTL::Texture* depthRenderTarget)
|
MTL::RenderCommandEncoder* GetRenderCommandEncoder(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* colorRenderTargets[8], MTL::Texture* depthRenderTarget, bool rebindStateIfNewEncoder = true)
|
||||||
{
|
{
|
||||||
EnsureCommandBuffer();
|
EnsureCommandBuffer();
|
||||||
|
|
||||||
@ -274,8 +277,11 @@ private:
|
|||||||
m_commandEncoder = renderCommandEncoder;
|
m_commandEncoder = renderCommandEncoder;
|
||||||
m_encoderType = MetalEncoderType::Render;
|
m_encoderType = MetalEncoderType::Render;
|
||||||
|
|
||||||
// Rebind all the render state
|
if (rebindStateIfNewEncoder)
|
||||||
RebindRenderState(renderCommandEncoder);
|
{
|
||||||
|
// Rebind all the render state
|
||||||
|
RebindRenderState(renderCommandEncoder);
|
||||||
|
}
|
||||||
|
|
||||||
return renderCommandEncoder;
|
return renderCommandEncoder;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user