From ad989750fc042ae1b9813f1d6be11b4ff4e2dd8e Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Sat, 7 May 2022 03:22:21 +0530 Subject: [PATCH] Implement Maxwell3D Point Sprite Size Implements register state that corresponds to the size of a single point sprite in Maxwell 3D, this is emitted by the shader compiler in the preamble but needs to be only applied if the input topology is a point primitive and it is invalid to set the point size in any other case. --- .../gpu/interconnect/graphics_context.h | 19 +++++++++++++++++++ .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 4 ++++ 2 files changed, 23 insertions(+) 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 e180e6c5..c33b8aaa 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -1064,6 +1064,10 @@ namespace skyline::gpu::interconnect { if (!pipelineStage.enabled) continue; + auto fixedPointSize{runtimeInfo.fixed_state_point_size}; + if (fixedPointSize && pipelineStage.vkStage != vk::ShaderStageFlagBits::eVertex && pipelineStage.vkStage != vk::ShaderStageFlagBits::eGeometry) + runtimeInfo.fixed_state_point_size.reset(); // Only vertex/geometry stages are allowed to have a point size + if (pipelineStage.needsRecompile || bindings.unified != pipelineStage.bindingBase || pipelineStage.previousStageStores.mask != runtimeInfo.previous_stage_stores.mask) { pipelineStage.previousStageStores = runtimeInfo.previous_stage_stores; pipelineStage.bindingBase = bindings.unified; @@ -1071,6 +1075,8 @@ namespace skyline::gpu::interconnect { pipelineStage.bindingLast = bindings.unified; } + runtimeInfo.fixed_state_point_size = fixedPointSize; + auto &program{pipelineStage.program->program}; runtimeInfo.previous_stage_stores = program.info.stores; if (program.is_geometry_passthrough) @@ -1844,6 +1850,7 @@ namespace skyline::gpu::interconnect { /* Input Assembly */ private: vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState{}; + float pointSpriteSize{}; //!< The size of a point sprite to be defined in the shader void ValidatePrimitiveRestartState() { if (inputAssemblyState.primitiveRestartEnable) { @@ -1907,6 +1914,12 @@ namespace skyline::gpu::interconnect { inputAssemblyState.topology = vkTopology; needsQuadConversion = isQuad; + + if (shaderTopology == ShaderCompiler::InputTopology::Points) + UpdateRuntimeInformation(runtimeInfo.fixed_state_point_size, std::make_optional(pointSpriteSize), maxwell3d::PipelineStage::Vertex, maxwell3d::PipelineStage::Geometry); + else if (runtimeInfo.input_topology == ShaderCompiler::InputTopology::Points) + UpdateRuntimeInformation(runtimeInfo.fixed_state_point_size, std::optional{}, maxwell3d::PipelineStage::Vertex, maxwell3d::PipelineStage::Geometry); + UpdateRuntimeInformation(runtimeInfo.input_topology, shaderTopology, maxwell3d::PipelineStage::Geometry); } @@ -1914,6 +1927,12 @@ namespace skyline::gpu::interconnect { inputAssemblyState.primitiveRestartEnable = enable; } + void SetPointSpriteSize(float size) { + pointSpriteSize = size; + if (runtimeInfo.input_topology == ShaderCompiler::InputTopology::Points) + UpdateRuntimeInformation(runtimeInfo.fixed_state_point_size, std::make_optional(size), maxwell3d::PipelineStage::Vertex, maxwell3d::PipelineStage::Geometry); + } + /* Tessellation */ private: vk::PipelineTessellationStateCreateInfo tessellationState{}; 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 5bde3d22..88dd5733 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 @@ -101,6 +101,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d { static_assert(type::RenderTargetCount == 8 && type::RenderTargetCount < BOOST_PP_LIMIT_REPEAT); #undef RENDER_TARGET_ARRAY + ENGINE_CASE(pointSpriteSize, { + context.SetPointSpriteSize(pointSpriteSize); + }) + ENGINE_CASE(depthTargetEnable, { context.SetDepthRenderTargetEnabled(depthTargetEnable); })