mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Revert to software on out-of-bounds projected depth
This commit is contained in:
@@ -743,17 +743,18 @@ SoftwareTransformAction SoftwareTransform::ProjectClipAndExpand(SoftwareTransfor
|
||||
// minZ and maxZ will cut things off.
|
||||
|
||||
// If gstate_c.Use(GPU_USE_DEPTH_CLAMP), we can theoretically skip this. However, to keep behavior the same regardless of the flag, we won't.
|
||||
if (gstate.isDepthClipEnabled() && (maxZInt == 0 || maxZInt == 65535)) {
|
||||
if (gstate.isDepthClipEnabled() && (minZInt == 0 || maxZInt == 65535)) {
|
||||
for (int i = 0; i < numTrans - 2; i += 3) {
|
||||
TransformedVertex &v0 = transformed[indsIn[i]];
|
||||
TransformedVertex &v1 = transformed[indsIn[i + 1]];
|
||||
TransformedVertex &v2 = transformed[indsIn[i + 2]];
|
||||
TransformedVertex &v0 = transformed[newInds[i]];
|
||||
TransformedVertex &v1 = transformed[newInds[i + 1]];
|
||||
TransformedVertex &v2 = transformed[newInds[i + 2]];
|
||||
if (v0.x < 0.0f || v0.x > 4096.0f ||
|
||||
v1.x < 0.0f || v1.y > 4096.0f ||
|
||||
v2.x < 0.0f || v2.y > 4096.0f) {
|
||||
// If it's outside the viewport, we might as well skip the clamping, as it won't be visible anyway.
|
||||
// continue;
|
||||
}
|
||||
|
||||
if (minZInt == 0) {
|
||||
bool v0InFront = v0.z < 0.0f;
|
||||
bool v1InFront = v1.z < 0.0f;
|
||||
|
||||
@@ -240,7 +240,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
|
||||
const bool clipEnable = id.Bit(VS_BIT_CLIP_ENABLE) && !isModeThrough;
|
||||
const bool rangeCulling = id.Bit(VS_BIT_VERTEX_RANGE_CULLING);
|
||||
const bool depthCullEnable = gstate_c.Use(GPU_USE_CULL_DISTANCE) && !isModeThrough;
|
||||
const bool depthCullEnable = gstate_c.Use(GPU_USE_CULL_DISTANCE) && !isModeThrough && rangeCulling; // Range culling is gated on draw type, we don't want to do this culling for splines apparently.
|
||||
|
||||
const char *zClipPlaneSuffix = "[0]";
|
||||
const char *minZClipPlaneSuffix = "[1]";
|
||||
@@ -835,6 +835,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
|
||||
if (depthCullEnable) {
|
||||
// Before the viewport, discard any primitives that are fully outside the clipping volume in Z.
|
||||
// NOTE: This volume is very slightly too small. It's unclear to me how to allow hex 0x3F8000XX (1.0000.. + epsilon) where XX are arbitrary.
|
||||
WRITE(p, " %sgl_CullDistance[0] = outPos.z + outPos.w;\n", compat.vsOutPrefix);
|
||||
WRITE(p, " %sgl_CullDistance[1] = outPos.w - outPos.z;\n", compat.vsOutPrefix);
|
||||
}
|
||||
|
||||
@@ -295,6 +295,23 @@ void DrawEngineD3D11::Flush() {
|
||||
bool tess = gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE;
|
||||
bool useHWTransform = CanUseHardwareTransform(prim) && (tess || gstate.getShadeMode() != GE_SHADE_FLAT);
|
||||
|
||||
if (useHWTransform && boundingDepths_.valid) {
|
||||
if (boundingDepths_.hitClipSpaceZW) {
|
||||
// Revert to software transform so we can clip more accurately.
|
||||
useHWTransform = false;
|
||||
}
|
||||
if ((boundingDepths_.minProjZ < 0.0 || boundingDepths_.maxProjZ > 65535.0) && !gstate_c.Use(GPU_USE_DEPTH_CLAMP)) {
|
||||
// Revert to software transform so we can clamp more accurately.
|
||||
useHWTransform = false;
|
||||
}
|
||||
// Also handle clamping in software if it's not supported in hardware (or always?)
|
||||
}
|
||||
|
||||
if (useHWTransform != lastUseHwTransform_) {
|
||||
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_RASTER_STATE);
|
||||
lastUseHwTransform_ = useHWTransform;
|
||||
}
|
||||
|
||||
if (useHWTransform) {
|
||||
ID3D11Buffer *vb_ = nullptr;
|
||||
ID3D11Buffer *ib_ = nullptr;
|
||||
|
||||
@@ -222,14 +222,15 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
||||
bool wantCull = !gstate.isModeClear() && prim != GE_PRIM_RECTANGLES && prim > GE_PRIM_LINE_STRIP && gstate.isCullEnabled();
|
||||
keys_.raster.cullMode = wantCull ? (gstate.getCullMode() ? D3D11_CULL_FRONT : D3D11_CULL_BACK) : D3D11_CULL_NONE;
|
||||
|
||||
// In D3D11, depth clamping is on by default, we have to enable clipping. This is the opposite from the
|
||||
// other APIs.
|
||||
if (gstate.isModeClear() || gstate.isModeThrough()) {
|
||||
// TODO: Might happen in clear mode if not through...
|
||||
keys_.raster.depthClipEnable = 1;
|
||||
} else {
|
||||
if (gstate.getDepthRangeMin() == 0 || gstate.getDepthRangeMax() == 65535) {
|
||||
// TODO: Still has a bug where we clamp to depth range if one is not the full range.
|
||||
// But the alternate is not clamping in either direction...
|
||||
keys_.raster.depthClipEnable = !gstate.isDepthClipEnabled() || !gstate_c.Use(GPU_USE_DEPTH_CLAMP);
|
||||
// We get some extra clamping behavior if clipping is enabled.
|
||||
keys_.raster.depthClipEnable = !(gstate.isDepthClipEnabled() && !gstate_c.Use(GPU_USE_DEPTH_CLAMP));
|
||||
} else {
|
||||
// We just want to clip in this case, the clamp would be clipped anyway.
|
||||
keys_.raster.depthClipEnable = 1;
|
||||
|
||||
@@ -253,7 +253,26 @@ void DrawEngineGLES::Flush() {
|
||||
|
||||
GEPrimitiveType prim = prevPrim_;
|
||||
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, dec_->VertexType(), decOptions_.expandAllWeightsToFloat, applySkinInDecode_ || !CanUseHardwareTransform(prim), &vsid);
|
||||
bool useHWTransform = CanUseHardwareTransform(prim);
|
||||
|
||||
if (useHWTransform && boundingDepths_.valid) {
|
||||
if (boundingDepths_.hitClipSpaceZW) {
|
||||
// Revert to software transform so we can clip more accurately.
|
||||
useHWTransform = false;
|
||||
}
|
||||
if ((boundingDepths_.minProjZ < 0.0 || boundingDepths_.maxProjZ > 65535.0) && !gstate_c.Use(GPU_USE_DEPTH_CLAMP)) {
|
||||
// Revert to software transform so we can clamp more accurately.
|
||||
useHWTransform = false;
|
||||
}
|
||||
// Also handle clamping in software if it's not supported in hardware (or always?)
|
||||
}
|
||||
|
||||
if (useHWTransform != lastUseHwTransform_) {
|
||||
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_RASTER_STATE);
|
||||
lastUseHwTransform_ = useHWTransform;
|
||||
}
|
||||
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(useHWTransform, useHWTessellation_, dec_->VertexType(), decOptions_.expandAllWeightsToFloat, applySkinInDecode_ || !useHWTransform, &vsid);
|
||||
|
||||
GLRBuffer *vertexBuffer = nullptr;
|
||||
GLRBuffer *indexBuffer = nullptr;
|
||||
|
||||
@@ -223,8 +223,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
||||
depthClampEnable = false;
|
||||
} else {
|
||||
if (gstate.getDepthRangeMin() == 0 || gstate.getDepthRangeMax() == 65535) {
|
||||
// TODO: Still has a bug where we clamp to depth range if one is not the full range.
|
||||
// But the alternate is not clamping in either direction...
|
||||
// We get some extra clamping behavior if clipping is enabled.
|
||||
depthClampEnable = gstate.isDepthClipEnabled() && gstate_c.Use(GPU_USE_DEPTH_CLAMP);
|
||||
} else {
|
||||
// We just want to clip in this case, the clamp would be clipped anyway.
|
||||
|
||||
+1
-1
@@ -1009,7 +1009,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_CULL_CHECK_COUNT 64
|
||||
#define MAX_CULL_CHECK_COUNT 512
|
||||
|
||||
// For now, turn off culling on platforms where we don't have SIMD bounding box tests, like RISC-V.
|
||||
#if PPSSPP_ARCH(ARM_NEON) || PPSSPP_ARCH(SSE2)
|
||||
|
||||
@@ -244,13 +244,18 @@ void DrawEngineVulkan::Flush() {
|
||||
|
||||
if (useHWTransform && boundingDepths_.valid) {
|
||||
if (boundingDepths_.hitClipSpaceZW) {
|
||||
// Revert to software so we can clip more accurately.
|
||||
// Revert to software transform so we can clip more accurately.
|
||||
useHWTransform = false;
|
||||
}
|
||||
if ((boundingDepths_.minProjZ < 0.0 || boundingDepths_.maxProjZ > 65535.0) && !gstate_c.Use(GPU_USE_DEPTH_CLAMP)) {
|
||||
// Revert to software transform so we can clamp more accurately.
|
||||
useHWTransform = false;
|
||||
}
|
||||
// Also handle clamping in software if it's not supported in hardware (or always?)
|
||||
}
|
||||
|
||||
if (useHWTransform != lastUseHwTransform_) {
|
||||
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
|
||||
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_RASTER_STATE);
|
||||
lastUseHwTransform_ = useHWTransform;
|
||||
}
|
||||
|
||||
|
||||
@@ -224,10 +224,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
||||
key.depthClampEnable = false;
|
||||
} else {
|
||||
if (gstate.getDepthRangeMin() == 0 || gstate.getDepthRangeMax() == 65535) {
|
||||
// TODO: Still has a bug where we clamp to depth range if one is not the full range.
|
||||
// But the alternate is not clamping in either direction...
|
||||
|
||||
// Anyway, it seems that we get some extra clamping behavior if clipping is enabled.
|
||||
// We get some extra clamping behavior if clipping is enabled.
|
||||
key.depthClampEnable = gstate.isDepthClipEnabled() && gstate_c.Use(GPU_USE_DEPTH_CLAMP);
|
||||
} else {
|
||||
// We just want to clip in this case, the clamp would be clipped anyway.
|
||||
|
||||
Reference in New Issue
Block a user