Add support for VK_KHR_create_renderpass2

This commit is contained in:
baldurk
2018-10-11 16:14:55 +01:00
parent d8dc4d95ec
commit 03cddbf283
10 changed files with 947 additions and 28 deletions
+14
View File
@@ -465,6 +465,10 @@ enum class VulkanChunk : uint32_t
vkGetDeviceQueue2,
vkCmdDrawIndirectCountKHR,
vkCmdDrawIndexedIndirectCountKHR,
vkCreateRenderPass2KHR,
vkCmdBeginRenderPass2KHR,
vkCmdNextSubpass2KHR,
vkCmdEndRenderPass2KHR,
Max,
};
@@ -654,6 +658,13 @@ DECLARE_REFLECTION_STRUCT(VkProtectedSubmitInfo);
DECLARE_REFLECTION_STRUCT(VkImageFormatListCreateInfoKHR);
DECLARE_REFLECTION_STRUCT(VkImageViewASTCDecodeModeEXT);
DECLARE_REFLECTION_STRUCT(VkShaderModuleValidationCacheCreateInfoEXT);
DECLARE_REFLECTION_STRUCT(VkAttachmentDescription2KHR);
DECLARE_REFLECTION_STRUCT(VkSubpassDescription2KHR);
DECLARE_REFLECTION_STRUCT(VkSubpassDependency2KHR);
DECLARE_REFLECTION_STRUCT(VkAttachmentReference2KHR);
DECLARE_REFLECTION_STRUCT(VkRenderPassCreateInfo2KHR);
DECLARE_REFLECTION_STRUCT(VkSubpassBeginInfoKHR);
DECLARE_REFLECTION_STRUCT(VkSubpassEndInfoKHR);
DECLARE_REFLECTION_STRUCT(VkDispatchIndirectCommand);
DECLARE_REFLECTION_STRUCT(VkDrawIndirectCommand);
DECLARE_REFLECTION_STRUCT(VkDrawIndexedIndirectCommand);
@@ -733,6 +744,9 @@ DECLARE_DESERIALISE_TYPE(VkDeviceGroupRenderPassBeginInfo);
DECLARE_DESERIALISE_TYPE(VkMemoryAllocateFlagsInfo);
DECLARE_DESERIALISE_TYPE(VkProtectedSubmitInfo);
DECLARE_DESERIALISE_TYPE(VkImageFormatListCreateInfoKHR);
DECLARE_DESERIALISE_TYPE(VkRenderPassCreateInfo2KHR);
DECLARE_DESERIALISE_TYPE(VkSubpassBeginInfoKHR);
DECLARE_DESERIALISE_TYPE(VkSubpassEndInfoKHR);
#if defined(VK_KHR_external_memory_win32) || defined(VK_NV_external_memory_win32)
DECLARE_REFLECTION_STRUCT(VkImportMemoryWin32HandleInfoNV);
+12
View File
@@ -699,6 +699,9 @@ static const VkExtensionProperties supportedExtensions[] = {
{
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_KHR_BIND_MEMORY_2_SPEC_VERSION,
},
{
VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION,
},
{
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION,
},
@@ -2670,6 +2673,15 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
VK_NULL_HANDLE, 0, 0, 0);
break;
case VulkanChunk::vkCreateRenderPass2KHR:
return Serialise_vkCreateRenderPass2KHR(ser, VK_NULL_HANDLE, NULL, NULL, NULL);
case VulkanChunk::vkCmdBeginRenderPass2KHR:
return Serialise_vkCmdBeginRenderPass2KHR(ser, VK_NULL_HANDLE, NULL, NULL);
case VulkanChunk::vkCmdNextSubpass2KHR:
return Serialise_vkCmdNextSubpass2KHR(ser, VK_NULL_HANDLE, NULL, NULL);
case VulkanChunk::vkCmdEndRenderPass2KHR:
return Serialise_vkCmdEndRenderPass2KHR(ser, VK_NULL_HANDLE, NULL);
default:
{
SystemChunk system = (SystemChunk)chunk;
+14 -2
View File
@@ -742,8 +742,6 @@ private:
std::vector<VkImageMemoryBarrier> GetImplicitRenderPassBarriers(uint32_t subpass = 0);
string MakeRenderPassOpString(bool store);
void MakeSubpassLoadRP(VkRenderPassCreateInfo &info, const VkRenderPassCreateInfo *origInfo,
uint32_t s);
bool IsDrawInRenderPass();
@@ -1915,4 +1913,18 @@ public:
// VK_KHR_shared_presentable_image
VkResult vkGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain);
// VK_KHR_create_renderpass2
IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkCreateRenderPass2KHR, VkDevice device,
const VkRenderPassCreateInfo2KHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdBeginRenderPass2KHR, VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo *pRenderPassBegin,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo);
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdNextSubpass2KHR, VkCommandBuffer commandBuffer,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
const VkSubpassEndInfoKHR *pSubpassEndInfo);
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdEndRenderPass2KHR, VkCommandBuffer commandBuffer,
const VkSubpassEndInfoKHR *pSubpassEndInfo);
\
};
+17 -1
View File
@@ -351,7 +351,8 @@
CheckExt(MVK_moltenvk, VKXX); \
CheckExt(KHR_draw_indirect_count, VKXX); \
CheckExt(EXT_validation_cache, VKXX); \
CheckExt(KHR_shared_presentable_image, VKXX);
CheckExt(KHR_shared_presentable_image, VKXX); \
CheckExt(KHR_create_renderpass2, VKXX);
#define HookInitVulkanInstanceExts() \
HookInitExtension(KHR_surface, DestroySurfaceKHR); \
@@ -468,6 +469,10 @@
HookInitExtension(EXT_validation_cache, MergeValidationCachesEXT); \
HookInitExtension(EXT_validation_cache, GetValidationCacheDataEXT); \
HookInitExtension(KHR_shared_presentable_image, GetSwapchainStatusKHR); \
HookInitExtension(KHR_create_renderpass2, CreateRenderPass2KHR); \
HookInitExtension(KHR_create_renderpass2, CmdBeginRenderPass2KHR); \
HookInitExtension(KHR_create_renderpass2, CmdNextSubpass2KHR); \
HookInitExtension(KHR_create_renderpass2, CmdEndRenderPass2KHR); \
HookInitDevice_PlatformSpecific()
#define DefineHooks() \
@@ -994,6 +999,17 @@
HookDefine4(VkResult, vkGetValidationCacheDataEXT, VkDevice, device, VkValidationCacheEXT, \
validationCache, size_t *, pDataSize, void *, pData); \
HookDefine2(VkResult, vkGetSwapchainStatusKHR, VkDevice, device, VkSwapchainKHR, swapchain); \
HookDefine4(VkResult, vkCreateRenderPass2KHR, VkDevice, device, \
const VkRenderPassCreateInfo2KHR *, pCreateInfo, const VkAllocationCallbacks *, \
pAllocator, VkRenderPass *, pRenderPass); \
HookDefine3(void, vkCmdBeginRenderPass2KHR, VkCommandBuffer, commandBuffer, \
const VkRenderPassBeginInfo *, pRenderPassBegin, const VkSubpassBeginInfoKHR *, \
pSubpassBeginInfo); \
HookDefine3(void, vkCmdNextSubpass2KHR, VkCommandBuffer, commandBuffer, \
const VkSubpassBeginInfoKHR *, pSubpassBeginInfo, const VkSubpassEndInfoKHR *, \
pSubpassEndInfo); \
HookDefine2(void, vkCmdEndRenderPass2KHR, VkCommandBuffer, commandBuffer, \
const VkSubpassEndInfoKHR *, pSubpassEndInfo); \
HookDefine_PlatformSpecific()
struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable
+75 -2
View File
@@ -503,9 +503,20 @@ void VulkanCreationInfo::RenderPass::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info,
const VkRenderPassCreateInfo *pCreateInfo)
{
attachments.reserve(pCreateInfo->attachmentCount);
attachments.resize(pCreateInfo->attachmentCount);
for(uint32_t i = 0; i < pCreateInfo->attachmentCount; i++)
attachments.push_back(pCreateInfo->pAttachments[i]);
{
Attachment &dst = attachments[i];
dst.flags = pCreateInfo->pAttachments[i].flags;
dst.format = pCreateInfo->pAttachments[i].format;
dst.samples = pCreateInfo->pAttachments[i].samples;
dst.loadOp = pCreateInfo->pAttachments[i].loadOp;
dst.storeOp = pCreateInfo->pAttachments[i].storeOp;
dst.stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp;
dst.stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp;
dst.initialLayout = pCreateInfo->pAttachments[i].initialLayout;
dst.finalLayout = pCreateInfo->pAttachments[i].finalLayout;
}
// VK_KHR_multiview
const VkRenderPassMultiviewCreateInfo *multiview =
@@ -559,6 +570,68 @@ void VulkanCreationInfo::RenderPass::Init(VulkanResourceManager *resourceMan,
}
}
void VulkanCreationInfo::RenderPass::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info,
const VkRenderPassCreateInfo2KHR *pCreateInfo)
{
attachments.resize(pCreateInfo->attachmentCount);
for(uint32_t i = 0; i < pCreateInfo->attachmentCount; i++)
{
Attachment &dst = attachments[i];
dst.flags = pCreateInfo->pAttachments[i].flags;
dst.format = pCreateInfo->pAttachments[i].format;
dst.samples = pCreateInfo->pAttachments[i].samples;
dst.loadOp = pCreateInfo->pAttachments[i].loadOp;
dst.storeOp = pCreateInfo->pAttachments[i].storeOp;
dst.stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp;
dst.stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp;
dst.initialLayout = pCreateInfo->pAttachments[i].initialLayout;
dst.finalLayout = pCreateInfo->pAttachments[i].finalLayout;
}
subpasses.resize(pCreateInfo->subpassCount);
for(uint32_t subp = 0; subp < pCreateInfo->subpassCount; subp++)
{
const VkSubpassDescription2KHR &src = pCreateInfo->pSubpasses[subp];
Subpass &dst = subpasses[subp];
dst.inputAttachments.resize(src.inputAttachmentCount);
dst.inputLayouts.resize(src.inputAttachmentCount);
for(uint32_t i = 0; i < src.inputAttachmentCount; i++)
{
dst.inputAttachments[i] = src.pInputAttachments[i].attachment;
dst.inputLayouts[i] = src.pInputAttachments[i].layout;
}
dst.colorAttachments.resize(src.colorAttachmentCount);
dst.resolveAttachments.resize(src.colorAttachmentCount);
dst.colorLayouts.resize(src.colorAttachmentCount);
for(uint32_t i = 0; i < src.colorAttachmentCount; i++)
{
dst.resolveAttachments[i] =
src.pResolveAttachments ? src.pResolveAttachments[i].attachment : ~0U;
dst.colorAttachments[i] = src.pColorAttachments[i].attachment;
dst.colorLayouts[i] = src.pColorAttachments[i].layout;
}
dst.depthstencilAttachment =
(src.pDepthStencilAttachment != NULL &&
src.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED
? (int32_t)src.pDepthStencilAttachment->attachment
: -1);
dst.depthstencilLayout = (src.pDepthStencilAttachment != NULL &&
src.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED
? src.pDepthStencilAttachment->layout
: VK_IMAGE_LAYOUT_UNDEFINED);
for(uint32_t i = 0; i < 32; i++)
{
if(src.viewMask & (1 << i))
dst.multiviews.push_back(i);
}
}
}
void VulkanCreationInfo::Framebuffer::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info,
const VkFramebufferCreateInfo *pCreateInfo)
+16 -1
View File
@@ -252,8 +252,23 @@ struct VulkanCreationInfo
{
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkRenderPassCreateInfo *pCreateInfo);
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkRenderPassCreateInfo2KHR *pCreateInfo);
vector<VkAttachmentDescription> attachments;
struct Attachment
{
VkAttachmentDescriptionFlags flags;
VkFormat format;
VkSampleCountFlagBits samples;
VkAttachmentLoadOp loadOp;
VkAttachmentStoreOp storeOp;
VkAttachmentLoadOp stencilLoadOp;
VkAttachmentStoreOp stencilStoreOp;
VkImageLayout initialLayout;
VkImageLayout finalLayout;
};
vector<Attachment> attachments;
struct Subpass
{
+156
View File
@@ -2560,6 +2560,159 @@ void DoSerialise(SerialiserType &ser, VkShaderModuleValidationCacheCreateInfoEXT
// SERIALISE_MEMBER(validationCache);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkAttachmentDescription2KHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER_TYPED(VkAttachmentDescriptionFlagBits, flags);
SERIALISE_MEMBER(format);
SERIALISE_MEMBER(samples);
SERIALISE_MEMBER(loadOp);
SERIALISE_MEMBER(storeOp);
SERIALISE_MEMBER(stencilLoadOp);
SERIALISE_MEMBER(stencilStoreOp);
SERIALISE_MEMBER(initialLayout);
SERIALISE_MEMBER(finalLayout);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkAttachmentReference2KHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER(attachment);
SERIALISE_MEMBER(layout);
SERIALISE_MEMBER(aspectMask);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSubpassDescription2KHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER_TYPED(VkSubpassDescriptionFlagBits, flags);
SERIALISE_MEMBER(pipelineBindPoint);
SERIALISE_MEMBER(viewMask);
SERIALISE_MEMBER(inputAttachmentCount);
SERIALISE_MEMBER_ARRAY(pInputAttachments, inputAttachmentCount);
SERIALISE_MEMBER(colorAttachmentCount);
SERIALISE_MEMBER_ARRAY(pColorAttachments, colorAttachmentCount);
SERIALISE_MEMBER_ARRAY(pResolveAttachments, colorAttachmentCount);
SERIALISE_MEMBER_OPT(pDepthStencilAttachment);
SERIALISE_MEMBER(preserveAttachmentCount);
SERIALISE_MEMBER_ARRAY(pPreserveAttachments, preserveAttachmentCount);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSubpassDependency2KHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER(srcSubpass);
SERIALISE_MEMBER(dstSubpass);
SERIALISE_MEMBER_TYPED(VkPipelineStageFlagBits, srcStageMask);
SERIALISE_MEMBER_TYPED(VkPipelineStageFlagBits, dstStageMask);
SERIALISE_MEMBER_TYPED(VkAccessFlagBits, srcAccessMask);
SERIALISE_MEMBER_TYPED(VkAccessFlagBits, dstAccessMask);
SERIALISE_MEMBER_TYPED(VkDependencyFlagBits, dependencyFlags);
SERIALISE_MEMBER(viewOffset);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkRenderPassCreateInfo2KHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
SERIALISE_MEMBER(attachmentCount);
SERIALISE_MEMBER_ARRAY(pAttachments, attachmentCount);
SERIALISE_MEMBER(subpassCount);
SERIALISE_MEMBER_ARRAY(pSubpasses, subpassCount);
SERIALISE_MEMBER(dependencyCount);
SERIALISE_MEMBER_ARRAY(pDependencies, dependencyCount);
SERIALISE_MEMBER(correlatedViewMaskCount);
SERIALISE_MEMBER_ARRAY(pCorrelatedViewMasks, correlatedViewMaskCount);
}
template <>
void Deserialise(const VkRenderPassCreateInfo2KHR &el)
{
DeserialiseNext(el.pNext);
for(uint32_t i = 0; i < el.attachmentCount; i++)
{
DeserialiseNext(el.pAttachments[i].pNext);
}
delete[] el.pAttachments;
for(uint32_t i = 0; i < el.subpassCount; i++)
{
DeserialiseNext(el.pSubpasses[i].pNext);
if(el.pSubpasses[i].pDepthStencilAttachment)
DeserialiseNext(el.pSubpasses[i].pDepthStencilAttachment->pNext);
for(uint32_t j = 0; j < el.pSubpasses[i].colorAttachmentCount; j++)
{
DeserialiseNext(el.pSubpasses[i].pColorAttachments[j].pNext);
if(el.pSubpasses[i].pResolveAttachments)
DeserialiseNext(el.pSubpasses[i].pResolveAttachments[j].pNext);
}
for(uint32_t j = 0; j < el.pSubpasses[i].inputAttachmentCount; j++)
DeserialiseNext(el.pSubpasses[i].pInputAttachments[j].pNext);
delete el.pSubpasses[i].pDepthStencilAttachment;
delete[] el.pSubpasses[i].pInputAttachments;
delete[] el.pSubpasses[i].pColorAttachments;
delete[] el.pSubpasses[i].pResolveAttachments;
delete[] el.pSubpasses[i].pPreserveAttachments;
}
delete[] el.pSubpasses;
for(uint32_t i = 0; i < el.dependencyCount; i++)
{
DeserialiseNext(el.pDependencies[i].pNext);
}
delete[] el.pDependencies;
delete[] el.pCorrelatedViewMasks;
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSubpassBeginInfoKHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER(contents);
}
template <>
void Deserialise(const VkSubpassBeginInfoKHR &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSubpassEndInfoKHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR);
SerialiseNext(ser, el.sType, el.pNext);
}
template <>
void Deserialise(const VkSubpassEndInfoKHR &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkDispatchIndirectCommand &el)
{
@@ -3177,6 +3330,9 @@ INSTANTIATE_SERIALISE_TYPE(VkProtectedSubmitInfo);
INSTANTIATE_SERIALISE_TYPE(VkImageFormatListCreateInfoKHR);
INSTANTIATE_SERIALISE_TYPE(VkImageViewASTCDecodeModeEXT);
INSTANTIATE_SERIALISE_TYPE(VkShaderModuleValidationCacheCreateInfoEXT);
INSTANTIATE_SERIALISE_TYPE(VkRenderPassCreateInfo2KHR);
INSTANTIATE_SERIALISE_TYPE(VkSubpassBeginInfoKHR);
INSTANTIATE_SERIALISE_TYPE(VkSubpassEndInfoKHR);
INSTANTIATE_SERIALISE_TYPE(VkDispatchIndirectCommand);
INSTANTIATE_SERIALISE_TYPE(VkDrawIndirectCommand);
INSTANTIATE_SERIALISE_TYPE(VkDrawIndexedIndirectCommand);
+5 -1
View File
@@ -28,7 +28,7 @@
template <>
std::string DoStringise(const VulkanChunk &el)
{
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1118, "Chunks changed without updating names");
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1122, "Chunks changed without updating names");
BEGIN_ENUM_STRINGISE(VulkanChunk)
{
@@ -150,6 +150,10 @@ std::string DoStringise(const VulkanChunk &el)
STRINGISE_ENUM_CLASS(vkGetDeviceQueue2);
STRINGISE_ENUM_CLASS(vkCmdDrawIndirectCountKHR);
STRINGISE_ENUM_CLASS(vkCmdDrawIndexedIndirectCountKHR);
STRINGISE_ENUM_CLASS(vkCreateRenderPass2KHR);
STRINGISE_ENUM_CLASS(vkCmdBeginRenderPass2KHR);
STRINGISE_ENUM_CLASS(vkCmdNextSubpass2KHR);
STRINGISE_ENUM_CLASS(vkCmdEndRenderPass2KHR);
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
}
END_ENUM_STRINGISE()
@@ -219,7 +219,7 @@ string WrappedVulkan::MakeRenderPassOpString(bool store)
const VulkanCreationInfo::Framebuffer &fbinfo =
m_CreationInfo.m_Framebuffer[m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer];
const vector<VkAttachmentDescription> &atts = info.attachments;
const vector<VulkanCreationInfo::RenderPass::Attachment> &atts = info.attachments;
if(atts.empty())
{
@@ -1352,6 +1352,389 @@ void WrappedVulkan::vkCmdEndRenderPass(VkCommandBuffer commandBuffer)
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdBeginRenderPass2KHR(SerialiserType &ser,
VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo *pRenderPassBegin,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo)
{
SERIALISE_ELEMENT(commandBuffer);
SERIALISE_ELEMENT_LOCAL(RenderPassBegin, *pRenderPassBegin);
SERIALISE_ELEMENT_LOCAL(SubpassBegin, *pSubpassBeginInfo);
Serialise_DebugMessages(ser);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
VkRenderPassBeginInfo unwrappedInfo = RenderPassBegin;
unwrappedInfo.renderPass = Unwrap(unwrappedInfo.renderPass);
unwrappedInfo.framebuffer = Unwrap(unwrappedInfo.framebuffer);
VkSubpassBeginInfoKHR unwrappedBeginInfo = SubpassBegin;
byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedInfo.pNext) +
GetNextPatchSize(unwrappedBeginInfo.pNext));
UnwrapNextChain(m_State, "VkRenderPassBeginInfo", tempMem, (VkBaseInStructure *)&unwrappedInfo);
UnwrapNextChain(m_State, "VkSubpassBeginInfoKHR", tempMem,
(VkBaseInStructure *)&unwrappedBeginInfo);
m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer));
if(IsActiveReplaying(m_State))
{
if(InRerecordRange(m_LastCmdBufferID))
{
commandBuffer = RerecordCmdBuf(m_LastCmdBufferID);
// always track this, for WrappedVulkan::IsDrawInRenderPass()
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass = 0;
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass =
GetResID(RenderPassBegin.renderPass);
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer =
GetResID(RenderPassBegin.framebuffer);
// only if we're partially recording do we update this state
if(ShouldUpdateRenderState(m_LastCmdBufferID, true))
{
m_Partial[Primary].renderPassActive = true;
m_RenderState.subpass = 0;
m_RenderState.renderPass = GetResID(RenderPassBegin.renderPass);
m_RenderState.framebuffer = GetResID(RenderPassBegin.framebuffer);
m_RenderState.renderArea = RenderPassBegin.renderArea;
}
ObjDisp(commandBuffer)
->CmdBeginRenderPass2KHR(Unwrap(commandBuffer), &unwrappedInfo, &unwrappedBeginInfo);
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
(uint32_t)imgBarriers.size(), imgBarriers.data());
}
}
else
{
ObjDisp(commandBuffer)
->CmdBeginRenderPass2KHR(Unwrap(commandBuffer), &unwrappedInfo, &unwrappedBeginInfo);
// track while reading, for fetching the right set of outputs in AddDrawcall
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass = 0;
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = GetResID(RenderPassBegin.renderPass);
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer =
GetResID(RenderPassBegin.framebuffer);
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
(uint32_t)imgBarriers.size(), imgBarriers.data());
AddEvent();
DrawcallDescription draw;
draw.name =
StringFormat::Fmt("vkCmdBeginRenderPass2KHR(%s)", MakeRenderPassOpString(false).c_str());
draw.flags |= DrawFlags::PassBoundary | DrawFlags::BeginPass;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedVulkan::vkCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo *pRenderPassBegin,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo)
{
SCOPED_DBG_SINK();
VkRenderPassBeginInfo unwrappedInfo = *pRenderPassBegin;
unwrappedInfo.renderPass = Unwrap(unwrappedInfo.renderPass);
unwrappedInfo.framebuffer = Unwrap(unwrappedInfo.framebuffer);
VkSubpassBeginInfoKHR unwrappedBeginInfo = *pSubpassBeginInfo;
byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedInfo.pNext) +
GetNextPatchSize(unwrappedBeginInfo.pNext));
UnwrapNextChain(m_State, "VkRenderPassBeginInfo", tempMem, (VkBaseInStructure *)&unwrappedInfo);
UnwrapNextChain(m_State, "VkSubpassBeginInfoKHR", tempMem,
(VkBaseInStructure *)&unwrappedBeginInfo);
SERIALISE_TIME_CALL(
ObjDisp(commandBuffer)
->CmdBeginRenderPass2KHR(Unwrap(commandBuffer), &unwrappedInfo, &unwrappedBeginInfo));
if(IsCaptureMode(m_State))
{
VkResourceRecord *record = GetRecord(commandBuffer);
CACHE_THREAD_SERIALISER();
ser.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginRenderPass2KHR);
Serialise_vkCmdBeginRenderPass2KHR(ser, commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
record->AddChunk(scope.Get());
record->MarkResourceFrameReferenced(GetResID(pRenderPassBegin->renderPass), eFrameRef_Read);
VkResourceRecord *fb = GetRecord(pRenderPassBegin->framebuffer);
record->MarkResourceFrameReferenced(fb->GetResourceID(), eFrameRef_Read);
for(size_t i = 0; fb->imageAttachments[i].barrier.sType; i++)
{
VkResourceRecord *att = fb->imageAttachments[i].record;
if(att == NULL)
break;
record->MarkResourceFrameReferenced(att->baseResource, eFrameRef_Write);
if(att->baseResourceMem != ResourceId())
record->MarkResourceFrameReferenced(att->baseResourceMem, eFrameRef_Read);
if(att->sparseInfo)
record->cmdInfo->sparse.insert(att->sparseInfo);
record->cmdInfo->dirtied.insert(att->baseResource);
}
record->cmdInfo->framebuffer = fb;
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdNextSubpass2KHR(SerialiserType &ser, VkCommandBuffer commandBuffer,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
const VkSubpassEndInfoKHR *pSubpassEndInfo)
{
SERIALISE_ELEMENT(commandBuffer);
SERIALISE_ELEMENT_LOCAL(SubpassBegin, *pSubpassBeginInfo);
SERIALISE_ELEMENT_LOCAL(SubpassEnd, *pSubpassEndInfo);
Serialise_DebugMessages(ser);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
VkSubpassBeginInfoKHR unwrappedBeginInfo = SubpassBegin;
VkSubpassEndInfoKHR unwrappedEndInfo = SubpassEnd;
byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedBeginInfo.pNext) +
GetNextPatchSize(unwrappedEndInfo.pNext));
UnwrapNextChain(m_State, "VkSubpassBeginInfoKHR", tempMem,
(VkBaseInStructure *)&unwrappedBeginInfo);
UnwrapNextChain(m_State, "VkSubpassEndInfoKHR", tempMem, (VkBaseInStructure *)&unwrappedEndInfo);
m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer));
if(IsActiveReplaying(m_State))
{
// don't do anything if we're executing a single draw, NextSubpass is meaningless (and invalid
// on a partial render pass)
if(InRerecordRange(m_LastCmdBufferID) && m_FirstEventID != m_LastEventID)
{
commandBuffer = RerecordCmdBuf(m_LastCmdBufferID);
// always track this, for WrappedVulkan::IsDrawInRenderPass()
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass++;
if(ShouldUpdateRenderState(m_LastCmdBufferID, true))
m_RenderState.subpass++;
ObjDisp(commandBuffer)
->CmdNextSubpass2KHR(Unwrap(commandBuffer), &unwrappedBeginInfo, &unwrappedEndInfo);
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
(uint32_t)imgBarriers.size(), imgBarriers.data());
}
}
else
{
ObjDisp(commandBuffer)
->CmdNextSubpass2KHR(Unwrap(commandBuffer), &unwrappedBeginInfo, &unwrappedEndInfo);
// track while reading, for fetching the right set of outputs in AddDrawcall
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass++;
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
(uint32_t)imgBarriers.size(), &imgBarriers[0]);
AddEvent();
DrawcallDescription draw;
draw.name = StringFormat::Fmt("vkCmdNextSubpass2KHR() => %u",
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass);
draw.flags |= DrawFlags::PassBoundary | DrawFlags::BeginPass | DrawFlags::EndPass;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedVulkan::vkCmdNextSubpass2KHR(VkCommandBuffer commandBuffer,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
const VkSubpassEndInfoKHR *pSubpassEndInfo)
{
SCOPED_DBG_SINK();
VkSubpassBeginInfoKHR unwrappedBeginInfo = *pSubpassBeginInfo;
VkSubpassEndInfoKHR unwrappedEndInfo = *pSubpassEndInfo;
byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedBeginInfo.pNext) +
GetNextPatchSize(unwrappedEndInfo.pNext));
UnwrapNextChain(m_State, "VkSubpassBeginInfoKHR", tempMem,
(VkBaseInStructure *)&unwrappedBeginInfo);
UnwrapNextChain(m_State, "VkSubpassEndInfoKHR", tempMem, (VkBaseInStructure *)&unwrappedEndInfo);
SERIALISE_TIME_CALL(
ObjDisp(commandBuffer)
->CmdNextSubpass2KHR(Unwrap(commandBuffer), &unwrappedBeginInfo, &unwrappedEndInfo));
if(IsCaptureMode(m_State))
{
VkResourceRecord *record = GetRecord(commandBuffer);
CACHE_THREAD_SERIALISER();
ser.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdNextSubpass2KHR);
Serialise_vkCmdNextSubpass2KHR(ser, commandBuffer, pSubpassBeginInfo, pSubpassEndInfo);
record->AddChunk(scope.Get());
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdEndRenderPass2KHR(SerialiserType &ser,
VkCommandBuffer commandBuffer,
const VkSubpassEndInfoKHR *pSubpassEndInfo)
{
SERIALISE_ELEMENT(commandBuffer);
SERIALISE_ELEMENT_LOCAL(SubpassEnd, *pSubpassEndInfo);
Serialise_DebugMessages(ser);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
VkSubpassEndInfoKHR unwrappedEndInfo = SubpassEnd;
byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedEndInfo.pNext));
UnwrapNextChain(m_State, "VkSubpassEndInfoKHR", tempMem, (VkBaseInStructure *)&unwrappedEndInfo);
m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer));
if(IsActiveReplaying(m_State))
{
if(InRerecordRange(m_LastCmdBufferID))
{
commandBuffer = RerecordCmdBuf(m_LastCmdBufferID);
// always track this, for WrappedVulkan::IsDrawInRenderPass()
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = ResourceId();
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer = ResourceId();
if(ShouldUpdateRenderState(m_LastCmdBufferID, true))
{
m_Partial[Primary].renderPassActive = false;
}
ObjDisp(commandBuffer)->CmdEndRenderPass2KHR(Unwrap(commandBuffer), &unwrappedEndInfo);
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers(~0U);
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
(uint32_t)imgBarriers.size(), imgBarriers.data());
}
}
else
{
ObjDisp(commandBuffer)->CmdEndRenderPass2KHR(Unwrap(commandBuffer), &unwrappedEndInfo);
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers(~0U);
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
(uint32_t)imgBarriers.size(), &imgBarriers[0]);
AddEvent();
DrawcallDescription draw;
draw.name =
StringFormat::Fmt("vkCmdEndRenderPass2KHR(%s)", MakeRenderPassOpString(true).c_str());
draw.flags |= DrawFlags::PassBoundary | DrawFlags::EndPass;
AddDrawcall(draw, true);
// track while reading, reset this to empty so AddDrawcall sets no outputs,
// but only AFTER the above AddDrawcall (we want it grouped together)
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = ResourceId();
m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer = ResourceId();
}
}
return true;
}
void WrappedVulkan::vkCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer,
const VkSubpassEndInfoKHR *pSubpassEndInfo)
{
SCOPED_DBG_SINK();
VkSubpassEndInfoKHR unwrappedEndInfo = *pSubpassEndInfo;
byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedEndInfo.pNext));
UnwrapNextChain(m_State, "VkSubpassEndInfoKHR", tempMem, (VkBaseInStructure *)&unwrappedEndInfo);
SERIALISE_TIME_CALL(
ObjDisp(commandBuffer)->CmdEndRenderPass2KHR(Unwrap(commandBuffer), &unwrappedEndInfo));
if(IsCaptureMode(m_State))
{
VkResourceRecord *record = GetRecord(commandBuffer);
CACHE_THREAD_SERIALISER();
ser.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndRenderPass2KHR);
Serialise_vkCmdEndRenderPass2KHR(ser, commandBuffer, pSubpassEndInfo);
record->AddChunk(scope.Get());
VkResourceRecord *fb = record->cmdInfo->framebuffer;
std::vector<VkImageMemoryBarrier> barriers;
for(size_t i = 0; fb->imageAttachments[i].barrier.sType; i++)
{
if(fb->imageAttachments[i].barrier.oldLayout == fb->imageAttachments[i].barrier.newLayout)
continue;
barriers.push_back(fb->imageAttachments[i].barrier);
}
// apply the implicit layout transitions here
{
SCOPED_LOCK(m_ImageLayoutsLock);
GetResourceManager()->RecordBarriers(GetRecord(commandBuffer)->cmdInfo->imgbarriers,
m_ImageLayouts, (uint32_t)barriers.size(), &barriers[0]);
}
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdBindPipeline(SerialiserType &ser, VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
@@ -3915,6 +4298,15 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdNextSubpass, VkCommandBuffer commandB
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdEndRenderPass, VkCommandBuffer commandBuffer);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdBeginRenderPass2KHR, VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo *pRenderPassBegin,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdNextSubpass2KHR, VkCommandBuffer commandBuffer,
const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
const VkSubpassEndInfoKHR *pSubpassEndInfo);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdEndRenderPass2KHR, VkCommandBuffer commandBuffer,
const VkSubpassEndInfoKHR *pSubpassEndInfo);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdBindPipeline, VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
@@ -4004,4 +4396,4 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdInsertDebugUtilsLabelEXT, VkCommandBu
const VkDebugUtilsLabelEXT *pLabelInfo);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetDeviceMask, VkCommandBuffer commandBuffer,
uint32_t deviceMask);
uint32_t deviceMask);
@@ -24,23 +24,8 @@
#include "../vk_core.h"
template <>
VkFramebufferCreateInfo WrappedVulkan::UnwrapInfo(const VkFramebufferCreateInfo *info)
{
VkFramebufferCreateInfo ret = *info;
VkImageView *unwrapped = GetTempArray<VkImageView>(info->attachmentCount);
for(uint32_t i = 0; i < info->attachmentCount; i++)
unwrapped[i] = Unwrap(info->pAttachments[i]);
ret.renderPass = Unwrap(ret.renderPass);
ret.pAttachments = unwrapped;
return ret;
}
void WrappedVulkan::MakeSubpassLoadRP(VkRenderPassCreateInfo &info,
const VkRenderPassCreateInfo *origInfo, uint32_t s)
template <typename RPCreateInfo>
static void MakeSubpassLoadRP(RPCreateInfo &info, const RPCreateInfo *origInfo, uint32_t s)
{
info.subpassCount = 1;
info.pSubpasses = origInfo->pSubpasses + s;
@@ -48,8 +33,14 @@ void WrappedVulkan::MakeSubpassLoadRP(VkRenderPassCreateInfo &info,
// remove any dependencies
info.dependencyCount = 0;
const VkSubpassDescription *sub = info.pSubpasses;
VkAttachmentDescription *att = (VkAttachmentDescription *)info.pAttachments;
// we use decltype here because this is templated to work for regular and create_renderpass2
// structs
using SubpassInfo = typename std::remove_reference<decltype(info.pSubpasses[0])>::type;
using AttachmentInfo =
std::remove_cv<typename std::remove_reference<decltype(info.pAttachments[0])>::type>::type;
SubpassInfo *sub = info.pSubpasses;
AttachmentInfo *att = (AttachmentInfo *)info.pAttachments;
// apply this subpass's attachment layouts to the initial and final layouts
// so that this RP doesn't perform any layout transitions
@@ -79,6 +70,21 @@ void WrappedVulkan::MakeSubpassLoadRP(VkRenderPassCreateInfo &info,
}
}
template <>
VkFramebufferCreateInfo WrappedVulkan::UnwrapInfo(const VkFramebufferCreateInfo *info)
{
VkFramebufferCreateInfo ret = *info;
VkImageView *unwrapped = GetTempArray<VkImageView>(info->attachmentCount);
for(uint32_t i = 0; i < info->attachmentCount; i++)
unwrapped[i] = Unwrap(info->pAttachments[i]);
ret.renderPass = Unwrap(ret.renderPass);
ret.pAttachments = unwrapped;
return ret;
}
// note, for threading reasons we ensure to release the wrappers before
// releasing the underlying object. Otherwise after releasing the vulkan object
// that same handle could be returned by create on another thread, and we
@@ -907,6 +913,221 @@ VkResult WrappedVulkan::vkCreateRenderPass(VkDevice device, const VkRenderPassCr
return ret;
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCreateRenderPass2KHR(SerialiserType &ser, VkDevice device,
const VkRenderPassCreateInfo2KHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass)
{
SERIALISE_ELEMENT(device);
SERIALISE_ELEMENT_LOCAL(CreateInfo, *pCreateInfo);
SERIALISE_ELEMENT_OPT(pAllocator);
SERIALISE_ELEMENT_LOCAL(RenderPass, GetResID(*pRenderPass)).TypedAs("VkRenderPass");
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
VkRenderPass rp = VK_NULL_HANDLE;
VulkanCreationInfo::RenderPass rpinfo;
rpinfo.Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
// we want to store off the data so we can display it after the pass.
// override any user-specified DONT_CARE.
// Likewise we don't want to throw away data before we're ready, so change
// any load ops to LOAD instead of DONT_CARE (which is valid!). We of course
// leave any LOAD_OP_CLEAR alone.
VkAttachmentDescription2KHR *att = (VkAttachmentDescription2KHR *)CreateInfo.pAttachments;
for(uint32_t i = 0; i < CreateInfo.attachmentCount; i++)
{
att[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
att[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
if(att[i].loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(att[i].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
att[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
// renderpass can't start or end in presentable layout on replay
ReplacePresentableImageLayout(att[i].initialLayout);
ReplacePresentableImageLayout(att[i].finalLayout);
}
VkResult ret = ObjDisp(device)->CreateRenderPass2KHR(Unwrap(device), &CreateInfo, NULL, &rp);
if(ret != VK_SUCCESS)
{
RDCERR("Failed on resource serialise-creation, VkResult: %s", ToStr(ret).c_str());
return false;
}
else
{
ResourceId live;
if(GetResourceManager()->HasWrapper(ToTypedHandle(rp)))
{
live = GetResourceManager()->GetNonDispWrapper(rp)->id;
// destroy this instance of the duplicate, as we must have matching create/destroy
// calls and there won't be a wrapped resource hanging around to destroy this one.
ObjDisp(device)->DestroyRenderPass(Unwrap(device), rp, NULL);
// whenever the new ID is requested, return the old ID, via replacements.
GetResourceManager()->ReplaceResource(RenderPass, GetResourceManager()->GetOriginalID(live));
}
else
{
live = GetResourceManager()->WrapResource(Unwrap(device), rp);
GetResourceManager()->AddLiveResource(RenderPass, rp);
// make a version of the render pass that loads from its attachments,
// so it can be used for replaying a single draw after a render pass
// without doing a clear or a DONT_CARE load.
for(uint32_t i = 0; i < CreateInfo.attachmentCount; i++)
{
att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
att[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
}
VkRenderPassCreateInfo2KHR loadInfo = CreateInfo;
rpinfo.loadRPs.resize(CreateInfo.subpassCount);
// create a render pass for each subpass that maintains attachment layouts
for(uint32_t s = 0; s < CreateInfo.subpassCount; s++)
{
MakeSubpassLoadRP(loadInfo, &CreateInfo, s);
ret = ObjDisp(device)->CreateRenderPass2KHR(Unwrap(device), &loadInfo, NULL,
&rpinfo.loadRPs[s]);
RDCASSERTEQUAL(ret, VK_SUCCESS);
// handle the loadRP being a duplicate
if(GetResourceManager()->HasWrapper(ToTypedHandle(rpinfo.loadRPs[s])))
{
// just fetch the existing wrapped object
rpinfo.loadRPs[s] =
(VkRenderPass)(uint64_t)GetResourceManager()->GetNonDispWrapper(rpinfo.loadRPs[s]);
// destroy this instance of the duplicate, as we must have matching create/destroy
// calls and there won't be a wrapped resource hanging around to destroy this one.
ObjDisp(device)->DestroyRenderPass(Unwrap(device), rpinfo.loadRPs[s], NULL);
// don't need to ReplaceResource as no IDs are involved
}
else
{
ResourceId loadRPid =
GetResourceManager()->WrapResource(Unwrap(device), rpinfo.loadRPs[s]);
// register as a live-only resource, so it is cleaned up properly
GetResourceManager()->AddLiveResource(loadRPid, rpinfo.loadRPs[s]);
}
}
m_CreationInfo.m_RenderPass[live] = rpinfo;
}
}
AddResource(RenderPass, ResourceType::RenderPass, "Render Pass");
DerivedResource(device, RenderPass);
}
return true;
}
VkResult WrappedVulkan::vkCreateRenderPass2KHR(VkDevice device,
const VkRenderPassCreateInfo2KHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass)
{
VkResult ret;
SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateRenderPass2KHR(Unwrap(device), pCreateInfo,
pAllocator, pRenderPass));
if(ret == VK_SUCCESS)
{
ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), *pRenderPass);
if(IsCaptureMode(m_State))
{
Chunk *chunk = NULL;
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCreateRenderPass2KHR);
Serialise_vkCreateRenderPass2KHR(ser, device, pCreateInfo, NULL, pRenderPass);
chunk = scope.Get();
}
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pRenderPass);
record->AddChunk(chunk);
// +1 for the terminal value
uint32_t arrayCount = pCreateInfo->attachmentCount + 1;
record->imageAttachments = new AttachmentInfo[arrayCount];
RDCEraseMem(record->imageAttachments, sizeof(AttachmentInfo) * arrayCount);
for(uint32_t i = 0; i < pCreateInfo->attachmentCount; i++)
{
record->imageAttachments[i].record = NULL;
record->imageAttachments[i].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
record->imageAttachments[i].barrier.oldLayout = pCreateInfo->pAttachments[i].initialLayout;
record->imageAttachments[i].barrier.newLayout = pCreateInfo->pAttachments[i].finalLayout;
}
}
else
{
GetResourceManager()->AddLiveResource(id, *pRenderPass);
VulkanCreationInfo::RenderPass rpinfo;
rpinfo.Init(GetResourceManager(), m_CreationInfo, pCreateInfo);
VkRenderPassCreateInfo2KHR info = *pCreateInfo;
VkAttachmentDescription2KHR atts[16];
RDCASSERT(ARRAY_COUNT(atts) >= (size_t)info.attachmentCount);
// make a version of the render pass that loads from its attachments,
// so it can be used for replaying a single draw after a render pass
// without doing a clear or a DONT_CARE load.
for(uint32_t i = 0; i < info.attachmentCount; i++)
{
atts[i] = info.pAttachments[i];
atts[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
atts[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
}
info.pAttachments = atts;
rpinfo.loadRPs.resize(pCreateInfo->subpassCount);
// create a render pass for each subpass that maintains attachment layouts
for(uint32_t s = 0; s < pCreateInfo->subpassCount; s++)
{
MakeSubpassLoadRP(info, pCreateInfo, s);
ret = ObjDisp(device)->CreateRenderPass2KHR(Unwrap(device), &info, NULL, &rpinfo.loadRPs[s]);
RDCASSERTEQUAL(ret, VK_SUCCESS);
ResourceId loadRPid = GetResourceManager()->WrapResource(Unwrap(device), rpinfo.loadRPs[s]);
// register as a live-only resource, so it is cleaned up properly
GetResourceManager()->AddLiveResource(loadRPid, rpinfo.loadRPs[s]);
}
m_CreationInfo.m_RenderPass[id] = rpinfo;
}
}
return ret;
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCreateQueryPool(SerialiserType &ser, VkDevice device,
const VkQueryPoolCreateInfo *pCreateInfo,
@@ -1706,6 +1927,10 @@ INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateRenderPass, VkDevice device,
const VkRenderPassCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateRenderPass2KHR, VkDevice device,
const VkRenderPassCreateInfo2KHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateQueryPool, VkDevice device,
const VkQueryPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool);