New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Graphics refactoring + add names and descriptions in FIFO analyzer #9497
Conversation
24b7bc5
to
66bd5da
Compare
break; | ||
} | ||
return format_to(ctx.out(), | ||
"Projection: {}\nInput form: {}\nTex gen type: {}\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we call this 'Size' instead of 'Projection'? I think of different things when I hear 'projection' but maybe I'm misunderstanding
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YAGCD calls it projection, while libogc's GX_SetTexCoordGen
calls it tgen_typ
and has GX_TG_MTX3x4
and GX_TG_MTX2x4
; the 3 by 4 version divides by Q
which I think is the actual projection step. But I don't think calling it projection is particularly obvious (nor is typ(e)); size might be better.
fmt::format("Number of color channels: {}", value & 3)); | ||
break; | ||
|
||
case XFMEM_SETCHAN0_AMBCOLOR: // Channel Ambient Color |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too bad we can't somehow pass the color from here to Qt. It'd be nice to somehow see the color in addition to the hex code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we could use rich text tags like I did for the tooltips. Kinda muddies the description text though..
b85d6ef
to
673a949
Compare
bee8cb3
to
f9d5564
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is much closer to a final version (though I still need to rebase and tidy up the commits).
I've converted a lot of graphics code to use BitField
and enum class
es, and have created fmt::formatter
s for most of those enums (and a EnumFormatter
to simplify creating such fomatters) and the corresponding structures. Those formatters are used in the fifo analyzer but also can be used in logging, which is fairly convenient (and thus I've put them into the header file instead of the cpp files used by the fifo analyzer).
One issue caused by the use of enum class
is that there are many std::array
s that map some enum into different host API equivalents or code snippets for shaders. These can't be indexed using an enum class
, so I need to cast them; I've been doing e.g. u32(state.logicmode.Value())
(the Value()
part is needed because of BitField
; it cannot cast directly to u32
). This is a bit messy, but I'm not sure if there's a better solution.
@@ -1697,7 +1697,7 @@ bool Renderer::UseVertexDepthRange() const | |||
return false; | |||
|
|||
// We need a full depth range if a ztexture is used. | |||
if (bpmem.ztex2.type != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest) | |||
if (bpmem.ztex2.op != ZTexOp::Disabled && !bpmem.zcontrol.early_ztest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to have been a typo originally; type
was the format (previously TEV_ZTEX_TYPE_U8
/_U16
/_U24
). I'm not sure if that affected anything though.
BitField<12, 3, u32> bi2; | ||
BitField<15, 3, u32> bc3; // Typo? | ||
BitField<18, 3, u32> bi4; | ||
BitField<21, 3, u32> bc4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These names are somewhat odd since it skips bc2
and bi3
; I don't think it should have gone up to 4 at all. I've left this unchanged in case there's some intended meaning though.
// TODO: This previously had a warning about SRC and DST being aliased and not to mix them, | ||
// but INVSRCCLR and INVDSTCLR were also aliased and were mixed. | ||
// Thus, NOR, EQUIV, INVERT, COPY_INVERTED, and OR_INVERTED duplicate(d) other values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I split BlendFactor
into SrcBlendFactor
and DstBlendFactor
since DstClr
/InvDstClr
and SrcClr
/InvSrcClr
have differences in behavior and are worth treating differently, and I found that some entries in this table use InvDstClr
/InvSrcClr
even though they're not actually available. I'm not sure exactly what to do here, but the behavior here may be (and have been) wrong.
Cursor m_blank_cursor = None; | ||
Cursor m_blank_cursor = 0L; // None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is some jank due to me needing to undefine None
which X.h
defines to be 0L, since that define interferes with some enums. I'm not sure if there's a better workaround.
Note: As an example: https://bugs.dolphin-emu.org/attachments/8076/nes%20nekkotsu.dff |
More specifically it plays correctly the first time, but after stopping playback, trying to play again or analyze the opened FIFO causes a crash. (I'm guessing that that's also what's breaking the radeon fifoci builder, since it's segfaulting, but I haven't confirmed). EDIT: The crash when analyzing the opened FIFO after stopping playback also happens on 5.0-13603, but I seem to have introduced the crash on playing again in this PR in 650b236. |
548f70c
to
d67ca33
Compare
ASSERT_MSG(VIDEO, FORMAT_UBYTE <= format && format <= FORMAT_FLOAT, | ||
"Invalid texture coordinates format!\n(format = %d)", format); | ||
ASSERT_MSG(VIDEO, 0 <= elements && elements <= 1, | ||
"Invalid number of texture coordinates elements!\n(elements = %d)", elements); | ||
ASSERT_MSG(VIDEO, ComponentFormat::UByte <= format && format <= ComponentFormat::Float, | ||
"Invalid texture coordinates format!\n(format = %d)", (u32)format); | ||
ASSERT_MSG(VIDEO, elements == TexComponentCount::S || elements == TexComponentCount::ST, | ||
"Invalid number of texture coordinates elements!\n(elements = %d)", (u32)elements); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note the (u32)format
here; ideally I'd just let the enum formatter handle this, but there doesn't seem to be an fmt equivalent of ASSERT_MSG.
9b01626
to
a23b638
Compare
I've fixed a typo that was causing rendering differences (044b078), including slightly different rendering in Need For Speed: Underground (JMC confirmed that the blue windows are what show up on hardware, even though they do look somewhat worse). I've also rebased to the latest master, which includes #9501, so FifoCI should run properly now. I've also fixed the crashes with the fifo player. One (which triggered on playing back a fifolog a second time) was introduced in 17186b0, and fixed in a127320 by fixing a few places where I didn't update to |
267ee7f
to
7b3a289
Compare
I've created a new I've also changed the fifo player window to be a separate window (that can be maximized and doesn't cause the main window to cover the render window), and done a bit more What remains before I mark this ready for review is fixing the most recent compile errors and fifoci regressions, and then rebasing everything so that it's in a more sane series of commits where each builds and the changes are specific and complete (so that the massive diff isn't as much of an issue). |
c915a69
to
e4bda20
Compare
@@ -489,13 +489,15 @@ bool CullTest(const OutputVertexData* v0, const OutputVertexData* v1, const Outp | |||
|
|||
backface = normalZDir <= 0.0f; | |||
|
|||
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing | |||
if ((bpmem.genMode.cullmode == CullMode::Back || bpmem.genMode.cullmode == CullMode::All) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These enum choices are odd with the comment. Just checking to make sure that's intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mask is correct (1 is back, 2 is front, 3 is all), but the behavior seems odd to me. YAGCD says that the bit is for what should be rejected (REJECT_EN in GEN_MODE near §5.11.1). It's possible that the software renderer's definition of backface is reversed from the hardware renderer's, which was canceled out here. (The changes needed for #9350 were less than I expected at least).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a TODO comment for this; it might be an inconsistency with the software renderer but probably shouldn't be addressed here.
@@ -367,21 +367,21 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config, | |||
"// which are common to both color and alpha channels\n" | |||
"bool tevCompare(uint op, int3 color_A, int3 color_B) {{\n" | |||
" switch (op) {{\n" | |||
" case 0u: // TEVCMP_R8_GT\n" | |||
" case 0u: // TevCompareMode::R8, TevComparison::GT\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surprised these aren't using the case {:s}:\n
trick
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's because there are two enums, instead of one pseudo-enum/set of random values that don't really make sense. The values were previously these (note how they don't match what's in the switch statement):
TEVCMP_R8_GT = 8,
TEVCMP_R8_EQ = 9,
TEVCMP_GR16_GT = 10,
TEVCMP_GR16_EQ = 11,
TEVCMP_BGR24_GT = 12,
TEVCMP_BGR24_EQ = 13,
TEVCMP_RGB8_GT = 14,
TEVCMP_RGB8_EQ = 15,
TEVCMP_A8_GT = TEVCMP_RGB8_GT,
TEVCMP_A8_EQ = TEVCMP_RGB8_EQ
and the enum was used by ((cc.shift << 1) | cc.op | 8)
. I decided to just split it up into two enums; for the software renderer I was able to split it into two parts (acting on cc.compare
and then looking at whether it was using eq or gt), but for the hardware backends I left it in the combined form since it would require further restructuring for no real gain.
It does look like there are other switch statements in this file that hardcode enum values, though; those could be changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the binary search tree structure used for the other enums (in addition to the switch statements), I've decided not to deal with the hardcoded enum values in this PR; it can be handled in a later one.
2d3771d
to
53bd7ac
Compare
Additionally, VCacheEnhance has been added to UVAT_group1. According to YAGCD, this field is always 1. TVtxDesc also now has separate low and high fields whose hex values correspond with the proper registers, instead of having one 33-bit value. This change was made in a way that should be backwards-compatible.
Additionally a new ClipDisable union has been added (though it is not currently used by Dolphin).
This value will be used in the register description; so expose it in a way that can be re-used instead of calculating it in 2 places later.
Additional changes: - For TevStageCombiner's ColorCombiner and AlphaCombiner, op/comparison and scale/compare_mode have been split as there are different meanings and enums if bias is set to compare. (Shift has also been renamed to scale) - In TexMode0, min_filter has been split into min_mip and min_filter. - In TexImage1, image_type is now cache_manually_managed. - The unused bit in GenMode is now exposed. - LPSize's lineaspect is now named adjust_for_aspect_ratio.
BPMEM_TEV_COLOR_ENV + 6 (0xC6) was missing due to a typo. BPMEM_BP_MASK (0xFE) does not lend itself well to documentation with the current FIFO analyzer implementation (since it requires remembering the values in BP memory) but still shouldn't be treated as unknown. BPMEM_TX_SETMODE0_4 and BPMEM_TX_SETMODE1_4 (0xA4-0xAB) were missing entirely.
53bd7ac
to
df81210
Compare
The big thing here is names and detailed descriptions for most XF, BP, and CP registers, and the names being shown in the overview, along with refactoring of the graphics code to use
BitField
andenum class
.Additionally, the way the frame and object ranges work has been tweaked to be inclusive (for frames) and not require selecting 2 objects.For the most part, I've done the descriptions by creating custom
fmt::formatter
s, and then usingfmt::format
orfmt::to_string
on the objects. I construct the objects to print using e.g.LitChannel{.hex = value}
(since most of them do not have constructors). For enums, I've also introduced a newEnumFormatter
that makes it easy to createfmt::formatter
s for the enums (including clean handling of invalid values). I also tried to expand most of the abbreviations, but I may have done some of them wrong. There may be typos or other mistakes in the results.Screenshots
Two things that I'd like to do that I haven't included here: 1, Show state changes before the draw instead of after (see the unintuitive warning in the wiki), and 2, make the FIFO player a separate window that can be shown over the render window (currently, at least on Windows, the main dolphin window will always show up behind the FIFO player, blocking the render window).Further changes to the FIFO analyzer itself are found in #9540, which has a weak dependency on this PR.