Commit 4e47b92f by Cooper Partin Committed by Jamie Madill

Fix instanced point sprites when gl_PointSize is specified but not used

Change-Id: I2350fa60cae55f02d7b484c34544c035acaba6ad Reviewed-on: https://chromium-review.googlesource.com/245703Reviewed-by: 's avatarAustin Kinross <aukinros@microsoft.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 358c8a95
......@@ -109,7 +109,7 @@ gl::Error RendererD3D::drawElements(const gl::Data &data,
}
GLsizei vertexCount = indexInfo.indexRange.length() + 1;
error = applyVertexBuffer(*data.state, indexInfo.indexRange.start, vertexCount, instances);
error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances);
if (error.isError())
{
return error;
......@@ -182,7 +182,7 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data,
return error;
}
error = applyVertexBuffer(*data.state, first, count, instances);
error = applyVertexBuffer(*data.state, mode, first, count, instances);
if (error.isError())
{
return error;
......
......@@ -101,7 +101,7 @@ class RendererD3D : public Renderer
bool rasterizerDiscard, bool transformFeedbackActive) = 0;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) = 0;
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
......
......@@ -92,13 +92,14 @@ void InputLayoutCache::markDirty()
}
gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
gl::Program *program)
GLenum mode, gl::Program *program)
{
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS];
programD3D->sortAttributesByLayout(attributes, sortedSemanticIndices);
bool usesInstancedPointSpriteEmulation = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
if (!mDevice || !mDeviceContext)
{
......@@ -118,8 +119,8 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
if (attributes[i].active)
{
D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
// If instanced pointsprite emulation is being used, the inputClass is required to be configured as per instance data
inputClass = usesInstancedPointSpriteEmulation ? D3D11_INPUT_PER_INSTANCE_DATA : inputClass;
// If rendering points and instanced pointsprite emulation is being used, the inputClass is required to be configured as per instance data
inputClass = instancedPointSpritesActive ? D3D11_INPUT_PER_INSTANCE_DATA : inputClass;
gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType);
const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel);
......@@ -135,7 +136,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = usesInstancedPointSpriteEmulation ? 1 : attributes[i].divisor;
ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = instancedPointSpritesActive ? 1 : attributes[i].divisor;
if (inputClass == D3D11_INPUT_PER_VERTEX_DATA && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS)
{
......@@ -153,7 +154,8 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
// Instanced PointSprite emulation requires additional entries in the
// inputlayout to support the vertices that make up the pointsprite quad.
if (usesInstancedPointSpriteEmulation)
// We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the input layout must match the shader
if (programUsesInstancedPointSprites)
{
ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITEPOSITION";
ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0;
......@@ -198,7 +200,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
// Instanced PointSprite emulation uses multiple layout entries across a single vertex buffer.
// If an index swap is performed, we need to ensure that all elements get the proper InputSlot.
if (usesInstancedPointSpriteEmulation)
if (programUsesInstancedPointSprites)
{
ilKey.elements[firstIndexedElement + 1].desc.InputSlot = 0;
}
......@@ -316,7 +318,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
// PointSprite quad.
// An index buffer also needs to be created and applied because rendering instanced
// data on D3D11 FL9_3 requires DrawIndexedInstanced() to be used.
if (usesInstancedPointSpriteEmulation)
if (instancedPointSpritesActive)
{
HRESULT result = S_OK;
const UINT pointSpriteVertexStride = sizeof(float) * 5;
......
......@@ -39,7 +39,7 @@ class InputLayoutCache
void markDirty();
gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
gl::Program *program);
GLenum mode, gl::Program *program);
private:
DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
......
......@@ -1167,7 +1167,7 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances)
{
TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
......@@ -1176,7 +1176,7 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLs
return error;
}
return mInputLayoutCache.applyVertexBuffers(attributes, state.getProgram());
return mInputLayoutCache.applyVertexBuffers(attributes, mode, state.getProgram());
}
gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
......
......@@ -86,7 +86,7 @@ class Renderer11 : public RendererD3D
bool rasterizerDiscard, bool transformFeedbackActive);
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
virtual void applyTransformFeedbackBuffers(const gl::State &state);
......
......@@ -1377,7 +1377,7 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer());
}
gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances)
{
TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
......
......@@ -87,7 +87,7 @@ class Renderer9 : public RendererD3D
bool rasterizerDiscard, bool transformFeedbackActive);
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
virtual void applyTransformFeedbackBuffers(const gl::State& state);
......
......@@ -388,3 +388,39 @@ TYPED_TEST(PointSpritesTest, PointSizeEnabledCompliance)
glDeleteBuffers(1, &vertexObject);
}
// Verify that rendering works correctly when gl_PointSize is declared in a shader but isn't used
TYPED_TEST(PointSpritesTest, PointSizeDeclaredButUnused)
{
const std::string vs = SHADER_SOURCE
(
attribute highp vec4 position;
void main(void)
{
gl_PointSize = 1.0;
gl_Position = position;
}
);
const std::string fs = SHADER_SOURCE
(
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
GLuint program = CompileProgram(vs, fs);
ASSERT_NE(program, 0u);
ASSERT_GL_NO_ERROR();
glUseProgram(program);
drawQuad(program, "position", 0.5f, 1.0f);
ASSERT_GL_NO_ERROR();
// expect the center pixel to be red
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
glDeleteProgram(program);
}
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