Skip to content

Commit

Permalink
rend: modifier volumes must be clipped
Browse files Browse the repository at this point in the history
Modifier volumes should also be clipped when needed.
Implement outside clipping for non-OIT renderers.
OIT renderers are less affected since the shadowed polys themselves are
usually also clipped after shadow is applied.
Fixes overflowing shadows in baserunner cams in WSB 2K1.
  • Loading branch information
flyinghead committed Nov 17, 2024
1 parent b7163dd commit d618abc
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 76 deletions.
2 changes: 2 additions & 0 deletions core/hw/pvr/ta_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct ModifierVolumeParam
u32 first;
u32 count;
ISP_Modvol isp;
u32 tileclip;

int mvMatrix;
int projMatrix;
Expand All @@ -121,6 +122,7 @@ struct ModifierVolumeParam
first = 0;
count = 0;
isp.full = 0;
tileclip = 0;
mvMatrix = -1;
projMatrix = -1;
}
Expand Down
1 change: 1 addition & 0 deletions core/hw/pvr/ta_vtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,7 @@ case num : {\
p->isp.full = param->isp.full;
p->isp.VolumeLast = param->pcw.Volume != 0;
p->first = vd_rc.modtrig.size();
p->tileclip = tileclip_val;
}

static void AppendModVolVertexA(TA_ModVolA* mvv)
Expand Down
40 changes: 23 additions & 17 deletions core/rend/dx11/dx11_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "hw/pvr/ta.h"
#include "hw/pvr/pvr_mem.h"
#include "ui/gui.h"
#include "rend/tileclip.h"
#include "rend/sorter.h"

#include <memory>
Expand Down Expand Up @@ -605,6 +604,19 @@ void DX11Renderer::setCullMode(int mode)
deviceContext->RSSetState(rasterizer);
}

TileClipping DX11Renderer::setTileClip(u32 tileclip, int clip_rect[4])
{
TileClipping clipmode = GetTileClip(tileclip, matrices.GetViewportMatrix(), clip_rect);
if (clipmode == TileClipping::Outside) {
RECT rect { clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3] };
deviceContext->RSSetScissorRects(1, &rect);
}
else {
deviceContext->RSSetScissorRects(1, &scissorRect);
}
return clipmode;
}

template <u32 Type, bool SortingEnabled>
void DX11Renderer::setRenderState(const PolyParam *gp)
{
Expand All @@ -623,7 +635,7 @@ void DX11Renderer::setRenderState(const PolyParam *gp)
int fog_ctrl = config::Fog ? gp->tsp.FogCtrl : 2;

int clip_rect[4] = {};
TileClipping clipmode = GetTileClip(gp->tileclip, matrices.GetViewportMatrix(), clip_rect);
TileClipping clipmode = setTileClip(gp->tileclip, clip_rect);
DX11Texture *texture = (DX11Texture *)gp->texture;
int gpuPalette = texture == nullptr || !texture->gpuPalette ? 0
: gp->tsp.FilterMode + 1;
Expand Down Expand Up @@ -662,21 +674,12 @@ void DX11Renderer::setRenderState(const PolyParam *gp)
constants.paletteIndex = (float)((gp->tcw.PalSelect >> 4) << 8);
}

