diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp index 46cb3de9..31992ee1 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp @@ -213,63 +213,23 @@ namespace skyline::gpu::interconnect::maxwell3d { } /* Vertex Input State */ + // TODO: check if better individually void VertexInputState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { - ranges::for_each(vertexStreamRegisters, [&](const auto ®s) { manager.Bind(handle, regs.format, regs.frequency); }); + ranges::for_each(vertexStreams, [&](const auto ®s) { manager.Bind(handle, regs.format, regs.frequency); }); auto bindFull{[&](const auto ®s) { manager.Bind(handle, regs); }}; - ranges::for_each(vertexStreamInstanceRegisters, bindFull); - ranges::for_each(vertexAttributesRegisters, bindFull); + ranges::for_each(vertexStreamInstance, bindFull); + ranges::for_each(vertexAttributes, bindFull); } - vk::StructureChain VertexInputState::Build(InterconnectContext &ctx, const EngineRegisters &engine) { - activeBindingDivisorDescs.clear(); - activeAttributeDescs.clear(); + VertexInputState::VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {} - for (size_t i{}; i < engine::VertexStreamCount; i++) { - if (bindingDescs[i].inputRate == vk::VertexInputRate::eInstance) { - if (!ctx.gpu.traits.supportsVertexAttributeDivisor) [[unlikely]] - Logger::Warn("Vertex attribute divisor used on guest without host support"); - else if (!ctx.gpu.traits.supportsVertexAttributeZeroDivisor && bindingDivisorDescs[i].divisor == 0) [[unlikely]] - Logger::Warn("Vertex attribute zero divisor used on guest without host support"); - else - activeBindingDivisorDescs.push_back(bindingDivisorDescs[i]); - } - } + void VertexInputState::Flush(Key &key) { + for (u32 i{}; i < engine::VertexStreamCount; i++) + key.SetVertexBinding(i, engine->vertexStreams[i], engine->vertexStreamInstance[i]); - // TODO: check shader inputs - for (size_t i{}; i < engine::VertexAttributeCount; i++) - if (engine.vertexAttributesRegisters[i].source == engine::VertexAttribute::Source::Active) - activeAttributeDescs.push_back(attributeDescs[i]); - - vk::StructureChain chain{ - vk::PipelineVertexInputStateCreateInfo{ - .vertexBindingDescriptionCount = static_cast(bindingDescs.size()), - .pVertexBindingDescriptions = bindingDescs.data(), - .vertexAttributeDescriptionCount = static_cast(activeAttributeDescs.size()), - .pVertexAttributeDescriptions = activeAttributeDescs.data(), - }, - vk::PipelineVertexInputDivisorStateCreateInfoEXT{ - .vertexBindingDivisorCount = static_cast(activeBindingDivisorDescs.size()), - .pVertexBindingDivisors = activeBindingDivisorDescs.data(), - }, - }; - - if (activeBindingDivisorDescs.empty()) - chain.unlink(); - - return chain; - } - - void VertexInputState::SetStride(u32 index, u32 stride) { - bindingDescs[index].stride = stride; - } - - void VertexInputState::SetInputRate(u32 index, engine::VertexStreamInstance instance) { - bindingDescs[index].inputRate = instance.isInstanced ? vk::VertexInputRate::eInstance : vk::VertexInputRate::eVertex; - } - - void VertexInputState::SetDivisor(u32 index, u32 divisor) { - bindingDivisorDescs[index].divisor = divisor; + for (u32 i{}; i < engine::VertexAttributeCount; i++) + key.vertexAttributes[i] = engine->vertexAttributes[i]; } static vk::Format ConvertVertexInputAttributeFormat(engine::VertexAttribute::ComponentBitWidths componentBitWidths, engine::VertexAttribute::NumericalType numericalType) { @@ -354,20 +314,6 @@ namespace skyline::gpu::interconnect::maxwell3d { return Shader::AttributeType::Disabled; } } - - void VertexInputState::SetAttribute(u32 index, engine::VertexAttribute attribute) { - auto &vkAttribute{attributeDescs[index]}; - if (attribute.source == engine::VertexAttribute::Source::Active) { - vkAttribute.binding = attribute.stream; - vkAttribute.format = ConvertVertexInputAttributeFormat(attribute.componentBitWidths, attribute.numericalType); - vkAttribute.offset = attribute.offset; - - - // UpdateRuntimeInformation(runtimeInfo.generic_input_types[index], ConvertShaderGenericInputType(attribute.numericalType), maxwell3d::PipelineStage::Vertex); - } else { - // UpdateRuntimeInformation(runtimeInfo.generic_input_types[index], Shader::AttributeType::Disabled, maxwell3d::PipelineStage::Vertex); - } - } /* Input Assembly State */ void InputAssemblyState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { @@ -830,13 +776,12 @@ namespace skyline::gpu::interconnect::maxwell3d { : engine{manager, dirtyHandle, engine}, colorRenderTargets{util::MergeInto, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT{})}, depthRenderTarget{manager, engine.depthRenderTargetRegisters}, + vertexInput{manager, engine.vertexInputRegisters}, rasterization{manager, engine.rasterizationRegisters}, depthStencil{manager, engine.depthStencilRegisters}, colorBlend{manager, engine.colorBlendRegisters} {} void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) { - Key key; - boost::container::static_vector colorAttachments; for (auto &colorRenderTarget : colorRenderTargets) if (auto view{colorRenderTarget.UpdateGet(ctx, key).view}; view) @@ -844,7 +789,7 @@ namespace skyline::gpu::interconnect::maxwell3d { TextureView *depthAttachment{depthRenderTarget.UpdateGet(ctx, key).view.get()}; - auto vertexInputState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)}; + vertexInput.Update(key); const auto &inputAssemblyState{directState.inputAssembly.Build()}; const auto &tessellationState{directState.tessellation.Build()}; const auto &rasterizationState{rasterization.UpdateGet().rasterizationState}; diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h index 9587c128..df7bc85c 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h @@ -14,7 +14,17 @@ namespace skyline::gpu::interconnect::maxwell3d { u8 ztFormat : 5; // ZtFormat - 0xA as u8 }; + struct VertexBinding { + u16 stride : 12; + bool instanced : 1; + bool enable : 1; + u8 _pad_ : 2; + u32 divisor; + }; + static_assert(sizeof(VertexBinding) == 0x8); + std::array ctFormats; //!< ColorTarget::Format as u8 + std::array vertexBindings; public: std::array vertexAttributes; @@ -26,6 +36,13 @@ namespace skyline::gpu::interconnect::maxwell3d { void SetZtFormat(engine::ZtFormat format) { ztFormat = static_cast(format) - static_cast(engine::ZtFormat::ZF32); } + + void SetVertexBinding(u32 index, engine::VertexStream stream, engine::VertexStreamInstance instance) { + vertexBindings[index].stride = stream.format.stride; + vertexBindings[index].instanced = instance.isInstanced; + vertexBindings[index].enable = stream.format.enable; + vertexBindings[index].divisor = stream.frequency; + } }; class ColorRenderTargetState : dirty::ManualDirty { @@ -73,39 +90,23 @@ namespace skyline::gpu::interconnect::maxwell3d { void Flush(InterconnectContext &ctx, Key &key); }; - struct VertexInputState { - private: - std::array bindingDescs{ - util::MergeInto(util::IncrementingT{}) - }; - std::array bindingDivisorDescs{ - util::MergeInto(util::IncrementingT{}) - }; - std::array attributeDescs{ - util::MergeInto(util::IncrementingT{}) - }; - - boost::container::static_vector activeBindingDivisorDescs; - boost::container::static_vector activeAttributeDescs; - + class VertexInputState : dirty::ManualDirty { public: struct EngineRegisters { - const std::array &vertexStreamRegisters; - const std::array &vertexStreamInstanceRegisters; - const std::array &vertexAttributesRegisters; + const std::array &vertexStreams; + const std::array &vertexStreamInstance; + const std::array &vertexAttributes; void DirtyBind(DirtyManager &manager, dirty::Handle handle) const; }; - vk::StructureChain Build(InterconnectContext &ctx, const EngineRegisters &engine); + private: + dirty::BoundSubresource engine; - void SetStride(u32 index, u32 stride); + public: + VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); - void SetInputRate(u32 index, engine::VertexStreamInstance instance); - - void SetDivisor(u32 index, u32 divisor); - - void SetAttribute(u32 index, engine::VertexAttribute attribute); + void Flush(Key &key); }; struct InputAssemblyState { @@ -158,7 +159,6 @@ namespace skyline::gpu::interconnect::maxwell3d { * @brief Holds pipeline state that is directly written by the engine code, without using dirty tracking */ struct DirectPipelineState { - VertexInputState vertexInput; InputAssemblyState inputAssembly; TessellationState tessellation; }; @@ -269,6 +269,7 @@ namespace skyline::gpu::interconnect::maxwell3d { std::array, engine::ColorTargetCount> colorRenderTargets; dirty::ManualDirtyState depthRenderTarget; + dirty::ManualDirtyState vertexInput; dirty::ManualDirtyState rasterization; dirty::ManualDirtyState depthStencil; dirty::ManualDirtyState colorBlend; 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 8056b3f4..d472a64b 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 @@ -153,31 +153,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d { dirtyManager.MarkDirty(method); switch (method) { - #define VERTEX_STREAM_CALLBACKS(z, idx, data) \ - ENGINE_ARRAY_STRUCT_CASE(vertexStreams, idx, format, { \ - interconnect.directState.vertexInput.SetStride(idx, format.stride); \ - }) \ - ENGINE_ARRAY_STRUCT_CASE(vertexStreams, idx, frequency, { \ - interconnect.directState.vertexInput.SetDivisor(idx, frequency); \ - }) \ - ENGINE_ARRAY_CASE(vertexStreamInstance, idx, { \ - interconnect.directState.vertexInput.SetInputRate(idx, vertexStreamInstance); \ - }) - - BOOST_PP_REPEAT(16, VERTEX_STREAM_CALLBACKS, 0) - static_assert(type::VertexStreamCount == 16 && type::VertexStreamCount < BOOST_PP_LIMIT_REPEAT); - #undef VERTEX_STREAM_CALLBACKS - - - #define VERTEX_ATTRIBUTE_CALLBACKS(z, idx, data) \ - ENGINE_ARRAY_CASE(vertexAttributes, idx, { \ - interconnect.directState.vertexInput.SetAttribute(idx, vertexAttributes); \ - }) - - BOOST_PP_REPEAT(16, VERTEX_ATTRIBUTE_CALLBACKS, 0) - static_assert(type::VertexAttributeCount == 32 && type::VertexAttributeCount < BOOST_PP_LIMIT_REPEAT); - #undef VERTEX_ATTRIBUTE_CALLBACKS - ENGINE_CASE(primitiveRestartEnable, { interconnect.directState.inputAssembly.SetPrimitiveRestart(primitiveRestartEnable != 0);