Commit 37dde692 by Geoff Lang

Add support for transform feedback queries.

Change-Id: I0aab43b146f87259898db57acb9f74fdbfdb1b96 Reviewed-on: https://chromium-review.googlesource.com/184580Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent d5da329c
......@@ -171,6 +171,10 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
bindDrawFramebuffer(0);
bindRenderbuffer(0);
mState.activeQueries[GL_ANY_SAMPLES_PASSED].set(NULL);
mState.activeQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL);
mState.activeQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL);
bindGenericUniformBuffer(0);
for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
{
......@@ -267,11 +271,6 @@ Context::~Context()
mState.vertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
}
for (int i = 0; i < QUERY_TYPE_COUNT; i++)
{
mState.activeQuery[i].set(NULL);
}
mState.arrayBuffer.set(NULL);
mState.renderbuffer.set(NULL);
......@@ -280,6 +279,11 @@ Context::~Context()
mTexture3DZero.set(NULL);
mTexture2DArrayZero.set(NULL);
for (State::ActiveQueryMap::iterator i = mState.activeQueries.begin(); i != mState.activeQueries.end(); i++)
{
i->second.set(NULL);
}
mState.genericUniformBuffer.set(NULL);
for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
{
......@@ -749,28 +753,11 @@ GLuint Context::getArrayBufferHandle() const
GLuint Context::getActiveQuery(GLenum target) const
{
Query *queryObject = NULL;
switch (target)
{
case GL_ANY_SAMPLES_PASSED_EXT:
queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
break;
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
break;
default:
ASSERT(false);
}
// All query types should already exist in the activeQueries map
ASSERT(mState.activeQueries.find(target) != mState.activeQueries.end());
if (queryObject)
{
return queryObject->id();
}
else
{
return 0;
}
const Query *queryObject = mState.activeQueries.at(target).get();
return queryObject ? queryObject->id() : 0;
}
void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
......@@ -1322,28 +1309,14 @@ void Context::beginQuery(GLenum target, GLuint query)
// b) There are no active queries for the requested target (and in the case
// of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
// no query may be active for either if glBeginQuery targets either.
for (int i = 0; i < QUERY_TYPE_COUNT; i++)
for (State::ActiveQueryMap::iterator i = mState.activeQueries.begin(); i != mState.activeQueries.end(); i++)
{
if (mState.activeQuery[i].get() != NULL)
if (i->second.get() != NULL)
{
return gl::error(GL_INVALID_OPERATION);
}
}
QueryType qType;
switch (target)
{
case GL_ANY_SAMPLES_PASSED_EXT:
qType = QUERY_ANY_SAMPLES_PASSED;
break;
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
break;
default:
ASSERT(false);
return;
}
Query *queryObject = getQuery(query, true, target);
// check that name was obtained with glGenQueries
......@@ -1359,7 +1332,7 @@ void Context::beginQuery(GLenum target, GLuint query)
}
// set query as active for specified target
mState.activeQuery[qType].set(queryObject);
mState.activeQueries[target].set(queryObject);
// begin query
queryObject->begin();
......@@ -1367,22 +1340,7 @@ void Context::beginQuery(GLenum target, GLuint query)
void Context::endQuery(GLenum target)
{
QueryType qType;
switch (target)
{
case GL_ANY_SAMPLES_PASSED_EXT:
qType = QUERY_ANY_SAMPLES_PASSED;
break;
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
break;
default:
ASSERT(false);
return;
}
Query *queryObject = mState.activeQuery[qType].get();
Query *queryObject = mState.activeQueries[target].get();
if (queryObject == NULL)
{
......@@ -1391,7 +1349,7 @@ void Context::endQuery(GLenum target)
queryObject->end();
mState.activeQuery[qType].set(NULL);
mState.activeQueries[target].set(NULL);
}
void Context::setFramebufferZero(Framebuffer *buffer)
......
......@@ -68,14 +68,6 @@ class VertexAttribute;
class VertexArray;
class Sampler;
enum QueryType
{
QUERY_ANY_SAMPLES_PASSED,
QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,
QUERY_TYPE_COUNT
};
// Helper structure to store all raw state
struct State
{
......@@ -117,9 +109,11 @@ struct State
unsigned int vertexArray;
BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
GLuint samplers[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
typedef std::map< GLenum, BindingPointer<Query> > ActiveQueryMap;
ActiveQueryMap activeQueries;
BindingPointer<Buffer> genericUniformBuffer;
OffsetBindingPointer<Buffer> uniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
......
......@@ -112,12 +112,12 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
try
{
switch (target)
gl::Context *context = gl::getNonLostContext();
if (context)
{
if (!ValidQueryType(context, target))
{
case GL_ANY_SAMPLES_PASSED_EXT:
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
break;
default:
return gl::error(GL_INVALID_ENUM);
}
......@@ -126,10 +126,6 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
return gl::error(GL_INVALID_OPERATION);
}
gl::Context *context = gl::getNonLostContext();
if (context)
{
context->beginQuery(target, id);
}
}
......@@ -1858,19 +1854,15 @@ void __stdcall glEndQueryEXT(GLenum target)
try
{
switch (target)
{
case GL_ANY_SAMPLES_PASSED_EXT:
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
break;
default:
return gl::error(GL_INVALID_ENUM);
}
gl::Context *context = gl::getNonLostContext();
if (context)
{
if (!ValidQueryType(context, target))
{
return gl::error(GL_INVALID_ENUM);
}
context->endQuery(target);
}
}
......@@ -2231,16 +2223,16 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
try
{
gl::Context *context = gl::getNonLostContext();
if (context)
{
if (n < 0)
{
return gl::error(GL_INVALID_VALUE);
}
gl::Context *context = gl::getNonLostContext();
if (context)
{
for (int i = 0; i < n; i++)
for (GLsizei i = 0; i < n; i++)
{
ids[i] = context->createQuery();
}
......@@ -3122,19 +3114,24 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
try
{
gl::Context *context = gl::getNonLostContext();
if (context)
{
if (!ValidQueryType(context, target))
{
return gl::error(GL_INVALID_ENUM);
}
switch (pname)
{
case GL_CURRENT_QUERY_EXT:
params[0] = context->getActiveQuery(target);
break;
default:
return gl::error(GL_INVALID_ENUM);
}
gl::Context *context = gl::getNonLostContext();
if (context)
{
params[0] = context->getActiveQuery(target);
}
}
catch(std::bad_alloc&)
......@@ -3149,14 +3146,6 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
try
{
switch (pname)
{
case GL_QUERY_RESULT_EXT:
case GL_QUERY_RESULT_AVAILABLE_EXT:
break;
default:
return gl::error(GL_INVALID_ENUM);
}
gl::Context *context = gl::getNonLostContext();
if (context)
......@@ -3182,7 +3171,7 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
params[0] = queryObject->isResultAvailable();
break;
default:
ASSERT(false);
return gl::error(GL_INVALID_ENUM);
}
}
}
......@@ -4181,21 +4170,11 @@ GLboolean __stdcall glIsQueryEXT(GLuint id)
try
{
if (id == 0)
{
return GL_FALSE;
}
gl::Context *context = gl::getNonLostContext();
if (context)
{
gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
if (queryObject)
{
return GL_TRUE;
}
return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
}
}
catch(std::bad_alloc&)
......@@ -6438,7 +6417,15 @@ void __stdcall glGenQueries(GLsizei n, GLuint* ids)
return gl::error(GL_INVALID_OPERATION);
}
glGenQueriesEXT(n, ids);
if (n < 0)
{
return gl::error(GL_INVALID_VALUE);
}
for (GLsizei i = 0; i < n; i++)
{
ids[i] = context->createQuery();
}
}
}
catch(std::bad_alloc&)
......@@ -6462,7 +6449,15 @@ void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids)
return gl::error(GL_INVALID_OPERATION);
}
glDeleteQueriesEXT(n, ids);
if (n < 0)
{
return gl::error(GL_INVALID_VALUE);
}
for (GLsizei i = 0; i < n; i++)
{
context->deleteQuery(ids[i]);
}
}
}
catch(std::bad_alloc&)
......@@ -6486,8 +6481,7 @@ GLboolean __stdcall glIsQuery(GLuint id)
return gl::error(GL_INVALID_OPERATION, GL_FALSE);
}
// TODO: XFB queries
return glIsQueryEXT(id);
return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
}
}
catch(std::bad_alloc&)
......@@ -6513,13 +6507,8 @@ void __stdcall glBeginQuery(GLenum target, GLuint id)
return gl::error(GL_INVALID_OPERATION);
}
switch (target)
if (!ValidQueryType(context, target))
{
case GL_ANY_SAMPLES_PASSED:
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
break;
default:
return gl::error(GL_INVALID_ENUM);
}
......@@ -6528,17 +6517,9 @@ void __stdcall glBeginQuery(GLenum target, GLuint id)
return gl::error(GL_INVALID_OPERATION);
}
if (target == GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
{
// TODO: XFB queries
UNIMPLEMENTED();
}
else
{
context->beginQuery(target, id);
}
}
}
catch(std::bad_alloc&)
{
return gl::error(GL_OUT_OF_MEMORY);
......@@ -6560,15 +6541,12 @@ void __stdcall glEndQuery(GLenum target)
return gl::error(GL_INVALID_OPERATION);
}
if (target == GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
{
// TODO: XFB queries
UNIMPLEMENTED();
}
else
if (!ValidQueryType(context, target))
{
glEndQueryEXT(target);
return gl::error(GL_INVALID_ENUM);
}
context->endQuery(target);
}
}
catch(std::bad_alloc&)
......@@ -6592,14 +6570,19 @@ void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params)
return gl::error(GL_INVALID_OPERATION);
}
if (target == GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
if (!ValidQueryType(context, target))
{
// TODO: XFB queries
UNIMPLEMENTED();
return gl::error(GL_INVALID_ENUM);
}
else
switch (pname)
{
glGetQueryivEXT(target, pname, params);
case GL_CURRENT_QUERY:
params[0] = context->getActiveQuery(target);
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
}
......@@ -6624,8 +6607,29 @@ void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
return gl::error(GL_INVALID_OPERATION);
}
// TODO: XFB queries
glGetQueryObjectuivEXT(id, pname, params);
gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
if (!queryObject)
{
return gl::error(GL_INVALID_OPERATION);
}
if (context->getActiveQuery(queryObject->getType()) == id)
{
return gl::error(GL_INVALID_OPERATION);
}
switch(pname)
{
case GL_QUERY_RESULT:
params[0] = queryObject->getResult();
break;
case GL_QUERY_RESULT_AVAILABLE:
params[0] = queryObject->isResultAvailable();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
}
catch(std::bad_alloc&)
......
......@@ -9,11 +9,26 @@
#include "libGLESv2/renderer/d3d11/Query11.h"
#include "libGLESv2/renderer/d3d11/Renderer11.h"
#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
#include "libGLESv2/main.h"
namespace rx
{
static bool checkOcclusionQuery(ID3D11DeviceContext *context, ID3D11Query *query, UINT64 *numPixels)
{
HRESULT result = context->GetData(query, numPixels, sizeof(UINT64), 0);
return (result == S_OK);
}
static bool checkStreamOutPrimitivesWritten(ID3D11DeviceContext *context, ID3D11Query *query, UINT64 *numPrimitives)
{
D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 };
HRESULT result = context->GetData(query, &soStats, sizeof(D3D11_QUERY_DATA_SO_STATISTICS), 0);
*numPrimitives = soStats.NumPrimitivesWritten;
return (result == S_OK);
}
Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type)
{
mRenderer = renderer;
......@@ -30,7 +45,7 @@ void Query11::begin()
if (mQuery == NULL)
{
D3D11_QUERY_DESC queryDesc;
queryDesc.Query = D3D11_QUERY_OCCLUSION;
queryDesc.Query = gl_d3d11::ConvertQueryType(getType());
queryDesc.MiscFlags = 0;
if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
......@@ -88,21 +103,42 @@ GLboolean Query11::testQuery()
{
if (mQuery != NULL && mStatus != GL_TRUE)
{
UINT64 numPixels = 0;
HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0);
if (result == S_OK)
{
mStatus = GL_TRUE;
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
bool queryFinished = false;
switch (getType())
{
case GL_ANY_SAMPLES_PASSED_EXT:
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
{
UINT64 numPixels = 0;
queryFinished = checkOcclusionQuery(context, mQuery, &numPixels);
if (queryFinished)
{
mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
}
}
break;
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
{
UINT64 numPrimitives = 0;
queryFinished = checkStreamOutPrimitivesWritten(context, mQuery, &numPrimitives);
if (queryFinished)
{
mResult = static_cast<GLuint>(numPrimitives);
}
}
break;
default:
UNREACHABLE();
break;
}
if (queryFinished)
{
mStatus = GL_TRUE;
}
else if (mRenderer->testDeviceLost(true))
{
......
......@@ -213,6 +213,17 @@ FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset)
return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : FLT_MAX;
}
D3D11_QUERY ConvertQueryType(GLenum queryType)
{
switch (queryType)
{
case GL_ANY_SAMPLES_PASSED_EXT:
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION;
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS;
default: UNREACHABLE(); return D3D11_QUERY_EVENT;
}
}
}
namespace d3d11
......
......@@ -34,6 +34,8 @@ D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset);
FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset);
D3D11_QUERY ConvertQueryType(GLenum queryType);
}
namespace d3d11
......
......@@ -133,6 +133,23 @@ bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat,
return true;
}
bool ValidQueryType(const Context *context, GLenum queryType)
{
META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT);
META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
switch (queryType)
{
case GL_ANY_SAMPLES_PASSED:
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
return true;
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
return (context->getClientVersion() >= 3);
default:
return false;
}
}
bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height,
bool angleExtension)
......
......@@ -20,6 +20,7 @@ bool ValidFramebufferTarget(GLenum target);
bool ValidMipLevel(const Context *context, GLenum target, GLint level);
bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth);
bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height);
bool ValidQueryType(const gl::Context *context, GLenum queryType);
bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height,
......
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