Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}