if (clipmode == TileClipping::Outside)
{
RECT rect { clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3] };
deviceContext->RSSetScissorRects(1, &rect);
}
else
if (clipmode == TileClipping::Inside)
{
deviceContext->RSSetScissorRects(1, &scissorRect);
if (clipmode == TileClipping::Inside)
{
constants.clipTest[0] = (float)clip_rect[0];
constants.clipTest[1] = (float)clip_rect[1];
constants.clipTest[2] = (float)(clip_rect[0] + clip_rect[2]);
constants.clipTest[3] = (float)(clip_rect[1] + clip_rect[3]);
}
constants.clipTest[0] = (float)clip_rect[0];
constants.clipTest[1] = (float)clip_rect[1];
constants.clipTest[2] = (float)(clip_rect[0] + clip_rect[2]);
constants.clipTest[3] = (float)(clip_rect[1] + clip_rect[3]);
}
if (constants.trilinearAlpha != 1.f || gpuPalette != 0 || clipmode == TileClipping::Inside)
{
Expand Down Expand Up @@ -827,7 +830,6 @@ void DX11Renderer::drawModVols(int first, int count)

deviceContext->PSSetShader(shaders->getModVolShader(), nullptr, 0);

deviceContext->RSSetScissorRects(1, &scissorRect);
setCullMode(0);

const ModifierVolumeParam *params = &pvrrc.global_param_mvo[first];
Expand Down Expand Up @@ -859,6 +861,10 @@ void DX11Renderer::drawModVols(int first, int count)
// XOR'ing (closed volume)
deviceContext->OMSetDepthStencilState(depthStencilStates.getMVState(DepthStencilStates::Xor), 0);

int clip_rect[4] = {};
setTileClip(param.tileclip, clip_rect);
// TODO inside clipping

if (param.count > 0)
{
setCullMode(param.isp.CullMode);
Expand Down
2 changes: 2 additions & 0 deletions core/rend/dx11/dx11_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "dx11_shaders.h"
#include "dx11_renderstate.h"
#include "dx11_naomi2.h"
#include "rend/tileclip.h"
#ifndef LIBRETRO
#include "dx11_driver.h"
#endif
Expand Down Expand Up @@ -102,6 +103,7 @@ struct DX11Renderer : public Renderer
void writeFramebufferToVRAM();
void renderVideoRouting();
void resetContextState();
TileClipping setTileClip(u32 val, int clip_rect[4]);

ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> deviceContext;
Expand Down
21 changes: 6 additions & 15 deletions core/rend/dx11/oit/dx11_oitrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ struct DX11OITRenderer : public DX11Renderer
constants.trilinearAlpha = 1.f;

int clip_rect[4] = {};
TileClipping clipmode = GetTileClip(gp->tileclip, matrices.GetViewportMatrix(), clip_rect);
TileClipping clipmode = setTileClip(gp->tileclip, clip_rect);
int gpuPalette = gp->texture == nullptr || !gp->texture->gpuPalette ? 0
: gp->tsp.FilterMode + 1;
if (gpuPalette != 0)
Expand Down Expand Up @@ -248,21 +248,12 @@ struct DX11OITRenderer : public DX11Renderer
constants.paletteIndex = (float)((gp->tcw.PalSelect >> 4) << 8);
}

if (clipmode == TileClipping::Outside)
if (clipmode == TileClipping::Inside)
{
RECT rect { clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3] };
deviceContext->RSSetScissorRects(1, &rect);
}
else
{
deviceContext->RSSetScissorRects(1, &scissorRect);
if (clipmode == TileClipping::Inside)
{
constants.clipTest[0] = (float)clip_rect[0];
constants.clipTest[1] = (float)clip_rect[1];
constants.clipTest[2] = (float)(clip_rect[0] + clip_rect[2]);
constants.clipTest[3] = (float)(clip_rect[1] + clip_rect[3]);
}
constants.clipTest[0] = (float)clip_rect[0];
constants.clipTest[1] = (float)clip_rect[1];
constants.clipTest[2] = (float)(clip_rect[0] + clip_rect[2]);
constants.clipTest[3] = (float)(clip_rect[1] + clip_rect[3]);
}
constants.blend_mode0[0] = gp->tsp.SrcInstr;
constants.blend_mode0[1] = gp->tsp.DstInstr;
Expand Down
45 changes: 27 additions & 18 deletions core/rend/dx9/d3d_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include "d3d_renderer.h"
#include "hw/pvr/ta.h"
#include "hw/pvr/pvr_mem.h"
#include "rend/tileclip.h"
#include "ui/gui.h"
#include "rend/sorter.h"

Expand Down Expand Up @@ -336,6 +335,25 @@ inline void D3DRenderer::setTexMode(D3DSAMPLERSTATETYPE state, u32 clamp, u32 mi
}
}

TileClipping D3DRenderer::setTileClip(u32 tileclip, int clip_rect[4])
{
TileClipping clipmode = GetTileClip(tileclip, matrices.GetViewportMatrix(), clip_rect);
if (clipmode == TileClipping::Outside)
{
devCache.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
RECT rect { clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3] };
// TODO cache
device->SetScissorRect(&rect);
}
else
{
devCache.SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnable);
if (scissorEnable)
device->SetScissorRect(&scissorRect);
}
return clipmode;
}

template <u32 Type, bool SortingEnabled>
void D3DRenderer::setGPState(const PolyParam *gp)
{
Expand All @@ -354,7 +372,7 @@ void D3DRenderer::setGPState(const PolyParam *gp)
int fog_ctrl = config::Fog ? gp->tsp.FogCtrl : 2;

int clip_rect[4] = {};
TileClipping clipmode = GetTileClip(gp->tileclip, matrices.GetViewportMatrix(), clip_rect);
TileClipping clipmode = setTileClip(gp->tileclip, clip_rect);
D3DTexture *texture = (D3DTexture *)gp->texture;
int gpuPalette = texture == nullptr || !texture->gpuPalette ? 0
: gp->tsp.FilterMode + 1;
Expand Down Expand Up @@ -400,23 +418,10 @@ void D3DRenderer::setGPState(const PolyParam *gp)
devCache.SetVertexShader(shaders.getVertexShader(gp->pcw.Gouraud));
devCache.SetRenderState(D3DRS_SHADEMODE, gp->pcw.Gouraud == 1 ? D3DSHADE_GOURAUD : D3DSHADE_FLAT);

if (clipmode == TileClipping::Outside)
if (clipmode == TileClipping::Inside)
{
devCache.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
RECT rect { clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3] };
// TODO cache
device->SetScissorRect(&rect);
}
else
{
devCache.SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnable);
if (scissorEnable)
device->SetScissorRect(&scissorRect);
if (clipmode == TileClipping::Inside)
{
float f[] = { (float)clip_rect[0], (float)clip_rect[1], (float)(clip_rect[0] + clip_rect[2]), (float)(clip_rect[1] + clip_rect[3]) };
device->SetPixelShaderConstantF(4, f, 1);
}
float f[] = { (float)clip_rect[0], (float)clip_rect[1], (float)(clip_rect[0] + clip_rect[2]), (float)(clip_rect[1] + clip_rect[3]) };
device->SetPixelShaderConstantF(4, f, 1);
}

