[Sparse #6] Implement sparse initial state stubs - page tables only

This commit is contained in:
baldurk
2015-11-08 22:23:29 +01:00
parent fe8440363b
commit 9be607255e
2 changed files with 293 additions and 15 deletions
+2 -2
View File
@@ -445,8 +445,8 @@ private:
bool Prepare_SparseInitialState(WrappedVkBuffer *buf);
bool Prepare_SparseInitialState(WrappedVkImage *im);
bool Serialise_SparseInitialState(WrappedVkBuffer *buf, VulkanResourceManager::InitialContentData contents);
bool Serialise_SparseInitialState(WrappedVkImage *im, VulkanResourceManager::InitialContentData contents);
bool Serialise_SparseInitialState(ResourceId id, WrappedVkBuffer *buf, VulkanResourceManager::InitialContentData contents);
bool Serialise_SparseInitialState(ResourceId id, WrappedVkImage *im, VulkanResourceManager::InitialContentData contents);
bool Apply_SparseInitialState(WrappedVkBuffer *buf, VulkanResourceManager::InitialContentData contents);
bool Apply_SparseInitialState(WrappedVkImage *im, VulkanResourceManager::InitialContentData contents);
+291 -13
View File
@@ -26,39 +26,317 @@
// VKTODOHIGH we are assuming in all the initial state handling that the image is VK_IMAGE_ASPECT_COLOR
struct PageInitState
{
ResourceId memId;
VkDeviceSize memOffs;
};
template<>
void Serialiser::Serialise(const char *name, PageInitState &el)
{
Serialise("memId", el.memId);
Serialise("memOffs", el.memOffs);
}
struct SparseInitState
{
uint32_t opaqueCount;
VkSparseMemoryBindInfo *opaque;
VkExtent3D imgdim; // in pages
VkExtent3D pagedim;
uint32_t pageCount[VK_IMAGE_ASPECT_NUM];
// available on capture - filled out in Prepare_SparseInitialState and serialised to disk
PageInitState *pages[VK_IMAGE_ASPECT_NUM];
// available on replay - filled out in the READING path of Serialise_SparseInitialState
VkSparseImageMemoryBindInfo *pageBinds[VK_IMAGE_ASPECT_NUM];
};
bool WrappedVulkan::Prepare_SparseInitialState(WrappedVkBuffer *buf)
{
ResourceId id = buf->id;
// VKTODOMED fetch contents of memory for the unique bound memory regions
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, 0, (byte *)NULL));
uint32_t numElems = (uint32_t)buf->record->sparseInfo->opaquemappings.size();
VkSparseMemoryBindInfo *info = (VkSparseMemoryBindInfo *)Serialiser::AllocAlignedBuffer(sizeof(VkSparseMemoryBindInfo)*numElems);
RDCEraseMem(info, sizeof(VkSparseMemoryBindInfo)*numElems);
memcpy(info, &buf->record->sparseInfo->opaquemappings[0], sizeof(VkSparseMemoryBindInfo)*numElems);
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, numElems, (byte *)info));
return true;
}
bool WrappedVulkan::Prepare_SparseInitialState(WrappedVkImage *im)
{
ResourceId id = im->id;
SparseMapping *sparse = im->record->sparseInfo;
// VKTODOMED fetch contents of memory for the unique bound memory regions
uint32_t pagePerAspect = sparse->imgdim.width*sparse->imgdim.height*sparse->imgdim.depth;
uint32_t totalPageCount = 0;
for(uint32_t a=0; a < VK_IMAGE_ASPECT_NUM; a++)
totalPageCount += sparse->pages[a] ? pagePerAspect : 0;
uint32_t opaqueCount = (uint32_t)sparse->opaquemappings.size();
byte *blob = Serialiser::AllocAlignedBuffer(sizeof(SparseInitState) +
sizeof(VkSparseMemoryBindInfo)*opaqueCount +
sizeof(PageInitState)*totalPageCount);
SparseInitState *state = (SparseInitState *)blob;
VkSparseMemoryBindInfo *opaque = (VkSparseMemoryBindInfo *)(state + 1);
PageInitState *pages = (PageInitState *)(opaque + opaqueCount);
state->opaque = opaque;
state->opaqueCount = opaqueCount;
state->pagedim = sparse->pagedim;
state->imgdim = sparse->imgdim;
if(opaqueCount > 0)
memcpy(opaque, &sparse->opaquemappings[0], sizeof(VkSparseMemoryBindInfo)*opaqueCount);
for(uint32_t a=0; a < VK_IMAGE_ASPECT_NUM; a++)
{
state->pageCount[a] = (sparse->pages[a] ? pagePerAspect : 0);
if(state->pageCount[a] != 0)
{
state->pages[a] = pages;
for(uint32_t i=0; i < pagePerAspect; i++)
{
state->pages[a][i].memId = GetResID(sparse->pages[a][i].first);
state->pages[a][i].memOffs = sparse->pages[a][i].second;
}
pages += pagePerAspect;
}
else
{
state->pages[a] = NULL;
}
}
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, 0, blob));
return true;
}
bool WrappedVulkan::Serialise_SparseInitialState(WrappedVkBuffer *buf, VulkanResourceManager::InitialContentData contents)
bool WrappedVulkan::Serialise_SparseInitialState(ResourceId id, WrappedVkBuffer *buf, VulkanResourceManager::InitialContentData contents)
{
VkSparseMemoryBindInfo *info = (VkSparseMemoryBindInfo *)contents.blob;
uint32_t numElems = contents.num;
m_pSerialiser->Serialise("numBinds", numElems);
if(m_State < WRITING)
info = (VkSparseMemoryBindInfo *)Serialiser::AllocAlignedBuffer(sizeof(VkSparseMemoryBindInfo)*numElems);
VkSparseMemoryBindInfo *binds = NULL;
m_pSerialiser->SerialiseComplexArray("binds", binds, numElems);
memcpy(info, binds, sizeof(VkSparseMemoryBindInfo)*numElems);
delete[] binds;
if(m_State < WRITING)
GetResourceManager()->SetInitialContents(id, contents);
return true;
}
bool WrappedVulkan::Serialise_SparseInitialState(WrappedVkImage *im, VulkanResourceManager::InitialContentData contents)
bool WrappedVulkan::Serialise_SparseInitialState(ResourceId id, WrappedVkImage *im, VulkanResourceManager::InitialContentData contents)
{
if(m_State >= WRITING)
{
SparseInitState *state = (SparseInitState *)contents.blob;
uint32_t totalPageCount = 0;
for(uint32_t a=0; a < VK_IMAGE_ASPECT_NUM; a++)
totalPageCount += state->pageCount[a];
m_pSerialiser->Serialise("opaqueCount", state->opaqueCount);
m_pSerialiser->Serialise("totalPageCount", totalPageCount);
m_pSerialiser->Serialise("imgdim", state->imgdim);
m_pSerialiser->Serialise("pagedim", state->pagedim);
if(state->opaqueCount > 0)
m_pSerialiser->SerialiseComplexArray("opaque", state->opaque, state->opaqueCount);
if(totalPageCount > 0)
{
for(uint32_t a=0; a < VK_IMAGE_ASPECT_NUM; a++)
{
m_pSerialiser->Serialise("aspectPageCount", state->pageCount[a]);
if(state->pageCount[a] > 0)
m_pSerialiser->SerialiseComplexArray("pages", state->pages[a], state->pageCount[a]);
}
}
}
else
{
uint32_t opaqueCount = 0;
uint32_t pageCount = 0;
VkExtent3D imgdim = {};
VkExtent3D pagedim = {};
m_pSerialiser->Serialise("opaqueCount", opaqueCount);
m_pSerialiser->Serialise("pageCount", pageCount);
m_pSerialiser->Serialise("imgdim", imgdim);
m_pSerialiser->Serialise("pagedim", pagedim);
byte *blob = Serialiser::AllocAlignedBuffer(sizeof(SparseInitState) +
sizeof(VkSparseMemoryBindInfo)*opaqueCount +
sizeof(VkSparseImageMemoryBindInfo)*pageCount);
SparseInitState *state = (SparseInitState *)blob;
VkSparseMemoryBindInfo *opaque = (VkSparseMemoryBindInfo *)(state + 1);
VkSparseImageMemoryBindInfo *pageBinds = (VkSparseImageMemoryBindInfo *)(opaque + opaqueCount);
RDCEraseEl(state->pageBinds);
state->opaqueCount = opaqueCount;
state->opaque = opaque;
state->imgdim = imgdim;
state->pagedim = pagedim;
if(opaqueCount > 0)
{
VkSparseMemoryBindInfo *o = NULL;
m_pSerialiser->SerialiseComplexArray("opaque", o, opaqueCount);
memcpy(opaque, o, sizeof(VkSparseMemoryBindInfo)*opaqueCount);
delete[] o;
}
else
{
state->opaque = NULL;
}
if(pageCount > 0)
{
for(uint32_t a=0; a < VK_IMAGE_ASPECT_NUM; a++)
{
m_pSerialiser->Serialise("aspectPageCount", state->pageCount[a]);
if(state->pageCount[a] == 0)
{
state->pageBinds[a] = NULL;
}
else
{
state->pageBinds[a] = pageBinds;
pageBinds += state->pageCount[a];
PageInitState *pages = NULL;
m_pSerialiser->SerialiseComplexArray("pages", pages, state->pageCount[a]);
uint32_t i=0;
for(int32_t z=0; z < imgdim.depth; z++)
{
for(int32_t y=0; y < imgdim.height; y++)
{
for(int32_t x=0; x < imgdim.width; x++)
{
VkSparseImageMemoryBindInfo &p = state->pageBinds[a][i];
p.mem = Unwrap(GetResourceManager()->GetLiveHandle<VkDeviceMemory>(pages[i].memId));
p.memOffset = pages[i].memOffs;
p.extent = pagedim;
p.flags = 0; // VKTODOLOW do we need to preserve these flags?
p.subresource.aspect = (VkImageAspect)a;
p.subresource.arrayLayer = 0;
p.subresource.mipLevel = 0;
p.offset.x = x*p.extent.width;
p.offset.y = y*p.extent.height;
p.offset.z = z*p.extent.depth;
i++;
}
}
}
delete[] pages;
}
}
}
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, eInitialContents_Sparse, blob));
}
return true;
}
bool WrappedVulkan::Apply_SparseInitialState(WrappedVkBuffer *buf, VulkanResourceManager::InitialContentData contents)
{
VkSparseMemoryBindInfo *info = (VkSparseMemoryBindInfo *)contents.blob;
uint32_t numElems = contents.num;
// unbind the entire buffer so that any new areas that are bound are unbound again
VkSparseMemoryBindInfo unbind = {
0, m_CreationInfo.m_Buffer[buf->id].size,
0, VK_NULL_HANDLE, 0
};
VkQueue q = GetQ();
ObjDisp(q)->QueueBindSparseBufferMemory(Unwrap(q), buf->real.As<VkBuffer>(), 1, &unbind);
ObjDisp(q)->QueueBindSparseBufferMemory(Unwrap(q), buf->real.As<VkBuffer>(), numElems, info);
return true;
}
bool WrappedVulkan::Apply_SparseInitialState(WrappedVkImage *im, VulkanResourceManager::InitialContentData contents)
{
SparseInitState *info = (SparseInitState *)contents.blob;
VkQueue q = GetQ();
if(info->opaque)
{
// unbind the entire image so that any new areas that are bound are unbound again
// VKTODOMED not sure if this is the right size for opaque portion of partial resident
// sparse image? how is that determined?
VkSparseMemoryBindInfo unbind = {
0, 0,
0, VK_NULL_HANDLE, 0
};
VkMemoryRequirements mrq;
ObjDisp(q)->GetImageMemoryRequirements(Unwrap(GetDev()), im->real.As<VkImage>(), &mrq);
unbind.rangeSize = mrq.size;
ObjDisp(q)->QueueBindSparseImageOpaqueMemory(Unwrap(q), im->real.As<VkImage>(), 1, &unbind);
ObjDisp(q)->QueueBindSparseImageOpaqueMemory(Unwrap(q), im->real.As<VkImage>(), info->opaqueCount, info->opaque);
}
for(uint32_t a=0; a < VK_IMAGE_ASPECT_NUM; a++)
{
if(!info->pageBinds[a]) continue;
// unbind the entire image so that any new areas that are bound are unbound again
VkSparseImageMemoryBindInfo unbind = {
{ (VkImageAspect)a, 0, 0 },
{ 0, 0, 0 },
m_CreationInfo.m_Image[im->id].extent,
0, VK_NULL_HANDLE, 0
};
ObjDisp(q)->QueueBindSparseImageMemory(Unwrap(q), im->real.As<VkImage>(), 1, &unbind);
ObjDisp(q)->QueueBindSparseImageMemory(Unwrap(q), im->real.As<VkImage>(), info->pageCount[a], info->pageBinds[a]);
}
return true;
}
@@ -102,12 +380,6 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
{
VkResult vkr = VK_SUCCESS;
VkDevice d = GetDev();
// VKTODOLOW ideally the prepares could be batched up
// a bit more - maybe not all in one command buffer, but
// at least more than one each
VkCmdBuffer cmd = GetNextCmd();
WrappedVkImage *im = (WrappedVkImage *)res;
if(im->record->sparseInfo)
@@ -117,6 +389,12 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
return Prepare_SparseInitialState((WrappedVkImage *)res);
}
VkDevice d = GetDev();
// VKTODOLOW ideally the prepares could be batched up
// a bit more - maybe not all in one command buffer, but
// at least more than one each
VkCmdBuffer cmd = GetNextCmd();
ImageLayouts *layout = NULL;
{
SCOPED_LOCK(m_ImageLayoutsLock);
@@ -377,7 +655,7 @@ bool WrappedVulkan::Serialise_InitialState(WrappedVkRes *res)
}
else if(type == eResBuffer)
{
return Serialise_SparseInitialState((WrappedVkBuffer *)res, initContents);
return Serialise_SparseInitialState(id, (WrappedVkBuffer *)res, initContents);
}
else if(type == eResDeviceMemory || type == eResImage)
{
@@ -391,7 +669,7 @@ bool WrappedVulkan::Serialise_InitialState(WrappedVkRes *res)
{
// contains page mapping
RDCASSERT(type == eResImage);
return Serialise_SparseInitialState((WrappedVkImage *)res, initContents);
return Serialise_SparseInitialState(id, (WrappedVkImage *)res, initContents);
}
byte *ptr = NULL;
@@ -530,7 +808,7 @@ bool WrappedVulkan::Serialise_InitialState(WrappedVkRes *res)
}
else if(type == eResBuffer)
{
return Serialise_SparseInitialState((WrappedVkBuffer *)NULL, VulkanResourceManager::InitialContentData());
return Serialise_SparseInitialState(id, (WrappedVkBuffer *)NULL, VulkanResourceManager::InitialContentData());
}
else if(type == eResImage)
{
@@ -539,7 +817,7 @@ bool WrappedVulkan::Serialise_InitialState(WrappedVkRes *res)
if(isSparse)
{
return Serialise_SparseInitialState((WrappedVkImage *)NULL, VulkanResourceManager::InitialContentData());
return Serialise_SparseInitialState(id, (WrappedVkImage *)NULL, VulkanResourceManager::InitialContentData());
}
byte *data = NULL;