Now there is just one primary command buffer where all work is enqueued
into. At the end of the frame, the next frame's CPU-side fence is waited
on before resetting and beginning its command buffer again for
recording. This command buffer must always be in the RECORDING state.
While we wait on the CPU-side fence for these command buffers, we must
also wait on the GPU-side semaphore to be compliant to validation
layers synchronization. We still get an error on the very first frame
since it will wait for a semaphore that has nothing signaling it.
Rather than allocating new command buffers for each small task, schedule
all work onto the frame's main command buffer to be dispatched at
display-time. Fixes all layout transition and synchronization issues.
Technically we can generate every possible render-pass up-front based on
the possible combinations of ColorFmt and DepthFmt, but we should only
allocate what the game asks for. Save that pattern for pipelines.
This surface is managed by SDL itself, so there is no need to keep it in
a Unique handle for us to delete. Fixes the bug where vulkan crashes
during shutdown.
Instead of operating directly on the swapchain images, we have our own
top/bottom framebuffer images that will be rendered to independent of
having an available swapchain. The images are blitted into the swapchain
images, allowing for resizing too!
Lots of todos, this should probably just be its own self-contained
object to allow the emulator to render "headlessly" regardless of a
swapchain existing or not.
Use a stable_partitioning of the list of devices the driver gave us with
the addition of checking of the physical device supports the
display-surface that SDL gave us as well.
This value is needed for vulkan to properly allocate a surface, and would benefit OpenGL to move more of its initialization code into here rather than in `emulator.cpp`.
Headlessly creates a new vulkan instance, with conditional MacOS
support, and enables the `VK_EXT_debug_utils` instance-extension with a
debug-messenger to hook onto validation layer messages.
A lot of the architecture of the emulator here does not allow for vulkan
to initialize easily since it involves a bit of data to be exchanged
between SDL and Vulkan. This commit just adds the foundational linkage
and library code for vulkan support.
`config` was being consumed much too early before it has a chance to
call `load`. This caused GPU to read weird uninitialized data, and then
`load` called, and then further initialization to occur based on default
data and the data inside of `config.toml`. `EmulatorConfig` needs to be
loaded in first before any sort of initialization happens, by adding a
new constructor so that it can be initialized sooner.
There are still some initialization errors to work through, such as
config not being initialized properly by the time GPU tries to utilize
it too. Also some life-time issues. But manually forcing it to use the
Null backnd successfully works and allows games to be "played"
headlessly.
Rather than declaring a big C++ literal for these strings, they are now
proper `.vert` and `.frag` files that will become embedded into the
application at build-time. It also allows for clang-format to format the
glsl files the same as our C++ code. CMake will also automatically track
and re-embed the file if it detects that the glsl source files have
changed since the last build. Ex, making a change to
`opengl_display.frag` and compiling will automatically recompile and
link the resource-target that it is associated with.
Allows the OpenGL backend to be fully disabled, continuing a modular
pattern of having multiple possible rendering backends. Also defines the
`ENABLE_OPENGL` preprocessor in the case of conditional source-file
changes depending on the rendering backend.
Rather than having the entire implementation within `emulator.cpp`,
causing incremental builds to be much slower, give it its own
translation unit `stb_image_write.c`.
Allows the return-type to be specified, allowing a concise final cast
after extracting the bit-type. Addresses the remaining `C4244` warnings
regarding `getBits`.
The non-error-code version of these functions are susceptible to
throwing an exception in the case of system errors like permission
issues or underlying device errors.
Adds a project-wide setting for allowing renderer code to add additional
diagnostic data. Currently used to allow `opengl.hpp` to conditionally
implement debug-labeling and scopes.
Simply define this object in a C++ scope like:
```cpp
OpenGL::DebugScope glScope("Renderer::display");
```
and it will associate all functions within the current scope within a
named group. Supports `printf` formatting.
Makes the implementation of `IOFile` private, allowing inclusions and
defines such as `#define fseeko` and `#include <io.h>` to not poison
client-code or the global namespace.
Makes framebuffer-formats unrepresentable from texture formats while
allowing them to alias each other. Add utility functions as well that
just re-use the `TextureFmt` ones.
Slowly stepping the codebase towards having renderer-agnostic types and keeping the translation of PICA-types to OpenGL/VK/DX/Software/etc to the renderer-backend.
Following the trend of #33: `std::span` provides some useful utility
functions like `size_bytes()` and `as_bytes()` and serves as a better
non-owning "chunk of data"-type over just passing around an
`std::array&`.
Use the command `clang-format -i tests/**/*.c src/**/*.cpp include/**/*.hpp`
to process all of the project's files.
Using the one from [pcsx-redux](https://github.com/grumpycoders/pcsx-redux/blob/main/src/.clang-format)
as a basis and then made additional edits to be the _least_ disruptive
to the pre-existing formatting patterns.
`constexpr` functions for extractint bitfields that lends itself a bit
better to emitting instructions like `bextr` on x86 or `ubfx` on arm64.
And may subjectively make things a bit more readable.
"Extract `5` bits" rather than `& 0x1F`.