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 ...@@ -150,6 +150,7 @@ class DeclareDefaultUniformsTraverser : public TIntermTraverser
}; };
constexpr ImmutableString kFlippedPointCoordName = ImmutableString("flippedPointCoord"); 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 // Declares a new variable to replace gl_PointCoord with a version that is flipping the Y
// coordinate. // coordinate.
...@@ -233,6 +234,28 @@ void FlipGLPointCoord(TIntermBlock *root, ...@@ -233,6 +234,28 @@ void FlipGLPointCoord(TIntermBlock *root,
mainSequence->insert(mainSequence->begin(), assignment); 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 // 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 // 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 // Viewport". In Vulkan the corresponding spec section is currently "23.4. Coordinate
...@@ -300,6 +323,34 @@ const TVariable *AddDriverUniformsToShader(TIntermBlock *root, TSymbolTable *sym ...@@ -300,6 +323,34 @@ const TVariable *AddDriverUniformsToShader(TIntermBlock *root, TSymbolTable *sym
TSourceLoc(), SymbolType::AngleInternal); TSourceLoc(), SymbolType::AngleInternal);
driverFieldList->push_back(driverViewportScaleFactorSize); 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". // Define a driver uniform block "ANGLEUniformBlock".
TLayoutQualifier driverLayoutQualifier = TLayoutQualifier::Create(); TLayoutQualifier driverLayoutQualifier = TLayoutQualifier::Create();
TInterfaceBlock *interfaceBlock = TInterfaceBlock *interfaceBlock =
...@@ -384,6 +435,8 @@ void TranslatorVulkan::translate(TIntermBlock *root, ...@@ -384,6 +435,8 @@ void TranslatorVulkan::translate(TIntermBlock *root,
const TVariable *driverUniformsVariable = AddDriverUniformsToShader(root, &getSymbolTable()); const TVariable *driverUniformsVariable = AddDriverUniformsToShader(root, &getSymbolTable());
ReplaceGLDepthRangeWithDriverUniform(root, driverUniformsVariable, &getSymbolTable());
// Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
// if it's core profile shaders and they are used. // if it's core profile shaders and they are used.
if (getShaderType() == GL_FRAGMENT_SHADER) if (getShaderType() == GL_FRAGMENT_SHADER)
......
...@@ -20,7 +20,7 @@ namespace ...@@ -20,7 +20,7 @@ namespace
class ReplaceVariableTraverser : public TIntermTraverser class ReplaceVariableTraverser : public TIntermTraverser
{ {
public: public:
ReplaceVariableTraverser(const TVariable *toBeReplaced, const TVariable *replacement) ReplaceVariableTraverser(const TVariable *toBeReplaced, const TIntermTyped *replacement)
: TIntermTraverser(true, false, false), : TIntermTraverser(true, false, false),
mToBeReplaced(toBeReplaced), mToBeReplaced(toBeReplaced),
mReplacement(replacement) mReplacement(replacement)
...@@ -31,13 +31,13 @@ class ReplaceVariableTraverser : public TIntermTraverser ...@@ -31,13 +31,13 @@ class ReplaceVariableTraverser : public TIntermTraverser
{ {
if (&node->variable() == mToBeReplaced) if (&node->variable() == mToBeReplaced)
{ {
queueReplacement(new TIntermSymbol(mReplacement), OriginalNode::IS_DROPPED); queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED);
} }
} }
private: private:
const TVariable *const mToBeReplaced; const TVariable *const mToBeReplaced;
const TVariable *const mReplacement; const TIntermTyped *const mReplacement;
}; };
} // anonymous namespace } // anonymous namespace
...@@ -47,6 +47,16 @@ void ReplaceVariable(TIntermBlock *root, ...@@ -47,6 +47,16 @@ void ReplaceVariable(TIntermBlock *root,
const TVariable *toBeReplaced, const TVariable *toBeReplaced,
const TVariable *replacement) 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); ReplaceVariableTraverser traverser(toBeReplaced, replacement);
root->traverse(&traverser); root->traverse(&traverser);
traverser.updateTree(); traverser.updateTree();
......
...@@ -14,11 +14,14 @@ namespace sh ...@@ -14,11 +14,14 @@ namespace sh
class TIntermBlock; class TIntermBlock;
class TVariable; class TVariable;
class TIntermTyped;
void ReplaceVariable(TIntermBlock *root, void ReplaceVariable(TIntermBlock *root,
const TVariable *toBeReplaced, const TVariable *toBeReplaced,
const TVariable *replacement); const TVariable *replacement);
void ReplaceVariableWithTyped(TIntermBlock *root,
const TVariable *toBeReplaced,
const TIntermTyped *replacement);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_ #endif // COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_
...@@ -245,8 +245,8 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -245,8 +245,8 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
// Bind the graphics descriptor sets. // Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers. // TODO(jmadill): Handle multiple command buffers.
const auto &descriptorSets = programVk->getDescriptorSets(); const auto &descriptorSets = programVk->getDescriptorSets();
const gl::RangeUI &usedRange = programVk->getUsedDescriptorSetRange(); const gl::RangeUI &usedRange = programVk->getUsedDescriptorSetRange();
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout(); const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
if (!usedRange.empty()) if (!usedRange.empty())
{ {
...@@ -470,11 +470,12 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -470,11 +470,12 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(), mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(),
glState.getNearPlane(), glState.getFarPlane(), glState.getNearPlane(), glState.getFarPlane(),
isViewportFlipEnabledForDrawFBO()); isViewportFlipEnabledForDrawFBO());
ANGLE_TRY(updateDriverUniforms()); ANGLE_TRY(updateDriverUniforms(glState));
break; break;
} }
case gl::State::DIRTY_BIT_DEPTH_RANGE: case gl::State::DIRTY_BIT_DEPTH_RANGE:
mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane()); mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
ANGLE_TRY(updateDriverUniforms(glState));
break; break;
case gl::State::DIRTY_BIT_BLEND_ENABLED: case gl::State::DIRTY_BIT_BLEND_ENABLED:
mPipelineDesc->updateBlendEnabled(glState.isBlendEnabled()); mPipelineDesc->updateBlendEnabled(glState.isBlendEnabled());
...@@ -588,8 +589,8 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -588,8 +589,8 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
break; break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
{ {
ANGLE_TRY(updateDriverUniforms()); ANGLE_TRY(updateDriverUniforms(glState));
updateFlipViewportDrawFramebuffer(context->getGLState()); updateFlipViewportDrawFramebuffer(glState);
FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer()); FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(), mPipelineDesc->updateViewport(framebufferVk, glState.getViewport(),
glState.getNearPlane(), glState.getFarPlane(), glState.getNearPlane(), glState.getFarPlane(),
...@@ -687,7 +688,7 @@ gl::Error ContextVk::onMakeCurrent(const gl::Context *context) ...@@ -687,7 +688,7 @@ gl::Error ContextVk::onMakeCurrent(const gl::Context *context)
const gl::State &glState = context->getGLState(); const gl::State &glState = context->getGLState();
updateFlipViewportDrawFramebuffer(glState); updateFlipViewportDrawFramebuffer(glState);
updateFlipViewportReadFramebuffer(glState); updateFlipViewportReadFramebuffer(glState);
ANGLE_TRY(updateDriverUniforms()); ANGLE_TRY(updateDriverUniforms(glState));
return gl::NoError(); return gl::NoError();
} }
...@@ -857,7 +858,7 @@ const FeaturesVk &ContextVk::getFeatures() const ...@@ -857,7 +858,7 @@ const FeaturesVk &ContextVk::getFeatures() const
return mRenderer->getFeatures(); return mRenderer->getFeatures();
} }
angle::Result ContextVk::updateDriverUniforms() angle::Result ContextVk::updateDriverUniforms(const gl::State &glState)
{ {
if (!mDriverUniformsBuffer.valid()) if (!mDriverUniformsBuffer.valid())
{ {
...@@ -869,7 +870,7 @@ angle::Result ContextVk::updateDriverUniforms() ...@@ -869,7 +870,7 @@ angle::Result ContextVk::updateDriverUniforms()
// Release any previously retained buffers. // Release any previously retained buffers.
mDriverUniformsBuffer.releaseRetainedBuffers(mRenderer); mDriverUniformsBuffer.releaseRetainedBuffers(mRenderer);
const gl::Rectangle &glViewport = mState.getState().getViewport(); const gl::Rectangle &glViewport = glState.getViewport();
// Allocate a new region in the dynamic buffer. // Allocate a new region in the dynamic buffer.
uint8_t *ptr = nullptr; uint8_t *ptr = nullptr;
...@@ -880,12 +881,17 @@ angle::Result ContextVk::updateDriverUniforms() ...@@ -880,12 +881,17 @@ angle::Result ContextVk::updateDriverUniforms()
&newBufferAllocated)); &newBufferAllocated));
float scaleY = isViewportFlipEnabledForDrawFBO() ? 1.0f : -1.0f; 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. // Copy and flush to the device.
DriverUniforms *driverUniforms = reinterpret_cast<DriverUniforms *>(ptr); DriverUniforms *driverUniforms = reinterpret_cast<DriverUniforms *>(ptr);
*driverUniforms = { *driverUniforms = {
{static_cast<float>(glViewport.x), static_cast<float>(glViewport.y), {static_cast<float>(glViewport.x), static_cast<float>(glViewport.y),
static_cast<float>(glViewport.width), static_cast<float>(glViewport.height)}, 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)); ANGLE_TRY(mDriverUniformsBuffer.flush(this));
......
...@@ -182,7 +182,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -182,7 +182,7 @@ class ContextVk : public ContextImpl, public vk::Context
void updateFlipViewportDrawFramebuffer(const gl::State &glState); void updateFlipViewportDrawFramebuffer(const gl::State &glState);
void updateFlipViewportReadFramebuffer(const gl::State &glState); void updateFlipViewportReadFramebuffer(const gl::State &glState);
angle::Result updateDriverUniforms(); angle::Result updateDriverUniforms(const gl::State &glState);
vk::PipelineAndSerial *mCurrentPipeline; vk::PipelineAndSerial *mCurrentPipeline;
gl::PrimitiveMode mCurrentDrawMode; gl::PrimitiveMode mCurrentDrawMode;
...@@ -217,6 +217,9 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -217,6 +217,9 @@ class ContextVk : public ContextImpl, public vk::Context
{ {
std::array<float, 4> viewport; std::array<float, 4> viewport;
std::array<float, 4> viewportScaleFactor; std::array<float, 4> viewportScaleFactor;
// We'll use x, y, z for near / far / diff respectively.
std::array<float, 4> depthRange;
}; };
vk::DynamicBuffer mDriverUniformsBuffer; vk::DynamicBuffer mDriverUniformsBuffer;
VkDescriptorSet mDriverUniformsDescriptorSet; VkDescriptorSet mDriverUniformsDescriptorSet;
......
...@@ -267,7 +267,6 @@ ...@@ -267,7 +267,6 @@
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
// Vulkan failures // Vulkan failures
2592 VULKAN : dEQP-GLES2.functional.shaders.builtin_variable.depth_range* = SKIP
2598 VULKAN : dEQP-GLES2.functional.rasterization.primitives.line* = SKIP 2598 VULKAN : dEQP-GLES2.functional.rasterization.primitives.line* = SKIP
2599 VULKAN : dEQP-GLES2.functional.rasterization.limits.points = SKIP 2599 VULKAN : dEQP-GLES2.functional.rasterization.limits.points = SKIP
2601 VULKAN : dEQP-GLES2.functional.clipping.* = SKIP 2601 VULKAN : dEQP-GLES2.functional.clipping.* = SKIP
......
...@@ -4627,10 +4627,20 @@ ANGLE_INSTANTIATE_TEST(GLSLTest, ...@@ -4627,10 +4627,20 @@ ANGLE_INSTANTIATE_TEST(GLSLTest,
ES2_OPENGLES(), ES2_OPENGLES(),
ES3_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 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_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