@@ -670,9 +670,8 @@ class IOpenGL_LogicalDevice : public ILogicalDevice, protected impl::IOpenGL_Log
670
670
auto & p = std::get<SRequestGetQueryPoolResults>(req.params_variant );
671
671
const COpenGLQueryPool* qp = IBackendObject::device_compatibility_cast<const COpenGLQueryPool*>(p.queryPool .get (), device);
672
672
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
+
676
675
if (p.pData != nullptr )
677
676
{
678
677
IQueryPool::E_QUERY_TYPE queryType = qp->getCreationParameters ().queryType ;
@@ -681,6 +680,8 @@ class IOpenGL_LogicalDevice : public ILogicalDevice, protected impl::IOpenGL_Log
681
680
bool waitForAllResults = p.flags .hasValue (IQueryPool::E_QUERY_RESULTS_FLAGS::EQRF_WAIT_BIT);
682
681
bool partialResults = p.flags .hasValue (IQueryPool::E_QUERY_RESULTS_FLAGS::EQRF_PARTIAL_BIT);
683
682
683
+ assert (queryType == IQueryPool::E_QUERY_TYPE::EQT_OCCLUSION || queryType == IQueryPool::E_QUERY_TYPE::EQT_TIMESTAMP);
684
+
684
685
if (p.firstQuery + p.queryCount > queryPoolQueriesCount)
685
686
{
686
687
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
692
693
}
693
694
694
695
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
706
707
{
707
708
if (use64Version)
708
- {
709
709
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;
710
725
}
711
726
else
712
727
{
713
- gl.extGlGetQueryObjectuiv (queryId, pname, reinterpret_cast <GLuint*>(pData));
728
+ GLuint* dataPtr = reinterpret_cast <GLuint*>(pData);
729
+ *dataPtr = static_cast <uint32_t >(value);
714
730
}
715
731
};
716
732
733
+ // iterate on each query
717
734
for (uint32_t i = 0 ; i < p.queryCount ; ++i)
718
735
{
719
- // Don't write queries that exceed the dataSize
720
736
if (currentDataPtrOffset >= p.dataSize )
737
+ {
738
+ assert (false );
721
739
break ;
740
+ }
722
741
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)
724
750
{
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;
727
755
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);
731
782
}
732
- else
783
+
784
+ if (availabilityFlag)
733
785
{
734
- assert (false && " QueryType is not supported." );
786
+ if (waitForAllResults)
787
+ writeValueToData (pAvailabilityData, (allGlQueriesAvailable) ? 1ull : 0ull );
788
+ else
789
+ writeValueToData (pAvailabilityData, 1ull );
735
790
}
736
791
737
792
currentDataPtrOffset += p.stride ;
738
-
739
793
}
740
794
}
741
795
}
0 commit comments