implement viewports

This commit is contained in:
Samuliak 2024-07-08 17:04:50 +02:00
parent db08f73530
commit d80ddafb24
3 changed files with 31 additions and 2 deletions

View file

@ -41,7 +41,7 @@ struct RenderTarget {
const u32 startOffset = (inputAddress - location) / sizePerPixel(format);
const u32 x0 = (startOffset % (size.x() * 8)) / 8;
const u32 y0 = (startOffset / (size.x() * 8)) * 8;
return Math::Rect<u32>{x0, y0, x0 + width, y0 + height};
return Math::Rect<u32>{x0, size.y() - y0, x0 + width, size.y() - height - y0};
}
// For 2 textures to "match" we only care about their locations, formats, and dimensions to match

View file

@ -376,6 +376,13 @@ void RendererMTL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize,
nextRenderPassName = "Display transfer";
beginRenderPassIfNeeded(renderPassDescriptor, false, destFramebuffer->texture);
renderCommandEncoder->setRenderPipelineState(blitPipeline);
// Viewport
renderCommandEncoder->setViewport(MTL::Viewport{double(destRect.left), double(destRect.bottom), double(destRect.right - destRect.left), double(destRect.top - destRect.bottom), 0.0, 1.0});
float srcRectNDC[4] = {srcRect.left / (float)srcFramebuffer->size.u(), srcRect.bottom / (float)srcFramebuffer->size.v(), (srcRect.right - srcRect.left) / (float)srcFramebuffer->size.u(), (srcRect.top - srcRect.bottom) / (float)srcFramebuffer->size.v()};
// Bind resources
renderCommandEncoder->setVertexBytes(&srcRectNDC, sizeof(srcRectNDC), 0);
renderCommandEncoder->setFragmentTexture(srcFramebuffer->texture, 0);
renderCommandEncoder->setFragmentSamplerState(nearestSampler, 0);
@ -460,6 +467,13 @@ void RendererMTL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32
nextRenderPassName = "Texture copy";
beginRenderPassIfNeeded(renderPassDescriptor, false, destFramebuffer->texture);
renderCommandEncoder->setRenderPipelineState(blitPipeline);
// Viewport
renderCommandEncoder->setViewport(MTL::Viewport{double(destRect.left), double(destRect.bottom), double(destRect.right - destRect.left), double(destRect.top - destRect.bottom), 0.0, 1.0});
float srcRectNDC[4] = {srcRect.left / (float)srcFramebuffer->size.u(), srcRect.bottom / (float)srcFramebuffer->size.v(), (srcRect.right - srcRect.left) / (float)srcFramebuffer->size.u(), (srcRect.top - srcRect.bottom) / (float)srcFramebuffer->size.v()};
// Bind resources
renderCommandEncoder->setVertexBytes(&srcRectNDC, sizeof(srcRectNDC), 0);
renderCommandEncoder->setFragmentTexture(srcFramebuffer->texture, 0);
renderCommandEncoder->setFragmentSamplerState(nearestSampler, 0);
@ -563,6 +577,15 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::span<const PICA::Ve
renderCommandEncoder->setVertexBuffer(buffer.buffer, buffer.offset, VERTEX_BUFFER_BINDING_INDEX);
}
// Viewport
const u32 viewportX = regs[PICA::InternalRegs::ViewportXY] & 0x3ff;
const u32 viewportY = (regs[PICA::InternalRegs::ViewportXY] >> 16) & 0x3ff;
const u32 viewportWidth = Floats::f24::fromRaw(regs[PICA::InternalRegs::ViewportWidth] & 0xffffff).toFloat32() * 2.0f;
const u32 viewportHeight = Floats::f24::fromRaw(regs[PICA::InternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0f;
const auto rect = colorRenderTarget->getSubRect(colourBufferLoc, fbSize[0], fbSize[1]);
MTL::Viewport viewport{double(rect.left + viewportX), double(rect.bottom + viewportY), double(viewportWidth), double(viewportHeight), 0.0, 1.0};
renderCommandEncoder->setViewport(viewport);
// Blend color
if (pipelineHash.blendEnabled) {
u32 constantColor = regs[PICA::InternalRegs::BlendColour];

View file

@ -32,11 +32,17 @@ fragment float4 fragmentDisplay(BasicVertexOut in [[stage_in]], texture2d<float>
return tex.sample(samplr, in.uv);
}
vertex BasicVertexOut vertexBlit(uint vid [[vertex_id]]) {
struct NDCViewport {
float2 offset;
float2 scale;
};
vertex BasicVertexOut vertexBlit(uint vid [[vertex_id]], constant NDCViewport& viewport [[buffer(0)]]) {
BasicVertexOut out;
out.uv = float2((vid << 1) & 2, vid & 2);
out.position = float4(out.uv * 2.0 - 1.0, 0.0, 1.0);
out.position.y = -out.position.y;
out.uv = out.uv * viewport.scale + viewport.offset;
return out;
}