Commit e835609c by Luc Ferron Committed by Commit Bot

Vulkan: Implement gl_DepthRange support using driver uniform

Bug: angleproject:2592 Change-Id: Iec3d111df4d8e5cef205c8afb177f0514ffac5c8 Reviewed-on: https://chromium-review.googlesource.com/1135448 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent f786b706
......@@ -150,6 +150,7 @@ class DeclareDefaultUniformsTraverser : public TIntermTraverser
};
constexpr ImmutableString kFlippedPointCoordName = ImmutableString("flippedPointCoord");
constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams");
// Declares a new variable to replace gl_PointCoord with a version that is flipping the Y
// coordinate.
......@@ -233,6 +234,28 @@ void FlipGLPointCoord(TIntermBlock *root,
mainSequence->insert(mainSequence->begin(), assignment);
}
// Declares a new variable to replace gl_DepthRange, its values are fed from a driver uniform.
void ReplaceGLDepthRangeWithDriverUniform(TIntermBlock *root,
const TVariable *driverUniforms,
TSymbolTable *symbolTable)
{
// Create a symbol reference to "gl_DepthRange"
const TVariable *depthRangeVar = static_cast<const TVariable *>(
symbolTable->findBuiltIn(ImmutableString("gl_DepthRange"), 0));
// ANGLEUniforms.depthRange
TIntermSymbol *angleUniformsRef = new TIntermSymbol(driverUniforms);
TConstantUnion *depthRangeConstant = new TConstantUnion;
depthRangeConstant->setIConst(2);
TIntermConstantUnion *depthRangeIndex =
new TIntermConstantUnion(depthRangeConstant, *StaticType::GetBasic<EbtInt>());
TIntermBinary *angleEmulatedDepthRangeRef =
new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, depthRangeIndex);
// Use this variable instead of gl_DepthRange everywhere.
ReplaceVariableWithTyped(root, depthRangeVar, angleEmulatedDepthRangeRef);
}
// This operation performs the viewport depth translation needed by Vulkan. In GL the viewport
// transformation is slightly different - see the GL 2.0 spec section "2.12.1 Controlling the
// Viewport". In Vulkan the corresponding spec section is currently "23.4. Coordinate
......@@ -300,6 +323,34 @@ const TVariable *AddDriverUniformsToShader(TIntermBlock *root, TSymbolTable *sym
TSourceLoc(), SymbolType::AngleInternal);
driverFieldList->push_back(driverViewportScaleFactorSize);
// Add a new struct field "depthRange" to the driver uniform fields.
const TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
TFieldList *depthRangeParamsFields = new TFieldList();
depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
ImmutableString("near"), zeroSourceLoc,
SymbolType::AngleInternal));
depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
ImmutableString("far"), zeroSourceLoc,
SymbolType::AngleInternal));
depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
ImmutableString("diff"), zeroSourceLoc,
SymbolType::AngleInternal));
depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
ImmutableString("dummyPacker"), zeroSourceLoc,
SymbolType::AngleInternal));
TStructure *emulatedDepthRangeParams = new TStructure(
symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
TType *emulatedDepthRangeType = new TType(emulatedDepthRangeParams, false);
TVariable *depthRangeVar =
new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty,
TExtension::UNDEFINED, emulatedDepthRangeType);
DeclareGlobalVariable(root, depthRangeVar);
TField *driverDepthRangeSize = new TField(emulatedDepthRangeType, ImmutableString("depthRange"),
TSourceLoc(), SymbolType::AngleInternal);
driverFieldList->push_back(driverDepthRangeSize);
// Define a driver uniform block "ANGLEUniformBlock".
TLayoutQualifier driverLayoutQualifier = TLayoutQualifier::Create();
TInterfaceBlock *interfaceBlock =
......@@ -384,6 +435,8 @@ void TranslatorVulkan::translate(TIntermBlock *root,
const TVariable *driverUniformsVariable = AddDriverUniformsToShader(root, &getSymbolTable());
ReplaceGLDepthRangeWithDriverUniform(root, driverUniformsVariable, &getSymbolTable());
// Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
// if it's core profile shaders and they are used.
if (getShaderType() == GL_FRAGMENT_SHADER)
......
......@@ -20,7 +20,7 @@ namespace
class ReplaceVariableTraverser : public TIntermTraverser
{
public:
ReplaceVariableTraverser(const TVariable *toBeReplaced, const TVariable *replacement)
ReplaceVariableTraverser(const TVariable *toBeReplaced, const TIntermTyped *replacement)
: TIntermTraverser(true, false, false),
mToBeReplaced(toBeReplaced),
mReplacement(replacement)
......@@ -31,13 +31,13 @@ class ReplaceVariableTraverser : public TIntermTraverser
{
if (&node->variable() == mToBeReplaced)
{
queueReplacement(new TIntermSymbol(mReplacement), OriginalNode::IS_DROPPED);
queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED);
}
}
private:
const TVariable *const mToBeReplaced;
const TVariable *const mReplacement;
const TIntermTyped *const mReplacement;
};
} // anonymous namespace
......@@ -47,6 +47,16 @@ void ReplaceVariable(TIntermBlock *root,
const TVariable *toBeReplaced,
const TVariable *replacement)
{
ReplaceVariableTraverser traverser(toBeReplaced, new TIntermSymbol(replacement));
root->traverse(&traverser);
traverser.updateTree();
}
// Replaces every occurrence of a variable with a TIntermNode.
void ReplaceVariableWithTyped(TIntermBlock *root,
const TVariable *toBeReplaced,
const TIntermTyped *replacement)
{
ReplaceVariableTraverser traverser(toBeReplaced, replacement);
root->traverse(&traverser);
traverser.updateTree();
......
......@@ -14,11 +14,14 @@ namespace sh
class TIntermBlock;
class TVariable;
class TIntermTyped;
void ReplaceVariable(TIntermBlock *root,
const TVariable *toBeReplaced,
const TVariable *replacement);
void ReplaceVariableWithTyped(TIntermBlock *root,
const TVariable *toBeReplaced,
const TIntermTyped *replacement);
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_
......@@ -245,8 +245,8 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
// Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers.
const auto &descriptorSets = programVk->getDescriptorSets();
const gl::RangeUI &usedRange = programVk->getUsedDescriptorSetRange();
const auto &descriptorSets = programVk->getDescriptorSets();
const gl::RangeUI &usedRange = programVk->getUsedDescriptorSetRange();
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
if (!usedRange.empty())
{
......@@ -470,11 +470,12 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(),
glState.getNearPlane(), glState.getFarPlane(),
isViewportFlipEnabledForDrawFBO());
ANGLE_TRY(updateDriverUniforms());
ANGLE_TRY(updateDriverUniforms(glState));
break;
}
case gl::State::DIRTY_BIT_DEPTH_RANGE:
mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
ANGLE_TRY(updateDriverUniforms(glState));
break;
case gl::State::DIRTY_BIT_BLEND_ENABLED:
mPipelineDesc->updateBlendEnabled(glState.isBlendEnabled());
......@@ -588,8 +589,8 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
{
ANGLE_TRY(updateDriverUniforms());
updateFlipViewportDrawFramebuffer(context->getGLState());
ANGLE_TRY(updateDriverUniforms(glState));
updateFlipViewportDrawFramebuffer(glState);
FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(),
glState.getNearPlane(), glState.getFarPlane(),
......@@ -687,7 +688,7 @@ gl::Error ContextVk::onMakeCurrent(const gl::Context *context)
const gl::State &glState = context->getGLState();
updateFlipViewportDrawFramebuffer(glState);
updateFlipViewportReadFramebuffer(glState);
ANGLE_TRY(updateDriverUniforms());
ANGLE_TRY(updateDriverUniforms(glState));
return gl::NoError();
}
......@@ -857,7 +858,7 @@ const FeaturesVk &ContextVk::getFeatures() const
return mRenderer->getFeatures();
}
angle::Result ContextVk::updateDriverUniforms()
angle::Result ContextVk::updateDriverUniforms(const gl::State &glState)
{
if (!mDriverUniformsBuffer.valid())
{
......@@ -869,7 +870,7 @@ angle::Result ContextVk::updateDriverUniforms()
// Release any previously retained buffers.
mDriverUniformsBuffer.releaseRetainedBuffers(mRenderer);
const gl::Rectangle &glViewport = mState.getState().getViewport();
const gl::Rectangle &glViewport = glState.getViewport();
// Allocate a new region in the dynamic buffer.
uint8_t *ptr = nullptr;
......@@ -880,12 +881,17 @@ angle::Result ContextVk::updateDriverUniforms()
&newBufferAllocated));
float scaleY = isViewportFlipEnabledForDrawFBO() ? 1.0f : -1.0f;
float depthRangeNear = glState.getNearPlane();
float depthRangeFar = glState.getFarPlane();
float depthRangeDiff = depthRangeFar - depthRangeNear;
// Copy and flush to the device.
DriverUniforms *driverUniforms = reinterpret_cast<DriverUniforms *>(ptr);
*driverUniforms = {
{static_cast<float>(glViewport.x), static_cast<float>(glViewport.y),
static_cast<float>(glViewport.width), static_cast<float>(glViewport.height)},
{1.0f, scaleY, 1.0f, 1.0f}};
{1.0f, scaleY, 1.0f, 1.0f},
{depthRangeNear, depthRangeFar, depthRangeDiff, 0.0f}};
ANGLE_TRY(mDriverUniformsBuffer.flush(this));
......
......@@ -182,7 +182,7 @@ class ContextVk : public ContextImpl, public vk::Context
void updateFlipViewportDrawFramebuffer(const gl::State &glState);
void updateFlipViewportReadFramebuffer(const gl::State &glState);
angle::Result updateDriverUniforms();
angle::Result updateDriverUniforms(const gl::State &glState);
vk::PipelineAndSerial *mCurrentPipeline;
gl::PrimitiveMode mCurrentDrawMode;
......@@ -217,6 +217,9 @@ class ContextVk : public ContextImpl, public vk::Context
{
std::array<float, 4> viewport;
std::array<float, 4> viewportScaleFactor;
// We'll use x, y, z for near / far / diff respectively.
std::array<float, 4> depthRange;
};
vk::DynamicBuffer mDriverUniformsBuffer;
VkDescriptorSet mDriverUniformsDescriptorSet;
......
......@@ -267,7 +267,6 @@
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
// Vulkan failures
2592 VULKAN : dEQP-GLES2.functional.shaders.builtin_variable.depth_range* = SKIP
2598 VULKAN : dEQP-GLES2.functional.rasterization.primitives.line* = SKIP
2599 VULKAN : dEQP-GLES2.functional.rasterization.limits.points = SKIP
2601 VULKAN : dEQP-GLES2.functional.clipping.* = SKIP
......
......@@ -4627,10 +4627,20 @@ ANGLE_INSTANTIATE_TEST(GLSLTest,
ES2_OPENGLES(),
ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(GLSLTestNoValidation,
ES2_D3D9(),
ES2_D3D11(),
ES2_D3D11_FL9_3(),
ES2_OPENGL(),
ES2_VULKAN(),
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
\ No newline at end of file
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