Skip to content

Commit

Permalink
rend: clear framebuffer when vram address changes
Browse files Browse the repository at this point in the history
Fixes top and bottom leftovers from BIOS boot in San Francisco Rush
2049.
Issue #1197
  • Loading branch information
flyinghead committed Sep 25, 2023
1 parent e57ccde commit 0f6e175
Show file tree
Hide file tree
Showing 15 changed files with 74 additions and 36 deletions.
16 changes: 16 additions & 0 deletions core/hw/pvr/Renderer_if.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static bool rendererEnabled = true;
TA_context* _pvrrc;

static bool presented;
static u32 fbAddrHistory[2] { 1, 1 };

class PvrMessageQueue
{
Expand Down Expand Up @@ -343,6 +344,8 @@ void rend_reset()
fb_w_cur = 1;
pvrQueue.reset();
rendererEnabled = true;
fbAddrHistory[0] = 1;
fbAddrHistory[1] = 1;
}

void rend_start_render()
Expand Down Expand Up @@ -395,7 +398,18 @@ void rend_start_render()
ctx->rend.fog_clamp_max = FOG_CLAMP_MAX;

if (!ctx->rend.isRTT)
{
if (FB_W_SOF1 != fbAddrHistory[0] && FB_W_SOF1 != fbAddrHistory[1])
{
ctx->rend.clearFramebuffer = true;
fbAddrHistory[0] = fbAddrHistory[1];
fbAddrHistory[1] = FB_W_SOF1;
}
else {
ctx->rend.clearFramebuffer = false;
}
ggpo::endOfFrame();
}

if (QueueRender(ctx))
{
Expand Down Expand Up @@ -530,4 +544,6 @@ void rend_deserialize(Deserializer& deser)
deser >> fb_watch_addr_end;
}
pend_rend = false;
fbAddrHistory[0] = 1;
fbAddrHistory[1] = 1;
}
18 changes: 8 additions & 10 deletions core/hw/pvr/ta_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,10 @@ struct SortedTriangle

struct rend_context
{
u8* proc_start;
u8* proc_end;

f32 fZ_min;
f32 fZ_max;

bool isRTT;
bool clearFramebuffer;

TA_GLOB_TILE_CLIP_type ta_GLOB_TILE_CLIP;
SCALER_CTL_type scaler_ctl;
Expand Down Expand Up @@ -280,10 +277,10 @@ struct rend_context
global_param_op.back().init();
verts.resize(4);

fZ_min = 1000000.0f;
fZ_max = 1.0f;
matrices.clear();
lightModels.clear();
clearFramebuffer = false;
}

void newRenderPass();
Expand Down Expand Up @@ -329,10 +326,12 @@ struct TA_context
sa2: idx: 36094, vtx: 24520, op: 1330, pt: 10, tr: 177, mvo: 39, modt: 360, ov: 0
*/

void MarkRend()
{
rend.proc_start = tad.thd_root;
rend.proc_end = tad.End();
u8 *getTADataBegin() {
return tad.thd_root;
}

u8 *getTADataEnd() {
return tad.End();
}

void Alloc()
Expand Down Expand Up @@ -362,7 +361,6 @@ struct TA_context
tad.Clear();
nextContext = nullptr;
rend.Clear();
rend.proc_end = rend.proc_start = tad.thd_root;
}

~TA_context()
Expand Down
8 changes: 2 additions & 6 deletions core/hw/pvr/ta_vtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1210,12 +1210,8 @@ static void ta_parse_vdrc(TA_context* ctx, bool primRestart)

