Commit 5274202f by Gregoire Payen de La Garanderie Committed by Geoff Lang

Unbind unused stream out from the D3D11 pipeline to avoid conflicts.

Also allow points drawing without gl_PointSize if transform feedback is active. Change-Id: I172d423e847b35b94ebaea102dd97b695575c828 Reviewed-on: https://chromium-review.googlesource.com/246100Tested-by: 's avatarGregoire Payen de La Garanderie <Gregory.Payen@imgtec.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent f4780c1c
...@@ -900,6 +900,12 @@ TransformFeedback *State::getCurrentTransformFeedback() const ...@@ -900,6 +900,12 @@ TransformFeedback *State::getCurrentTransformFeedback() const
return mTransformFeedback.get(); return mTransformFeedback.get();
} }
bool State::isTransformFeedbackActiveUnpaused() const
{
gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
return curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused();
}
void State::detachTransformFeedback(GLuint transformFeedback) void State::detachTransformFeedback(GLuint transformFeedback)
{ {
if (mTransformFeedback.id() == transformFeedback) if (mTransformFeedback.id() == transformFeedback)
......
...@@ -177,6 +177,7 @@ class State ...@@ -177,6 +177,7 @@ class State
// Transform feedback object (not buffer) binding manipulation // Transform feedback object (not buffer) binding manipulation
void setTransformFeedbackBinding(TransformFeedback *transformFeedback); void setTransformFeedbackBinding(TransformFeedback *transformFeedback);
TransformFeedback *getCurrentTransformFeedback() const; TransformFeedback *getCurrentTransformFeedback() const;
bool isTransformFeedbackActiveUnpaused() const;
void detachTransformFeedback(GLuint transformFeedback); void detachTransformFeedback(GLuint transformFeedback);
// Query binding manipulation // Query binding manipulation
......
...@@ -108,6 +108,11 @@ gl::Error RendererD3D::drawElements(const gl::Data &data, ...@@ -108,6 +108,11 @@ gl::Error RendererD3D::drawElements(const gl::Data &data,
return error; return error;
} }
applyTransformFeedbackBuffers(*data.state);
// Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
// layer.
ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
GLsizei vertexCount = indexInfo.indexRange.length() + 1; GLsizei vertexCount = indexInfo.indexRange.length() + 1;
error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances); error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances);
if (error.isError()) if (error.isError())
...@@ -115,12 +120,7 @@ gl::Error RendererD3D::drawElements(const gl::Data &data, ...@@ -115,12 +120,7 @@ gl::Error RendererD3D::drawElements(const gl::Data &data,
return error; return error;
} }
bool transformFeedbackActive = applyTransformFeedbackBuffers(data); error = applyShaders(data);
// Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
// layer.
ASSERT(!transformFeedbackActive);
error = applyShaders(data, transformFeedbackActive);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -182,15 +182,15 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data, ...@@ -182,15 +182,15 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data,
return error; return error;
} }
applyTransformFeedbackBuffers(*data.state);
error = applyVertexBuffer(*data.state, mode, first, count, instances); error = applyVertexBuffer(*data.state, mode, first, count, instances);
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
bool transformFeedbackActive = applyTransformFeedbackBuffers(data); error = applyShaders(data);
error = applyShaders(data, transformFeedbackActive);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -210,13 +210,13 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data, ...@@ -210,13 +210,13 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data,
if (!skipDraw(data, mode)) if (!skipDraw(data, mode))
{ {
error = drawArrays(data, mode, count, instances, transformFeedbackActive, program->usesPointSize()); error = drawArrays(data, mode, count, instances, program->usesPointSize());
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
if (transformFeedbackActive) if (data.state->isTransformFeedbackActiveUnpaused())
{ {
markTransformFeedbackUsage(data); markTransformFeedbackUsage(data);
} }
...@@ -356,22 +356,8 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) ...@@ -356,22 +356,8 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
bool RendererD3D::applyTransformFeedbackBuffers(const gl::Data &data)
{
gl::TransformFeedback *curTransformFeedback = data.state->getCurrentTransformFeedback();
if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
{
applyTransformFeedbackBuffers(*data.state);
return true;
}
else
{
return false;
}
}
// Applies the shaders and shader constants to the Direct3D device // Applies the shaders and shader constants to the Direct3D device
gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedbackActive) gl::Error RendererD3D::applyShaders(const gl::Data &data)
{ {
gl::Program *program = data.state->getProgram(); gl::Program *program = data.state->getProgram();
...@@ -380,7 +366,7 @@ gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedback ...@@ -380,7 +366,7 @@ gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedback
const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); const gl::Framebuffer *fbo = data.state->getDrawFramebuffer();
gl::Error error = applyShaders(program, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, transformFeedbackActive); gl::Error error = applyShaders(program, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, data.state->isTransformFeedbackActiveUnpaused());
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -520,7 +506,7 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) ...@@ -520,7 +506,7 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode)
// ProgramBinary assumes non-point rendering if gl_PointSize isn't written, // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
// which affects varying interpolation. Since the value of gl_PointSize is // which affects varying interpolation. Since the value of gl_PointSize is
// undefined when not written, just skip drawing to avoid unexpected results. // undefined when not written, just skip drawing to avoid unexpected results.
if (!data.state->getProgram()->usesPointSize()) if (!data.state->getProgram()->usesPointSize() && !data.state->isTransformFeedbackActiveUnpaused())
{ {
// This is stictly speaking not an error, but developers should be // This is stictly speaking not an error, but developers should be
// notified of risking undefined behavior. // notified of risking undefined behavior.
......
...@@ -166,7 +166,7 @@ class RendererD3D : public Renderer ...@@ -166,7 +166,7 @@ class RendererD3D : public Renderer
gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut); gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut);
protected: protected:
virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive, bool usesPointSize) = 0; virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) = 0;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0;
...@@ -188,8 +188,7 @@ class RendererD3D : public Renderer ...@@ -188,8 +188,7 @@ class RendererD3D : public Renderer
gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport); gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport);
gl::Error applyState(const gl::Data &data, GLenum drawMode); gl::Error applyState(const gl::Data &data, GLenum drawMode);
bool applyTransformFeedbackBuffers(const gl::Data &data); gl::Error applyShaders(const gl::Data &data);
gl::Error applyShaders(const gl::Data &data, bool transformFeedbackActive);
gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType, gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType,
const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount); const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount);
gl::Error applyTextures(const gl::Data &data); gl::Error applyTextures(const gl::Data &data);
......
...@@ -180,6 +180,8 @@ Renderer11::Renderer11(egl::Display *display) ...@@ -180,6 +180,8 @@ Renderer11::Renderer11(egl::Display *display)
mAppliedGeometryShader = NULL; mAppliedGeometryShader = NULL;
mAppliedPixelShader = NULL; mAppliedPixelShader = NULL;
mAppliedNumXFBBindings = -1;
const auto &attributes = mDisplay->getAttributeMap(); const auto &attributes = mDisplay->getAttributeMap();
EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
...@@ -1238,31 +1240,36 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen ...@@ -1238,31 +1240,36 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
void Renderer11::applyTransformFeedbackBuffers(const gl::State& state) void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
{ {
size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange(); size_t numXFBBindings = 0;
ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
bool requiresUpdate = false; bool requiresUpdate = false;
for (size_t i = 0; i < numXFBBindings; i++)
if (state.isTransformFeedbackActiveUnpaused())
{ {
gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); numXFBBindings = state.getTransformFeedbackBufferIndexRange();
GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
ID3D11Buffer *d3dBuffer = NULL;
if (curXFBBuffer)
{
Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
}
// TODO: mAppliedTFBuffers and friends should also be kept in a vector. for (size_t i = 0; i < numXFBBindings; i++)
if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i])
{ {
requiresUpdate = true; gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
ID3D11Buffer *d3dBuffer = NULL;
if (curXFBBuffer)
{
Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
}
// TODO: mAppliedTFBuffers and friends should also be kept in a vector.
if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i])
{
requiresUpdate = true;
}
} }
} }
if (requiresUpdate) if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings)
{ {
for (size_t i = 0; i < numXFBBindings; ++i) for (size_t i = 0; i < numXFBBindings; ++i)
{ {
...@@ -1286,14 +1293,16 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State& state) ...@@ -1286,14 +1293,16 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State& state)
mAppliedTFOffsets[i] = curXFBOffset; mAppliedTFOffsets[i] = curXFBOffset;
} }
mAppliedNumXFBBindings = numXFBBindings;
mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets); mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets);
} }
} }
gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive, bool usesPointSize) gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize)
{ {
bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation; bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation;
if (mode == GL_POINTS && transformFeedbackActive) if (mode == GL_POINTS && data.state->isTransformFeedbackActiveUnpaused())
{ {
// Since point sprites are generated with a geometry shader, too many vertices will // Since point sprites are generated with a geometry shader, too many vertices will
// be written if transform feedback is active. To work around this, draw only the points // be written if transform feedback is active. To work around this, draw only the points
...@@ -1321,7 +1330,7 @@ gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei coun ...@@ -1321,7 +1330,7 @@ gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei coun
} }
// Skip this step if we're doing rasterizer discard. // Skip this step if we're doing rasterizer discard.
if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard) if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard && usesPointSize)
{ {
ID3D11PixelShader *pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); ID3D11PixelShader *pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader); ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
...@@ -1910,6 +1919,8 @@ void Renderer11::markAllStateDirty() ...@@ -1910,6 +1919,8 @@ void Renderer11::markAllStateDirty()
mAppliedGeometryShader = DirtyPointer; mAppliedGeometryShader = DirtyPointer;
mAppliedPixelShader = DirtyPointer; mAppliedPixelShader = DirtyPointer;
mAppliedNumXFBBindings = -1;
for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
{ {
mAppliedTFBuffers[i] = NULL; mAppliedTFBuffers[i] = NULL;
......
...@@ -88,9 +88,9 @@ class Renderer11 : public RendererD3D ...@@ -88,9 +88,9 @@ class Renderer11 : public RendererD3D
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray); virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, 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 gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
virtual void applyTransformFeedbackBuffers(const gl::State &state); void applyTransformFeedbackBuffers(const gl::State &state) override;
virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive, bool usesPointSize); gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
...@@ -304,6 +304,7 @@ class Renderer11 : public RendererD3D ...@@ -304,6 +304,7 @@ class Renderer11 : public RendererD3D
unsigned int mAppliedIBOffset; unsigned int mAppliedIBOffset;
// Currently applied transform feedback buffers // Currently applied transform feedback buffers
size_t mAppliedNumXFBBindings;
ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers
// in use for streamout // in use for streamout
GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified
......
...@@ -1425,9 +1425,9 @@ void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) ...@@ -1425,9 +1425,9 @@ void Renderer9::applyTransformFeedbackBuffers(const gl::State& state)
UNREACHABLE(); UNREACHABLE();
} }
gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive, bool usesPointSize) gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize)
{ {
ASSERT(!transformFeedbackActive); ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
startScene(); startScene();
......
...@@ -90,9 +90,9 @@ class Renderer9 : public RendererD3D ...@@ -90,9 +90,9 @@ class Renderer9 : public RendererD3D
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, 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 gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
virtual void applyTransformFeedbackBuffers(const gl::State& state); void applyTransformFeedbackBuffers(const gl::State &state) override;
virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive, bool usesPointSize); gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
......
...@@ -113,3 +113,84 @@ TYPED_TEST(TransformFeedbackTest, ZeroSizedViewport) ...@@ -113,3 +113,84 @@ TYPED_TEST(TransformFeedbackTest, ZeroSizedViewport)
EXPECT_EQ(primitivesWritten, 2); EXPECT_EQ(primitivesWritten, 2);
} }
// Test that XFB can write back vertices to a buffer and that we can draw from this buffer afterward.
TYPED_TEST(TransformFeedbackTest, RecordAndDraw)
{
// Set the program's transform feedback varyings (just gl_Position)
const GLchar* transformFeedbackVaryings[] =
{
"gl_Position"
};
glTransformFeedbackVaryings(mProgram, ArraySize(transformFeedbackVaryings), transformFeedbackVaryings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(mProgram);
// Re-link the program
GLint linkStatus;
glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
ASSERT_NE(linkStatus, 0);
glUseProgram(mProgram);
GLint positionLocation = glGetAttribLocation(mProgram, "position");
// First pass: draw 6 points to the XFB buffer
glEnable(GL_RASTERIZER_DISCARD);
const GLfloat vertices[] =
{
-1.0f, 1.0f, 0.5f,
-1.0f, -1.0f, 0.5f,
1.0f, -1.0f, 0.5f,
-1.0f, 1.0f, 0.5f,
1.0f, -1.0f, 0.5f,
1.0f, 1.0f, 0.5f,
};
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(positionLocation);
// Bind the buffer for transform feedback output and start transform feedback
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
glBeginTransformFeedback(GL_POINTS);
// Create a query to check how many primitives were written
GLuint primitivesWrittenQuery = 0;
glGenQueries(1, &primitivesWrittenQuery);
glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
glDrawArrays(GL_POINTS, 0, 6);
glDisableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, NULL);
// End the query and transform feedkback
glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
glEndTransformFeedback();
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
glDisable(GL_RASTERIZER_DISCARD);
// Check how many primitives were written and verify that some were written even if
// no pixels were rendered
GLuint primitivesWritten = 0;
glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(primitivesWritten, 6);
// Nothing should have been drawn to the framebuffer
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 0);
// Second pass: draw from the feedback buffer
glBindBuffer(GL_ARRAY_BUFFER, mTransformFeedbackBuffer);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(positionLocation);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
EXPECT_GL_NO_ERROR();
}
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