const u32 stencil = (gp->pcw.Shadow != 0) ? 0x80 : 0;
Expand Down Expand Up @@ -707,6 +712,10 @@ void D3DRenderer::drawModVols(int first, int count)
else
setMVS_Mode(Xor, param.isp); // XOR'ing (closed volume)

int clip_rect[4] = {};
setTileClip(param.tileclip, clip_rect);
//TODO inside clipping

device->DrawPrimitive(D3DPT_TRIANGLELIST, param.first * 3, param.count);

if (mv_mode == 1 || mv_mode == 2)
Expand Down
2 changes: 2 additions & 0 deletions core/rend/dx9/d3d_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "d3d_texture.h"
#include "d3d_shaders.h"
#include "ui/imgui_driver.h"
#include "rend/tileclip.h"

class RenderStateCache
{
Expand Down Expand Up @@ -140,6 +141,7 @@ struct D3DRenderer : public Renderer
void prepareRttRenderTarget(u32 texAddress, int& vpWidth, int& vpHeight);
void readRttRenderTarget(u32 texAddress);
void writeFramebufferToVRAM();
TileClipping setTileClip(u32 tileclip, int rect[4]);

RenderStateCache devCache;
ComPtr<IDirect3DDevice9> device;
Expand Down
26 changes: 18 additions & 8 deletions core/rend/gles/gldraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ static void SetBaseClipping()
glcache.Disable(GL_SCISSOR_TEST);
}

static TileClipping setTileClip(u32 tileclip, int clip_rect[4])
{
TileClipping clipmode = GetTileClip(tileclip, ViewportMatrix, clip_rect);
if (clipmode == TileClipping::Outside)
{
glcache.Enable(GL_SCISSOR_TEST);
glcache.Scissor(clip_rect[0], clip_rect[1], clip_rect[2], clip_rect[3]);
}
else {
SetBaseClipping();
}
return clipmode;
}

