mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-27 04:11:05 +00:00
521 lines
17 KiB
C++
521 lines
17 KiB
C++
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2015 Baldur Karlsson
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
#include "vk_core.h"
|
|
|
|
bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
|
|
{
|
|
ResourceId id = GetResourceManager()->GetID(res);
|
|
|
|
VkResourceType type = IdentifyTypeByPtr(res);
|
|
|
|
if(type == eResDescriptorSet)
|
|
{
|
|
VkResourceRecord *record = GetResourceManager()->GetResourceRecord(id);
|
|
RDCASSERT(record->layout);
|
|
const DescSetLayout &layout = *record->layout;
|
|
|
|
uint32_t numElems = 0;
|
|
for(size_t i=0; i < layout.bindings.size(); i++)
|
|
numElems += layout.bindings[i].arraySize;
|
|
|
|
VkDescriptorInfo *info = (VkDescriptorInfo *)Serialiser::AllocAlignedBuffer(sizeof(VkDescriptorInfo)*numElems);
|
|
RDCEraseMem(info, sizeof(VkDescriptorInfo)*numElems);
|
|
|
|
uint32_t e=0;
|
|
for(size_t i=0; i < layout.bindings.size(); i++)
|
|
for(uint32_t b=0; b < layout.bindings[i].arraySize; b++)
|
|
info[e++] = record->descBindings[i][b];
|
|
|
|
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, 0, (byte *)info));
|
|
return true;
|
|
}
|
|
else if(type == eResDeviceMemory)
|
|
{
|
|
VkResourceRecord *record = GetResourceManager()->GetResourceRecord(id);
|
|
RDCASSERT(record->Length > 0);
|
|
|
|
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();
|
|
|
|
VkDeviceMemory mem = VK_NULL_HANDLE;
|
|
|
|
VkBufferCreateInfo bufInfo = {
|
|
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL,
|
|
record->Length, VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0,
|
|
VK_SHARING_MODE_EXCLUSIVE, 0, NULL,
|
|
};
|
|
|
|
// since these are very short lived, they are not wrapped
|
|
VkBuffer srcBuf, dstBuf;
|
|
|
|
vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &srcBuf);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &dstBuf);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
VkMemoryRequirements mrq = { 0 };
|
|
|
|
vkr = ObjDisp(d)->GetBufferMemoryRequirements(Unwrap(d), srcBuf, &mrq);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
VkMemoryAllocInfo allocInfo = {
|
|
VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, NULL,
|
|
record->Length, GetReadbackMemoryIndex(mrq.memoryTypeBits),
|
|
};
|
|
|
|
allocInfo.allocationSize = AlignUp(allocInfo.allocationSize, mrq.alignment);
|
|
|
|
vkr = ObjDisp(d)->AllocMemory(Unwrap(d), &allocInfo, &mem);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
GetResourceManager()->WrapResource(Unwrap(d), mem);
|
|
|
|
vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), srcBuf, ToHandle<VkDeviceMemory>(res), 0);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), dstBuf, Unwrap(mem), 0);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT };
|
|
|
|
vkr = ObjDisp(d)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
VkBufferCopy region = { 0, 0, record->Length };
|
|
|
|
ObjDisp(d)->CmdCopyBuffer(Unwrap(cmd), srcBuf, dstBuf, 1, ®ion);
|
|
|
|
vkr = ObjDisp(d)->EndCommandBuffer(Unwrap(cmd));
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
// VKTODOLOW would be nice to store up all these buffers so that
|
|
// we don't have to submit & flush here before destroying, but
|
|
// instead could submit all cmds, then flush once, then destroy
|
|
// buffers. (or even not flush at all until capture is over)
|
|
SubmitCmds();
|
|
FlushQ();
|
|
|
|
ObjDisp(d)->DestroyBuffer(Unwrap(d), srcBuf);
|
|
ObjDisp(d)->DestroyBuffer(Unwrap(d), dstBuf);
|
|
|
|
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(GetWrapped(mem), (uint32_t)record->Length, NULL));
|
|
|
|
return true;
|
|
}
|
|
else if(type == eResImage)
|
|
{
|
|
VULKANNOTIMP("image initial states not implemented");
|
|
|
|
// VKTODOHIGH: need to copy off contents to memory somewhere else
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Unhandled resource type %d", type);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool WrappedVulkan::Serialise_InitialState(WrappedVkRes *res)
|
|
{
|
|
// use same serialiser as resource manager
|
|
Serialiser *localSerialiser = GetMainSerialiser();
|
|
|
|
SERIALISE_ELEMENT(VkResourceType, type, IdentifyTypeByPtr(res));
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(res));
|
|
|
|
if(m_State < WRITING) res = GetResourceManager()->GetLiveResource(id);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
VulkanResourceManager::InitialContentData initContents = GetResourceManager()->GetInitialContents(id);
|
|
|
|
if(type == eResDescriptorSet)
|
|
{
|
|
VkResourceRecord *record = GetResourceManager()->GetResourceRecord(id);
|
|
RDCASSERT(record->layout);
|
|
const DescSetLayout &layout = *record->layout;
|
|
|
|
VkDescriptorInfo *info = (VkDescriptorInfo *)initContents.blob;
|
|
|
|
uint32_t numElems = 0;
|
|
for(size_t i=0; i < layout.bindings.size(); i++)
|
|
numElems += layout.bindings[i].arraySize;
|
|
|
|
m_pSerialiser->SerialiseComplexArray("Bindings", info, numElems);
|
|
}
|
|
else if(type == eResDeviceMemory)
|
|
{
|
|
VkDevice d = GetDev();
|
|
|
|
byte *ptr = NULL;
|
|
ObjDisp(d)->MapMemory(Unwrap(d), ToHandle<VkDeviceMemory>(initContents.resource), 0, 0, 0, (void **)&ptr);
|
|
|
|
size_t dataSize = (size_t)initContents.num;
|
|
|
|
m_pSerialiser->SerialiseBuffer("data", ptr, dataSize);
|
|
|
|
ObjDisp(d)->UnmapMemory(Unwrap(d), ToHandle<VkDeviceMemory>(initContents.resource));
|
|
}
|
|
else if(type == eResImage)
|
|
{
|
|
VULKANNOTIMP("image initial states not implemented");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RDCASSERT(res != NULL);
|
|
|
|
ResourceId liveid = GetResourceManager()->GetLiveID(id);
|
|
|
|
if(type == eResDescriptorSet)
|
|
{
|
|
uint32_t numElems;
|
|
VkDescriptorInfo *bindings = NULL;
|
|
|
|
m_pSerialiser->SerialiseComplexArray("Bindings", bindings, numElems);
|
|
|
|
const DescSetLayout &layout = m_CreationInfo.m_DescSetLayout[ m_DescriptorSetState[liveid].layout ];
|
|
|
|
uint32_t numBinds = (uint32_t)layout.bindings.size();
|
|
|
|
// allocate memory to keep the descriptorinfo structures around, as well as a WriteDescriptorSet array
|
|
byte *blob = Serialiser::AllocAlignedBuffer(sizeof(VkDescriptorInfo)*numElems + sizeof(VkWriteDescriptorSet)*numBinds);
|
|
|
|
VkWriteDescriptorSet *writes = (VkWriteDescriptorSet *)blob;
|
|
VkDescriptorInfo *info = (VkDescriptorInfo *)(writes + numBinds);
|
|
memcpy(info, bindings, sizeof(VkDescriptorInfo)*numElems);
|
|
|
|
uint32_t validBinds = numBinds;
|
|
|
|
// i is the writedescriptor that we're updating, could be
|
|
// lower than j if a writedescriptor ended up being no-op and
|
|
// was skipped. j is the actual index.
|
|
for(uint32_t i=0, j=0; j < numBinds; j++)
|
|
{
|
|
writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
writes[i].pNext = NULL;
|
|
|
|
// update whole element (array or single)
|
|
writes[i].destSet = ToHandle<VkDescriptorSet>(res);
|
|
writes[i].destBinding = j;
|
|
writes[i].destArrayElement = 0;
|
|
writes[i].count = layout.bindings[j].arraySize;
|
|
writes[i].descriptorType = layout.bindings[j].descriptorType;
|
|
writes[i].pDescriptors = info;
|
|
|
|
info += layout.bindings[j].arraySize;
|
|
|
|
// check that the resources we need for this write are present,
|
|
// as some might have been skipped due to stale descriptor set
|
|
// slots or otherwise unreferenced objects (the descriptor set
|
|
// initial contents do not cause a frame reference for their
|
|
// resources
|
|
bool valid = true;
|
|
|
|
// quick check for slots that were completely uninitialised
|
|
// and so don't have valid data
|
|
if(writes[i].pDescriptors->bufferView == VK_NULL_HANDLE &&
|
|
writes[i].pDescriptors->sampler == VK_NULL_HANDLE &&
|
|
writes[i].pDescriptors->imageView == VK_NULL_HANDLE &&
|
|
writes[i].pDescriptors->bufferInfo.buffer == VK_NULL_HANDLE)
|
|
{
|
|
valid = false;
|
|
}
|
|
else
|
|
{
|
|
switch(writes[i].descriptorType)
|
|
{
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
{
|
|
for(uint32_t d=0; d < writes[i].count; d++)
|
|
valid &= (writes[i].pDescriptors[d].sampler != VK_NULL_HANDLE);
|
|
break;
|
|
}
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
{
|
|
for(uint32_t d=0; d < writes[i].count; d++)
|
|
{
|
|
valid &= (writes[i].pDescriptors[d].sampler != VK_NULL_HANDLE);
|
|
valid &= (writes[i].pDescriptors[d].imageView != VK_NULL_HANDLE);
|
|
}
|
|
break;
|
|
}
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
{
|
|
for(uint32_t d=0; d < writes[i].count; d++)
|
|
valid &= (writes[i].pDescriptors[d].imageView != VK_NULL_HANDLE);
|
|
break;
|
|
}
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
{
|
|
for(uint32_t d=0; d < writes[i].count; d++)
|
|
valid &= (writes[i].pDescriptors[d].bufferView != VK_NULL_HANDLE);
|
|
break;
|
|
}
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
{
|
|
for(uint32_t d=0; d < writes[i].count; d++)
|
|
valid &= (writes[i].pDescriptors[d].bufferInfo.buffer != VK_NULL_HANDLE);
|
|
break;
|
|
}
|
|
default:
|
|
RDCERR("Unexpected descriptor type %d", writes[i].descriptorType);
|
|
}
|
|
}
|
|
|
|
// if this write is not valid, skip it
|
|
// and start writing the next one in here
|
|
if(!valid)
|
|
validBinds--;
|
|
else
|
|
i++;
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY(bindings);
|
|
|
|
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, validBinds, blob));
|
|
}
|
|
else if(type == eResDeviceMemory)
|
|
{
|
|
byte *data = NULL;
|
|
size_t dataSize = 0;
|
|
m_pSerialiser->SerialiseBuffer("data", data, dataSize);
|
|
|
|
VkResult vkr = VK_SUCCESS;
|
|
|
|
VkDevice d = GetDev();
|
|
|
|
VkDeviceMemory mem = VK_NULL_HANDLE;
|
|
|
|
// VKTODOMED should get mem requirements for buffer - copy might enforce
|
|
// some restrictions?
|
|
VkMemoryRequirements mrq = { dataSize, 16, ~0U };
|
|
|
|
VkMemoryAllocInfo allocInfo = {
|
|
VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, NULL,
|
|
dataSize, GetUploadMemoryIndex(mrq.memoryTypeBits),
|
|
};
|
|
|
|
vkr = ObjDisp(d)->AllocMemory(Unwrap(d), &allocInfo, &mem);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
GetResourceManager()->WrapResource(Unwrap(d), mem);
|
|
|
|
VkBufferCreateInfo bufInfo = {
|
|
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL,
|
|
dataSize, VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0,
|
|
VK_SHARING_MODE_EXCLUSIVE, 0, NULL,
|
|
};
|
|
|
|
VkBuffer buf;
|
|
|
|
vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &buf);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
GetResourceManager()->WrapResource(Unwrap(d), buf);
|
|
|
|
vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), Unwrap(buf), Unwrap(mem), 0);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
byte *ptr = NULL;
|
|
ObjDisp(d)->MapMemory(Unwrap(d), Unwrap(mem), 0, 0, 0, (void **)&ptr);
|
|
|
|
// VKTODOLOW could deserialise directly into this ptr if we serialised
|
|
// size separately.
|
|
memcpy(ptr, data, dataSize);
|
|
|
|
ObjDisp(d)->UnmapMemory(Unwrap(d), Unwrap(mem));
|
|
|
|
SAFE_DELETE_ARRAY(data);
|
|
|
|
m_FreeMems.push_back(mem);
|
|
|
|
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(GetWrapped(buf), (uint32_t)dataSize, NULL));
|
|
}
|
|
else if(type == eResImage)
|
|
{
|
|
VULKANNOTIMP("image initial states not implemented");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedVulkan::Create_InitialState(ResourceId id, WrappedVkRes *live, bool hasData)
|
|
{
|
|
VkResourceType type = IdentifyTypeByPtr(live);
|
|
|
|
if(type == eResDescriptorSet)
|
|
{
|
|
// VKTODOMED need to create some default initial state for descriptor sets.
|
|
// if a descriptor set is alloc'd then used in frame we won't have prepared anything,
|
|
// but likewise all writes must happen within that frame so the initial state doesn't
|
|
// technically matter. We assume the app doesn't try to read from an uninitialised
|
|
// descriptor, so for now we can leave the initial state empty.
|
|
VULKANNOTIMP("Need to create initial state for descriptor set");
|
|
}
|
|
else if(type == eResImage)
|
|
{
|
|
VULKANNOTIMP("image initial states not implemented");
|
|
|
|
ResourceId liveid = GetResourceManager()->GetLiveID(id);
|
|
|
|
if(m_ImageLayouts.find(liveid) == m_ImageLayouts.end())
|
|
{
|
|
RDCERR("Couldn't find image info for %llu", id);
|
|
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, eInitialContents_ClearColorImage, NULL));
|
|
return;
|
|
}
|
|
|
|
ImageLayouts &layouts = m_ImageLayouts[liveid];
|
|
|
|
if(layouts.subresourceStates[0].range.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
|
|
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, eInitialContents_ClearColorImage, NULL));
|
|
else
|
|
GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(NULL, eInitialContents_ClearDepthStencilImage, NULL));
|
|
}
|
|
else if(type == eResDeviceMemory)
|
|
{
|
|
// ignore, it was probably dirty but not referenced in the frame
|
|
}
|
|
else if(type == eResFramebuffer)
|
|
{
|
|
RDCWARN("Framebuffer without initial state! should clear all attachments");
|
|
}
|
|
else if(type == eResBuffer)
|
|
{
|
|
// don't have to do anything for buffers, initial state is all handled by memory
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Unhandled resource type %d", type);
|
|
}
|
|
}
|
|
|
|
void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VulkanResourceManager::InitialContentData initial)
|
|
{
|
|
VkResourceType type = IdentifyTypeByPtr(live);
|
|
|
|
ResourceId id = GetResourceManager()->GetID(live);
|
|
|
|
if(type == eResDescriptorSet)
|
|
{
|
|
VkWriteDescriptorSet *writes = (VkWriteDescriptorSet *)initial.blob;
|
|
|
|
// if it ended up that no descriptors were valid, just skip
|
|
if(initial.num == 0)
|
|
return;
|
|
|
|
ObjDisp(GetDev())->UpdateDescriptorSets(Unwrap(GetDev()), initial.num, writes, 0, NULL);
|
|
|
|
// need to blat over the current descriptor set contents, so these are available
|
|
// when we want to fetch pipeline state
|
|
vector<VkDescriptorInfo *> &bindings = m_DescriptorSetState[id].currentBindings;
|
|
|
|
for(uint32_t i=0; i < initial.num; i++)
|
|
{
|
|
RDCASSERT(writes[i].destBinding < bindings.size());
|
|
RDCASSERT(writes[i].destArrayElement == 0);
|
|
|
|
VkDescriptorInfo *bind = bindings[writes[i].destBinding];
|
|
|
|
for(uint32_t d=0; d < writes[i].count; d++)
|
|
bind[d] = writes[i].pDescriptors[d];
|
|
}
|
|
}
|
|
else if(type == eResDeviceMemory)
|
|
{
|
|
VkBuffer srcBuf = (VkBuffer)(uint64_t)initial.resource;
|
|
uint32_t memsize = initial.num;
|
|
VkDeviceMemory dstMem = (VkDeviceMemory)(uint64_t)live; // maintain the wrapping, for consistency
|
|
|
|
VkResult vkr = VK_SUCCESS;
|
|
|
|
VkDevice d = GetDev();
|
|
VkCmdBuffer cmd = GetNextCmd();
|
|
|
|
VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT };
|
|
|
|
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
VkBufferCreateInfo bufInfo = {
|
|
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL,
|
|
memsize, VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0,
|
|
VK_SHARING_MODE_EXCLUSIVE, 0, NULL,
|
|
};
|
|
|
|
// since this is short lived it isn't wrapped. Note that we want
|
|
// to cache this up front, so it will then be wrapped
|
|
VkBuffer dstBuf;
|
|
|
|
// VKTODOMED this should be created once up front, not every time
|
|
vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &dstBuf);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), dstBuf, Unwrap(dstMem), 0);
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
VkBufferCopy region = { 0, 0, memsize };
|
|
|
|
ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), dstBuf, 1, ®ion);
|
|
|
|
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
|
|
RDCASSERT(vkr == VK_SUCCESS);
|
|
|
|
// VKTODOLOW if this dstBuf was persistent or at least cached
|
|
// we could batch these command buffers better and wouldn't
|
|
// need to flush at all until application of all init states
|
|
// is over
|
|
SubmitCmds();
|
|
FlushQ();
|
|
|
|
ObjDisp(d)->DestroyBuffer(Unwrap(d), dstBuf);
|
|
}
|
|
else if(type == eResImage)
|
|
{
|
|
// VKTODOHIGH: need to copy initial copy to live
|
|
VULKANNOTIMP("image initial states not implemented");
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Unhandled resource type %d", type);
|
|
}
|
|
}
|
|
|