vulkan: fix modvols. fix depth-write disabled poly. optimizations

stencil must be reset to zero if poly isn't shadowed -> fixes jet set
radio "see-through" shadows
take culling into account for modvols
oit: reduce per-pixel and per-poly mem usage
oit: framebuffers weren't resized when needed
oit: poly with depth write disabled weren't drawn (Soul calibur missing
water surface)
Fix glsl error when two-volume mode needs fog attachment
This commit is contained in:
Flyinghead 2019-12-05 18:48:54 +01:00
parent 21b2eb3e5d
commit 4730da31d5
8 changed files with 115 additions and 78 deletions

View File

@ -232,16 +232,16 @@ void Drawer::DrawModVols(const vk::CommandBuffer& cmdBuffer, int first, int coun
mod_base = param.first;
if (!param.isp.VolumeLast && mv_mode > 0)
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or); // OR'ing (open volume or quad)
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode); // OR'ing (open volume or quad)
else
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor); // XOR'ing (closed volume)
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode); // XOR'ing (closed volume)
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cmdBuffer.draw(param.count * 3, 1, param.first * 3, 0);
if (mv_mode == 1 || mv_mode == 2)
{
// Sum the area
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion);
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode);
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cmdBuffer.draw((param.first + param.count - mod_base) * 3, 1, mod_base * 3, 0);
mod_base = -1;
@ -253,7 +253,7 @@ void Drawer::DrawModVols(const vk::CommandBuffer& cmdBuffer, int first, int coun
std::array<float, 5> pushConstants = { 1 - FPU_SHAD_SCALE.scale_factor / 256.f, 0, 0, 0, 0 };
cmdBuffer.pushConstants<float>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants);
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Final);
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Final, 0);
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cmdBuffer.drawIndexed(4, 1, 0, 0, 0);
}

View File

@ -121,17 +121,17 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs
{
// OR'ing (open volume or quad)
if (Translucent)
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Or);
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode);
else
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or);
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode);
}
else
{
// XOR'ing (closed volume)
if (Translucent)
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Xor);
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode);
else
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor);
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode);
}
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cmdBuffer.draw(param.count * 3, 1, param.first * 3, 0);
@ -144,10 +144,10 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs
vk::MemoryBarrier barrier(vk::AccessFlagBits::eShaderWrite, vk::AccessFlagBits::eShaderRead);
cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eFragmentShader, vk::PipelineStageFlagBits::eFragmentShader,
vk::DependencyFlagBits::eByRegion, barrier, nullptr, nullptr);
pipeline = pipelineManager->GetTrModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion);
pipeline = pipelineManager->GetTrModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode);
}
else
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion);
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode);
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cmdBuffer.draw((param.first + param.count - mod_base) * 3, 1, mod_base * 3, 0);
@ -212,9 +212,16 @@ void OITDrawer::UploadMainBuffer(const OITDescriptorSets::VertexShaderUniforms&
chunks.push_back(nullptr);
chunkSizes.push_back(padding);
chunks.push_back(pvrrc.global_param_tr.head());
chunkSizes.push_back(pvrrc.global_param_tr.bytes());
u32 totalSize = offsets.polyParamsOffset + pvrrc.global_param_tr.bytes();
std::vector<u32> trPolyParams(pvrrc.global_param_tr.used() * 2);
for (int i = 0; i < pvrrc.global_param_tr.used(); i++)
{
const PolyParam& pp = pvrrc.global_param_tr.head()[i];
trPolyParams[i * 2] = (pp.tsp.full & 0xffff00c0) | ((pp.isp.full >> 16) & 0xe400) | ((pp.pcw.full >> 7) & 1);
trPolyParams[i * 2 + 1] = pp.tsp1.full;
}
chunks.push_back(trPolyParams.data());
chunkSizes.push_back(trPolyParams.size() * 4);
u32 totalSize = offsets.polyParamsOffset + trPolyParams.size() * 4;
BufferData *buffer = GetMainBuffer(totalSize);
buffer->upload(chunks.size(), &chunkSizes[0], &chunks[0]);
@ -269,11 +276,12 @@ bool OITDrawer::Draw(const Texture *fogTexture)
{
const RenderPass& current_pass = pvrrc.render_passes.head()[render_pass];
DEBUG_LOG(RENDERER, "Render pass %d OP %d PT %d TR %d MV %d autosort %d", render_pass + 1,
DEBUG_LOG(RENDERER, "Render pass %d OP %d PT %d TR %d MV %d TrMV %d autosort %d", render_pass + 1,
current_pass.op_count - previous_pass.op_count,
current_pass.pt_count - previous_pass.pt_count,
current_pass.tr_count - previous_pass.tr_count,
current_pass.mvo_count - previous_pass.mvo_count, current_pass.autosort);
current_pass.mvo_count - previous_pass.mvo_count,
current_pass.mvo_tr_count - previous_pass.mvo_tr_count, current_pass.autosort);
// Reset the pixel counter
oitBuffers->ResetPixelCounter(cmdBuffer);

View File

@ -119,6 +119,7 @@ public:
screenPipelineManager->GetPerPolyDSLayout(),
screenPipelineManager->GetColorInputDSLayout());
}
currentScreenScaling = 0;
MakeFramebuffers();
}
void Term()

