gl::Error Query11::testQuery() { if (!mQueryFinished) { ASSERT(mQuery); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); switch (getType()) { case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: { UINT64 numPixels = 0; HRESULT result = context->GetData(mQuery, &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); } if (result == S_OK) { mQueryFinished = true; mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; } } break; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: { D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; HRESULT result = context->GetData(mQuery, &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); } if (result == S_OK) { mQueryFinished = true; mResult = static_cast<GLuint>(soStats.NumPrimitivesWritten); } } break; default: UNREACHABLE(); break; } if (!mQueryFinished && mRenderer->testDeviceLost(true)) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); } } return gl::Error(GL_NO_ERROR); }
gl::Error Query11::testQuery() { if (!mQueryFinished) { ASSERT(mQuery); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); switch (getType()) { case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: { UINT64 numPixels = 0; HRESULT result = context->GetData(mQuery, &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); } if (result == S_OK) { mQueryFinished = true; mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; } } break; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: { D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; HRESULT result = context->GetData(mQuery, &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); } if (result == S_OK) { mQueryFinished = true; 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; default: UNREACHABLE(); break; } if (!mQueryFinished && mRenderer->testDeviceLost()) { mRenderer->notifyDeviceLost(); return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); } } return gl::Error(GL_NO_ERROR); }