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 | 168 |
1 files changed, 157 insertions, 11 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 4979ff51a9..972c289412 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -18,7 +18,14 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS { UINT64 NumPrimitivesWritten; UINT64 PrimitivesStorageNeeded; } D3D11_QUERY_DATA_SO_STATISTICS; -#endif +#endif // ANGLE_MINGW32_COMPAT + +#ifdef __MINGW32__ +typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT { + UINT64 Frequency; + BOOL Disjoint; +} D3D11_QUERY_DATA_TIMESTAMP_DISJOINT; +#endif // MINGW32 namespace rx { @@ -28,38 +35,81 @@ Query11::Query11(Renderer11 *renderer, GLenum type) mResult(0), mQueryFinished(false), mRenderer(renderer), - mQuery(NULL) + mQuery(nullptr), + mTimestampBeginQuery(nullptr), + mTimestampEndQuery(nullptr) { } Query11::~Query11() { SafeRelease(mQuery); + SafeRelease(mTimestampBeginQuery); + SafeRelease(mTimestampEndQuery); } gl::Error Query11::begin() { - if (mQuery == NULL) + if (mQuery == nullptr) { D3D11_QUERY_DESC queryDesc; queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); queryDesc.MiscFlags = 0; - HRESULT result = mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery); + ID3D11Device *device = mRenderer->getDevice(); + + HRESULT result = device->CreateQuery(&queryDesc, &mQuery); if (FAILED(result)) { return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); } + + // 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); + } + } } - mRenderer->getDeviceContext()->Begin(mQuery); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->Begin(mQuery); + + // 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); } gl::Error Query11::end() { ASSERT(mQuery); - mRenderer->getDeviceContext()->End(mQuery); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + // If we are doing time elapsed query the end timestamp + if (getType() == GL_TIME_ELAPSED_EXT) + { + context->End(mTimestampEndQuery); + } + + context->End(mQuery); mQueryFinished = false; mResult = GL_FALSE; @@ -67,7 +117,17 @@ gl::Error Query11::end() return gl::Error(GL_NO_ERROR); } -gl::Error Query11::getResult(GLuint *params) +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); +} + +template <typename T> +gl::Error Query11::getResultBase(T *params) { while (!mQueryFinished) { @@ -84,12 +144,32 @@ gl::Error Query11::getResult(GLuint *params) } ASSERT(mQueryFinished); - *params = mResult; + *params = static_cast<T>(mResult); return gl::Error(GL_NO_ERROR); } -gl::Error Query11::isResultAvailable(GLuint *available) +gl::Error Query11::getResult(GLint *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLuint *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLuint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query11::isResultAvailable(bool *available) { gl::Error error = testQuery(); if (error.isError()) @@ -97,7 +177,7 @@ gl::Error Query11::isResultAvailable(GLuint *available) return error; } - *available = (mQueryFinished ? GL_TRUE : GL_FALSE); + *available = mQueryFinished; return gl::Error(GL_NO_ERROR); } @@ -141,8 +221,74 @@ gl::Error Query11::testQuery() if (result == S_OK) { mQueryFinished = true; - mResult = static_cast<GLuint>(soStats.NumPrimitivesWritten); + mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten); + } + } + break; + + case GL_TIME_ELAPSED_EXT: + { + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0}; + HRESULT result = context->GetData(mQuery, &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); } + + if (result == S_OK) + { + UINT64 beginTime = 0; + HRESULT beginRes = + context->GetData(mTimestampBeginQuery, &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); + } + UINT64 endTime = 0; + HRESULT endRes = + context->GetData(mTimestampEndQuery, &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); + } + + if (beginRes == S_OK && endRes == S_OK) + { + mQueryFinished = 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)) + { + mResult = ((endTime - beginTime) * 1000000000ull) / timeStats.Frequency; + } + else + { + mResult = std::numeric_limits<GLuint64>::max() / timeStats.Frequency; + // If an overflow does somehow occur, there is no way the elapsed time + // is accurate, so we generate a disjoint event + mRenderer->setGPUDisjoint(); + } + } + } + } + break; + + case GL_TIMESTAMP_EXT: + { + // 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; } break; |