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) 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");

View File

@ -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;

View File

@ -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;
} }