mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 14: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
|
||||
* @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) {
|
||||
return GetIndexCount(count) * [&]() -> size_t {
|
||||
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;
|
||||
}
|
||||
}();
|
||||
constexpr size_t GetRequiredBufferSize(u32 count, size_t indexSize) {
|
||||
return GetIndexCount(count) * indexSize;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1722,19 +1722,25 @@ namespace skyline::gpu::interconnect {
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, vk::IndexType::eUint32)};
|
||||
std::tuple<BufferView, vk::IndexType, u32> GetNonIndexedQuadConversionBuffer(u32 count, u32 first) {
|
||||
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) {
|
||||
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)};
|
||||
|
||||
ContextLock lock{executor.tag, indexBuffer.view};
|
||||
@ -1742,7 +1748,8 @@ namespace skyline::gpu::interconnect {
|
||||
// TODO: see Read()
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2085,19 +2092,22 @@ namespace skyline::gpu::interconnect {
|
||||
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
|
||||
|
||||
vk::DeviceSize GetIndexBufferSize(u32 elementCount) {
|
||||
constexpr size_t GetIndexSize() const {
|
||||
switch (type) {
|
||||
case vk::IndexType::eUint8EXT:
|
||||
return sizeof(u8) * elementCount;
|
||||
case vk::IndexType::eUint16:
|
||||
return sizeof(u16) * elementCount;
|
||||
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:
|
||||
throw exception("Unsupported Vulkan Index Type: {}", vk::to_string(type));
|
||||
}
|
||||
}
|
||||
|
||||
vk::DeviceSize GetIndexBufferSize(u32 elementCount) {
|
||||
return GetIndexSize() * elementCount;
|
||||
}
|
||||
} indexBuffer{};
|
||||
|
||||
/* Textures */
|
||||
@ -3025,10 +3035,12 @@ namespace skyline::gpu::interconnect {
|
||||
boundIndexBuffer->type = indexBuffer.type;
|
||||
|
||||
if (needsQuadConversion) {
|
||||
auto allocation{GetIndexedQuadConversionBuffer(count)};
|
||||
Logger::Warn("Drawing indexed quads");
|
||||
auto allocation{GetIndexedQuadConversionBuffer(count, first)};
|
||||
boundIndexBuffer->handle = allocation.buffer;
|
||||
boundIndexBuffer->offset = allocation.offset;
|
||||
count = conversion::quads::GetIndexCount(count);
|
||||
first = 0;
|
||||
} else {
|
||||
executor.AttachBuffer(indexBufferView);
|
||||
|
||||
@ -3046,10 +3058,11 @@ namespace skyline::gpu::interconnect {
|
||||
}
|
||||
} else if (needsQuadConversion) {
|
||||
// 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);
|
||||
|
||||
count = indexCount;
|
||||
first = 0;
|
||||
boundIndexBuffer = std::make_shared<BoundIndexBuffer>();
|
||||
boundIndexBuffer->type = indexType;
|
||||
boundIndexBuffer->handle = bufferView->buffer->GetBacking();
|
||||
|
Loading…
Reference in New Issue
Block a user