Skip to content

Commit 6c2cdea

Browse files
committed
OpenGL queryPool still broken but GET_QUERY_POOL_RESULTS Logic updated
1 parent 5cb29bd commit 6c2cdea

File tree

2 files changed

+88
-50
lines changed

2 files changed

+88
-50
lines changed

src/nbl/video/COpenGLQueryPool.h

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,29 @@ class COpenGLQueryPool final : public IQueryPool
1919
protected:
2020
virtual ~COpenGLQueryPool();
2121

22-
// queries.size() is a multiple of params.queryCount
2322
core::vector<GLuint> queries;
23+
uint32_t glQueriesPerQuery = 0u;
2424

2525
public:
2626
COpenGLQueryPool(core::smart_refctd_ptr<const ILogicalDevice>&& dev, IOpenGL_FunctionTable* gl, IQueryPool::SCreationParams&& _params)
2727
: IQueryPool(std::move(dev), std::move(_params))
2828
{
2929
if(_params.queryType == EQT_OCCLUSION)
3030
{
31-
queries.resize(_params.queryCount);
31+
glQueriesPerQuery = 1u;
3232
gl->extGlCreateQueries(GL_SAMPLES_PASSED, _params.queryCount, queries.data());
3333
}
3434
else if(_params.queryType == EQT_TIMESTAMP)
3535
{
36-
queries.resize(_params.queryCount);
36+
glQueriesPerQuery = 1u;
3737
gl->extGlCreateQueries(GL_TIMESTAMP, _params.queryCount, queries.data());
3838
}
3939
else
4040
{
4141
// TODO: Add ARB_pipeline_statistics support: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_pipeline_statistics_query.txt
4242
assert(false && "QueryType is not supported.");
4343
}
44+
queries.resize(_params.queryCount * glQueriesPerQuery);
4445
}
4546

4647
inline core::SRange<const GLuint> getQueries() const
@@ -61,6 +62,8 @@ class COpenGLQueryPool final : public IQueryPool
6162
}
6263
}
6364

