Implement Maxwell3D Viewport Y Swizzle & Lower-Left Origin

This commit is contained in:
PixelyIon 2022-01-22 03:04:49 +05:30
parent 3be30e68c3
commit 40a3887695
4 changed files with 61 additions and 2 deletions

View File

@ -365,6 +365,8 @@ namespace skyline::gpu::interconnect {
/* Viewport */
private:
bool viewportOriginLowerLeft{}; //!< If the viewport origin follows the lower left convention (OpenGL) as opposed to upper left (Vulkan/Direct3D)
std::array<bool, maxwell3d::ViewportCount> viewportsFlipY{}; //!< If the Y axis of a viewport has been flipped via a viewport swizzle
std::array<vk::Viewport, maxwell3d::ViewportCount> viewports;
std::array<vk::Rect2D, maxwell3d::ViewportCount> scissors; //!< The scissors applied to viewports/render targets for masking writes during draws or clears
constexpr static vk::Rect2D DefaultScissor{
@ -387,6 +389,11 @@ namespace skyline::gpu::interconnect {
auto &viewport{viewports.at(index)};
viewport.y = translate - scale; // Counteract the addition of the half of the height (p_y/2 is center) to the host translation (o_y)
viewport.height = scale * 2.0f; // Counteract the division of the height (p_y) by 2 for the host scale
if (viewportOriginLowerLeft ^ viewportsFlipY[index]) {
// Flip the viewport given that the viewport origin is lower left or the viewport Y has been flipped via a swizzle but not if both are active at the same time
viewport.y += viewport.height;
viewport.height = -viewport.height;
}
}
void SetViewportZ(size_t index, float scale, float translate) {
@ -395,6 +402,33 @@ namespace skyline::gpu::interconnect {
viewport.maxDepth = scale + translate; // Counteract the subtraction of the maxDepth (p_z - o_z) by minDepth (o_z) for the host scale
}
void SetViewportSwizzle(size_t index, maxwell3d::ViewportTransform::Swizzle x, maxwell3d::ViewportTransform::Swizzle y, maxwell3d::ViewportTransform::Swizzle z, maxwell3d::ViewportTransform::Swizzle w) {
using Swizzle = maxwell3d::ViewportTransform::Swizzle;
if (x != Swizzle::PositiveX && y != Swizzle::PositiveY && y != Swizzle::NegativeY && z != Swizzle::PositiveZ && w != Swizzle::PositiveW)
throw exception("Unsupported viewport swizzle: {}x{}x{}", maxwell3d::ViewportTransform::ToString(x), maxwell3d::ViewportTransform::ToString(y), maxwell3d::ViewportTransform::ToString(z));
bool shouldFlipY{y == Swizzle::NegativeY};
auto &viewportFlipY{viewportsFlipY[index]};
if (viewportFlipY != shouldFlipY) {
auto &viewport{viewports[index]};
viewport.y += viewport.height;
viewport.height = -viewport.height;
viewportFlipY = shouldFlipY;
}
}
void SetViewportOrigin(bool isLowerLeft) {
if (viewportOriginLowerLeft != isLowerLeft) {
for (auto &viewport : viewports) {
viewport.y += viewport.height;
viewport.height = -viewport.height;
}
viewportOriginLowerLeft = isLowerLeft;
}
}
void SetScissor(size_t index, std::optional<maxwell3d::Scissor> scissor) {
scissors.at(index) = scissor ? vk::Rect2D{
.offset.x = scissor->horizontal.minimum,

View File

@ -176,7 +176,18 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
NegativeW = 7,
};
struct {
ENUM_STRING(Swizzle, {
ENUM_CASE_PAIR(PositiveX, "+X");
ENUM_CASE_PAIR(NegativeX, "-X");
ENUM_CASE_PAIR(PositiveY, "+Y");
ENUM_CASE_PAIR(NegativeY, "-Y");
ENUM_CASE_PAIR(PositiveZ, "+Z");
ENUM_CASE_PAIR(NegativeZ, "-Z");
ENUM_CASE_PAIR(PositiveW, "+W");
ENUM_CASE_PAIR(NegativeW, "-W");
})
struct Swizzles {
Swizzle x : 3;
u8 _pad0_ : 1;
Swizzle y : 3;

View File

@ -132,7 +132,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
context.SetDepthRenderTargetArrayMode(depthTargetArrayMode);
})
#define VIEWPORT_TRANSFORM_CALLBACKS(z, index, data) \
#define VIEWPORT_TRANSFORM_CALLBACKS(_z, index, data) \
MAXWELL3D_ARRAY_STRUCT_CASE(viewportTransforms, index, scaleX, { \
context.SetViewportX(index, scaleX, registers.viewportTransforms[index].translateX); \
}) \
@ -150,6 +150,9 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(viewportTransforms, index, translateZ, { \
context.SetViewportZ(index, registers.viewportTransforms[index].scaleZ, translateZ); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(viewportTransforms, index, swizzles, { \
context.SetViewportSwizzle(index, swizzles.x, swizzles.y, swizzles.z, swizzles.w); \
})
BOOST_PP_REPEAT(16, VIEWPORT_TRANSFORM_CALLBACKS, 0)
@ -303,6 +306,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
context.SetStencilBackWriteMask(writeMask);
})
MAXWELL3D_CASE(windowOriginMode, {
context.SetViewportOrigin(windowOriginMode.isOriginLowerLeft);
})
MAXWELL3D_CASE(independentBlendEnable, {
context.SetIndependentBlendingEnabled(independentBlendEnable);
})

View File

@ -166,6 +166,13 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
};
Register<0x4E1, StencilFront> stencilFront;
struct WindowOriginMode {
bool isOriginLowerLeft : 1;
u8 _pad_ : 3;
bool flipFrontFace : 1;
};
Register<0x4EB, WindowOriginMode> windowOriginMode;
Register<0x4EC, float> lineWidthSmooth;
Register<0x4ED, float> lineWidthAliased;