MoonWorks-docs/content/Graphics/GraphicsDevice.md

2.7 KiB

title date
Graphics Device 2021-01-24T20:52:59-08:00

GraphicsDevice is your main entry point for graphics-related behavior. You can obtain a reference to the current GraphicsDevice from your Game class.

Rendering in MoonWorks.Graphics is mostly handled through an abstraction known as the command buffer. You will acquire a command buffer from the GraphicsDevice, tell it to do things, and then submit it to the GraphicsDevice for processing.

var commandBuffer = GraphicsDevice.AcquireCommandBuffer();

// do things with command buffer

GraphicsDevice.Submit(commandBuffer);

You will also need to provide the GraphicsDevice to load graphics resources. For example:

var myTexture = Texture.LoadPNG(GraphicsDevice, "grass.png");

There is one last thing that the GraphicsDevice can do, and that is Wait. To understand waiting, you need to understand a little bit about how MoonWorks.Graphics processes rendering.

Rendering is asynchronous. This means that when you submit a command buffer, the program doesn't actually wait for the GPU to finish working on whatever commands you submitted. It just tells the GPU what to do and then keeps going with your program. This is very good for performance because it means your CPU can get started working on the next frame before the current frame is even rendered.

Sometimes you actually do want to wait for the GPU to be done with the work you asked it to do, like if you are grabbing a screenshot for example. This is where Wait comes in.

// in initializer
screenshotThread = new Thread(new ThreadStart(SaveScreenshot));

...

protected void Draw(double dt, double alpha)
{
    // do other rendering stuff

    if (screenshotActivated)
    {
        commandBuffer.CopyTextureToBuffer(myTextureSlice, screenshotBuffer);
    }

    GraphicsDevice.Submit(commandBuffer);

    if (screenshotActivated)
    {
        screenshotThread.Start();
    }
}

...

private void SaveScreenshot()
{
    GraphicsDevice.Wait();
    screenshotBuffer.GetData(screenshotPixels, screenShotBufferSize);
    Texture.SavePNG("screenshot.png", 1280, 720, screenshotPixels);
}

In this example, a separate CPU thread waits for the GPU to be done working. Then it saves some pixels that the GPU moved into a buffer to the disk as a PNG. Note that this means the game doesn't stutter at all while the disk is written to, because a separate thread from the main execution thread handles saving to disk.

If you need to squeeze some performance out of your game or avoid a lengthy stutter while the disk is accessed, threading can go a long way.

Before we talk too much more about command buffers and threading, let's explain the different kinds of graphics resources that you need for rendering.