View File

@ -53,7 +53,7 @@ void OITPipelineManager::CreatePipeline(u32 listType, bool autosort, const PolyP
// Depth and stencil
vk::CompareOp depthOp;
if (pass == 1)
if (pass == 1 && !pp.isp.ZWriteDis)
depthOp = vk::CompareOp::eEqual;
else if (listType == ListType_Punch_Through || autosort)
depthOp = vk::CompareOp::eGreaterOrEqual;
@ -69,12 +69,17 @@ void OITPipelineManager::CreatePipeline(u32 listType, bool autosort, const PolyP
else
depthWriteEnable = !pp.isp.ZWriteDis;
bool shadowed = pass == 0 && (listType == ListType_Opaque || listType == ListType_Punch_Through) && pp.pcw.Shadow != 0;
bool shadowed = pass == 0 && (listType == ListType_Opaque || listType == ListType_Punch_Through);
vk::StencilOpState stencilOpState;
if (shadowed)
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0x80);
{
if (pp.pcw.Shadow != 0)
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0x80);
else
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0);
}
else
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways);
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eNever);
vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo
(
vk::PipelineDepthStencilStateCreateFlags(), // flags
@ -346,7 +351,7 @@ void OITPipelineManager::CreateClearPipeline()
clearPipeline = GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(), graphicsPipelineCreateInfo);
}
void OITPipelineManager::CreateModVolPipeline(ModVolMode mode)
void OITPipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
{
verify(mode != ModVolMode::Final);
@ -379,7 +384,9 @@ void OITPipelineManager::CreateModVolPipeline(ModVolMode mode)
false, // depthClampEnable
false, // rasterizerDiscardEnable
vk::PolygonMode::eFill, // polygonMode
vk::CullModeFlagBits::eNone, // cullMode
cullMode == 3 ? vk::CullModeFlagBits::eBack
: cullMode == 2 ? vk::CullModeFlagBits::eFront
: vk::CullModeFlagBits::eNone, // cullMode
vk::FrontFace::eCounterClockwise, // frontFace
false, // depthBiasEnable
0.0f, // depthBiasConstantFactor
@ -462,14 +469,12 @@ void OITPipelineManager::CreateModVolPipeline(ModVolMode mode)
0 // subpass
);
if (modVolPipelines.empty())
modVolPipelines.resize((size_t)ModVolMode::Final);
modVolPipelines[(size_t)mode] =
modVolPipelines[hash(mode, cullMode)] =
GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
graphicsPipelineCreateInfo);
}
void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode)
void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode, int cullMode)
{
verify(mode != ModVolMode::Final);
@ -502,7 +507,9 @@ void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode)
false, // depthClampEnable
false, // rasterizerDiscardEnable
vk::PolygonMode::eFill, // polygonMode
vk::CullModeFlagBits::eNone, // cullMode
cullMode == 3 ? vk::CullModeFlagBits::eBack
: cullMode == 2 ? vk::CullModeFlagBits::eFront
: vk::CullModeFlagBits::eNone, // cullMode
vk::FrontFace::eCounterClockwise, // frontFace
false, // depthBiasEnable
0.0f, // depthBiasConstantFactor
@ -557,9 +564,7 @@ void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode)
2 // subpass
);
if (trModVolPipelines.empty())
trModVolPipelines.resize((size_t)ModVolMode::Final);
trModVolPipelines[(size_t)mode] =
trModVolPipelines[hash(mode, cullMode)] =
GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
graphicsPipelineCreateInfo);
}

View File

