mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-28 09:35:29 +03:00
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:
parent
8fc3bc75f4
commit
e6cfdeb06a
@ -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,38 +2820,39 @@ 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) {
|
std::scoped_lock lock(indexBufferView);
|
||||||
if (indexBufferView) {
|
|
||||||
throw exception("Indexed quad conversion is not supported");
|
boundIndexBuffer = std::make_shared<BoundIndexBuffer>();
|
||||||
} else {
|
boundIndexBuffer->type = indexBuffer.type;
|
||||||
auto[bufferView, indexType, indexCount] = GetQuadListConversionBuffer(count);
|
if (auto megaBufferOffset{indexBufferView.AcquireMegaBuffer(executor.megaBuffer)}) {
|
||||||
indexBufferView = bufferView;
|
// 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
|
||||||
indexBuffer.type = indexType;
|
boundIndexBuffer->handle = executor.megaBuffer.GetBacking();
|
||||||
count = indexCount;
|
boundIndexBuffer->offset = megaBufferOffset;
|
||||||
}
|
} else {
|
||||||
|
indexBufferView.RegisterUsage(executor.cycle, [=](const Buffer::BufferViewStorage &view, const std::shared_ptr<Buffer> &buffer) {
|
||||||
|
boundIndexBuffer->handle = buffer->GetBacking();
|
||||||
|
boundIndexBuffer->offset = view.offset;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
executor.AttachBuffer(indexBufferView);
|
||||||
std::scoped_lock lock(indexBufferView);
|
} else if (needsQuadConversion) {
|
||||||
|
// Convert the guest-supplied quad list to an indexed triangle list
|
||||||
boundIndexBuffer->type = indexBuffer.type;
|
auto[bufferView, indexType, indexCount] = GetNonIndexedQuadConversionBuffer(count);
|
||||||
if (auto megaBufferOffset{indexBufferView.AcquireMegaBuffer(executor.megaBuffer)}) {
|
std::scoped_lock lock(bufferView);
|
||||||
// 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
|
count = indexCount;
|
||||||
boundIndexBuffer->handle = executor.megaBuffer.GetBacking();
|
boundIndexBuffer = std::make_shared<BoundIndexBuffer>();
|
||||||
boundIndexBuffer->offset = megaBufferOffset;
|
boundIndexBuffer->type = indexType;
|
||||||
} else {
|
boundIndexBuffer->handle = bufferView->buffer->GetBacking();
|
||||||
indexBufferView.RegisterUsage(executor.cycle, [=](const Buffer::BufferViewStorage &view, const std::shared_ptr<Buffer> &buffer) {
|
boundIndexBuffer->offset = bufferView->view->offset;
|
||||||
boundIndexBuffer->handle = buffer->GetBacking();
|
executor.AttachBuffer(bufferView);
|
||||||
boundIndexBuffer->offset = view.offset;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
executor.AttachBuffer(indexBufferView);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,10 +3016,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Draw(u32 vertexCount, u32 firstVertex, u32 instanceCount) {
|
void Draw(u32 vertexCount, u32 firstVertex, u32 instanceCount) {
|
||||||
if (needsQuadConversion)
|
Draw<false>(vertexCount, firstVertex, instanceCount);
|
||||||
Draw<true>(vertexCount, firstVertex, instanceCount);
|
|
||||||
else
|
|
||||||
Draw<false>(vertexCount, firstVertex, instanceCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawIndexed(u32 indexCount, u32 firstIndex, u32 instanceCount, i32 vertexOffset) {
|
void DrawIndexed(u32 indexCount, u32 firstIndex, u32 instanceCount, i32 vertexOffset) {
|
||||||
|
Loading…
Reference in New Issue
Block a user