Fix non-indexed quad draws

Certain non-indexed quad draws would mistakenly take the indexed quad path because of the assumption that they would not have a bound index buffer. This resulted in a crash for most games using quads due to a faulty exception `Indexed quad conversion is not supported`, when in fact they were not using indexed quads.

Co-authored-by: PixelyIon <pixelyion@protonmail.com>
Co-authored-by: Billy Laws <blaws05@gmail.com>
This commit is contained in:
lynxnb 2022-06-23 00:14:58 +02:00
parent 8fc3bc75f4
commit e6cfdeb06a

View File

@ -1687,7 +1687,7 @@ namespace skyline::gpu::interconnect {
* @brief Retrieves an index buffer for converting a non-indexed quad list to a triangle list * @brief Retrieves an index buffer for converting a non-indexed quad list to a triangle list
* @result A tuple containing a view over the index buffer, the index type and the index count * @result A tuple containing a view over the index buffer, the index type and the index count
*/ */
std::tuple<BufferView, vk::IndexType, u32> GetQuadListConversionBuffer(u32 count) { std::tuple<BufferView, vk::IndexType, u32> GetNonIndexedQuadConversionBuffer(u32 count) {
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, vk::IndexType::eUint32)}; vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, vk::IndexType::eUint32)};
if (!quadListConversionBuffer || quadListConversionBuffer->GetBackingSpan().size_bytes() < size) { if (!quadListConversionBuffer || quadListConversionBuffer->GetBackingSpan().size_bytes() < size) {
quadListConversionBuffer = std::make_shared<Buffer>(gpu, size); quadListConversionBuffer = std::make_shared<Buffer>(gpu, size);
@ -2820,24 +2820,16 @@ namespace skyline::gpu::interconnect {
vk::IndexType type{}; vk::IndexType type{};
}; };
auto boundIndexBuffer{std::make_shared<BoundIndexBuffer>()}; std::shared_ptr<BoundIndexBuffer> boundIndexBuffer{};
if constexpr (IsIndexed) { if constexpr (IsIndexed) {
if (needsQuadConversion)
throw exception("Indexed quad conversion is not supported");
auto indexBufferView{GetIndexBuffer(count)}; auto indexBufferView{GetIndexBuffer(count)};
if (needsQuadConversion) {
if (indexBufferView) {
throw exception("Indexed quad conversion is not supported");
} else {
auto[bufferView, indexType, indexCount] = GetQuadListConversionBuffer(count);
indexBufferView = bufferView;
indexBuffer.type = indexType;
count = indexCount;
}
}
{
std::scoped_lock lock(indexBufferView); std::scoped_lock lock(indexBufferView);
boundIndexBuffer = std::make_shared<BoundIndexBuffer>();
boundIndexBuffer->type = indexBuffer.type; boundIndexBuffer->type = indexBuffer.type;
if (auto megaBufferOffset{indexBufferView.AcquireMegaBuffer(executor.megaBuffer)}) { if (auto megaBufferOffset{indexBufferView.AcquireMegaBuffer(executor.megaBuffer)}) {
// If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage // If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage
@ -2851,7 +2843,16 @@ namespace skyline::gpu::interconnect {
} }
executor.AttachBuffer(indexBufferView); executor.AttachBuffer(indexBufferView);
} } else if (needsQuadConversion) {
// Convert the guest-supplied quad list to an indexed triangle list
auto[bufferView, indexType, indexCount] = GetNonIndexedQuadConversionBuffer(count);
std::scoped_lock lock(bufferView);
count = indexCount;
boundIndexBuffer = std::make_shared<BoundIndexBuffer>();
boundIndexBuffer->type = indexType;
boundIndexBuffer->handle = bufferView->buffer->GetBacking();
boundIndexBuffer->offset = bufferView->view->offset;
executor.AttachBuffer(bufferView);
} }
// Vertex Buffer Setup // Vertex Buffer Setup
@ -3003,7 +3004,7 @@ namespace skyline::gpu::interconnect {
commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
if constexpr (IsIndexed) { if (IsIndexed || boundIndexBuffer) {
commandBuffer.bindIndexBuffer(boundIndexBuffer->handle, boundIndexBuffer->offset, boundIndexBuffer->type); commandBuffer.bindIndexBuffer(boundIndexBuffer->handle, boundIndexBuffer->offset, boundIndexBuffer->type);
commandBuffer.drawIndexed(count, instanceCount, first, vertexOffset, 0); commandBuffer.drawIndexed(count, instanceCount, first, vertexOffset, 0);
} else { } else {
@ -3015,9 +3016,6 @@ namespace skyline::gpu::interconnect {
} }
void Draw(u32 vertexCount, u32 firstVertex, u32 instanceCount) { void Draw(u32 vertexCount, u32 firstVertex, u32 instanceCount) {
if (needsQuadConversion)
Draw<true>(vertexCount, firstVertex, instanceCount);
else
Draw<false>(vertexCount, firstVertex, instanceCount); Draw<false>(vertexCount, firstVertex, instanceCount);
} }