@ -262,17 +262,25 @@ public:
return *pipelines[pipehash];
}
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode)
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode, int cullMode)
{
if (modVolPipelines.empty() || !modVolPipelines[(size_t)mode])
CreateModVolPipeline(mode);
return *modVolPipelines[(size_t)mode];
u32 pipehash = hash(mode, cullMode);
const auto &pipeline = modVolPipelines.find(pipehash);
if (pipeline != modVolPipelines.end())
return pipeline->second.get();
CreateModVolPipeline(mode, cullMode);
return *modVolPipelines[pipehash];
}
vk::Pipeline GetTrModifierVolumePipeline(ModVolMode mode)
vk::Pipeline GetTrModifierVolumePipeline(ModVolMode mode, int cullMode)
{
if (trModVolPipelines.empty() || !trModVolPipelines[(size_t)mode])
CreateTrModVolPipeline(mode);
return *trModVolPipelines[(size_t)mode];
u32 pipehash = hash(mode, cullMode);
const auto &pipeline = trModVolPipelines.find(pipehash);
if (pipeline != trModVolPipelines.end())
return pipeline->second.get();
CreateTrModVolPipeline(mode, cullMode);
return *trModVolPipelines[pipehash];
}
vk::Pipeline GetFinalPipeline(bool autosort)
{
@ -295,8 +303,8 @@ public:
vk::RenderPass GetRenderPass(bool initial, bool last) { return renderPasses->GetRenderPass(initial, last); }
private:
void CreateModVolPipeline(ModVolMode mode);
void CreateTrModVolPipeline(ModVolMode mode);
void CreateModVolPipeline(ModVolMode mode, int cullMode);
void CreateTrModVolPipeline(ModVolMode mode, int cullMode);
u32 hash(u32 listType, bool autosort, const PolyParam *pp, int pass) const
{
@ -319,6 +327,10 @@ private:
return hash;
}
u32 hash(ModVolMode mode, int cullMode) const
{
return ((int)mode << 2) | cullMode;
}
vk::PipelineVertexInputStateCreateInfo GetMainVertexInputStateCreateInfo(bool full = true) const
{
@ -354,8 +366,8 @@ private:
void CreateClearPipeline();
std::map<u32, vk::UniquePipeline> pipelines;
std::vector<vk::UniquePipeline> modVolPipelines;
std::vector<vk::UniquePipeline> trModVolPipelines;
std::map<u32, vk::UniquePipeline> modVolPipelines;
std::map<u32, vk::UniquePipeline> trModVolPipelines;
vk::UniquePipeline finalAutosortPipeline;
vk::UniquePipeline finalNosortPipeline;
vk::UniquePipeline clearPipeline;

View File

@ -88,7 +88,7 @@ layout (std140, set = 0, binding = 1) uniform FragmentShaderUniforms
layout(set = 3, binding = 2, r32ui) uniform coherent restrict uimage2D abufferPointerImg;
struct Pixel {
vec4 color;
uint color;
float depth;
uint seq_num;
uint next;
@ -126,26 +126,14 @@ void setFragDepth(void)
gl_FragDepth = log2(1.0 + w) / 34.0;
}
struct PolyParam {
int first;
int count;
int texid_low;
int texid_high;
int tsp;
int tcw;
int pcw;
int isp;
float zvZ;
int tileclip;
int tsp_isp_pcw;
int tsp1;
int tcw1;
int texid1_low;
int texid1_high;
};
layout (set = 0, binding = 3, std430) readonly buffer TrPolyParamBuffer {
PolyParam tr_poly_params[];
} TrPolyParam;
#define GET_TSP_FOR_AREA int tsp = area1 ? pp.tsp1 : pp.tsp;
#define GET_TSP_FOR_AREA int tsp = area1 ? pp.tsp1 : pp.tsp_isp_pcw;
int getSrcBlendFunc(const PolyParam pp, bool area1)
{
@ -197,17 +185,17 @@ int getShadingInstruction(const PolyParam pp, bool area1)
int getDepthFunc(const PolyParam pp)
{
return (pp.isp >> 29) & 7;
return (pp.tsp_isp_pcw >> 13) & 7;
}
bool getDepthMask(const PolyParam pp)
{
return ((pp.isp >> 26) & 1) != 1;
return ((pp.tsp_isp_pcw >> 10) & 1) != 1;
}
bool getShadowEnable(const PolyParam pp)
{
return ((pp.pcw >> 7) & 1) != 0;
return (pp.tsp_isp_pcw & 1) != 0;
}
uint getPolyNumber(const Pixel pixel)
@ -225,7 +213,17 @@ bool isShadowed(const Pixel pixel)
bool isTwoVolumes(const PolyParam pp)
{
return pp.tsp1 != -1 || pp.tcw1 != -1;
return pp.tsp1 != -1;
}
uint packColors(vec4 v)
{
return (uint(round(v.r * 255.0)) << 24) | (uint(round(v.g * 255.0)) << 16) | (uint(round(v.b * 255.0)) << 8) | uint(round(v.a * 255.0));
}
vec4 unpackColors(uint u)
{
return vec4(float((u >> 24) & 255) / 255.0, float((u >> 16) & 255) / 255.0, float((u >> 8) & 255) / 255.0, float(u & 255) / 255.0);
}
)";
@ -304,7 +302,7 @@ layout (location = 3) INTERPOLATION in lowp vec4 vtx_base1; // new for OIT. On
layout (location = 4) INTERPOLATION in lowp vec4 vtx_offs1;
layout (location = 5) in mediump vec2 vtx_uv1;
#if pp_FogCtrl != 2
#if pp_FogCtrl != 2 || pp_TwoVolumes == 1
layout (set = 0, binding = 2) uniform sampler2D fog_table;
float fog_mode2(float w)
@ -331,7 +329,7 @@ vec4 colorClamp(vec4 col)
void main()
{
setFragDepth();
#if PASS == 3
// Manual depth testing
highp float frontDepth = subpassLoad(DepthTex).r;
@ -548,7 +546,7 @@ void main()
uint idx = getNextPixelIndex();
Pixel pixel;
pixel.color = color;
pixel.color = packColors(clamp(color, vec4(0.0), vec4(1.0)));
pixel.depth = gl_FragDepth;
pixel.seq_num = uint(pushConstants.pp_Number);
pixel.next = imageAtomicExchange(abufferPointerImg, coords, idx);
@ -680,7 +678,7 @@ vec4 resolveAlphaBlend(ivec2 coords) {
srcColor = secondaryBuffer;
else
{
srcColor = pixel.color;
srcColor = unpackColors(pixel.color);
if (shadowed)
srcColor.rgb *= uniformBuffer.shade_scale_factor;
}

View File

@ -23,7 +23,7 @@
#include "rend/osd.h"
#include "quad.h"
void PipelineManager::CreateModVolPipeline(ModVolMode mode)
void PipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
{
// Vertex input state
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo;
@ -66,7 +66,9 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
false, // depthClampEnable
false, // rasterizerDiscardEnable
vk::PolygonMode::eFill, // polygonMode
vk::CullModeFlagBits::eNone, // cullMode
cullMode == 3 ? vk::CullModeFlagBits::eBack
: cullMode == 2 ? vk::CullModeFlagBits::eFront
: vk::CullModeFlagBits::eNone, // cullMode
vk::FrontFace::eCounterClockwise, // frontFace
false, // depthBiasEnable
0.0f, // depthBiasConstantFactor
@ -161,9 +163,7 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
renderPass // renderPass
);
if (modVolPipelines.empty())
modVolPipelines.resize((size_t)ModVolMode::Final + 1);
modVolPipelines[(size_t)mode] =
modVolPipelines[hash(mode, cullMode)] =
GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
graphicsPipelineCreateInfo);
}
@ -217,12 +217,17 @@ void PipelineManager::CreatePipeline(u32 listType, bool sortTriangles, const Pol
depthWriteEnable = !pp.isp.ZWriteDis;
}
bool shadowed = (listType == ListType_Opaque || listType == ListType_Punch_Through) && pp.pcw.Shadow != 0;
bool shadowed = listType == ListType_Opaque || listType == ListType_Punch_Through;
vk::StencilOpState stencilOpState;
if (shadowed)
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0x80);
{
if (pp.pcw.Shadow != 0)
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0x80);
else
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0);
}
else
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways);
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eNever);
vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo
(
vk::PipelineDepthStencilStateCreateFlags(), // flags

View File

@ -172,11 +172,15 @@ public:
return *pipelines[pipehash];
}
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode)
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode, int cullMode)
{
if (modVolPipelines.empty() || !modVolPipelines[(size_t)mode])
CreateModVolPipeline(mode);
return *modVolPipelines[(size_t)mode];
u32 pipehash = hash(mode, cullMode);
const auto &pipeline = modVolPipelines.find(pipehash);
if (pipeline != modVolPipelines.end())
return pipeline->second.get();
CreateModVolPipeline(mode, cullMode);
return *modVolPipelines[pipehash];
}
vk::PipelineLayout GetPipelineLayout() const { return *pipelineLayout; }
vk::DescriptorSetLayout GetPerFrameDSLayout() const { return *perFrameLayout; }
@ -184,7 +188,7 @@ public:
vk::RenderPass GetRenderPass() const { return renderPass; }
private:
void CreateModVolPipeline(ModVolMode mode);
void CreateModVolPipeline(ModVolMode mode, int cullMode);
u32 hash(u32 listType, bool sortTriangles, const PolyParam *pp) const
{
@ -199,6 +203,10 @@ private:
return hash;
}
u32 hash(ModVolMode mode, int cullMode) const
{
return ((int)mode << 2) | cullMode;
}
vk::PipelineVertexInputStateCreateInfo GetMainVertexInputStateCreateInfo(bool full = true) const
{
@ -229,7 +237,7 @@ private:
void CreatePipeline(u32 listType, bool sortTriangles, const PolyParam& pp);
std::map<u32, vk::UniquePipeline> pipelines;
std::vector<vk::UniquePipeline> modVolPipelines;
std::map<u32, vk::UniquePipeline> modVolPipelines;
vk::UniquePipelineLayout pipelineLayout;
vk::UniqueDescriptorSetLayout perFrameLayout;