template <u32 Type, bool SortingEnabled>
void SetGPState(const PolyParam* gp,u32 cflip=0)
{
Expand All @@ -123,7 +137,7 @@ void SetGPState(const PolyParam* gp,u32 cflip=0)
int fog_ctrl = config::Fog ? gp->tsp.FogCtrl : 2;

int clip_rect[4] = {};
TileClipping clipmode = GetTileClip(gp->tileclip, ViewportMatrix, clip_rect);
TileClipping clipmode = setTileClip(gp->tileclip, clip_rect);
TextureCacheData *texture = (TextureCacheData *)gp->texture;
int gpuPalette = texture == nullptr || !texture->gpuPalette ? 0
: gp->tsp.FilterMode + 1;
Expand Down Expand Up @@ -172,13 +186,6 @@ void SetGPState(const PolyParam* gp,u32 cflip=0)
if (clipmode == TileClipping::Inside)
glUniform4f(CurrentShader->pp_ClipTest, (float)clip_rect[0], (float)clip_rect[1],
(float)(clip_rect[0] + clip_rect[2]), (float)(clip_rect[1] + clip_rect[3]));
if (clipmode == TileClipping::Outside)
{
glcache.Enable(GL_SCISSOR_TEST);
glcache.Scissor(clip_rect[0], clip_rect[1], clip_rect[2], clip_rect[3]);
}
else
SetBaseClipping();

if (config::ModifierVolumes)
{
Expand Down Expand Up @@ -534,6 +541,9 @@ void DrawModVols(int first, int count)
{
glcache.UseProgram(gl.modvol_shader.program);
}
int clip_rect[4];
setTileClip(param.tileclip, clip_rect);
// TODO inside clipping

u32 mv_mode = param.isp.DepthMode;

Expand Down
22 changes: 10 additions & 12 deletions core/rend/vulkan/drawer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "hw/pvr/pvr_mem.h"
#include "rend/sorter.h"

TileClipping BaseDrawer::SetTileClip(u32 val, vk::Rect2D& clipRect)
TileClipping BaseDrawer::SetTileClip(vk::CommandBuffer cmdBuffer, u32 val, vk::Rect2D& clipRect)
{
int rect[4] = {};
TileClipping clipmode = ::GetTileClip(val, matrices.GetViewportMatrix(), rect);
Expand All @@ -33,6 +33,10 @@ TileClipping BaseDrawer::SetTileClip(u32 val, vk::Rect2D& clipRect)
clipRect.extent.width = rect[2];
clipRect.extent.height = rect[3];
}
if (clipmode == TileClipping::Outside)
SetScissor(cmdBuffer, clipRect);
else
SetScissor(cmdBuffer, baseScissor);

return clipmode;
}
Expand Down Expand Up @@ -169,11 +173,7 @@ void Drawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool sor
CommandBufferDebugScope _(cmdBuffer, "DrawPoly", scopeColor);

vk::Rect2D scissorRect;
TileClipping tileClip = SetTileClip(poly.tileclip, scissorRect);
if (tileClip == TileClipping::Outside)
SetScissor(cmdBuffer, scissorRect);
else
SetScissor(cmdBuffer, baseScissor);
TileClipping tileClip = SetTileClip(cmdBuffer, poly.tileclip, scissorRect);

float trilinearAlpha = 1.f;
if (poly.tsp.FilterMode > 1 && poly.pcw.Texture && listType != ListType_Punch_Through && poly.tcw.MipMapped == 1)
Expand Down Expand Up @@ -263,11 +263,7 @@ void Drawer::DrawSorted(const vk::CommandBuffer& cmdBuffer, const std::vector<So
vk::Pipeline pipeline = pipelineManager->GetDepthPassPipeline(polyParam.isp.CullMode, polyParam.isNaomi2());
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
vk::Rect2D scissorRect;
TileClipping tileClip = SetTileClip(polyParam.tileclip, scissorRect);
if (tileClip == TileClipping::Outside)
SetScissor(cmdBuffer, scissorRect);
else
SetScissor(cmdBuffer, baseScissor);
SetTileClip(cmdBuffer, polyParam.tileclip, scissorRect);
cmdBuffer.drawIndexed(param.count, 1, pvrrc.idx.size() + param.first, 0, 0);
}
}
Expand Down Expand Up @@ -296,7 +292,6 @@ void Drawer::DrawModVols(const vk::CommandBuffer& cmdBuffer, int first, int coun
CommandBufferDebugScope _(cmdBuffer, "DrawModVols", scopeColor);

cmdBuffer.bindVertexBuffers(0, curMainBuffer, offsets.modVolOffset);
SetScissor(cmdBuffer, baseScissor);

ModifierVolumeParam* params = &pvrrc.global_param_mvo[first];

Expand All @@ -322,6 +317,9 @@ void Drawer::DrawModVols(const vk::CommandBuffer& cmdBuffer, int first, int coun

cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
descriptorSets.bindPerPolyDescriptorSets(cmdBuffer, param, first + cmv, curMainBuffer, offsets.naomi2ModVolOffset);
vk::Rect2D scissorRect;
SetTileClip(cmdBuffer, param.tileclip, scissorRect);
// TODO inside clipping

cmdBuffer.draw(param.count * 3, 1, param.first * 3, 0);

Expand Down
2 changes: 1 addition & 1 deletion core/rend/vulkan/drawer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class BaseDrawer

protected:
VulkanContext *GetContext() const { return VulkanContext::Instance(); }
TileClipping SetTileClip(u32 val, vk::Rect2D& clipRect);
TileClipping SetTileClip(vk::CommandBuffer cmdBuffer, u32 val, vk::Rect2D& clipRect);
void SetBaseScissor(const vk::Extent2D& viewport = vk::Extent2D());
void scaleAndWriteFramebuffer(vk::CommandBuffer commandBuffer, FramebufferAttachment *finalFB);

Expand Down
6 changes: 1 addition & 5 deletions core/rend/vulkan/oit/oit_drawer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ void OITDrawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool
CommandBufferDebugScope _(cmdBuffer, "DrawPoly(OIT)", scopeColor);

vk::Rect2D scissorRect;
TileClipping tileClip = SetTileClip(poly.tileclip, scissorRect);
if (tileClip == TileClipping::Outside)
SetScissor(cmdBuffer, scissorRect);
else
SetScissor(cmdBuffer, baseScissor);
SetTileClip(cmdBuffer, poly.tileclip, scissorRect);

float trilinearAlpha = 1.f;
if (poly.tsp.FilterMode > 1 && poly.pcw.Texture && listType != ListType_Punch_Through && poly.tcw.MipMapped == 1)
Expand Down

0 comments on commit d618abc

Please sign in to comment.