corona icon indicating copy to clipboard operation
corona copied to clipboard

Vulkan backend (Windows)

Open ggcrunchy opened this issue 3 years ago • 2 comments

This is version 1.0 of a Vulkan backend—Windows only so far—aimed at parity with its GL counterpart.

I've run it through the samples, as well as a battery of my own projects, and generally everything seems to line up. (I get some very minor disagreement in the Filter Viewer's crystallize results, to be investigated further.)

To enable the backend, we add either of the following lines to the application table in config.lua:

backend = "wantVulkan"

or

backend = "requireVulkan".

The first case says we would like to use Vulkan, but can fall back to OpenGL if it's not installed / unsupported.

The latter says we MUST use Vulkan; we will get an error dialog if this isn't possible and then either exit (shell or build) or put the current session into an inert state until we relaunch / close (simulator). At the moment this is of limited use, but advanced features down the road might call for it.

We can query the backend using system.getInfo("graphicsBackend"), currently returning either "glBackend" or "vulkanBackend".


This is a lot of code all at once, but I'll try to give an overview.

I won't cover most headers, since the interesting details usually come up in their C++ files.

(Apologies for the formatting.)

  • external:

Added a vulkan folder containing headers and libraries, the volk library, plus some notes.

  • Display/Shader/kernel_filter_sobel_gl.lua:

    sample was renamed to samples since the former has a meaning already in the newer GL version.

  • Display/Rtt_Display.cpp:

    The ShaderFactory is provided the backend info. Ditto the Display itself, which if desired will load the Vulkan renderer instead.

    Captures will pass an isCapture value of true to give BeginFrame() some context.

    The Vulkan renderer will be given a callback and an opaque pointer to the display so that it can manually invalidate the scene when we have size changes and such. Vulkan must rebuild its swapchain in these circumstances, but only realizes this after the underlying surface is out of date; however, although the scene does get force-invalidated due to those changes, Vulkan detects this during the post-invalidation frame. This is not a problem if objects are updating; if not, however, the scene remains "valid" and we just get a black screen until clicking, switching windows, etc.

    CaptureFrameBuffer() was GL-centric. It's now tied to the renderer.

    Added an EndCapture() to do some renderer-specific post-capture cleanup.

  • Display/Rtt_Scene.cpp:

    Added a BeginDrawing() method to do some renderer-specific pre-render logic. Originally I tried to piggyback this onto methods like Clear() called around the same time, but was running into issues of ordering, being optional, etc.

  • Display/Rtt_Shader.cpp:

    BeginDrawing() appears again for the same reason.

  • Display/Rtt_ShaderBuiltin.cpp:

    The backend info is provided and used to install the appropriate default shader shell.

  • Display/Rtt_ShaderFactory.cpp:

    The backend info is also provided here and calls the above ShaderBuiltin logic. Also, the appropriate GL language is chosen.

  • Display/Rtt_SnapshotObject.cpp:

    Once again we have BeginDrawing(), for the reasons described in Scene and Shader.

    Also, the frame buffer object now takes a final argument of false meaning "we don't always clear this". This accounts for different canvas modes and indicates that we should create both clear- and load-type frame buffer objects.

  • Display/Rtt_TextureResourceCanvas.cpp:

    As with snapshots.

  • Renderer/Rtt_CommandBuffer.cpp:

    ReadBytes() and WriteBytes() pulled out of GLCommandBuffer for reuse in VulkanCommandBuffer. This also dovetails with another PR I hope to submit later (custom display objects).

    (Argh, I just realized I never adjusted GLCommandBuffer itself to use this.)

  • Renderer/Rtt_FrameBufferObject.cpp:

    As described in SnapshotObject, a frame buffer now tracks whether it should always be cleared before use or might also leave its contents intact.

    The underlying texture is told that it will be used as a render target.

  • Renderer/Rtt_GLCommandBuffer.cpp:

    Various constants get #undef'd at the end so that we can also use them in VulkanCommandBuffer.

  • Renderer/Rtt_Program.cpp:

    The Vulkan GLSL header source is also available as an option.

  • Renderer/Rtt_Renderer.cpp:

    Added dummy boolean final argument to BeginFrame() to comply with new signature.

    Kludgy parenthesizing of max() function since the Windows macro now seems to conflict with it otherwise.

    Clearing some things in the constructor. (I don't know if these still matter, but they're harmless.)

    Aforementioned BeginDrawing() function and the default (OpenGL) CaptureFrameBuffer().

  • Renderer/Rtt_ShaderCode.cpp:

    This is new. Allowing shaders written for OpenGL to work in Vulkan requires a lot of code transformation. If we're not careful, we might end up locating, trying to modify, etc. code found inside comments. This figures out where those off-limits ranges are and lets us work around them. (This does not account for #ifdef and friends.)

  • Renderer/Rtt_Texture.cpp:

    Textures now have a flag to track whether they're used as a render target. This is used by the Vulkan-side resources.

  • Renderer/Rtt_Uniform.cpp:

    Added a non-allocating constructor. This is to just make a dummy Uniform to use some of its methods.

  • Renderer/Rtt_Uniform.h:

    Added a ContentSize uniform. This is used to get gl_FragCoord to conform to what we see in OpenGL, since Vulkan flips the y-axis and offers no way to change that. (Maybe this is worth adding to the GL backend, since it's potentially useful information.)

  • Renderer/Rtt_Vulkan*:

    All the new Vulkan stuff!

  • Rtt_LuaLibSystem.cpp:

    Added "graphicsBackend" option to system.getInfo(), returning either "glBackend" or "vulkanBackend".

  • Rtt_Runtime.cpp:

    Display initialized with backend details.

  • Project:

    In Debug we link to the Vulkan library; in Release we use volk. Some SPIRV libraries and shaderc are also linked.

    One of the debug libraries (shaderc_combinedd.lib) was exceeding 100 MB, making GitHub complain, but crunched down well; a pre-build event is used to inflate it.

  • valid_config_lua:

    Added backend stub.

  • Rtt_ProjectSettings.cpp:

    We do a lookup for application.backend in config.lua to see if Vulkan is requested.

    A getter for the backend.

  • Rtt_ReadOnlyProjectSettings.cpp:

    A getter that basically passes the ProjectSettings backend stuff through.

  • CoronaWin32.cpp:

    When we validate OpenGL, it will affect the window we do our tests on, effectively making it unusable for Vulkan. One way to circumvent this, when Vulkan is requested, is to test a secondary window and discard it after getting the results.

  • Interop/RuntimeEnvironment.cpp:

    Set up "Vulkan wanted" params and pass them to the RenderSurfaceControl when we construct it.

    When Vulkan is wanted, register the backend and its state.

  • Interop/UI/RenderSurfaceControl.cpp:

    Constructor and CreateContext() now take parameters with Vulkan configuration.

    Various changes in flow of control when Vulkan is chosen. (Hard to summarize, but wherever you see fVulkanContext, and also in CreateContext(), of course.)

    Vulkan will assign its version as GL 4.6 so that Solar relaunches cleanly.

  • Corona.Simulator: SimulatorView.cpp:

    The "Corona container control" is destroyed and recreated when we launch or stop the simulation. This concerns the issue mentioned above for validating OpenGL: a GL-"tainted" window becomes unusable for Vulkan, and vice versa. Because we do this we don't actually need a secondary window for the simulator.

  • Corona.Shell: Main.cpp:

    As described above for validating OpenGL, we make a secondary test window.

  • .gitignore:

    It was mentioned above that a too-large library has to be unzipped in a pre-build step. We tell Git to ignore the extracted library.

ggcrunchy avatar Jul 16 '21 07:07 ggcrunchy

So much to go through :) Thanks a lot for doing this!

Shchvova avatar Jul 16 '21 19:07 Shchvova

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Aug 16 '21 20:08 CLAassistant