mirror of
https://github.com/skyline-emu/skyline.git
synced 2025-01-01 10:15:29 +03:00
Fix quads index buffer conversion not accounting for first index
Unindexed quad draws were broken when multiple draw calls were done on the same vertex buffer, with a non-zero `first` index. Indexed quad draws also suffered from the same issue, but was never encountered in games. This commit fixes both cases by accounting for the `first` drawn index when generating conversion index buffers.
This commit is contained in:
parent
e316bf5877
commit
34bd16426c
@ -21,21 +21,10 @@ namespace skyline::gpu::interconnect::conversion::quads {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The minimum size (in bytes) required to store the quad index buffer of the given type after conversion
|
* @return The minimum size (in bytes) required to store the quad index buffer of the given type after conversion
|
||||||
* @param type The type of an element in the index buffer
|
* @param indexSize The size of an element in the index buffer in bytes
|
||||||
*/
|
*/
|
||||||
constexpr size_t GetRequiredBufferSize(u32 count, vk::IndexType type) {
|
constexpr size_t GetRequiredBufferSize(u32 count, size_t indexSize) {
|
||||||
return GetIndexCount(count) * [&]() -> size_t {
|
return GetIndexCount(count) * indexSize;
|
||||||
switch (type) {
|
|
||||||
case vk::IndexType::eUint32:
|
|
||||||
return sizeof(u32);
|
|
||||||
case vk::IndexType::eUint16:
|
|
||||||
return sizeof(u16);
|
|
||||||
case vk::IndexType::eUint8EXT:
|
|
||||||
return sizeof(u8);
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1722,19 +1722,25 @@ 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
|
* @return A tuple containing a view over the index buffer, the index type and the index count
|
||||||
*/
|
*/
|
||||||
std::tuple<BufferView, vk::IndexType, u32> GetNonIndexedQuadConversionBuffer(u32 count) {
|
std::tuple<BufferView, vk::IndexType, u32> GetNonIndexedQuadConversionBuffer(u32 count, u32 first) {
|
||||||
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, vk::IndexType::eUint32)};
|
size_t firstPos{conversion::quads::GetRequiredBufferSize(first, sizeof(u32))};
|
||||||
|
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, sizeof(u32)) + firstPos};
|
||||||
|
|
||||||
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);
|
||||||
conversion::quads::GenerateQuadListConversionBuffer(quadListConversionBuffer->GetBackingSpan().cast<u32>().data(), count);
|
conversion::quads::GenerateQuadListConversionBuffer(quadListConversionBuffer->GetBackingSpan().cast<u32>().data(), first + count);
|
||||||
}
|
}
|
||||||
return {quadListConversionBuffer->GetView(0, size), vk::IndexType::eUint32, conversion::quads::GetIndexCount(count)};
|
return {quadListConversionBuffer->GetView(firstPos, size), vk::IndexType::eUint32, conversion::quads::GetIndexCount(count)};
|
||||||
}
|
}
|
||||||
|
|
||||||
MegaBufferAllocator::Allocation GetIndexedQuadConversionBuffer(u32 count) {
|
/**
|
||||||
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, indexBuffer.type)};
|
* @brief Generates an index buffer for converting an indexed quad list to a triangle list
|
||||||
|
* @return The megabuffer allocation containing the generated index buffer
|
||||||
|
*/
|
||||||
|
MegaBufferAllocator::Allocation GetIndexedQuadConversionBuffer(u32 count, u32 first) {
|
||||||
|
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, indexBuffer.GetIndexSize())};
|
||||||
auto allocation{executor.AcquireMegaBufferAllocator().Allocate(executor.cycle, size)};
|
auto allocation{executor.AcquireMegaBufferAllocator().Allocate(executor.cycle, size)};
|
||||||
|
|
||||||
ContextLock lock{executor.tag, indexBuffer.view};
|
ContextLock lock{executor.tag, indexBuffer.view};
|
||||||
@ -1742,7 +1748,8 @@ namespace skyline::gpu::interconnect {
|
|||||||
// TODO: see Read()
|
// TODO: see Read()
|
||||||
Logger::Error("Dirty index buffer reads for attached buffers are unimplemented");
|
Logger::Error("Dirty index buffer reads for attached buffers are unimplemented");
|
||||||
})};
|
})};
|
||||||
conversion::quads::GenerateIndexedQuadConversionBuffer(allocation.region.data(), guestIndexBuffer.data(), count, indexBuffer.type);
|
u8 *guestBufferStart{guestIndexBuffer.data() + first * indexBuffer.GetIndexSize()};
|
||||||
|
conversion::quads::GenerateIndexedQuadConversionBuffer(allocation.region.data(), guestBufferStart, count, indexBuffer.type);
|
||||||
return allocation;
|
return allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2085,19 +2092,22 @@ namespace skyline::gpu::interconnect {
|
|||||||
vk::DeviceSize viewSize{}; //!< The size of the cached view
|
vk::DeviceSize viewSize{}; //!< The size of the cached view
|
||||||
BufferView view{}; //!< A cached view tied to the IOVAs and size to allow for a faster lookup
|
BufferView view{}; //!< A cached view tied to the IOVAs and size to allow for a faster lookup
|
||||||
|
|
||||||
vk::DeviceSize GetIndexBufferSize(u32 elementCount) {
|
constexpr size_t GetIndexSize() const {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case vk::IndexType::eUint8EXT:
|
|
||||||
return sizeof(u8) * elementCount;
|
|
||||||
case vk::IndexType::eUint16:
|
|
||||||
return sizeof(u16) * elementCount;
|
|
||||||
case vk::IndexType::eUint32:
|
case vk::IndexType::eUint32:
|
||||||
return sizeof(u32) * elementCount;
|
return sizeof(u32);
|
||||||
|
case vk::IndexType::eUint16:
|
||||||
|
return sizeof(u16);
|
||||||
|
case vk::IndexType::eUint8EXT:
|
||||||
|
return sizeof(u8);
|
||||||
default:
|
default:
|
||||||
throw exception("Unsupported Vulkan Index Type: {}", vk::to_string(type));
|
throw exception("Unsupported Vulkan Index Type: {}", vk::to_string(type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::DeviceSize GetIndexBufferSize(u32 elementCount) {
|
||||||
|
return GetIndexSize() * elementCount;
|
||||||
|
}
|
||||||
} indexBuffer{};
|
} indexBuffer{};
|
||||||
|
|
||||||
/* Textures */
|
/* Textures */
|
||||||
@ -3025,10 +3035,12 @@ namespace skyline::gpu::interconnect {
|
|||||||
boundIndexBuffer->type = indexBuffer.type;
|
boundIndexBuffer->type = indexBuffer.type;
|
||||||
|
|
||||||
if (needsQuadConversion) {
|
if (needsQuadConversion) {
|
||||||
auto allocation{GetIndexedQuadConversionBuffer(count)};
|
Logger::Warn("Drawing indexed quads");
|
||||||
|
auto allocation{GetIndexedQuadConversionBuffer(count, first)};
|
||||||
boundIndexBuffer->handle = allocation.buffer;
|
boundIndexBuffer->handle = allocation.buffer;
|
||||||
boundIndexBuffer->offset = allocation.offset;
|
boundIndexBuffer->offset = allocation.offset;
|
||||||
count = conversion::quads::GetIndexCount(count);
|
count = conversion::quads::GetIndexCount(count);
|
||||||
|
first = 0;
|
||||||
} else {
|
} else {
|
||||||
executor.AttachBuffer(indexBufferView);
|
executor.AttachBuffer(indexBufferView);
|
||||||
|
|
||||||
@ -3046,10 +3058,11 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
} else if (needsQuadConversion) {
|
} else if (needsQuadConversion) {
|
||||||
// Convert the guest-supplied quad list to an indexed triangle list
|
// Convert the guest-supplied quad list to an indexed triangle list
|
||||||
auto[bufferView, indexType, indexCount]{GetNonIndexedQuadConversionBuffer(count)};
|
auto[bufferView, indexType, indexCount]{GetNonIndexedQuadConversionBuffer(count, first)};
|
||||||
executor.AttachBuffer(bufferView);
|
executor.AttachBuffer(bufferView);
|
||||||
|
|
||||||
count = indexCount;
|
count = indexCount;
|
||||||
|
first = 0;
|
||||||
boundIndexBuffer = std::make_shared<BoundIndexBuffer>();
|
boundIndexBuffer = std::make_shared<BoundIndexBuffer>();
|
||||||
boundIndexBuffer->type = indexType;
|
boundIndexBuffer->type = indexType;
|
||||||
boundIndexBuffer->handle = bufferView->buffer->GetBacking();
|
boundIndexBuffer->handle = bufferView->buffer->GetBacking();
|
||||||
|
Loading…
Reference in New Issue
Block a user