2017-05-30 36 views
2

假設我有一個VkBuffer綁定到每個設備分配,並使用vkCmdCopyBuffer的適當組合來逐塊執行碎片整理。Vulkan:使用緩衝區別名實現碎片整理方案

說一個競技場可能包含任何適當排列的線性和非線性數據。由於綁定後VkImage的不變性,碎片整理將涉及在已移動的圖像數據的新位置構建和綁定新的VkImage

在舞臺上進行碎片整理的任何資源都不受任何約束,或者可能被視爲「正在使用」。

這並不難實現,但我有一個擔憂:

是否UB使用vkCmdCopyBuffer使圖像移動的數據(以避免多餘的佈局轉換),然後在新構造一個新的VkImage位置?

我的想法是,也許一個實現會做一些奇怪的事情,比如依靠某些內部簿記結構中的絕對設備地址,使UB將圖像數據視爲POD,直到綁定到新對象。

+1

您的最後一段描述了這個問題。 「圖像佈局」涵蓋無損壓縮等內容。壓縮通常涉及與像素數據分離的元數據,該數據告訴如何解釋存儲在「像素」存儲器中的字節。在某些實現中,此元數據是VkImage內存的一部分,但是以非位置無關的方式進行尋址。在其他地方,它可能被存儲在其他地方並由像素數據的物理地址來尋址。還有其他障礙,比如對物理對齊敏感的混合佈局,以實現在內存通道/銀行上的良好分配。 –

回答

2

那麼,我們來看看這個系統。

因此,您可以爲圖像找到合適的目的地區域。你做一個vkCmdCopyBuffer從源區域複製到目標區域。現在您爲該目標區域創建一個新的VkImage,並且您指定的初始佈局是...什麼?

請參閱VkCreateImageInfo中只有兩個有效的initialLayout值:未定義或預初始化。預初始化僅適用於使用線性平鋪的圖像,因爲沒有爲最佳平鋪圖像定義明確的佈局。

所以你不能使用預初始化的佈局。使用未定義的佈局意味着您使用的下一個圖像轉換可能會破壞所有數據。現在,在一些實現中,未定義的佈局可能會工作。在不關心佈局的實現上,它可能工作。如果源圖像位於總體佈局中,它也可能適用於實現。

但是沒有一個是保證工作的標準。就標準而言,如果您將佈局設置爲未定義,那麼數據將不會被保留。因此,不管緩衝區/圖像別名的問題如何,這都無法工作。

您必須在目的地創建VkImage,然後使用vkCmdCopyImage將源圖像複製到目標。

還應該注意的是,即使佈局問題奏效,aliasing rules也告訴我們,從非主機可訪問的內存(即:以最佳平鋪或非一般/預初始化佈局的圖像)複製到主機可訪問內存產生未定義的值。所以即使佈局問題不是問題,副本本身也不起作用。理論上,至少。

+0

我正在手動跟蹤圖像佈局。我會提供最後一個已知的佈局(或'未定義'),因爲數據沒有改變,只是「傳送」。因爲我必須爲每個屏障提供已知的佈局,所以我沒有理由相信這個驅動程序也是這樣做的(TBH,這個API的一個令人惱火的方面)。除非vkBindImageMemory不僅僅將一個'VkImage'與某些內存關聯起來(可能會摧毀一些元數據),否則我認爲只有內部樹或鏈表出現問題...... – defube

+0

@defube:沒關係。您無法提供「最後所知的佈局」,因爲Vulkan *不允許您*。 'initialLayout'只能被初始化或未定義。如果您從未定義過渡到最後一個已知佈局,則該標準不會保證該內存的內容。因此,你會依賴未定義的行爲。而且,實際上,因爲您將不得不創建目的地'VkImage' *無論如何*,做圖像複製有什麼不好?它是否需要進行多次轉賬? –

+0

@defube:順便說一句,我在官方的Vulkan倉庫中增加了一個[關於此問題](https://github.com/KhronosGroup/Vulkan-Docs/issues/509)。你可能想要密切關注它,看看他們如何支持這樣的事情。 –