Commit 4cef8a49 by Le Hoang Quyen Committed by Commit Bot

Metal: Support depthRange near > far

Metal doesn't natively support near > far depthRange, need to emulate it via shader. Bug: angleproject:2634 Change-Id: I1885cad3467478a0dcc4b25b7d41f980b9e03103 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1919282 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com>
parent ab63fd28
......@@ -96,4 +96,32 @@ bool TranslatorMetal::translate(TIntermBlock *root,
return true;
}
// Metal needs to inverse the depth if depthRange is is reverse order, i.e. depth near > depth far
// This is achieved by multiply the depth value with scale value stored in
// driver uniform's depthRange.reserved
bool TranslatorMetal::transformDepthBeforeCorrection(TIntermBlock *root,
const TVariable *driverUniforms)
{
// Create a symbol reference to "gl_Position"
const TVariable *position = BuiltInVariable::gl_Position();
TIntermSymbol *positionRef = new TIntermSymbol(position);
// Create a swizzle to "gl_Position.z"
TVector<int> swizzleOffsetZ = {2};
TIntermSwizzle *positionZ = new TIntermSwizzle(positionRef, swizzleOffsetZ);
// Create a ref to "depthRange.reserved"
TIntermBinary *viewportZScale = getDriverUniformDepthRangeReservedFieldRef(driverUniforms);
// Create the expression "gl_Position.z * depthRange.reserved".
TIntermBinary *zScale = new TIntermBinary(EOpMul, positionZ->deepCopy(), viewportZScale);
// Create the assignment "gl_Position.z = gl_Position.z * depthRange.reserved"
TIntermTyped *positionZLHS = positionZ->deepCopy();
TIntermBinary *assignment = new TIntermBinary(TOperator::EOpAssign, positionZLHS, zScale);
// Append the assignment as a statement at the end of the shader.
return RunAtTheEndOfShader(this, root, assignment, &getSymbolTable());
}
} // namespace sh
......@@ -29,6 +29,9 @@ class TranslatorMetal : public TranslatorVulkan
ANGLE_NO_DISCARD bool translate(TIntermBlock *root,
ShCompileOptions compileOptions,
PerformanceDiagnostics *perfDiagnostics) override;
ANGLE_NO_DISCARD bool transformDepthBeforeCorrection(TIntermBlock *root,
const TVariable *driverUniforms) override;
};
} // namespace sh
......
......@@ -351,8 +351,9 @@ const TVariable *AddGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTa
depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
ImmutableString("diff"), TSourceLoc(),
SymbolType::AngleInternal));
// This additional field might be used by subclass such as TranslatorMetal.
depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
ImmutableString("dummyPacker"), TSourceLoc(),
ImmutableString("reserved"), TSourceLoc(),
SymbolType::AngleInternal));
TStructure *emulatedDepthRangeParams = new TStructure(
symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
......@@ -938,6 +939,10 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
}
// Append depth range translation to main.
if (!transformDepthBeforeCorrection(root, driverUniforms))
{
return false;
}
if (!AppendVertexShaderDepthCorrectionToMain(this, root, &getSymbolTable()))
{
return false;
......@@ -1001,4 +1006,12 @@ TIntermBinary *TranslatorVulkan::getDriverUniformNegViewportYScaleRef(
return CreateDriverUniformRef(driverUniforms, kNegViewportYScale);
}
TIntermBinary *TranslatorVulkan::getDriverUniformDepthRangeReservedFieldRef(
const TVariable *driverUniforms) const
{
TIntermBinary *depthRange = CreateDriverUniformRef(driverUniforms, kDepthRange);
return new TIntermBinary(EOpIndexDirectStruct, depthRange, CreateIndexNode(3));
}
} // namespace sh
......@@ -31,6 +31,8 @@ class TranslatorVulkan : public TCompiler
bool shouldFlattenPragmaStdglInvariantAll() override;
TIntermBinary *getDriverUniformNegViewportYScaleRef(const TVariable *driverUniforms) const;
TIntermBinary *getDriverUniformDepthRangeReservedFieldRef(
const TVariable *driverUniforms) const;
// Subclass can call this method to transform the AST before writing the final output.
// See TranslatorMetal.cpp.
ANGLE_NO_DISCARD bool translateImpl(TIntermBlock *root,
......@@ -38,6 +40,14 @@ class TranslatorVulkan : public TCompiler
PerformanceDiagnostics *perfDiagnostics,
const TVariable **driverUniformsOut,
TOutputVulkanGLSL *outputGLSL);
// Give subclass such as TranslatorMetal a chance to do depth transform before
// TranslatorVulkan apply its own transform.
ANGLE_NO_DISCARD virtual bool transformDepthBeforeCorrection(TIntermBlock *root,
const TVariable *driverUniforms)
{
return true;
}
};
} // namespace sh
......
......@@ -385,7 +385,7 @@ class ContextMtl : public ContextImpl, public mtl::Context
int32_t xfbBufferOffsets[4];
uint32_t acbBufferOffsets[4];
// We'll use x, y, z for near / far / diff respectively.
// We'll use x, y, z, w for near / far / diff / zscale respectively.
float depthRange[4];
};
......
......@@ -85,6 +85,11 @@ angle::Result AllocateTriangleFanBufferFromPool(ContextMtl *context,
return angle::Result::Continue;
}
bool NeedToInvertDepthRange(float near, float far)
{
return near > far;
}
} // namespace
ContextMtl::ContextMtl(const gl::State &state, gl::ErrorSet *errorSet, DisplayMtl *display)
......@@ -1205,6 +1210,12 @@ void ContextMtl::updateViewport(FramebufferMtl *framebufferMtl,
void ContextMtl::updateDepthRange(float nearPlane, float farPlane)
{
if (NeedToInvertDepthRange(nearPlane, farPlane))
{
// We also need to invert the depth in shader later by using scale value stored in driver
// uniform depthRange.reserved
std::swap(nearPlane, farPlane);
}
mViewport.znear = nearPlane;
mViewport.zfar = farPlane;
mDirtyBits.set(DIRTY_BIT_VIEWPORT);
......@@ -1572,6 +1583,7 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context)
mDriverUniforms.depthRange[0] = depthRangeNear;
mDriverUniforms.depthRange[1] = depthRangeFar;
mDriverUniforms.depthRange[2] = depthRangeDiff;
mDriverUniforms.depthRange[3] = NeedToInvertDepthRange(depthRangeNear, depthRangeFar) ? -1 : 1;
ASSERT(mRenderEncoder.valid());
mRenderEncoder.setFragmentData(mDriverUniforms, mtl::kDriverUniformsBindingIndex);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment