From 23faf1370c165ec9a28ee44e454616987d2478eb Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Tue, 7 Dec 2021 00:48:33 +0530 Subject: [PATCH] Use Static Arrays for Vertex Buffer Bindings & Attributes We cannot statically construct the vertex buffer/attribute arrays for Vulkan due to inactive attributes or buffers which isn't possible on Vulkan, we also cannot just change the count dynamically as there might be disabled buffers or attributes in the middle. We just have a `static_array` which should dynamically be filled in with buffer binding/attribute Vulkan structures before submission. --- .../gpu/interconnect/graphics_context.h | 80 ++++++++++++------- 1 file changed, 51 insertions(+), 29 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 b27975cf..7cc7b12f 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -3,7 +3,9 @@ #pragma once +#include #include +#include #include #include #include @@ -49,19 +51,17 @@ namespace skyline::gpu::interconnect { } u32 bindingIndex{}; - for (auto &vertexBinding : vertexBindings) - vertexBinding.binding = bindingIndex++; - if (gpu.quirks.supportsVertexAttributeDivisor) { - bindingIndex = 0; - for (auto &vertexBindingDivisor : vertexBindingDivisors) - vertexBindingDivisor.binding = bindingIndex++; - } else { - vertexState.unlink(); + for (auto &vertexBuffer : vertexBuffers) { + vertexBuffer.bindingDescription.binding = bindingIndex; + vertexBuffer.bindingDivisorDescription.binding = bindingIndex; + bindingIndex++; } + if (!gpu.quirks.supportsVertexAttributeDivisor) + vertexState.unlink(); u32 attributeIndex{}; for (auto &vertexAttribute : vertexAttributes) - vertexAttribute.location = attributeIndex++; + vertexAttribute.description.location = attributeIndex++; if (!gpu.quirks.supportsLastProvokingVertex) rasterizerState.unlink(); @@ -776,47 +776,64 @@ namespace skyline::gpu::interconnect { /* Vertex Buffers */ private: struct VertexBuffer { + bool disabled{}; + vk::VertexInputBindingDescription bindingDescription{}; + vk::VertexInputBindingDivisorDescriptionEXT bindingDivisorDescription{}; IOVA start{}, end{}; //!< IOVAs covering a contiguous region in GPU AS with the vertex buffer + GuestBuffer guest; + std::shared_ptr view; }; std::array vertexBuffers{}; - std::array vertexBindings{}; - std::array vertexBindingDivisors{}; - std::array vertexAttributes{}; + boost::container::static_vector vertexBindingDescriptions{}; + boost::container::static_vector vertexBindingDivisorsDescriptions{}; + + struct VertexAttribute { + bool enabled{}; + vk::VertexInputAttributeDescription description; + }; + std::array vertexAttributes{}; + boost::container::static_vector vertexAttributesDescriptions{}; + vk::StructureChain vertexState{ vk::PipelineVertexInputStateCreateInfo{ - .pVertexBindingDescriptions = vertexBindings.data(), - .vertexBindingDescriptionCount = maxwell3d::VertexBufferCount, - .pVertexAttributeDescriptions = vertexAttributes.data(), - .vertexAttributeDescriptionCount = maxwell3d::VertexAttributeCount, + .pVertexBindingDescriptions = vertexBindingDescriptions.data(), + .pVertexAttributeDescriptions = vertexAttributesDescriptions.data(), }, vk::PipelineVertexInputDivisorStateCreateInfoEXT{ - .pVertexBindingDivisors = vertexBindingDivisors.data(), - .vertexBindingDivisorCount = maxwell3d::VertexBufferCount, + .pVertexBindingDivisors = vertexBindingDivisorsDescriptions.data(), } }; public: void SetVertexBufferStride(u32 index, u32 stride) { - vertexBindings[index].stride = stride; + vertexBuffers[index].bindingDescription.stride = stride; } void SetVertexBufferInputRate(u32 index, bool isPerInstance) { - vertexBindings[index].inputRate = isPerInstance ? vk::VertexInputRate::eInstance : vk::VertexInputRate::eVertex; + vertexBuffers[index].bindingDescription.inputRate = isPerInstance ? vk::VertexInputRate::eInstance : vk::VertexInputRate::eVertex; } void SetVertexBufferStartIovaHigh(u32 index, u32 high) { - vertexBuffers[index].start.high = high; + auto &vertexBuffer{vertexBuffers[index]}; + vertexBuffer.start.high = high; + vertexBuffer.view.reset(); } void SetVertexBufferStartIovaLow(u32 index, u32 low) { - vertexBuffers[index].start.low = low; + auto &vertexBuffer{vertexBuffers[index]}; + vertexBuffer.start.low = low; + vertexBuffer.view.reset(); } void SetVertexBufferEndIovaHigh(u32 index, u32 high) { - vertexBuffers[index].end.high = high; + auto &vertexBuffer{vertexBuffers[index]}; + vertexBuffer.end.high = high; + vertexBuffer.view.reset(); } void SetVertexBufferEndIovaLow(u32 index, u32 low) { - vertexBuffers[index].end.low = low; + auto &vertexBuffer{vertexBuffers[index]}; + vertexBuffer.end.low = low; + vertexBuffer.view.reset(); } void SetVertexBufferDivisor(u32 index, u32 divisor) { @@ -824,7 +841,7 @@ namespace skyline::gpu::interconnect { Logger::Warn("Cannot set vertex attribute divisor without host GPU support"); else if (divisor == 0 && !gpu.quirks.supportsVertexAttributeZeroDivisor) Logger::Warn("Cannot set vertex attribute divisor to zero without host GPU support"); - vertexBindingDivisors[index].divisor = divisor; + vertexBuffers[index].bindingDivisorDescription.divisor = divisor; } vk::Format ConvertVertexBufferFormat(maxwell3d::VertexAttribute::ElementType type, maxwell3d::VertexAttribute::ElementSize size) { @@ -940,10 +957,15 @@ namespace skyline::gpu::interconnect { } void SetVertexAttributeState(u32 index, maxwell3d::VertexAttribute attribute) { - auto &vkAttributes{vertexAttributes[index]}; - vkAttributes.binding = attribute.bufferId; - vkAttributes.format = ConvertVertexBufferFormat(attribute.type, attribute.elementSize); - vkAttributes.offset = attribute.offset; + auto &vertexAttribute{vertexAttributes[index]}; + if (!attribute.isConstant) { + vertexAttribute.enabled = true; + vertexAttribute.description.binding = attribute.bufferId; + vertexAttribute.description.format = ConvertVertexBufferFormat(attribute.type, attribute.elementSize); + vertexAttribute.description.offset = attribute.offset; + } else { + vertexAttribute.enabled = false; + } } /* Input Assembly */