Implement Maxwell3D Vertex Buffer Bindings

This implements everything in Maxwell3D vertex buffer bindings including vertex attribute divisors which require the extension `VK_EXT_vertex_attribute_divisor` to emulate them correctly, this has been implemented in the form of of a quirk. It is dynamically enabled/disabled based on if the host GPU supports it and a warning is provided when it is used by the guest but the host GPU doesn't support it.
This commit is contained in:
PixelyIon
2021-11-16 10:32:01 +05:30
parent d163e4ffa6
commit ff5515d4d1
6 changed files with 83 additions and 1 deletions

View File

@ -43,6 +43,18 @@ namespace skyline::gpu::interconnect {
public:
GraphicsContext(GPU &gpu, soc::gm20b::ChannelContext &channelCtx, gpu::interconnect::CommandExecutor &executor) : gpu(gpu), channelCtx(channelCtx), executor(executor) {
scissors.fill(DefaultScissor);
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<vk::PipelineVertexInputDivisorStateCreateInfoEXT>();
}
if (!gpu.quirks.supportsLastProvokingVertex)
rasterizerState.unlink<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>();
}
@ -751,5 +763,39 @@ namespace skyline::gpu::interconnect {
void SetColorBlendConstant(u32 index, float constant) {
blendState.blendConstants[index] = constant;
}
/* Vertex Buffers */
private:
std::array<IOVA, maxwell3d::VertexBufferCount> vertexBindingIovas{};
std::array<vk::VertexInputBindingDescription, maxwell3d::VertexBufferCount> vertexBindings{};
std::array<vk::VertexInputBindingDivisorDescriptionEXT, maxwell3d::VertexBufferCount> vertexBindingDivisors{};
vk::StructureChain<vk::PipelineVertexInputStateCreateInfo, vk::PipelineVertexInputDivisorStateCreateInfoEXT> vertexState{
vk::PipelineVertexInputStateCreateInfo{
.pVertexBindingDescriptions = vertexBindings.data(),
.vertexBindingDescriptionCount = maxwell3d::VertexBufferCount,
}, vk::PipelineVertexInputDivisorStateCreateInfoEXT{
.pVertexBindingDivisors = vertexBindingDivisors.data(),
.vertexBindingDivisorCount = maxwell3d::VertexBufferCount,
}
};
public:
void SetVertexBufferStride(u32 index, u32 stride) {
vertexBindings[index].stride = stride;
}
void SetVertexBufferIovaHigh(u32 index, u32 high) {
vertexBindingIovas[index].high = high;
}
void SetVertexBufferIovaLow(u32 index, u32 low) {
vertexBindingIovas[index].low = low;
}
void SetVertexBufferDivisor(u32 index, u32 divisor) {
if (!gpu.quirks.supportsVertexAttributeDivisor)
Logger::Warn("Cannot set vertex attribute divisor without host GPU support");
vertexBindingDivisors[index].divisor = divisor;
}
};
}

View File

@ -25,6 +25,7 @@ namespace skyline {
auto extensionVersion{extension.specVersion};
switch (util::Hash(extensionName)) {
EXT_SET("VK_EXT_provoking_vertex", supportsLastProvokingVertex);
EXT_SET("VK_EXT_vertex_attribute_divisor", supportsVertexAttributeDivisor);
}
#undef EXT_SET
@ -43,6 +44,6 @@ namespace skyline {
}
std::string QuirkManager::Summary() {
return fmt::format("\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}", supportsLastProvokingVertex, supportsLogicOp);
return fmt::format("\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}\n* Supports Vertex Attribute Divisor: {}", supportsLastProvokingVertex, supportsLogicOp, supportsVertexAttributeDivisor);
}
}

View File

@ -14,6 +14,7 @@ namespace skyline {
public:
bool supportsLastProvokingVertex{}; //!< If the device supports setting the last vertex as the provoking vertex (with VK_EXT_provoking_vertex)
bool supportsLogicOp{}; //!< If the device supports framebuffer logical operations during blending
bool supportsVertexAttributeDivisor{}; //!< If the device supports a divisor for instance-rate vertex attributes (with VK_EXT_vertex_attribute_divisor)
QuirkManager() = default;