Commit c9bde926 by Jamie Madill Committed by Commit Bot

D3D11: Allow gl_PointCoord when not rendering points.

ANGLE D3D11 uses a geometry shader to expand points into quads. This led to an edge case with gl_PointCoord. When the user references gl_PointCoord in the fragment shader but renders with GL_TRIANGLES or other non-point primitives, gl_PointCoord is undefined, but ANGLE would produce a link error. This would break some very odd edge-case shaders (e.g. a shader that is used with both points and triangles). We can fix this by simply adding a dummy PointCoord value to our vertex shader is all cases. If the user renders points, we ignore the PointCoord value passed to the geometry shader. If they render tris or lines and use PointCoord, the shader signatures will match, and PointCoord will even have a sane value of (0.5, 0.5). BUG=angleproject:1380 Change-Id: I322155cd3801d0241cabc9bb639a5aaa502831b3 Reviewed-on: https://chromium-review.googlesource.com/362779 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Commit-Queue: Zhenyao Mo <zmo@chromium.org>
parent ce1ed238
...@@ -377,16 +377,14 @@ D3DVarying::D3DVarying(const std::string &semanticNameIn, ...@@ -377,16 +377,14 @@ D3DVarying::D3DVarying(const std::string &semanticNameIn,
// ProgramD3DMetadata Implementation // ProgramD3DMetadata Implementation
ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel, ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
const std::string &shaderModelSuffix,
bool usesInstancedPointSpriteEmulation,
bool usesViewScale,
const ShaderD3D *vertexShader, const ShaderD3D *vertexShader,
const ShaderD3D *fragmentShader) const ShaderD3D *fragmentShader)
: mRendererMajorShaderModel(rendererMajorShaderModel), : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
mShaderModelSuffix(shaderModelSuffix), mShaderModelSuffix(renderer->getShaderModelSuffix()),
mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation), mUsesInstancedPointSpriteEmulation(
mUsesViewScale(usesViewScale), renderer->getWorkarounds().useInstancedPointSpriteEmulation),
mUsesViewScale(renderer->presentPathFastEnabled()),
mVertexShader(vertexShader), mVertexShader(vertexShader),
mFragmentShader(fragmentShader) mFragmentShader(fragmentShader)
{ {
...@@ -424,7 +422,8 @@ bool ProgramD3DMetadata::usesPointSize() const ...@@ -424,7 +422,8 @@ bool ProgramD3DMetadata::usesPointSize() const
bool ProgramD3DMetadata::usesInsertedPointCoordValue() const bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
{ {
return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4; return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
mRendererMajorShaderModel >= 4;
} }
bool ProgramD3DMetadata::usesViewScale() const bool ProgramD3DMetadata::usesViewScale() const
...@@ -434,13 +433,12 @@ bool ProgramD3DMetadata::usesViewScale() const ...@@ -434,13 +433,12 @@ bool ProgramD3DMetadata::usesViewScale() const
bool ProgramD3DMetadata::addsPointCoordToVertexShader() const bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
{ {
// Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
// VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader. // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
// GeometryShader PointSprite emulation does not require this additional entry because the // Even with a geometry shader, the app can render triangles or lines and reference
// GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
// PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs // simplicity, we always add this to the vertex shader when the fragment shader
// gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need // references gl_PointCoord, even if we could skip it in the geometry shader.
// gl_PointSize in VS_OUTPUT.
return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) || return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
usesInsertedPointCoordValue(); usesInsertedPointCoordValue();
} }
...@@ -1380,10 +1378,7 @@ LinkResult ProgramD3D::link(const gl::ContextState &data, gl::InfoLog &infoLog) ...@@ -1380,10 +1378,7 @@ LinkResult ProgramD3D::link(const gl::ContextState &data, gl::InfoLog &infoLog)
return LinkResult(false, gl::Error(GL_NO_ERROR)); return LinkResult(false, gl::Error(GL_NO_ERROR));
} }
ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(), ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D);
usesInstancedPointSpriteEmulation(),
mRenderer->presentPathFastEnabled(), vertexShaderD3D,
fragmentShaderD3D);
varyingPacking.enableBuiltins(SHADER_VERTEX, metadata); varyingPacking.enableBuiltins(SHADER_VERTEX, metadata);
varyingPacking.enableBuiltins(SHADER_PIXEL, metadata); varyingPacking.enableBuiltins(SHADER_PIXEL, metadata);
......
...@@ -97,13 +97,10 @@ struct D3DVarying final ...@@ -97,13 +97,10 @@ struct D3DVarying final
unsigned int outputSlot; unsigned int outputSlot;
}; };
class ProgramD3DMetadata : angle::NonCopyable class ProgramD3DMetadata final : angle::NonCopyable
{ {
public: public:
ProgramD3DMetadata(int rendererMajorShaderModel, ProgramD3DMetadata(RendererD3D *renderer,
const std::string &shaderModelSuffix,
bool usesInstancedPointSpriteEmulation,
bool usesViewScale,
const ShaderD3D *vertexShader, const ShaderD3D *vertexShader,
const ShaderD3D *fragmentShader); const ShaderD3D *fragmentShader);
......
...@@ -2134,6 +2134,30 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValu ...@@ -2134,6 +2134,30 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValu
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
// From WebGL test conformance/rendering/point-specific-shader-variables.html
// See http://anglebug.com/1380
TEST_P(GLSLTest, RenderTrisWithPointCoord)
{
const std::string &vert =
"attribute vec2 aPosition;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPosition, 0, 1);\n"
" gl_PointSize = 1.0;\n"
"}";
const std::string &frag =
"void main()\n"
"{\n"
" gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
" gl_FragColor = vec4(0, 1, 0, 1);\n"
"}";
ANGLE_GL_PROGRAM(prog, vert, frag);
drawQuad(prog.get(), "aPosition", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest, ANGLE_INSTANTIATE_TEST(GLSLTest,
ES2_D3D9(), ES2_D3D9(),
......
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