mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-28 10:15:28 +03:00
Implement Maxwell3D Viewport Y Swizzle & Lower-Left Origin
This commit is contained in:
parent
3be30e68c3
commit
40a3887695
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
})
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user