diff options
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.cpp | 363 |
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 |