rend: clear framebuffer when vram address changes
Fixes top and bottom leftovers from BIOS boot in San Francisco Rush 2049. Issue #1197
This commit is contained in:
parent
e57ccde532
commit
0f6e1752e3
|
@ -38,6 +38,7 @@ static bool rendererEnabled = true;
|
|||
TA_context* _pvrrc;
|
||||
|
||||
static bool presented;
|
||||
static u32 fbAddrHistory[2] { 1, 1 };
|
||||
|
||||
class PvrMessageQueue
|
||||
{
|
||||
|
@ -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()
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -530,4 +544,6 @@ void rend_deserialize(Deserializer& deser)
|
|||
deser >> fb_watch_addr_end;
|
||||
}
|
||||
pend_rend = false;
|
||||
fbAddrHistory[0] = 1;
|
||||
fbAddrHistory[1] = 1;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -362,7 +361,6 @@ struct TA_context
|
|||
tad.Clear();
|
||||
nextContext = nullptr;
|
||||
rend.Clear();
|
||||
rend.proc_end = rend.proc_start = tad.thd_root;
|
||||
}
|
||||
|
||||
~TA_context()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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])));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()],
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -383,7 +383,7 @@ public:
|
|||
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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
@ -40,11 +40,11 @@ public:
|
|||
|
||||
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);
|
||||
|
@ -59,13 +59,13 @@ protected:
|
|||
}
|
||||
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue