1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-30 20:52:11 +01:00

[dxvk] Add structures for sparse binding operations

This commit is contained in:
Philip Rebohle 2022-08-21 15:50:55 +02:00
parent f9db4921e0
commit 3057f6a51b
2 changed files with 176 additions and 2 deletions

View File

@ -335,4 +335,65 @@ namespace dxvk {
}
}
VkBuffer DxvkSparsePageTable::getBufferHandle() const {
return m_buffer ? m_buffer->getSliceHandle().handle : VK_NULL_HANDLE;
}
VkImage DxvkSparsePageTable::getImageHandle() const {
return m_image ? m_image->handle() : VK_NULL_HANDLE;
}
uint32_t DxvkSparsePageTable::computePageIndex(
uint32_t subresource,
VkOffset3D regionOffset,
VkExtent3D regionExtent,
VkBool32 regionIsLinear,
uint32_t pageIndex) const {
auto subresourceInfo = getSubresourceProperties(subresource);
// The mip tail is always linear
if (subresourceInfo.isMipTail)
return m_properties.mipTailPageIndex + pageIndex;
// Compute offset into the given subresource
VkOffset3D pageOffset = regionOffset;
if (!regionIsLinear) {
pageOffset.x += (pageIndex % regionExtent.width);
pageOffset.y += (pageIndex / regionExtent.width) % regionExtent.height;
pageOffset.z += (pageIndex / regionExtent.width) / regionExtent.height;
pageIndex = 0;
}
uint32_t result = subresourceInfo.pageIndex + pageOffset.x
+ subresourceInfo.pageCount.width * (pageOffset.y
+ subresourceInfo.pageCount.height * pageOffset.z);
return result + pageIndex;
}
DxvkSparseMapping DxvkSparsePageTable::getMapping(
uint32_t page) {
return page < m_mappings.size()
? m_mappings[page]
: DxvkSparseMapping();
}
void DxvkSparsePageTable::updateMapping(
DxvkCommandList* cmd,
uint32_t page,
DxvkSparseMapping&& mapping) {
if (m_mappings[page] != page) {
if (m_mappings[page])
cmd->trackResource<DxvkAccess::None>(m_mappings[page].m_page);
m_mappings[page] = std::move(mapping);
}
}
}

View File

@ -9,8 +9,10 @@ namespace dxvk {
class DxvkDevice;
class DxvkBuffer;
class DxvkImage;
class DxvkPagedResource;
class DxvkSparsePage;
class DxvkSparsePageAllocator;
class DxvkSparsePageTable;
constexpr static VkDeviceSize SparseMemoryPageSize = 1ull << 16;
@ -112,6 +114,55 @@ namespace dxvk {
};
/**
* \brief Sparse binding flags
*/
enum class DxvkSparseBindFlag : uint32_t {
SkipSynchronization,
};
using DxvkSparseBindFlags = Flags<DxvkSparseBindFlag>;
/**
* \brief Sparse page binding mode
*/
enum class DxvkSparseBindMode : uint32_t {
Null, ///< Unbind the given resource page
Bind, ///< Bind to given allocator page
Copy, ///< Copy bindig from source resource
};
/**
* \brief Sparse page binding info for a given page
*
* Stores the resource page index as well as the index
* of the allocator page that should be bound to that
* resource page.
*/
struct DxvkSparseBind {
DxvkSparseBindMode mode;
uint32_t dstPage;
uint32_t srcPage;
};
/**
* \brief Sparse binding info
*
* Stores the resource to change page bindings for, the
* allocator from which pages will be allocated, and
* a list of page bidnings
*/
struct DxvkSparseBindInfo {
Rc<DxvkPagedResource> dstResource;
Rc<DxvkPagedResource> srcResource;
Rc<DxvkSparsePageAllocator> srcAllocator;
std::vector<DxvkSparseBind> binds;
};
/**
* \brief Sparse memory page
*
@ -153,6 +204,7 @@ namespace dxvk {
*/
class DxvkSparseMapping {
friend DxvkSparsePageAllocator;
friend DxvkSparsePageTable;
public:
DxvkSparseMapping();
@ -165,8 +217,15 @@ namespace dxvk {
~DxvkSparseMapping();
Rc<DxvkSparsePage> getPage() const {
return m_page;
/**
* \brief Queries memory handle
* \returns Memory information
*/
DxvkSparsePageHandle getHandle() const {
if (m_page == nullptr)
return DxvkSparsePageHandle();
return m_page->getHandle();
}
bool operator == (const DxvkSparseMapping& other) const {
@ -286,6 +345,18 @@ namespace dxvk {
return m_buffer || m_image;
}
/**
* \brief Queries buffer handle
* \returns Buffer handle
*/
VkBuffer getBufferHandle() const;
/**
* \brief Queries image handle
* \returns Image handle
*/
VkImage getImageHandle() const;
/**
* \brief Counts total number of pages in the resources
*
@ -340,6 +411,48 @@ namespace dxvk {
: DxvkSparsePageInfo();
}
/**
* \brief Computes page index within a given image region
*
* \param [in] subresource Subresource index
* \param [in] regionOffset Region offset, in pages
* \param [in] regionExtent Region extent, in pages
* \param [in] regionIsLinear Whether to use the region extent
* \param [in] pageIndex Page within the given region
* \returns Page index. The returned number may be out
* of bounds if the given region is invalid.
*/
uint32_t computePageIndex(
uint32_t subresource,
VkOffset3D regionOffset,
VkExtent3D regionExtent,
VkBool32 regionIsLinear,
uint32_t pageIndex) const;
/**
* \brief Queries page mapping
*
* \param [in] page Page index
* \returns Current page mapping
*/
DxvkSparseMapping getMapping(
uint32_t page);
/**
* \brief Changes a page mapping
*
* Updates the given page mapping in the table, and ensures
* that the previously mapped page does not get destroyed
* prematurely by tracking it in the given command list.
* \param [in] cmd Command list
* \param [in] page Page index
* \param [in] mapping New mapping
*/
void updateMapping(
DxvkCommandList* cmd,
uint32_t page,
DxvkSparseMapping&& mapping);
private:
const DxvkBuffer* m_buffer = nullptr;