65+
inline uint32_t getGLQueriesPerQuery() const { return glQueriesPerQuery; }
66+
6467
inline void beginQuery(IOpenGL_FunctionTable* gl, uint32_t queryIndex, E_QUERY_CONTROL_FLAGS flags) const
6568
{
6669
if(gl != nullptr)
@@ -103,27 +106,8 @@ class COpenGLQueryPool final : public IQueryPool
103106

104107
inline bool resetQueries(IOpenGL_FunctionTable* gl, uint32_t query, uint32_t queryCount)
105108
{
106-
// NOTE: There is no Reset Queries on OpenGL but to make the queries invalid/unavailable and not return the previous ones we just delete the queries and recreate them.
107-
// TODO: Needs test
108-
size_t querySize = queries.size();
109-
110-
if(query + queryCount > querySize)
111-
{
112-
assert(false);
113-
return false;
114-
}
115-
116-
if(params.queryType == EQT_OCCLUSION)
117-
{
118-
gl->glQuery.pglDeleteQueries(queryCount, queries.data() + query);
119-
gl->extGlCreateQueries(GL_SAMPLES_PASSED, queryCount, queries.data() + query);
120-
}
121-
else if(params.queryType == EQT_TIMESTAMP)
122-
{
123-
gl->glQuery.pglDeleteQueries(queryCount, queries.data() + query);
124-
gl->extGlCreateQueries(GL_TIMESTAMP, queryCount, queries.data() + query);
125-
}
126-
109+
// NOTE: There is no Reset Queries on OpenGL
110+
// NOOP
127111
return true;
128112
}
129113

src/nbl/video/IOpenGL_LogicalDevice.h

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -670,9 +670,8 @@ class IOpenGL_LogicalDevice : public ILogicalDevice, protected impl::IOpenGL_Log
670670
auto& p = std::get<SRequestGetQueryPoolResults>(req.params_variant);
671671
const COpenGLQueryPool* qp = IBackendObject::device_compatibility_cast<const COpenGLQueryPool*>(p.queryPool.get(), device);
672672
auto queryPoolQueriesCount = qp->getCreationParameters().queryCount;
673-
auto queriesRange = qp->getQueries(); // queriesRange.size() is a multiple of queryPoolQueriesCount
674-
auto queries = queriesRange.begin();
675-
673+
auto queries = qp->getQueries();
674+
676675
if(p.pData != nullptr)
677676
{
678677
IQueryPool::E_QUERY_TYPE queryType = qp->getCreationParameters().queryType;
@@ -681,6 +680,8 @@ class IOpenGL_LogicalDevice : public ILogicalDevice, protected impl::IOpenGL_Log
681680
bool waitForAllResults = p.flags.hasValue(IQueryPool::E_QUERY_RESULTS_FLAGS::EQRF_WAIT_BIT);
682681
bool partialResults = p.flags.hasValue(IQueryPool::E_QUERY_RESULTS_FLAGS::EQRF_PARTIAL_BIT);
683682

683+
assert(queryType == IQueryPool::E_QUERY_TYPE::EQT_OCCLUSION || queryType == IQueryPool::E_QUERY_TYPE::EQT_TIMESTAMP);
684+
684685
if(p.firstQuery + p.queryCount > queryPoolQueriesCount)
685686
{
686687
assert(false && "The sum of firstQuery and queryCount must be less than or equal to the number of queries in queryPool");
@@ -692,50 +693,103 @@ class IOpenGL_LogicalDevice : public ILogicalDevice, protected impl::IOpenGL_Log
692693
}
693694

694695
size_t currentDataPtrOffset = 0;
695-
size_t queryElementDataSize = (use64Version) ? sizeof(GLuint64) : sizeof(GLuint); // each query might write to multiple values/elements
696-
697-
GLenum pname;
698-
if(availabilityFlag)
699-
pname = GL_QUERY_RESULT_AVAILABLE;
700-
else if(waitForAllResults)
701-
pname = GL_QUERY_RESULT;
702-
else if(partialResults)
703-
pname = GL_QUERY_NO_WAIT;
704-
705-
auto getQueryObject = [&](GLuint queryId, GLenum pname, void * pData) -> void
696+
const uint32_t glQueriesPerQuery = qp->getGLQueriesPerQuery();
697+
const size_t queryElementDataSize = (use64Version) ? sizeof(GLuint64) : sizeof(GLuint); // each query might write to multiple values/elements
698+
const size_t eachQueryDataSize = queryElementDataSize * glQueriesPerQuery;
699+
const size_t eachQueryWithAvailabilityDataSize = (availabilityFlag) ? queryElementDataSize + eachQueryDataSize : eachQueryDataSize;
700+
701+
assert(p.stride >= eachQueryWithAvailabilityDataSize);
702+
assert(p.stride && core::is_aligned_to(p.stride, eachQueryWithAvailabilityDataSize)); // p.stride must be aligned to each query data size considering the specified flags
703+
assert(p.dataSize >= (p.queryCount * p.stride)); // dataSize is not enough for "queryCount" queries and specified stride
704+
assert(p.dataSize >= (p.queryCount * eachQueryWithAvailabilityDataSize)); // dataSize is not enough for "queryCount" queries with considering the specified flags
705+
706+
auto getQueryObject = [&](GLuint queryId, GLenum pname, void* pData) -> void
706707
{
707708
if(use64Version)
708-
{
709709
gl.extGlGetQueryObjectui64v(queryId, pname, reinterpret_cast<GLuint64*>(pData));
710+
else
711+
gl.extGlGetQueryObjectuiv(queryId, pname, reinterpret_cast<GLuint*>(pData));
712+
};
713+
auto getQueryAvailablity = [&](GLuint queryId) -> bool
714+
{
715+
GLuint ret = 0;
716+
gl.extGlGetQueryObjectuiv(queryId, GL_QUERY_RESULT_AVAILABLE, &ret);
717+
return (ret == GL_TRUE);
718+
};
719+
auto writeValueToData = [&](void* pData, const uint64_t value)
720+
{
721+
if(use64Version)
722+
{
723+
GLuint64* dataPtr = reinterpret_cast<GLuint64*>(pData);
724+
*dataPtr = value;
710725
}
711726
else
712727
{
713-
gl.extGlGetQueryObjectuiv(queryId, pname, reinterpret_cast<GLuint*>(pData));
728+
GLuint* dataPtr = reinterpret_cast<GLuint*>(pData);
729+
*dataPtr = static_cast<uint32_t>(value);
714730
}
715731
};
716732

733+
// iterate on each query
717734
for(uint32_t i = 0; i < p.queryCount; ++i)
718735
{
719-
// Don't write queries that exceed the dataSize
720736
if(currentDataPtrOffset >= p.dataSize)
737+
{
738+
assert(false);
721739
break;
740+
}
722741

723-
if(queryType == IQueryPool::E_QUERY_TYPE::EQT_TIMESTAMP || queryType == IQueryPool::E_QUERY_TYPE::EQT_OCCLUSION)
742+
uint8_t* pQueryData = reinterpret_cast<uint8_t*>(p.pData) + currentDataPtrOffset;
743+
uint8_t* pAvailabilityData = pQueryData + eachQueryDataSize; // Write Availability to this value if flag specified
744+
745+
// iterate on each gl query (we may have multiple gl queries per query like pipelinestatistics query type)
746+
const uint32_t queryIndex = i + p.firstQuery;
747+
const uint32_t glQueryBegin = queryIndex * glQueriesPerQuery;
748+
bool allGlQueriesAvailable = true;
749+
for(uint32_t q = 0; q < glQueriesPerQuery; ++q)
724750
{
725-
assert(queryPoolQueriesCount == queriesRange.size());
726-
assert(p.stride >= queryElementDataSize);
751+
uint8_t* pSubQueryData = pQueryData + q * queryElementDataSize;
752+
GLuint query = queries[glQueryBegin + q];
753+
754+
GLenum pname;
727755

728-
GLuint query = queries[i+p.firstQuery];
729-
uint8_t* pData = reinterpret_cast<uint8_t*>(p.pData) + currentDataPtrOffset;
730-
getQueryObject(query, pname, pData);
756+
if(waitForAllResults)
757+
{
758+
// Has WAIT_BIT -> Get Result with Wait (GL_QUERY_RESULT) + don't getQueryAvailability (if availability flag is set it will report true)
759+
pname = GL_QUERY_RESULT;
760+
}
761+
else if(partialResults)
762+
{
763+
// Has PARTIAL_BIT but no WAIT_BIT -> (read vk spec) -> result value between zero and the final result value
764+
// No PARTIAL queries for GL -> GL_QUERY_RESULT_NO_WAIT best match
765+
// TODO(Erfan): Maybe set the values to 0 before query so it's consistent with vulkan spec? (what to do about the cmd version where we have to upload 0's to buffer)
766+
pname = GL_QUERY_RESULT_NO_WAIT;
767+
}
768+
else if(availabilityFlag)
769+
{
770+
// Only Availablity -> Get Results with NoWait + get Query Availability
771+
pname = GL_QUERY_RESULT_NO_WAIT;
772+
}
773+
else
774+
{
775+
// No Flags -> GL_QUERY_RESULT_NO_WAIT
776+
pname = GL_QUERY_RESULT_NO_WAIT;
777+
}
778+
779+
if(availabilityFlag)
780+
allGlQueriesAvailable &= getQueryAvailablity(query);
781+
getQueryObject(query, pname, pSubQueryData);
731782
}
732-
else
783+
784+
if(availabilityFlag)
733785
{
734-
assert(false && "QueryType is not supported.");
786+
if(waitForAllResults)
787+
writeValueToData(pAvailabilityData, (allGlQueriesAvailable) ? 1ull : 0ull);
788+
else
789+
writeValueToData(pAvailabilityData, 1ull);
735790
}
736791

737792
currentDataPtrOffset += p.stride;
738-
739793
}
740794
}
741795
}

0 commit comments

Comments
 (0)