fix: viewport and scissor

This commit is contained in:
Samuliak 2024-08-01 17:55:16 +02:00
parent 1fbd6ad376
commit d4564c18f2
3 changed files with 59 additions and 30 deletions

View File

@ -80,6 +80,11 @@ void MetalMemoryManager::InitBufferCache(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)
{
printf("MetalMemoryManager::UploadToBufferCache: buffer cache not initialized\n");

View File

@ -29,6 +29,15 @@ MetalRenderer::MetalRenderer()
m_nearestSampler = m_device->newSamplerState(samplerDescriptor);
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()
@ -149,7 +158,8 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
MTL::Texture* colorRenderTargets[8] = {nullptr};
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
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)
{
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)
@ -872,22 +882,29 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
if (shader->resourceMapping.uniformBuffersBindingPoint[i] >= 0)
{
uint32 binding = shader->resourceMapping.uniformBuffersBindingPoint[i];
// TODO: don't hardcode
size_t offset = 0;
switch (shader->shaderType)
if (binding >= MAX_MTL_BUFFERS)
{
case LatteConst::ShaderType::Vertex:
{
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
break;
printf("too big buffer index (%u), skipping binding\n", binding);
continue;
}
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);
break;
}
default:
UNREACHABLE;
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;
}
}
}
}
@ -896,10 +913,10 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
void MetalRenderer::RebindRenderState(MTL::RenderCommandEncoder* renderCommandEncoder)
{
// Viewport
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);
//if (m_state.viewport.width != 0.0)
//{
renderCommandEncoder->setViewport(m_state.viewport);
/*
}
else
{
@ -919,26 +936,27 @@ void MetalRenderer::RebindRenderState(MTL::RenderCommandEncoder* renderCommandEn
{
framebufferWidth = texture->baseTexture->width;
framebufferHeight = texture->baseTexture->height;
break;
}
}
}
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);
}
*/
// Scissor
if (m_state.scissor.width != 0)
{
renderCommandEncoder->setScissorRect(m_state.scissor);
}
//if (m_state.scissor.width != 0)
//{
renderCommandEncoder->setScissorRect(m_state.scissor);
//}
// Vertex buffers
for (uint8 i = 0; i < MAX_MTL_BUFFERS; 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));
vertexBufferRange.needsRebind = false;

View File

@ -18,10 +18,12 @@
#define MAX_MTL_TEXTURES 31
constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
struct MetalBoundBuffer
{
bool needsRebind = false;
sint32 offset = -1;
size_t offset = INVALID_OFFSET;
};
struct MetalState
@ -30,6 +32,7 @@ struct MetalState
class CachedFBOMtl* activeFBO = nullptr;
MetalBoundBuffer vertexBuffers[MAX_MTL_BUFFERS] = {{}};
class LatteTextureViewMtl* textures[MAX_MTL_TEXTURES] = {nullptr};
size_t uniformBufferOffsets[(uint32)LatteConst::ShaderType::TotalCount][MAX_MTL_BUFFERS];
MTL::Texture* colorRenderTargets[8] = {nullptr};
MTL::Texture* depthRenderTarget = nullptr;
MTL::Viewport viewport = {0, 0, 0, 0, 0, 0};
@ -210,7 +213,7 @@ private:
MTL::CommandBuffer* m_commandBuffer = nullptr;
MetalEncoderType m_encoderType = MetalEncoderType::None;
MTL::CommandEncoder* m_commandEncoder = nullptr;
CA::MetalDrawable* m_drawable;
CA::MetalDrawable* m_drawable = nullptr;
// 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();
@ -274,8 +277,11 @@ private:
m_commandEncoder = renderCommandEncoder;
m_encoderType = MetalEncoderType::Render;
// Rebind all the render state
RebindRenderState(renderCommandEncoder);
if (rebindStateIfNewEncoder)
{
// Rebind all the render state
RebindRenderState(renderCommandEncoder);
}
return renderCommandEncoder;
}