It used to be the case that frame advance skipped duplicate frames
(i.e. it would take 30 frame advances to get through one second
of emulated time in a 30 fps game), but this broke in 9c5c3c0.
Skipping duplicate frames making TASing less annoying.
Hardware tests have shown that if the number of texgens/channels do not
match, you get garbage rendering. Presumably because the output
registers from the XF stage are fed into the incorrect input registers
for TEV/BP.
Currently, this causes Dolphin to crash/generate invalid shaders with an
assertion failure in the hardware backends. Instead, we log an error.
Perhaps in the future we should just spit out all texgens/colors anyway
from both stages, and let cross-stage optimization take care of DCE'ing
it away. But doing so would require changing the UIDs and invalidating
everyone's shader caches.
It seems that the newer version of fmt gets tripped up by bitfields
within structs. However, we can just specify the intended type where
necessary to get around this.
Migrates the shader generator off the use of a global array, eliminating
the use of some global state. This also allows us to move the shader
generation over to using fmt in a subsequent change.
Currently, we do not display every second frame in 25fps/30fps games
which run to vsync. This improves performance as there's less rendering
for the GPU to perform, but when combined with vsync, could cause frame
pacing issues.
This commit adds an option to force every frame generated by the console
to be displayed to the host, which may improve pacing for these games.
The frame number is incremented before the first frame is swapped out.
Fixes ffmpeg creating invalid video files on output if the emulator only
runs for a single frame, e.g. FifoCI.
Now that we have an actual interface to manage things, we can stop
duplicating the calls to to the pixel shader manager and remove the
need to remember to actually do so when disabling or enabling the
bounding box.
Rather than expose the bounding box members directly, we can instead
provide an interface for code to use. This makes it nicer to transition
from global data, as the interface function names are already in
place.
Now that we've extracted all of the stateless functions that can be
hidden, it's time to make the index generator a regular class with
active data members.
This can just be a member that sits within the vertex manager base
class. By deglobalizing the state of the index generator we also get rid
of the wonky dual-initializing that was going on within the OpenGL
backend.
Since the renderer is always initialized before the vertex manager, we
now only call Init() once throughout the execution lifecycle.
We can use if constexpr with the template functions that pass in a
non-type template parameter, allowing the removal of branches that
aren't taken at compile time.
Compilers will generally do this by default, however, we now give a
gentle prodding to the compiler if this would otherwise not be the case.
These don't rely on any of the static members within the IndexGenerator
class, so we can make all of these functions fully internal to the
translation unit.
We can make use of if constexpr in several scenarios here to allow
compilers to exise the relevant code paths out.
Technically a decent compiler would do this already, but now we can give
compilers a little more nudging here in the event that isn't the case.
cmd2 is a u32, so any bitwise arithmetic on it with a type of the same
size or smaller will result in a u32 value. This is also implicitly
converted to an unsigned type in the if statement as well, given that
size_t * int -> size_t.
This is just more explicit about the operations occurring and also
likely silences a sign conversion warning.
We only use these string streams to output into a final std::string
instance, we don't read into types with them. Because of this, we can
just make use of std::ostringstream, rather than the fully-fledged
std::stringstream.
No behavioral change. This is intended to make the transition to fmt
less noisy in subsequent changes by combining insertions of multiple
string literals into one where applicable.
Begins the conversion of the shader generators over to using fmt
formatting specifiers.
This also has a benefit over the older StringFromFormat-based API in
that all formatted data is appended to the existing buffer rather than
creating a completely separate string and then appending it to the
internal string buffer.
Migrates most of VideoCommon over to using fmt, with the exception being
the shader generator code. The shader generators are quite large and
have more corner cases to deal with in terms of conversion (shaders have
braces in them, so we need to make sure to escape them).
Because of the large amount of code that would need to be converted, the
conversion of VideoCommon will be in two parts:
- This change (which converts over the general case string formatting),
- A follow up change that will specifically deal with converting over
the shader generators.
OpenGL doesn't render to a 2-layer backbuffer like D3D/Vulkan for quad-buffered
stereo, instead drawing twice with the eye selected by glDrawBuffer()
(see OGL::Renderer::RenderXFBToScreen).
This is a giant hack which was previously removed because it causes
broken rendering. However, it seems that some devices still do not
support logical operations (looking at you, Adreno/Mali). Therefore, for
a handful of cases where the hack actually makes things slightly better,
we can use it.
... but not without spamming the log with warnings. With my warning
message PR, we can inform the users before emulation starts anyway.
Same behavior without hardcoding the type of the mutex within the lock
guards. This means the type of the mutex would be able to be changed
without needing to also change all occurrences lock guards are used.
Allows callers to std::move strings into the functions (or automatically
assume the move constructor/move assignment operator for rvalue
references, potentially avoiding copies altogether.