Is there anyway to know when the screen is updated / updated (maybe OpenGL or DirectX?)

I currently have an application that I am writing in C # (using .NET) that requires me to start a timer as soon as the user sees the image on the screen until he answers with a keystroke.

Now I understand that this is practically very difficult, given the delay time for the monitor input and response time, the time that the keyboard takes to physically send a message, the OS to process it, etc.

But I try to reduce it to most of the permanent error (the results of the answer will be used to compare one user with another, so a constant error is not really a problem). However, the annoying obstacle is the variable caused by the refresh rate of the monitor, since I gather when my onPaint message is called and executed with it, does this not mean that the image is actually processed and sent from the graphics buffer?

Unfortunately, time limits and other obligations realistically limit me to continuing this task in C # for windows.

So I was wondering if I would process the entire drawing in OpenGL or DirectX, or even better for me, if you could just use OpenGL or DirectX to create an event when the screen refreshes?

Another assumption given to me earlier was about V-Sync, if I turn it off, will the image be sent as soon as it is drawn? as opposed to sending images at a given speed synchronized with the refresh rate of the monitor?

+2
source share
2 answers

You must make your schedule in a separate thread in order to:

  • Use vertical sync to have an accurate time to efficiently display your image.
  • Get the exact time your user entered (as the user interface is not in the same stream as in the render loop.

Initialize Direct3D to enable VSync during rendering:

// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;

device = new Device(...

Render in a separate thread:

Thread renderThread = new Thread(RenderLoop);
renderThread.Start();

shouldDisplayImageEvent = new AutoResetEvent();

:

void RenderLoop()
{
    while(applicationActive)
    {
          device.BeginScene();

        // Other rendering task

        if (shouldDisplayImageEvent.WaitOne(0))
        {
            // Render image
            // ...

            userResponseStopwatch = new Stopwatch();
            userResponseStopwatch.Start();
        }

        device.EndScene();

        device.Present();
    }
}

:

void OnUserInput(object sender, EventArgs e)
{
    if (userResponseStopwatch != null)
    {
        userResponseStopwatch.Stop();

        float userResponseDuration = userResponseStopwatch.ElapsedMillisecond - 1000 / device.DisplayMode.RefreshRate - displayDeviceDelayConstant;
        userResponseStopwatch = null;
    }
}

eventDisplayImageEvent.Set() .

+3

VSync :

// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;

device = new Device(...

Application.Idle += new EventHandler(OnApplicationIdle);

// More on this here : http://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx
internal void OnApplicationIdle(object sender, EventArgs e)
{
    Msg msg = new Msg();
    while (true)
    {
        if (PeekMessage(out msg, IntPtr.Zero, 0, 0, 0))
            break;
    }

    // Clearing render
    // ...

    if (displayImage)
    {
        // Render image
        // ...

        renderTime = DateTime.now();
    }
    device.Present();
}

vsync device.Present , , renderTime + 16,67 , .

+1

Source: https://habr.com/ru/post/1544888/


All Articles