while (childCtx != nullptr)
{
childCtx->MarkRend();
vd_rc.proc_start = childCtx->rend.proc_start;
vd_rc.proc_end = childCtx->rend.proc_end;

Ta_Dma* ta_data = (Ta_Dma *)vd_rc.proc_start;
Ta_Dma* ta_data_end = (Ta_Dma *)vd_rc.proc_end;
Ta_Dma* ta_data = (Ta_Dma *)childCtx->getTADataBegin();
Ta_Dma* ta_data_end = (Ta_Dma *)childCtx->getTADataEnd();

while (ta_data < ta_data_end)
try {
Expand Down
7 changes: 7 additions & 0 deletions core/rend/dx11/dx11_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,13 @@ bool DX11Renderer::Render()
resize(pvrrc.framebufferWidth, pvrrc.framebufferHeight);
deviceContext->OMSetRenderTargets(1, &fbRenderTarget.get(), depthTexView);
deviceContext->ClearDepthStencilView(depthTexView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.f, 0);
if (pvrrc.clearFramebuffer)
{
float colors[4];
VO_BORDER_COL.getRGBColor(colors);
colors[3] = 1.f;
deviceContext->ClearRenderTargetView(fbRenderTarget, colors);
}
}
configVertexShader();

Expand Down
10 changes: 9 additions & 1 deletion core/rend/dx11/oit/dx11_oitrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ struct DX11OITRenderer : public DX11Renderer
deviceContext->PSSetShaderResources(0, 1, &opaqueTextureView.get());
auto sampler = samplers->getSampler(false);
deviceContext->PSSetSamplers(0, 1, &sampler.get());
deviceContext->RSSetScissorRects(1, &scissorRect);
D3D11_RECT rect { 0, 0, (LONG)width, (LONG)height };
deviceContext->RSSetScissorRects(1, &rect);
deviceContext->OMSetDepthStencilState(depthStencilStates.getState(false, false, 0, false), 0);
setCullMode(0);

Expand Down Expand Up @@ -512,6 +513,13 @@ struct DX11OITRenderer : public DX11Renderer
buffers.bind();
deviceContext->ClearDepthStencilView(depthTexView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.f, 0);
deviceContext->ClearDepthStencilView(depthStencilView2, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.f, 0);
if (pvrrc.clearFramebuffer && !pvrrc.isRTT)
{
float colors[4];
VO_BORDER_COL.getRGBColor(colors);
colors[3] = 1.f;
deviceContext->ClearRenderTargetView(opaqueRenderTarget, colors);
}

RenderPass previous_pass {};
int render_pass_count = (int)pvrrc.render_passes.size();
Expand Down
2 changes: 2 additions & 0 deletions core/rend/dx9/d3d_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,8 @@ bool D3DRenderer::Render()
else
{
resize(pvrrc.framebufferWidth, pvrrc.framebufferHeight);
if (pvrrc.clearFramebuffer)
device->ColorFill(framebufferSurface, 0, D3DCOLOR_ARGB(255, VO_BORDER_COL._red, VO_BORDER_COL._green, VO_BORDER_COL._blue));
rc = SUCCEEDED(device->SetRenderTarget(0, framebufferSurface));
verify(rc);
D3DVIEWPORT9 viewport;
Expand Down
9 changes: 9 additions & 0 deletions core/rend/gl4/gldraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,15 @@ void gl4DrawStrips(GLuint output_fbo, int width, int height)
{
checkOverflowAndReset();
glBindFramebuffer(GL_FRAMEBUFFER, geom_fbo);
if (!pvrrc.isRTT && pvrrc.clearFramebuffer)
{
glcache.Disable(GL_SCISSOR_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glcache.ClearColor(VO_BORDER_COL.red(), VO_BORDER_COL.green(), VO_BORDER_COL.blue(), 1.f);
glClear(GL_COLOR_BUFFER_BIT);
if (gl4ShaderUniforms.base_clipping.enabled)
glcache.Enable(GL_SCISSOR_TEST);
}
if (texSamplers[0] == 0)
glGenSamplers(2, texSamplers);

Expand Down
2 changes: 1 addition & 1 deletion core/rend/gles/gldraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ void writeFramebufferToVRAM()
gl.fbscaling.framebuffer->bind();
glViewport(0, 0, scaledW, scaledH);
glcache.Disable(GL_SCISSOR_TEST);
glcache.ClearColor(1.f, 0.f, 0.f, 1.f);
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
glcache.BindTexture(GL_TEXTURE_2D, gl.ofbo.framebuffer->getTexture());
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Expand Down
10 changes: 6 additions & 4 deletions core/rend/gles/gles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1173,7 +1173,6 @@ bool OpenGLRenderer::renderFrame(int width, int height)

bool is_rtt = pvrrc.isRTT;

float vtx_min_fZ = 0.f; //pvrrc.fZ_min;
float vtx_max_fZ = pvrrc.fZ_max;

//sanitise the values, now with NaN detection (for omap)
Expand All @@ -1182,7 +1181,6 @@ bool OpenGLRenderer::renderFrame(int width, int height)
vtx_max_fZ = 10 * 1024;

//add some extra range to avoid clipping border cases
vtx_min_fZ *= 0.98f;
vtx_max_fZ *= 1.001f;

TransformMatrix<COORD_OPENGL> matrices(pvrrc, is_rtt ? pvrrc.getFramebufferWidth() : width,
Expand All @@ -1191,8 +1189,8 @@ bool OpenGLRenderer::renderFrame(int width, int height)
const glm::mat4& scissor_mat = matrices.GetScissorMatrix();
ViewportMatrix = matrices.GetViewportMatrix();

ShaderUniforms.depth_coefs[0] = 2 / (vtx_max_fZ - vtx_min_fZ);
ShaderUniforms.depth_coefs[1] = -vtx_min_fZ - 1;
ShaderUniforms.depth_coefs[0] = 2.f / vtx_max_fZ;
ShaderUniforms.depth_coefs[1] = -1.f;
ShaderUniforms.depth_coefs[2] = 0;
ShaderUniforms.depth_coefs[3] = 0;

Expand Down Expand Up @@ -1310,6 +1308,8 @@ bool OpenGLRenderer::renderFrame(int width, int height)
glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glCheck();
if (!is_rtt)
glcache.ClearColor(VO_BORDER_COL.red(), VO_BORDER_COL.green(), VO_BORDER_COL.blue(), 1.f);
else
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);

if (!is_rtt && (FB_R_CTRL.fb_enable == 0 || VO_CONTROL.blank_video == 1))
{
Expand All @@ -1318,6 +1318,8 @@ bool OpenGLRenderer::renderFrame(int width, int height)
}
else
{
if (is_rtt || pvrrc.clearFramebuffer)
glClear(GL_COLOR_BUFFER_BIT);
//move vertex to gpu
//Main VBO
gl.vbo.geometry->update(&pvrrc.verts[0], pvrrc.verts.size() * sizeof(decltype(pvrrc.verts[0])));
Expand Down
2 changes: 1 addition & 1 deletion core/rend/gles/postprocess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ void PostProcessor::render(GLuint output_fbo)

if (_pvrrc == nullptr)
// Framebuffer render: no dithering
PostProcessShader::select(!config::EmulateFramebuffer,
PostProcessShader::select(false,
SPG_CONTROL.interlace,
FB_R_CTRL.vclk_div == 1 && SPG_CONTROL.interlace == 0);
else
Expand Down
2 changes: 1 addition & 1 deletion core/rend/vulkan/drawer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ vk::CommandBuffer ScreenDrawer::BeginRenderPass()
transitionNeeded[GetCurrentImage()] = false;
}

vk::RenderPass renderPass = clearNeeded[GetCurrentImage()] ? *renderPassClear : *renderPassLoad;
vk::RenderPass renderPass = clearNeeded[GetCurrentImage()] || pvrrc.clearFramebuffer ? *renderPassClear : *renderPassLoad;
clearNeeded[GetCurrentImage()] = false;
const std::array<vk::ClearValue, 2> clear_colors = { vk::ClearColorValue(std::array<float, 4> { 0.f, 0.f, 0.f, 1.f }), vk::ClearDepthStencilValue { 0.f, 0 } };
commandBuffer.beginRenderPass(vk::RenderPassBeginInfo(renderPass, *framebuffers[GetCurrentImage()],
Expand Down
2 changes: 1 addition & 1 deletion core/rend/vulkan/oit/oit_drawer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
else
targetFramebuffer = GetFinalFramebuffer();
cmdBuffer.beginRenderPass(
vk::RenderPassBeginInfo(pipelineManager->GetRenderPass(initialPass, finalPass),
vk::RenderPassBeginInfo(pipelineManager->GetRenderPass(initialPass, finalPass, initialPass && pvrrc.clearFramebuffer),
targetFramebuffer, viewport, clear_colors),
vk::SubpassContents::eInline);

Expand Down
2 changes: 1 addition & 1 deletion core/rend/vulkan/oit/oit_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ class OITPipelineManager
vk::DescriptorSetLayout GetPerPolyDSLayout() const { return *perPolyLayout; }
vk::DescriptorSetLayout GetColorInputDSLayout() const { return *colorInputLayout; }

vk::RenderPass GetRenderPass(bool initial, bool last) { return renderPasses->GetRenderPass(initial, last); }
vk::RenderPass GetRenderPass(bool initial, bool last, bool loadClear = false) { return renderPasses->GetRenderPass(initial, last, loadClear); }

private:
void CreateModVolPipeline(ModVolMode mode, int cullMode, bool naomi2);
Expand Down
4 changes: 2 additions & 2 deletions core/rend/vulkan/oit/oit_renderpass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
*/
#include "oit_renderpass.h"

vk::UniqueRenderPass RenderPasses::MakeRenderPass(bool initial, bool last)
vk::UniqueRenderPass RenderPasses::MakeRenderPass(bool initial, bool last, bool loadClear)
{
std::array<vk::AttachmentDescription, 4> attachmentDescriptions = {
// Swap chain image
GetAttachment0Description(initial, last),
GetAttachment0Description(initial, last, loadClear),
// OP+PT color attachment
vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), vk::Format::eR8G8B8A8Unorm, vk::SampleCountFlagBits::e1,
initial ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
Expand Down
16 changes: 8 additions & 8 deletions core/rend/vulkan/oit/oit_renderpass.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
class RenderPasses
{
public:
vk::RenderPass GetRenderPass(bool initial, bool last)
vk::RenderPass GetRenderPass(bool initial, bool last, bool loadClear = false)
{
size_t index = (initial ? 1 : 0) | (last ? 2 : 0);
size_t index = (initial ? 1 : 0) | (last ? 2 : 0) | (loadClear ? 4 : 0);
if (!renderPasses[index])
renderPasses[index] = MakeRenderPass(initial, last);
renderPasses[index] = MakeRenderPass(initial, last, loadClear);
return *renderPasses[index];
}
void Reset()
Expand All @@ -40,11 +40,11 @@ class RenderPasses

protected:
VulkanContext *GetContext() const { return VulkanContext::Instance(); }
vk::UniqueRenderPass MakeRenderPass(bool initial, bool last);
virtual vk::AttachmentDescription GetAttachment0Description(bool initial, bool last) const
vk::UniqueRenderPass MakeRenderPass(bool initial, bool last, bool loadClear);
virtual vk::AttachmentDescription GetAttachment0Description(bool initial, bool last, bool loadClear) const
{
return vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), vk::Format::eR8G8B8A8Unorm, vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eStore,
loadClear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eStore,
vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare,
config::EmulateFramebuffer && last ? vk::ImageLayout::eTransferSrcOptimal : vk::ImageLayout::eShaderReadOnlyOptimal,
config::EmulateFramebuffer && last ? vk::ImageLayout::eTransferSrcOptimal : vk::ImageLayout::eShaderReadOnlyOptimal);
Expand All @@ -59,13 +59,13 @@ class RenderPasses
}

private:
std::array<vk::UniqueRenderPass, 4> renderPasses;
std::array<vk::UniqueRenderPass, 8> renderPasses;
};

class RttRenderPasses : public RenderPasses
{
protected:
vk::AttachmentDescription GetAttachment0Description(bool initial, bool last) const override
vk::AttachmentDescription GetAttachment0Description(bool initial, bool last, bool loadClear) const override
{
return vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), vk::Format::eR8G8B8A8Unorm, vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore,
Expand Down

0 comments on commit 0f6e175

Please sign in to comment.