summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp363
1 files changed, 214 insertions, 149 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
index 0a79b26df0..66b9476e7f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
@@ -7,146 +7,96 @@
// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl.
#include "libANGLE/renderer/d3d/d3d11/Query11.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-#include "common/utilities.h"
#include <GLES2/gl2ext.h>
-#if defined(ANGLE_MINGW32_COMPAT)
-typedef struct D3D11_QUERY_DATA_SO_STATISTICS {
- UINT64 NumPrimitivesWritten;
- UINT64 PrimitivesStorageNeeded;
-} D3D11_QUERY_DATA_SO_STATISTICS;
-#endif // ANGLE_MINGW32_COMPAT
-
-#ifndef ANGLE_D3D11_QDTD_AVAILABLE
-typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT {
- UINT64 Frequency;
- BOOL Disjoint;
-} D3D11_QUERY_DATA_TIMESTAMP_DISJOINT;
-#endif // MINGW32
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-namespace rx
+namespace
{
-Query11::Query11(Renderer11 *renderer, GLenum type)
- : QueryImpl(type),
- mResult(0),
- mQueryFinished(false),
- mRenderer(renderer),
- mQuery(nullptr),
- mTimestampBeginQuery(nullptr),
- mTimestampEndQuery(nullptr)
+GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
{
-}
+ switch (type)
+ {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
-Query11::~Query11()
-{
- SafeRelease(mQuery);
- SafeRelease(mTimestampBeginQuery);
- SafeRelease(mTimestampEndQuery);
-}
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return currentResult + newResult;
-gl::Error Query11::begin()
-{
- if (mQuery == nullptr)
- {
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = gl_d3d11::ConvertQueryType(getType());
- queryDesc.MiscFlags = 0;
+ case GL_TIME_ELAPSED_EXT:
+ return currentResult + newResult;
- ID3D11Device *device = mRenderer->getDevice();
+ case GL_TIMESTAMP_EXT:
+ return newResult;
- HRESULT result = device->CreateQuery(&queryDesc, &mQuery);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result);
- }
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return newResult;
- // If we are doing time elapsed we also need a query to actually query the timestamp
- if (getType() == GL_TIME_ELAPSED_EXT)
- {
- D3D11_QUERY_DESC desc;
- desc.Query = D3D11_QUERY_TIMESTAMP;
- desc.MiscFlags = 0;
- result = device->CreateQuery(&desc, &mTimestampBeginQuery);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
- result);
- }
- result = device->CreateQuery(&desc, &mTimestampEndQuery);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
- result);
- }
- }
+ default:
+ UNREACHABLE();
+ return 0;
}
+}
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+} // anonymous namespace
- context->Begin(mQuery);
+namespace rx
+{
- // If we are doing time elapsed query the begin timestamp
- if (getType() == GL_TIME_ELAPSED_EXT)
- {
- context->End(mTimestampBeginQuery);
- }
- return gl::Error(GL_NO_ERROR);
+Query11::QueryState::QueryState() : query(), beginTimestamp(), endTimestamp(), finished(false)
+{
}
-gl::Error Query11::end()
+Query11::QueryState::~QueryState()
{
- ASSERT(mQuery);
-
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+}
- // If we are doing time elapsed query the end timestamp
- if (getType() == GL_TIME_ELAPSED_EXT)
- {
- context->End(mTimestampEndQuery);
- }
+Query11::Query11(Renderer11 *renderer, GLenum type)
+ : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer)
+{
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+}
- context->End(mQuery);
+Query11::~Query11()
+{
+ mRenderer->getStateManager()->onDeleteQueryObject(this);
+}
- mQueryFinished = false;
- mResult = GL_FALSE;
+gl::Error Query11::begin()
+{
+ mResultSum = 0;
+ mRenderer->getStateManager()->onBeginQuery(this);
+ return resume();
+}
- return gl::Error(GL_NO_ERROR);
+gl::Error Query11::end()
+{
+ return pause();
}
gl::Error Query11::queryCounter()
{
// This doesn't do anything for D3D11 as we don't support timestamps
ASSERT(getType() == GL_TIMESTAMP_EXT);
- mQueryFinished = true;
- mResult = 0;
- return gl::Error(GL_NO_ERROR);
+ mResultSum = 0;
+ mPendingQueries.push_back(std::unique_ptr<QueryState>(new QueryState()));
+ return gl::NoError();
}
template <typename T>
gl::Error Query11::getResultBase(T *params)
{
- while (!mQueryFinished)
- {
- gl::Error error = testQuery();
- if (error.isError())
- {
- return error;
- }
-
- if (!mQueryFinished)
- {
- ScheduleYield();
- }
- }
+ ASSERT(!mActiveQuery->query.valid());
+ ANGLE_TRY(flush(true));
+ ASSERT(mPendingQueries.empty());
+ *params = static_cast<T>(mResultSum);
- ASSERT(mQueryFinished);
- *params = static_cast<T>(mResult);
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Query11::getResult(GLint *params)
@@ -171,105 +121,197 @@ gl::Error Query11::getResult(GLuint64 *params)
gl::Error Query11::isResultAvailable(bool *available)
{
- gl::Error error = testQuery();
- if (error.isError())
+ ANGLE_TRY(flush(false));
+
+ *available = mPendingQueries.empty();
+ return gl::NoError();
+}
+
+gl::Error Query11::pause()
+{
+ if (mActiveQuery->query.valid())
{
- return error;
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ GLenum queryType = getType();
+
+ // If we are doing time elapsed query the end timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ context->End(mActiveQuery->endTimestamp.get());
+ }
+
+ context->End(mActiveQuery->query.get());
+
+ mPendingQueries.push_back(std::move(mActiveQuery));
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
}
- *available = mQueryFinished;
+ return flush(false);
+}
+
+gl::Error Query11::resume()
+{
+ if (!mActiveQuery->query.valid())
+ {
+ ANGLE_TRY(flush(false));
+
+ GLenum queryType = getType();
+ D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(queryType);
- return gl::Error(GL_NO_ERROR);
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = d3dQueryType;
+ queryDesc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(queryDesc, &mActiveQuery->query));
+
+ // If we are doing time elapsed we also need a query to actually query the timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ D3D11_QUERY_DESC desc;
+ desc.Query = D3D11_QUERY_TIMESTAMP;
+ desc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->beginTimestamp));
+ ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->endTimestamp));
+ }
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ if (d3dQueryType != D3D11_QUERY_EVENT)
+ {
+ context->Begin(mActiveQuery->query.get());
+ }
+
+ // If we are doing time elapsed, query the begin timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ context->End(mActiveQuery->beginTimestamp.get());
+ }
+ }
+
+ return gl::NoError();
}
-gl::Error Query11::testQuery()
+gl::Error Query11::flush(bool force)
{
- if (!mQueryFinished)
+ while (!mPendingQueries.empty())
{
- ASSERT(mQuery);
+ QueryState *query = mPendingQueries.front().get();
+ do
+ {
+ ANGLE_TRY(testQuery(query));
+ if (!query->finished && !force)
+ {
+ return gl::NoError();
+ }
+ } while (!query->finished);
+
+ mResultSum = MergeQueryResults(getType(), mResultSum, mResult);
+ mPendingQueries.pop_front();
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Query11::testQuery(QueryState *queryState)
+{
+ if (!queryState->finished)
+ {
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
switch (getType())
{
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
{
+ ASSERT(queryState->query.valid());
UINT64 numPixels = 0;
- HRESULT result = context->GetData(mQuery, &numPixels, sizeof(numPixels), 0);
+ HRESULT result =
+ context->GetData(queryState->query.get(), &numPixels, sizeof(numPixels), 0);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
}
if (result == S_OK)
{
- mQueryFinished = true;
- mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ queryState->finished = true;
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
}
}
break;
- case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
{
- D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 };
- HRESULT result = context->GetData(mQuery, &soStats, sizeof(soStats), 0);
+ ASSERT(queryState->query.valid());
+ D3D11_QUERY_DATA_SO_STATISTICS soStats = {0};
+ HRESULT result =
+ context->GetData(queryState->query.get(), &soStats, sizeof(soStats), 0);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
}
if (result == S_OK)
{
- mQueryFinished = true;
- mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten);
+ queryState->finished = true;
+ mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten);
}
}
break;
case GL_TIME_ELAPSED_EXT:
{
+ ASSERT(queryState->query.valid());
+ ASSERT(queryState->beginTimestamp.valid());
+ ASSERT(queryState->endTimestamp.valid());
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0};
- HRESULT result = context->GetData(mQuery, &timeStats, sizeof(timeStats), 0);
+ HRESULT result =
+ context->GetData(queryState->query.get(), &timeStats, sizeof(timeStats), 0);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to get the data of an internal query, result: 0x%X.",
- result);
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
}
if (result == S_OK)
{
UINT64 beginTime = 0;
- HRESULT beginRes =
- context->GetData(mTimestampBeginQuery, &beginTime, sizeof(UINT64), 0);
+ HRESULT beginRes = context->GetData(queryState->beginTimestamp.get(),
+ &beginTime, sizeof(UINT64), 0);
if (FAILED(beginRes))
{
- return gl::Error(
- GL_OUT_OF_MEMORY,
- "Failed to get the data of an internal query, result: 0x%X.", beginRes);
+ return gl::OutOfMemory() << "Failed to get the data of an internal query, "
+ << gl::FmtHR(beginRes);
}
UINT64 endTime = 0;
- HRESULT endRes =
- context->GetData(mTimestampEndQuery, &endTime, sizeof(UINT64), 0);
+ HRESULT endRes = context->GetData(queryState->endTimestamp.get(), &endTime,
+ sizeof(UINT64), 0);
if (FAILED(endRes))
{
- return gl::Error(
- GL_OUT_OF_MEMORY,
- "Failed to get the data of an internal query, result: 0x%X.", endRes);
+ return gl::OutOfMemory() << "Failed to get the data of an internal query, "
+ << gl::FmtHR(endRes);
}
if (beginRes == S_OK && endRes == S_OK)
{
- mQueryFinished = true;
+ queryState->finished = true;
if (timeStats.Disjoint)
{
mRenderer->setGPUDisjoint();
}
static_assert(sizeof(UINT64) == sizeof(unsigned long long),
"D3D UINT64 isn't 64 bits");
- if (rx::IsUnsignedMultiplicationSafe(endTime - beginTime, 1000000000ull))
+
+ angle::CheckedNumeric<UINT64> checkedTime(endTime);
+ checkedTime -= beginTime;
+ checkedTime *= 1000000000ull;
+ checkedTime /= timeStats.Frequency;
+ if (checkedTime.IsValid())
{
- mResult = ((endTime - beginTime) * 1000000000ull) / timeStats.Frequency;
+ mResult = checkedTime.ValueOrDie();
}
else
{
@@ -288,23 +330,46 @@ gl::Error Query11::testQuery()
// D3D11 doesn't support GL timestamp queries as D3D timestamps are not guaranteed
// to have any sort of continuity outside of a disjoint timestamp query block, which
// GL depends on
- mResult = 0;
+ ASSERT(!queryState->query.valid());
+ mResult = 0;
+ queryState->finished = true;
}
break;
- default:
- UNREACHABLE();
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ {
+ ASSERT(queryState->query.valid());
+ BOOL completed = 0;
+ HRESULT result =
+ context->GetData(queryState->query.get(), &completed, sizeof(completed), 0);
+ if (FAILED(result))
+ {
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
+ }
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ ASSERT(completed == TRUE);
+ mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+ }
+ }
break;
+
+ default:
+ UNREACHABLE();
+ break;
}
- if (!mQueryFinished && mRenderer->testDeviceLost())
+ if (!queryState->finished && mRenderer->testDeviceLost())
{
mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ return gl::OutOfMemory() << "Failed to test get query result, device is lost.";
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-}
+} // namespace rx