mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #16162 from unknownbrackets/geo-shader
Implement negative Z clipping in geometry shader
This commit is contained in:
commit
d6bd08cae7
6 changed files with 117 additions and 108 deletions
|
@ -97,7 +97,6 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
|||
CheckSetting(iniFile, gameID, "DateLimited", &flags_.DateLimited);
|
||||
CheckSetting(iniFile, gameID, "ShaderColorBitmask", &flags_.ShaderColorBitmask);
|
||||
CheckSetting(iniFile, gameID, "DisableFirstFrameReadback", &flags_.DisableFirstFrameReadback);
|
||||
CheckSetting(iniFile, gameID, "DisableRangeCulling", &flags_.DisableRangeCulling);
|
||||
CheckSetting(iniFile, gameID, "MpegAvcWarmUp", &flags_.MpegAvcWarmUp);
|
||||
CheckSetting(iniFile, gameID, "BlueToAlpha", &flags_.BlueToAlpha);
|
||||
CheckSetting(iniFile, gameID, "CenteredLines", &flags_.CenteredLines);
|
||||
|
|
|
@ -77,7 +77,6 @@ struct CompatFlags {
|
|||
bool DateLimited;
|
||||
bool ShaderColorBitmask;
|
||||
bool DisableFirstFrameReadback;
|
||||
bool DisableRangeCulling;
|
||||
bool MpegAvcWarmUp;
|
||||
bool BlueToAlpha;
|
||||
bool CenteredLines;
|
||||
|
|
|
@ -48,7 +48,7 @@ bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLangu
|
|||
|
||||
ShaderWriter p(buffer, compat, ShaderStage::Geometry, gl_exts.data(), gl_exts.size());
|
||||
p.C("layout(triangles) in;\n");
|
||||
p.C("layout(triangle_strip, max_vertices = 3) out;\n");
|
||||
p.C("layout(triangle_strip, max_vertices = 6) out;\n");
|
||||
|
||||
if (compat.shaderLanguage == GLSL_VULKAN) {
|
||||
WRITE(p, "\n");
|
||||
|
@ -76,6 +76,10 @@ bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLangu
|
|||
|
||||
// Apply culling
|
||||
p.C(" bool anyInside = false;\n");
|
||||
// And apply manual clipping if necessary.
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_CLIP_DISTANCE)) {
|
||||
p.C(" float clip0[3];\n");
|
||||
}
|
||||
|
||||
p.C(" for (int i = 0; i < 3; i++) {\n"); // TODO: 3 or gl_in.length()? which will be faster?
|
||||
p.C(" vec4 outPos = gl_in[i].gl_Position;\n");
|
||||
|
@ -98,6 +102,13 @@ bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLangu
|
|||
p.C(" if (projPos.z >= u_cullRangeMin.z) { anyInside = true; }\n");
|
||||
p.C(" if (projPos.z <= u_cullRangeMax.z) { anyInside = true; }\n");
|
||||
p.C(" }\n");
|
||||
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_CLIP_DISTANCE)) {
|
||||
// This is basically the same value as gl_ClipDistance would take, z + w.
|
||||
// TODO: Ignore triangles from GE_PRIM_RECTANGLES in transform mode, which should not clip to neg z.
|
||||
p.F(" clip0[i] = projZ * outPos.w + outPos.w;\n");
|
||||
}
|
||||
|
||||
p.C(" } // for\n");
|
||||
|
||||
// Cull any triangle fully outside in the same direction when depth clamp enabled.
|
||||
|
@ -106,27 +117,114 @@ bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLangu
|
|||
p.C(" return;\n");
|
||||
p.C(" }\n");
|
||||
|
||||
const char *clip0 = compat.shaderLanguage == HLSL_D3D11 ? "" : "[0]";
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_CLIP_DISTANCE)) {
|
||||
// Clipping against one half-space cuts a triangle (17/27), culls (7/27), or creates two triangles (3/27).
|
||||
p.C(" int indices[4];\n");
|
||||
p.C(" float factors[4];\n");
|
||||
p.C(" int ind = 0;\n");
|
||||
|
||||
p.C(" for (int i = 0; i < 3; i++) {\n"); // TODO: 3 or gl_in.length()? which will be faster?
|
||||
p.C(" vec4 outPos = gl_in[i].gl_Position;\n");
|
||||
p.C(" gl_Position = outPos;\n");
|
||||
// TODO: Not rectangles...
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_CLIP_DISTANCE)) {
|
||||
// Pass 1 - clip against first half-space.
|
||||
p.C(" for (int i = 0; i < 3; i++) {\n");
|
||||
// First, use this vertex if it doesn't need clipping.
|
||||
p.C(" if (clip0[i] >= 0.0) {\n");
|
||||
p.C(" indices[ind] = i;\n");
|
||||
p.C(" factors[ind] = 0.0;\n");
|
||||
p.C(" ind++;\n");
|
||||
p.C(" }\n");
|
||||
|
||||
// Next, we generate an interpolated vertex if signs differ.
|
||||
p.C(" int inext = i == 2 ? 0 : i + 1;\n");
|
||||
p.C(" if (clip0[i] * clip0[inext] < 0.0) {\n");
|
||||
p.C(" float t = clip0[i] < 0.0 ? clip0[i] / (clip0[i] - clip0[inext]) : 1.0 - (clip0[inext] / (clip0[inext] - clip0[i]));\n");
|
||||
p.C(" indices[ind] = i;\n");
|
||||
p.C(" factors[ind] = t;\n");
|
||||
p.C(" ind++;\n");
|
||||
p.C(" }\n");
|
||||
|
||||
p.C(" }\n");
|
||||
|
||||
p.C(" if (ind < 3) {\n");
|
||||
p.C(" return;\n");
|
||||
p.C(" }\n");
|
||||
|
||||
// Alright, time to actually emit the first triangle.
|
||||
p.C(" for (int i = 0; i < 3; i++) {\n");
|
||||
p.C(" int idx = indices[i];\n");
|
||||
p.C(" float factor = factors[i];\n");
|
||||
p.C(" int next = idx == 2 ? 0 : idx + 1;\n");
|
||||
p.C(" gl_Position = mix(gl_in[idx].gl_Position, gl_in[next].gl_Position, factor);\n");
|
||||
for (size_t i = 0; i < varyings.size(); i++) {
|
||||
VaryingDef &in = varyings[i];
|
||||
VaryingDef &out = outVaryings[i];
|
||||
p.F(" %s = mix(%s[idx], %s[next], factor);\n", outVaryings[i].name, varyings[i].name, varyings[i].name);
|
||||
}
|
||||
p.C(" EmitVertex();\n");
|
||||
p.C(" }\n");
|
||||
|
||||
// Did we end up with additional triangles? We'll do three points each for the rest.
|
||||
p.C(" for (int i = 3; i < ind; i++) {\n");
|
||||
p.C(" EndPrimitive();\n");
|
||||
|
||||
// Point one, always index zero.
|
||||
p.C(" int idx = indices[0];\n");
|
||||
p.C(" float factor = factors[0];\n");
|
||||
p.C(" int next = idx == 2 ? 0 : idx + 1;\n");
|
||||
p.C(" gl_Position = mix(gl_in[idx].gl_Position, gl_in[next].gl_Position, factor);\n");
|
||||
for (size_t i = 0; i < varyings.size(); i++) {
|
||||
VaryingDef &in = varyings[i];
|
||||
VaryingDef &out = outVaryings[i];
|
||||
p.F(" %s = mix(%s[idx], %s[next], factor);\n", outVaryings[i].name, varyings[i].name, varyings[i].name);
|
||||
}
|
||||
p.C(" EmitVertex();\n");
|
||||
|
||||
// After that, one less than i (basically a triangle fan.)
|
||||
p.C(" idx = indices[i - 1];\n");
|
||||
p.C(" factor = factors[i - 1];\n");
|
||||
p.C(" next = idx == 2 ? 0 : idx + 1;\n");
|
||||
p.C(" gl_Position = mix(gl_in[idx].gl_Position, gl_in[next].gl_Position, factor);\n");
|
||||
for (size_t i = 0; i < varyings.size(); i++) {
|
||||
VaryingDef &in = varyings[i];
|
||||
VaryingDef &out = outVaryings[i];
|
||||
p.F(" %s = mix(%s[idx], %s[next], factor);\n", outVaryings[i].name, varyings[i].name, varyings[i].name);
|
||||
}
|
||||
p.C(" EmitVertex();\n");
|
||||
|
||||
// And the new vertex itself.
|
||||
p.C(" idx = indices[i];\n");
|
||||
p.C(" factor = factors[i];\n");
|
||||
p.C(" next = idx == 2 ? 0 : idx + 1;\n");
|
||||
p.C(" gl_Position = mix(gl_in[idx].gl_Position, gl_in[next].gl_Position, factor);\n");
|
||||
for (size_t i = 0; i < varyings.size(); i++) {
|
||||
VaryingDef &in = varyings[i];
|
||||
VaryingDef &out = outVaryings[i];
|
||||
p.F(" %s = mix(%s[idx], %s[next], factor);\n", outVaryings[i].name, varyings[i].name, varyings[i].name);
|
||||
}
|
||||
p.C(" EmitVertex();\n");
|
||||
|
||||
p.C(" }\n");
|
||||
} else {
|
||||
const char *clipSuffix0 = compat.shaderLanguage == HLSL_D3D11 ? "" : "[0]";
|
||||
|
||||
p.C(" for (int i = 0; i < 3; i++) {\n"); // TODO: 3 or gl_in.length()? which will be faster?
|
||||
p.C(" vec4 outPos = gl_in[i].gl_Position;\n");
|
||||
p.C(" vec3 projPos = outPos.xyz / outPos.w;\n");
|
||||
p.C(" float projZ = (projPos.z - u_depthRange.z) * u_depthRange.w;\n");
|
||||
p.F(" gl_ClipDistance%s = projZ * outPos.w + outPos.w;\n", clip0);
|
||||
}
|
||||
// TODO: Ignore triangles from GE_PRIM_RECTANGLES in transform mode, which should not clip to neg z.
|
||||
p.F(" gl_ClipDistance%s = projZ * outPos.w + outPos.w;\n", clipSuffix0);
|
||||
p.C(" gl_Position = outPos;\n");
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_CLIP_DISTANCE)) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < varyings.size(); i++) {
|
||||
VaryingDef &in = varyings[i];
|
||||
VaryingDef &out = outVaryings[i];
|
||||
p.F(" %s = %s[i];\n", outVaryings[i].name, varyings[i].name);
|
||||
for (size_t i = 0; i < varyings.size(); i++) {
|
||||
VaryingDef &in = varyings[i];
|
||||
VaryingDef &out = outVaryings[i];
|
||||
p.F(" %s = %s[i];\n", outVaryings[i].name, varyings[i].name);
|
||||
}
|
||||
// Debug - null the red channel
|
||||
//p.C(" if (i == 0) v_color0Out.x = 0.0;\n");
|
||||
p.C(" EmitVertex();\n");
|
||||
p.C(" }\n");
|
||||
}
|
||||
// Debug - null the red channel
|
||||
//p.C(" if (i == 0) v_color0Out.x = 0.0;\n");
|
||||
p.C(" EmitVertex();\n");
|
||||
p.C(" }\n");
|
||||
|
||||
p.EndGSMain();
|
||||
|
||||
|
|
|
@ -1312,7 +1312,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
|||
const char *cull0 = compat.shaderLanguage == HLSL_D3D11 ? ".x" : "[0]";
|
||||
const char *cull1 = compat.shaderLanguage == HLSL_D3D11 ? ".y" : "[1]";
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_CLIP_DISTANCE)) {
|
||||
// TODO: Not rectangles...
|
||||
// TODO: Ignore triangles from GE_PRIM_RECTANGLES in transform mode, which should not clip to neg z.
|
||||
WRITE(p, " %sgl_ClipDistance%s = projZ * outPos.w + outPos.w;\n", compat.vsOutPrefix, vertexRangeClipSuffix);
|
||||
}
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_CULL_DISTANCE)) {
|
||||
|
|
|
@ -3306,11 +3306,7 @@ u32 GPUCommon::CheckGPUFeatures() const {
|
|||
}
|
||||
|
||||
if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) {
|
||||
// Ignore the compat setting if clip and cull are both enabled.
|
||||
// When supported, we can do the depth side of range culling more correctly.
|
||||
const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported;
|
||||
const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling;
|
||||
if (supported || !disabled) {
|
||||
if (draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,89 +156,6 @@ NPJH90062 = true
|
|||
# Phantasy Star Portable Infinity Demo
|
||||
NPJH90157 = true # Infinity demo
|
||||
|
||||
[DisableRangeCulling]
|
||||
# Phantasy Star games also have range culling issues.
|
||||
# Phantasy Star Portable 2 and Infinity
|
||||
ULJM05309 = true
|
||||
ULUS10410 = true
|
||||
ULES01218 = true
|
||||
ULJM08023 = true
|
||||
ULES01218 = true
|
||||
# Phantasy Star Portable 1 Demo
|
||||
NPUH90023 = true
|
||||
# Phantasy Star Portable 2
|
||||
ULES01439 = true
|
||||
ULUS10529 = true
|
||||
ULJM05493 = true
|
||||
NPJH50043 = true
|
||||
ULJM08030 = true
|
||||
NPUH90023 = true
|
||||
ULJM91014 = true
|
||||
NPJH90002 = true
|
||||
ULJM05732 = true
|
||||
NPJH50332 = true
|
||||
# Phantasy Star Portable 2 JP Demo
|
||||
ULJM91018 = true
|
||||
NPJH90062 = true
|
||||
# Phantasy Star Portable Infinity Demo
|
||||
NPJH90157 = true # Infinity demo
|
||||
|
||||
# Test Drive Unlimited
|
||||
ULET00386 = true
|
||||
ULES00637 = true
|
||||
ULKS46126 = true
|
||||
ULUS10249 = true
|
||||
|
||||
# Metal Gear Solid : Peace Walker (see issue #12348)
|
||||
ULUS10509 = true
|
||||
ULES01372 = true
|
||||
ULJM08038 = true
|
||||
NPJH50045 = true
|
||||
ULJM05630 = true
|
||||
NPJH90082 = true
|
||||
NPJH90063 = true
|
||||
|
||||
# Metal Gear Solid : Peace Walker Demo Ops (see issue #12348)
|
||||
NPUH90066 = true
|
||||
NPHH00145 = true
|
||||
NPEH90023 = true
|
||||
|
||||
# Metal Gear Solid: Portable Ops (see issue #12348)
|
||||
ULES00645 = true
|
||||
ULJM05193 = true
|
||||
ULJM05227 = true
|
||||
ULUS10202 = true
|
||||
ULES01003 = true
|
||||
ULJM05261 = true
|
||||
ULUS10290 = true
|
||||
ULED90040 = true
|
||||
ULJM05284 = true
|
||||
ULES00645 = true
|
||||
|
||||
# Splinter Cell Essentials (#13035)
|
||||
ULES00281 = true
|
||||
ULUS10070 = true
|
||||
|
||||
# Asphalt 2 (#14299)
|
||||
ULES00719 = true
|
||||
# No US release, it seems
|
||||
|
||||
# Star Wars: Lethal Alliance (#11551)
|
||||
ULES00599 = true
|
||||
ULUS10188 = true
|
||||
|
||||
# Digimon World Re:Digitize
|
||||
ULJS00496 = true
|
||||
NPJH50588 = true
|
||||
ULAS42319 = true
|
||||
|
||||
# NOVA: Near Orbit Vanguard Alliance
|
||||
NPUZ00179 = true
|
||||
NPEZ00222 = true
|
||||
|
||||
# Street Riders (only region found. See #14746)
|
||||
ULES00276 = true
|
||||
|
||||
[ClearToRAM]
|
||||
# SOCOM Navy Seals games require this. See issue #8973.
|
||||
# Navy Seals : Tactical Strike
|
||||
|
|
Loading…
Add table
Reference in a new issue