Initialize Maxwell3D Registers Correctly

Maxwell3D Registers weren't initialized to the correct values prior, this commit fixes that by doing `HandleMethod` calls with all the register values being initialized. This is in contrast to the registers being set without calling the methods in `GraphicsContext` or otherwise resulting in bugs.
This commit is contained in:
PixelyIon 2021-11-12 14:24:43 +05:30
parent ea87b8878c
commit 49cc0964e2
4 changed files with 1362 additions and 71 deletions

View File

@ -149,6 +149,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/soc/gm20b/engines/gpfifo.cpp
${source_DIR}/skyline/soc/gm20b/engines/maxwell_3d.cpp
${source_DIR}/skyline/soc/gm20b/engines/maxwell/macro_interpreter.cpp
${source_DIR}/skyline/soc/gm20b/engines/maxwell/initialization.cpp
${source_DIR}/skyline/input/npad.cpp
${source_DIR}/skyline/input/npad_device.cpp
${source_DIR}/skyline/input/touch.cpp

File diff suppressed because it is too large Load Diff

View File

@ -3,79 +3,15 @@
// Copyright © 2018-2020 fincs (https://github.com/devkitPro/deko3d)
#include <boost/preprocessor/repeat.hpp>
#include "maxwell_3d.h"
#include <soc.h>
#include "maxwell_3d.h"
namespace skyline::soc::gm20b::engine::maxwell3d {
Maxwell3D::Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, gpu::interconnect::CommandExecutor &executor) : Engine(state), macroInterpreter(*this), context(*state.gpu, channelCtx, executor), channelCtx(channelCtx) {
ResetRegs();
InitializeRegisters();
}
void Maxwell3D::ResetRegs() {
registers = {};
registers.rasterizerEnable = true;
for (auto &transform : *registers.viewportTransforms) {
transform.swizzles.x = type::ViewportTransform::Swizzle::PositiveX;
transform.swizzles.y = type::ViewportTransform::Swizzle::PositiveY;
transform.swizzles.z = type::ViewportTransform::Swizzle::PositiveZ;
transform.swizzles.w = type::ViewportTransform::Swizzle::PositiveW;
}
for (auto &viewport : *registers.viewports) {
viewport.depthRangeFar = 1.0f;
viewport.depthRangeNear = 0.0f;
}
registers.polygonMode->front = type::PolygonMode::Fill;
registers.polygonMode->back = type::PolygonMode::Fill;
registers.stencilFront->failOp = registers.stencilFront->zFailOp = registers.stencilFront->zPassOp = type::StencilOp::Keep;
registers.stencilFront->compare.op = type::CompareOp::Always;
registers.stencilFront->compare.mask = 0xFFFFFFFF;
registers.stencilFront->writeMask = 0xFFFFFFFF;
registers.stencilTwoSideEnable = true;
registers.stencilBack->failOp = registers.stencilBack->zFailOp = registers.stencilBack->zPassOp = type::StencilOp::Keep;
registers.stencilBack->compareOp = type::CompareOp::Always;
registers.stencilBackExtra->compareMask = 0xFFFFFFFF;
registers.stencilBackExtra->writeMask = 0xFFFFFFFF;
registers.rtSeparateFragData = true;
for (auto &attribute : *registers.vertexAttributeState)
attribute.fixed = true;
registers.depthTestFunc = type::CompareOp::Always;
registers.blendState->colorOp = registers.blendState->alphaOp = type::Blend::Op::Add;
registers.blendState->colorSrcFactor = registers.blendState->alphaSrcFactor = type::Blend::Factor::One;
registers.blendState->colorDestFactor = registers.blendState->alphaDestFactor = type::Blend::Factor::Zero;
registers.lineWidthSmooth = 1.0f;
registers.lineWidthAliased = 1.0f;
registers.pointSpriteEnable = true;
registers.pointSpriteSize = 1.0f;
registers.pointCoordReplace->enable = true;
registers.frontFace = type::FrontFace::CounterClockwise;
registers.cullFace = type::CullFace::Back;
for (auto &mask : *registers.colorMask)
mask.r = mask.g = mask.b = mask.a = 1;
for (auto &blend : *registers.independentBlend) {
blend.colorOp = blend.alphaOp = type::Blend::Op::Add;
blend.colorSrcFactor = blend.alphaSrcFactor = type::Blend::Factor::One;
blend.colorDestFactor = blend.alphaDestFactor = type::Blend::Factor::Zero;
}
registers.viewportTransformEnable = true;
}
void Maxwell3D::CallMethod(u32 method, u32 argument, bool lastCall) {
__attribute__((always_inline)) void Maxwell3D::CallMethod(u32 method, u32 argument, bool lastCall) {
Logger::Debug("Called method in Maxwell 3D: 0x{:X} args: 0x{:X}", method, argument);
// Methods that are greater than the register size are for macro control
@ -105,6 +41,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
return;
}
HandleMethod(method, argument, true);
}
void Maxwell3D::HandleMethod(u32 method, u32 argument, bool redundantCheck) {
#define MAXWELL3D_OFFSET(field) (sizeof(typeof(Registers::field)) - sizeof(typeof(*Registers::field))) / sizeof(u32)
#define MAXWELL3D_STRUCT_OFFSET(field, member) MAXWELL3D_OFFSET(field) + U32_OFFSET(typeof(*Registers::field), member)
#define MAXWELL3D_ARRAY_OFFSET(field, index) MAXWELL3D_OFFSET(field) + ((sizeof(typeof(Registers::field[0])) / sizeof(u32)) * index)
@ -133,7 +73,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
argument = shadowRegisters.raw[method];
}
bool redundant{registers.raw[method] == argument};
bool redundant{redundantCheck && registers.raw[method] == argument};
registers.raw[method] = argument;
if (!redundant) {

View File

@ -29,6 +29,11 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
gpu::interconnect::GraphicsContext context;
/**
* @brief Calls the appropriate function corresponding to a certain method with the supplied argument
*/
void HandleMethod(u32 method, u32 argument, bool redundantCheck = false);
/**
* @brief Writes back a semaphore result to the guest with an auto-generated timestamp (if required)
* @note If the semaphore is OneWord then the result will be downcasted to a 32-bit unsigned integer
@ -233,10 +238,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, gpu::interconnect::CommandExecutor &executor);
/**
* @brief Resets the Maxwell 3D registers to their default values
* @brief Initializes Maxwell 3D registers to their default values
*/
void ResetRegs();
void InitializeRegisters();
void CallMethod(u32 method, u32 argument, bool lastCall);
void CallMethod(u32 method, u32 argument, bool lastCall = false);
};
}