From 38119e21d4d310a7261c94b752f7c54af980c37c Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Wed, 17 Nov 2021 16:58:03 +0530 Subject: [PATCH] Implement Vulkan-Supported Maxwell3D Primitive Topologies Any primitive topologies that are directly supported by Vulkan were implemented but the rest were not and will be implemented with conversions as they are used by applications, they are: * LineLoop * QuadList * QuadStrip * Polygon --- .../gpu/interconnect/graphics_context.h | 39 +++++++++++++-- .../skyline/soc/gm20b/engines/maxwell/types.h | 47 +++++++++++++++++++ .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 4 ++ .../skyline/soc/gm20b/engines/maxwell_3d.h | 3 ++ 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index 607ae665..72c9c64f 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -829,7 +829,7 @@ namespace skyline::gpu::interconnect { if (size == Size::e0 || type == Type::None) return vk::Format::eUndefined; - switch(size | type) { + switch (size | type) { // @fmt:off /* 8-bit components */ @@ -930,15 +930,48 @@ namespace skyline::gpu::interconnect { // @fmt:on default: - throw exception("Unimplemented Vertex Buffer Format: {} | {}", maxwell3d::VertexAttribute::ToString(size), maxwell3d::VertexAttribute::ToString(type)); + throw exception("Unimplemented Maxwell3D Vertex Buffer Format: {} | {}", maxwell3d::VertexAttribute::ToString(size), maxwell3d::VertexAttribute::ToString(type)); } } void SetVertexAttributeState(u32 index, maxwell3d::VertexAttribute attribute) { - auto& vkAttributes{vertexAttributes[index]}; + auto &vkAttributes{vertexAttributes[index]}; vkAttributes.binding = attribute.bufferId; vkAttributes.format = ConvertVertexBufferFormat(attribute.type, attribute.elementSize); vkAttributes.offset = attribute.offset; } + + /* Input Assembly */ + private: + vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState{}; + + public: + void SetPrimitiveTopology(maxwell3d::PrimitiveTopology topology) { + inputAssemblyState.topology = [topology]() { + switch (topology) { + // @fmt:off + + case maxwell3d::PrimitiveTopology::PointList: return vk::PrimitiveTopology::ePointList; + + case maxwell3d::PrimitiveTopology::LineList: return vk::PrimitiveTopology::eLineList; + case maxwell3d::PrimitiveTopology::LineListWithAdjacency: return vk::PrimitiveTopology::eLineListWithAdjacency; + case maxwell3d::PrimitiveTopology::LineStrip: return vk::PrimitiveTopology::eLineStrip; + case maxwell3d::PrimitiveTopology::LineStripWithAdjacency: return vk::PrimitiveTopology::eLineStripWithAdjacency; + + case maxwell3d::PrimitiveTopology::TriangleList: return vk::PrimitiveTopology::eTriangleList; + case maxwell3d::PrimitiveTopology::TriangleListWithAdjacency: return vk::PrimitiveTopology::eTriangleListWithAdjacency; + case maxwell3d::PrimitiveTopology::TriangleStrip: return vk::PrimitiveTopology::eTriangleStrip; + case maxwell3d::PrimitiveTopology::TriangleStripWithAdjacency: return vk::PrimitiveTopology::eTriangleStripWithAdjacency; + case maxwell3d::PrimitiveTopology::TriangleFan: return vk::PrimitiveTopology::eTriangleFan; + + case maxwell3d::PrimitiveTopology::PatchList: return vk::PrimitiveTopology::ePatchList; + + // @fmt:on + + default: + throw exception("Unimplemented Maxwell3D Primitive Topology: {}", maxwell3d::ToString(topology)); + } + }(); + } }; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h index 4e3b07e6..734f3911 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h @@ -428,6 +428,53 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { }; static_assert(sizeof(PointCoordReplace) == sizeof(u32)); + enum class PrimitiveTopology : u16 { + PointList = 0, + LineList = 1, + LineLoop = 2, + LineStrip = 3, + TriangleList = 4, + TriangleStrip = 5, + TriangleFan = 6, + QuadList = 7, + QuadStrip = 8, + Polygon = 9, + LineListWithAdjacency = 10, + LineStripWithAdjacency = 11, + TriangleListWithAdjacency = 12, + TriangleStripWithAdjacency = 13, + PatchList = 14, + }; + + ENUM_STRING(PrimitiveTopology, { + ENUM_CASE(PointList); + ENUM_CASE(LineList); + ENUM_CASE(LineLoop); + ENUM_CASE(LineStrip); + ENUM_CASE(TriangleList); + ENUM_CASE(TriangleStrip); + ENUM_CASE(TriangleFan); + ENUM_CASE(QuadList); + ENUM_CASE(QuadStrip); + ENUM_CASE(Polygon); + ENUM_CASE(LineListWithAdjacency); + ENUM_CASE(LineStripWithAdjacency); + ENUM_CASE(TriangleListWithAdjacency); + ENUM_CASE(TriangleStripWithAdjacency); + ENUM_CASE(PatchList); + }) + + union VertexBeginGl { + u32 raw; + struct { + PrimitiveTopology topology; + u16 pad : 12; + bool instanceNext : 1; + bool instanceContinue : 1; + }; + }; + static_assert(sizeof(VertexBeginGl) == sizeof(u32)); + enum class FrontFace : u32 { Clockwise = 0x900, CounterClockwise = 0x901, diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp index d5b36064..c0592f54 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp @@ -393,6 +393,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d { static_assert(type::StageCount == 6 && type::StageCount < BOOST_PP_LIMIT_REPEAT); #undef SET_SHADER_ENABLE_CALLBACK + MAXWELL3D_CASE(vertexBeginGl, { + context.SetPrimitiveTopology(vertexBeginGl.topology); + }) + default: break; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h index c65ac30d..a940aba3 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h @@ -202,6 +202,9 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x581, type::PointCoordReplace> pointCoordReplace; Register<0x582, type::Address> setProgramRegion; + Register<0x586, u32> vertexEndGl; //!< Method-only register with no real value, used after calling vertexBeginGl and draws are complete + Register<0x586, type::VertexBeginGl> vertexBeginGl; //!< Similar to glVertexBegin semantically, supplies a primitive topology for draws alongside instancing data + Register<0x5A1, u32> provokingVertexIsLast; Register<0x61F, float> depthBiasClamp;