mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 20:31:48 +01:00
Take firstIndex into account when calculating index (quad) buffer size
Without this we would miss any elements beyond indexCount in the index buffer and they would be filled with random garbage causing vertex bombs
This commit is contained in:
parent
1f9de17e98
commit
7fed971b2d
@ -93,7 +93,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferBinding GenerateQuadConversionIndexBuffer(InterconnectContext &ctx, engine::IndexBuffer::IndexSize indexType, BufferView &view, u32 elementCount) {
|
static BufferBinding GenerateQuadConversionIndexBuffer(InterconnectContext &ctx, engine::IndexBuffer::IndexSize indexType, BufferView &view, u32 firstIndex, u32 elementCount) {
|
||||||
auto viewSpan{view.GetReadOnlyBackingSpan(false /* We attach above so always false */, []() {
|
auto viewSpan{view.GetReadOnlyBackingSpan(false /* We attach above so always false */, []() {
|
||||||
// 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");
|
||||||
@ -103,7 +103,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
vk::DeviceSize indexBufferSize{conversion::quads::GetRequiredBufferSize(elementCount, indexSize)};
|
vk::DeviceSize indexBufferSize{conversion::quads::GetRequiredBufferSize(elementCount, indexSize)};
|
||||||
auto quadConversionAllocation{ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, indexBufferSize)};
|
auto quadConversionAllocation{ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, indexBufferSize)};
|
||||||
|
|
||||||
conversion::quads::GenerateIndexedQuadConversionBuffer(quadConversionAllocation.region.data(), viewSpan.data(), elementCount, ConvertIndexType(indexType));
|
conversion::quads::GenerateIndexedQuadConversionBuffer(quadConversionAllocation.region.data(), viewSpan.subspan(GetIndexBufferSize(indexType, firstIndex)).data(), elementCount, ConvertIndexType(indexType));
|
||||||
|
|
||||||
return {quadConversionAllocation.buffer, quadConversionAllocation.offset, indexBufferSize};
|
return {quadConversionAllocation.buffer, quadConversionAllocation.offset, indexBufferSize};
|
||||||
}
|
}
|
||||||
@ -115,11 +115,12 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
IndexBufferState::IndexBufferState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {}
|
IndexBufferState::IndexBufferState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {}
|
||||||
|
|
||||||
void IndexBufferState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 elementCount) {
|
void IndexBufferState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 firstIndex, u32 elementCount) {
|
||||||
usedElementCount = elementCount;
|
usedElementCount = elementCount;
|
||||||
|
usedFirstIndex = firstIndex;
|
||||||
usedQuadConversion = quadConversion;
|
usedQuadConversion = quadConversion;
|
||||||
|
|
||||||
size_t size{GetIndexBufferSize(engine->indexBuffer.indexSize, elementCount)};
|
size_t size{GetIndexBufferSize(engine->indexBuffer.indexSize, firstIndex + elementCount)};
|
||||||
view.Update(ctx, engine->indexBuffer.address, size);
|
view.Update(ctx, engine->indexBuffer.address, size);
|
||||||
if (!*view) {
|
if (!*view) {
|
||||||
Logger::Warn("Unmapped index buffer: 0x{:X}", engine->indexBuffer.address);
|
Logger::Warn("Unmapped index buffer: 0x{:X}", engine->indexBuffer.address);
|
||||||
@ -131,7 +132,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
indexType = ConvertIndexType(engine->indexBuffer.indexSize);
|
indexType = ConvertIndexType(engine->indexBuffer.indexSize);
|
||||||
|
|
||||||
if (quadConversion)
|
if (quadConversion)
|
||||||
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, elementCount);
|
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, firstIndex, elementCount);
|
||||||
else
|
else
|
||||||
megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber);
|
megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber);
|
||||||
|
|
||||||
@ -141,16 +142,19 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
builder.SetIndexBuffer(*view, indexType);
|
builder.SetIndexBuffer(*view, indexType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IndexBufferState::Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 elementCount) {
|
bool IndexBufferState::Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 firstIndex, u32 elementCount) {
|
||||||
if (elementCount > usedElementCount)
|
if (elementCount > usedElementCount)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (quadConversion != usedQuadConversion)
|
if (quadConversion != usedQuadConversion)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (quadConversion != usedQuadConversion)
|
||||||
|
return true;
|
||||||
|
|
||||||
// TODO: optimise this to use buffer sequencing to avoid needing to regenerate the quad buffer every time. We can't use as it is rn though because sequences aren't globally unique and may conflict after buffer recreation
|
// TODO: optimise this to use buffer sequencing to avoid needing to regenerate the quad buffer every time. We can't use as it is rn though because sequences aren't globally unique and may conflict after buffer recreation
|
||||||
if (usedQuadConversion) {
|
if (usedQuadConversion) {
|
||||||
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, elementCount);
|
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, firstIndex, elementCount);
|
||||||
builder.SetIndexBuffer(megaBufferBinding, indexType);
|
builder.SetIndexBuffer(megaBufferBinding, indexType);
|
||||||
} else if (megaBufferBinding) {
|
} else if (megaBufferBinding) {
|
||||||
if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber)};
|
if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber)};
|
||||||
@ -390,7 +394,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
dirtyFunc(stencilValues);
|
dirtyFunc(stencilValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveState::Update(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, StateUpdateBuilder &builder, bool indexed, engine::DrawTopology topology, u32 drawElementCount) {
|
void ActiveState::Update(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, StateUpdateBuilder &builder, bool indexed, engine::DrawTopology topology, u32 drawFirstIndex, u32 drawElementCount) {
|
||||||
if (topology != directState.inputAssembly.GetPrimitiveTopology()) {
|
if (topology != directState.inputAssembly.GetPrimitiveTopology()) {
|
||||||
directState.inputAssembly.SetPrimitiveTopology(topology);
|
directState.inputAssembly.SetPrimitiveTopology(topology);
|
||||||
pipeline.MarkDirty(false);
|
pipeline.MarkDirty(false);
|
||||||
@ -400,7 +404,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
pipeline.Update(ctx, textures, constantBuffers, builder);
|
pipeline.Update(ctx, textures, constantBuffers, builder);
|
||||||
ranges::for_each(vertexBuffers, updateFunc);
|
ranges::for_each(vertexBuffers, updateFunc);
|
||||||
if (indexed)
|
if (indexed)
|
||||||
updateFunc(indexBuffer, directState.inputAssembly.NeedsQuadConversion(), drawElementCount);
|
updateFunc(indexBuffer, directState.inputAssembly.NeedsQuadConversion(), drawFirstIndex, drawElementCount);
|
||||||
ranges::for_each(transformFeedbackBuffers, updateFunc);
|
ranges::for_each(transformFeedbackBuffers, updateFunc);
|
||||||
ranges::for_each(viewports, updateFunc);
|
ranges::for_each(viewports, updateFunc);
|
||||||
ranges::for_each(scissors, updateFunc);
|
ranges::for_each(scissors, updateFunc);
|
||||||
|
@ -48,14 +48,15 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
BufferBinding megaBufferBinding{};
|
BufferBinding megaBufferBinding{};
|
||||||
vk::IndexType indexType{};
|
vk::IndexType indexType{};
|
||||||
u32 usedElementCount{};
|
u32 usedElementCount{};
|
||||||
|
u32 usedFirstIndex{};
|
||||||
bool usedQuadConversion{};
|
bool usedQuadConversion{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IndexBufferState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);
|
IndexBufferState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);
|
||||||
|
|
||||||
void Flush(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 elementCount);
|
void Flush(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 firstIndex, u32 elementCount);
|
||||||
|
|
||||||
bool Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 elementCount);
|
bool Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder, bool quadConversion, u32 firstIndex, u32 elementCount);
|
||||||
|
|
||||||
void PurgeCaches();
|
void PurgeCaches();
|
||||||
};
|
};
|
||||||
@ -256,7 +257,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
/**
|
/**
|
||||||
* @brief Updates the active state for a given draw operation, removing the dirtiness of all member states
|
* @brief Updates the active state for a given draw operation, removing the dirtiness of all member states
|
||||||
*/
|
*/
|
||||||
void Update(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, StateUpdateBuilder &builder, bool indexed, engine::DrawTopology topology, u32 drawElementCount);
|
void Update(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, StateUpdateBuilder &builder, bool indexed, engine::DrawTopology topology, u32 drawFirstIndex, u32 drawElementCount);
|
||||||
|
|
||||||
Pipeline *GetPipeline();
|
Pipeline *GetPipeline();
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
StateUpdateBuilder builder{*ctx.executor.allocator};
|
StateUpdateBuilder builder{*ctx.executor.allocator};
|
||||||
|
|
||||||
Pipeline *oldPipeline{activeState.GetPipeline()};
|
Pipeline *oldPipeline{activeState.GetPipeline()};
|
||||||
activeState.Update(ctx, textures, constantBuffers.boundConstantBuffers, builder, indexed, topology, count);
|
activeState.Update(ctx, textures, constantBuffers.boundConstantBuffers, builder, indexed, topology, first, count);
|
||||||
if (directState.inputAssembly.NeedsQuadConversion()) {
|
if (directState.inputAssembly.NeedsQuadConversion()) {
|
||||||
count = conversion::quads::GetIndexCount(count);
|
count = conversion::quads::GetIndexCount(count);
|
||||||
first = 0;
|
first = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user