mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +09:00
[Fix] (MG_Backend/DirectVulkan): fix 26.2 texture bug.
- Fix texture object / buffer lifecycle issues
This commit is contained in:
@@ -142,11 +142,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
SizeT count = 0;
|
||||
for (const auto& [raw, weak]: m_aliveObjects) {
|
||||
if (weak.expired()) {
|
||||
count++;
|
||||
m_pendingClears.erase(raw);
|
||||
m_aliveObjects.erase(raw);
|
||||
for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end();) {
|
||||
auto current = it++;
|
||||
if (current->second.expired()) {
|
||||
m_pendingClears.erase(current->first);
|
||||
m_aliveObjects.erase(current);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
||||
@@ -443,6 +443,21 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkTextureManager::TextureResource* VkTextureManager::SyncTextureAndGetDescriptor(MG_State::GLState::ITextureObject& texture) {
|
||||
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "SyncTextureAndGetDescriptor: m_device == VK_NULL_HANDLE");
|
||||
|
||||
auto aliveIt = m_aliveObjects.find(&texture);
|
||||
if (aliveIt != m_aliveObjects.end() && aliveIt->second.expired()) {
|
||||
auto resourceIt = m_textureResources.find(&texture);
|
||||
if (resourceIt != m_textureResources.end()) {
|
||||
DeferResourceRelease(Move(resourceIt->second));
|
||||
m_textureResources.erase(resourceIt);
|
||||
}
|
||||
m_aliveObjects.erase(aliveIt);
|
||||
}
|
||||
|
||||
const auto& liveTexture = MG_State::pGLContext->GetTextureObject(texture.GetExternalIndex());
|
||||
if (liveTexture && liveTexture.get() == &texture) {
|
||||
m_aliveObjects[&texture] = WeakPtr<MG_State::GLState::ITextureObject>(liveTexture);
|
||||
}
|
||||
|
||||
auto it = m_textureResources.find(&texture);
|
||||
if (it == m_textureResources.end()) {
|
||||
TextureResource initial{};
|
||||
@@ -668,11 +683,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return 0;
|
||||
}
|
||||
SizeT count = 0;
|
||||
for (const auto& [raw, weak]: m_aliveObjects) {
|
||||
if (weak.expired()) {
|
||||
count++;
|
||||
m_textureResources.erase(raw);
|
||||
m_aliveObjects.erase(raw);
|
||||
for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end();) {
|
||||
auto current = it++;
|
||||
if (current->second.expired()) {
|
||||
auto resourceIt = m_textureResources.find(current->first);
|
||||
if (resourceIt != m_textureResources.end()) {
|
||||
DeferResourceRelease(Move(resourceIt->second));
|
||||
m_textureResources.erase(resourceIt);
|
||||
}
|
||||
m_aliveObjects.erase(current);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
||||
@@ -1323,19 +1323,25 @@ void main() {
|
||||
"UploadAndBindVertexStreams failed to resolve shared source buffer");
|
||||
BufferSlice slice{};
|
||||
const Bool isDirty = (sourceBufferShared->GetChangeBits() & BufferChangeBits::DirtyBit);
|
||||
const Uint64 changeSerial = sourceBufferShared->GetChangeSerial();
|
||||
const SizeT sourceSize = sourceBufferShared->GetSize();
|
||||
auto cachedTransient = m_transientVertexIndexBufferSlicesThisFrame.find(sourceBufferShared.get());
|
||||
if (cachedTransient != m_transientVertexIndexBufferSlicesThisFrame.end() && !isDirty) {
|
||||
slice = cachedTransient->second;
|
||||
if (cachedTransient != m_transientVertexIndexBufferSlicesThisFrame.end() && !isDirty &&
|
||||
cachedTransient->second.changeSerial == changeSerial && cachedTransient->second.size == sourceSize) {
|
||||
slice = cachedTransient->second.slice;
|
||||
} else if (ShouldUseTransientVertexIndexBuffer(*sourceBufferShared) || isDirty) {
|
||||
const auto sourceData = sourceBufferShared->GetDataReadOnly();
|
||||
const SizeT sourceSize = sourceBufferShared->GetSize();
|
||||
if (!m_bufferManager.UploadTransient(BufferKind::Vertex, m_frameContext.GetCurrentFrameIndex(),
|
||||
sourceData->data(), static_cast<VkDeviceSize>(sourceSize), 16,
|
||||
slice)) {
|
||||
MOBILEGL_ASSERT(false, "UploadAndBindVertexStreams skipped: failed to upload transient binding %zu", binding);
|
||||
return false;
|
||||
}
|
||||
m_transientVertexIndexBufferSlicesThisFrame[sourceBufferShared.get()] = slice;
|
||||
m_transientVertexIndexBufferSlicesThisFrame[sourceBufferShared.get()] = {
|
||||
.slice = slice,
|
||||
.changeSerial = changeSerial,
|
||||
.size = sourceSize,
|
||||
};
|
||||
m_bufferManager.DowngradeResidentBufferToTransient(sourceBufferShared);
|
||||
sourceBufferShared->ClearDirty();
|
||||
} else {
|
||||
@@ -1415,9 +1421,12 @@ void main() {
|
||||
auto indexBufferShared = MG_State::pGLContext->GetBufferObject(indexBuffer->GetExternalIndex());
|
||||
MOBILEGL_ASSERT(indexBufferShared != nullptr, "UploadAndBindIndexBuffer failed to resolve shared EBO");
|
||||
const Bool isDirty = (indexBufferShared->GetChangeBits() & BufferChangeBits::DirtyBit);
|
||||
const Uint64 changeSerial = indexBufferShared->GetChangeSerial();
|
||||
const SizeT indexBufferSize = indexBufferShared->GetSize();
|
||||
auto cachedTransient = m_transientVertexIndexBufferSlicesThisFrame.find(indexBufferShared.get());
|
||||
if (cachedTransient != m_transientVertexIndexBufferSlicesThisFrame.end() && !isDirty) {
|
||||
slice = cachedTransient->second;
|
||||
if (cachedTransient != m_transientVertexIndexBufferSlicesThisFrame.end() && !isDirty &&
|
||||
cachedTransient->second.changeSerial == changeSerial && cachedTransient->second.size == indexBufferSize) {
|
||||
slice = cachedTransient->second.slice;
|
||||
vkCmdBindIndexBuffer(frame.commandBuffer,
|
||||
slice.buffer,
|
||||
slice.offset + static_cast<VkDeviceSize>(pIndexBufferView->indexByteOffset),
|
||||
@@ -1429,12 +1438,16 @@ void main() {
|
||||
MOBILEGL_ASSERT(indexData != nullptr && !indexData->empty(), "DrawElements requires non-empty EBO data");
|
||||
if (!m_bufferManager.UploadTransient(BufferKind::Index, m_frameContext.GetCurrentFrameIndex(),
|
||||
indexData->data(),
|
||||
static_cast<VkDeviceSize>(indexBufferShared->GetSize()), indexSize,
|
||||
static_cast<VkDeviceSize>(indexBufferSize), indexSize,
|
||||
slice)) {
|
||||
MOBILEGL_ASSERT(false, "DrawElements skipped: failed to prepare transient index buffer");
|
||||
return false;
|
||||
}
|
||||
m_transientVertexIndexBufferSlicesThisFrame[indexBufferShared.get()] = slice;
|
||||
m_transientVertexIndexBufferSlicesThisFrame[indexBufferShared.get()] = {
|
||||
.slice = slice,
|
||||
.changeSerial = changeSerial,
|
||||
.size = indexBufferSize,
|
||||
};
|
||||
m_bufferManager.DowngradeResidentBufferToTransient(indexBufferShared);
|
||||
indexBufferShared->ClearDirty();
|
||||
vkCmdBindIndexBuffer(frame.commandBuffer,
|
||||
|
||||
@@ -197,8 +197,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
||||
|
||||
struct TransientBufferSliceCacheEntry {
|
||||
BufferSlice slice;
|
||||
Uint64 changeSerial = 0;
|
||||
SizeT size = 0;
|
||||
};
|
||||
|
||||
VkBufferManager m_bufferManager;
|
||||
UnorderedMap<const MG_State::GLState::BufferObject*, BufferSlice> m_transientVertexIndexBufferSlicesThisFrame;
|
||||
UnorderedMap<const MG_State::GLState::BufferObject*, TransientBufferSliceCacheEntry>
|
||||
m_transientVertexIndexBufferSlicesThisFrame;
|
||||
|
||||
Uint m_imageIndexAcquired = 0;
|
||||
FrameContext m_frameContext;
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_dataPtr->resize(size);
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::PreferReallocationBit;
|
||||
++m_changeSerial;
|
||||
}
|
||||
|
||||
void BufferObject::UploadData(DataPtr data, SizeT atOffset) {
|
||||
@@ -35,6 +36,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
|
||||
++m_changeSerial;
|
||||
// This function may be called by `glBufferData`, but we still set the forbid bits above,
|
||||
// because when `PreferReallocationBit` is set, those bits are ignored anyway.
|
||||
// The bits can fit the `glBufferSubData` semantics
|
||||
@@ -54,6 +56,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_mappedRange.end - m_mappedRange.start);
|
||||
m_change.DirtyRanges.Add({m_mappedRange.start, m_mappedRange.end});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
++m_changeSerial;
|
||||
}
|
||||
|
||||
m_stagingData.clear();
|
||||
@@ -80,6 +83,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length);
|
||||
m_change.DirtyRanges.Add({start, end});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
++m_changeSerial;
|
||||
}
|
||||
|
||||
void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) {
|
||||
@@ -93,6 +97,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
|
||||
++m_changeSerial;
|
||||
}
|
||||
|
||||
void BufferObject::CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset, SizeT size) {
|
||||
@@ -109,6 +114,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
Memcpy(m_dataPtr->data() + dstOffset, srcData, size);
|
||||
m_change.DirtyRanges.Add({dstOffset, dstOffset + size});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
++m_changeSerial;
|
||||
}
|
||||
|
||||
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
|
||||
@@ -191,6 +197,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
return m_change.Bits;
|
||||
}
|
||||
|
||||
Uint64 BufferObject::GetChangeSerial() const {
|
||||
return m_changeSerial;
|
||||
}
|
||||
|
||||
Bool BufferObject::IsMapped() const {
|
||||
return m_isMapped;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ namespace MobileGL {
|
||||
Uint GetExternalIndex() const;
|
||||
const VecRange1D& GetDirtyRanges() const;
|
||||
Flags<BufferChangeBits> GetChangeBits() const;
|
||||
Uint64 GetChangeSerial() const;
|
||||
|
||||
private:
|
||||
const Uint m_externalIndex = 0;
|
||||
@@ -108,6 +109,7 @@ namespace MobileGL {
|
||||
Bool m_isMapped;
|
||||
Flags<BufferMappingAccessBit> m_mappingAccess;
|
||||
BufferChange m_change;
|
||||
Uint64 m_changeSerial = 0;
|
||||
Range1D m_mappedRange;
|
||||
Vector<Uint8> m_stagingData;
|
||||
Bool m_ownsStagingData;
|
||||
|
||||
Reference in New Issue
Block a user