Commit 3fc6893c by Alexis Hetu Committed by Alexis Hétu

Prevent glDeleteQueries from deleting a live Query

glDeleteQueries() instantly deletes all the es2::Query objects passed as arguments to this function. If some of these queries are still being used by the renderer, this will result in a use after free error. To solve this issue, sw::Query is now a also ref counted object. Bug chromium:904714 Change-Id: Ic1d5781bbf1724d8d07936fd49c8a172dc3d9fd4 Reviewed-on: https://swiftshader-review.googlesource.com/c/22548Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent d5f14892
...@@ -41,7 +41,7 @@ namespace D3D9 ...@@ -41,7 +41,7 @@ namespace D3D9
{ {
device->removeQuery(query); device->removeQuery(query);
delete query; query->release();
} }
} }
...@@ -202,7 +202,7 @@ namespace D3D9 ...@@ -202,7 +202,7 @@ namespace D3D9
return INVALIDCALL(); return INVALIDCALL();
} }
bool signaled = !query || query->reference == 0; bool signaled = !query || query->isReady();
if(size && signaled) if(size && signaled)
{ {
......
...@@ -32,7 +32,7 @@ Query::Query(GLuint name, GLenum type) : NamedObject(name) ...@@ -32,7 +32,7 @@ Query::Query(GLuint name, GLenum type) : NamedObject(name)
Query::~Query() Query::~Query()
{ {
delete mQuery; mQuery->release();
} }
void Query::begin() void Query::begin()
...@@ -140,7 +140,7 @@ GLboolean Query::testQuery() ...@@ -140,7 +140,7 @@ GLboolean Query::testQuery()
{ {
if(mQuery != nullptr && mStatus != GL_TRUE) if(mQuery != nullptr && mStatus != GL_TRUE)
{ {
if(!mQuery->building && mQuery->reference == 0) if(!mQuery->building && mQuery->isReady())
{ {
unsigned int resultSum = mQuery->data; unsigned int resultSum = mQuery->data;
mStatus = GL_TRUE; mStatus = GL_TRUE;
......
...@@ -96,6 +96,27 @@ namespace sw ...@@ -96,6 +96,27 @@ namespace sw
int threadIndex; int threadIndex;
}; };
Query::Query(Type type) : building(false), data(0), type(type), reference(1)
{
}
void Query::addRef()
{
++reference; // Atomic
}
void Query::release()
{
int ref = reference--; // Atomic
ASSERT(ref >= 0);
if(ref == 0)
{
delete this;
}
}
DrawCall::DrawCall() DrawCall::DrawCall()
{ {
queries = 0; queries = 0;
...@@ -325,7 +346,7 @@ namespace sw ...@@ -325,7 +346,7 @@ namespace sw
{ {
if(includePrimitivesWrittenQueries || (query->type != Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)) if(includePrimitivesWrittenQueries || (query->type != Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN))
{ {
++query->reference; // Atomic query->addRef();
draw->queries->push_back(query); draw->queries->push_back(query);
} }
} }
...@@ -1013,7 +1034,7 @@ namespace sw ...@@ -1013,7 +1034,7 @@ namespace sw
break; break;
} }
--query->reference; // Atomic query->release();
} }
delete draw.queries; delete draw.queries;
......
...@@ -89,26 +89,35 @@ namespace sw ...@@ -89,26 +89,35 @@ namespace sw
{ {
enum Type { FRAGMENTS_PASSED, TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN }; enum Type { FRAGMENTS_PASSED, TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN };
Query(Type type) : building(false), reference(0), data(0), type(type) Query(Type type);
{
} void addRef();
void release();
void begin() inline void begin()
{ {
building = true; building = true;
data = 0; data = 0;
} }
void end() inline void end()
{ {
building = false; building = false;
} }
inline bool isReady() const
{
return (reference == 1);
}
bool building; bool building;
AtomicInt reference;
AtomicInt data; AtomicInt data;
const Type type; const Type type;
private:
~Query() {} // Only delete a query within the release() function
AtomicInt reference;
}; };
struct DrawData struct DrawData
......
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