Exemplo n.º 1
0
void VulkanResourceManager::SerialiseImageStates(map<ResourceId, ImageLayouts> &states,
                                                 vector<VkImageMemoryBarrier> &barriers)
{
  Serialiser *localSerialiser = m_pSerialiser;

  SERIALISE_ELEMENT(uint32_t, NumMems, (uint32_t)states.size());

  auto srcit = states.begin();

  vector<pair<ResourceId, ImageRegionState> > vec;

  for(uint32_t i = 0; i < NumMems; i++)
  {
    SERIALISE_ELEMENT(ResourceId, id, srcit->first);
    SERIALISE_ELEMENT(uint32_t, NumStates, (uint32_t)srcit->second.subresourceStates.size());

    ResourceId liveid;
    if(m_State < WRITING && HasLiveResource(id))
      liveid = GetLiveID(id);

    for(uint32_t m = 0; m < NumStates; m++)
    {
      SERIALISE_ELEMENT(ImageRegionState, state, srcit->second.subresourceStates[m]);

      if(m_State < WRITING && liveid != ResourceId() && srcit != states.end())
      {
        VkImageMemoryBarrier t;
        t.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
        t.pNext = NULL;
        // these access masks aren't used, we need to apply a global memory barrier
        // to memory each time we restart log replaying. These barriers are just
        // to get images into the right layout
        t.srcAccessMask = 0;
        t.dstAccessMask = 0;
        // MULTIDEVICE need to handle multiple queues
        t.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        t.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        t.image = Unwrap(GetCurrentHandle<VkImage>(liveid));
        t.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
        ReplacePresentableImageLayout(state.newLayout);
        t.newLayout = state.newLayout;
        t.subresourceRange = state.subresourceRange;
        barriers.push_back(t);
        vec.push_back(std::make_pair(liveid, state));
      }
    }

    if(m_State >= WRITING)
      srcit++;
  }

  ApplyBarriers(vec, states);

  for(size_t i = 0; i < vec.size(); i++)
    barriers[i].oldLayout = vec[i].second.oldLayout;

  // erase any do-nothing barriers
  for(auto it = barriers.begin(); it != barriers.end();)
  {
    if(it->oldLayout == UNKNOWN_PREV_IMG_LAYOUT)
      it->oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;

    if(it->oldLayout == it->newLayout)
      it = barriers.erase(it);
    else
      ++it;
  }
}
Exemplo n.º 2
0
bool WrappedVulkan::Serialise_vkCmdWaitEvents(
			Serialiser*                                 localSerialiser,
			VkCommandBuffer                             cmdBuffer,
			uint32_t                                    eventCount,
			const VkEvent*                              pEvents,
			VkPipelineStageFlags                        srcStageMask,
			VkPipelineStageFlags                        dstStageMask,
			uint32_t                                    memoryBarrierCount,
			const VkMemoryBarrier*                      pMemoryBarriers,
			uint32_t                                    bufferMemoryBarrierCount,
			const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
			uint32_t                                    imageMemoryBarrierCount,
			const VkImageMemoryBarrier*                 pImageMemoryBarriers)
{
	SERIALISE_ELEMENT(ResourceId, cmdid, GetResID(cmdBuffer));
	SERIALISE_ELEMENT(VkPipelineStageFlagBits, srcStages, (VkPipelineStageFlagBits)srcStageMask);
	SERIALISE_ELEMENT(VkPipelineStageFlagBits, destStages, (VkPipelineStageFlagBits)dstStageMask);
	
	// we don't serialise the original events as we are going to replace this
	// with our own
	
	SERIALISE_ELEMENT(uint32_t, memCount, memoryBarrierCount);
	SERIALISE_ELEMENT(uint32_t, bufCount, bufferMemoryBarrierCount);
	SERIALISE_ELEMENT(uint32_t, imgCount, imageMemoryBarrierCount);

	// we keep the original memory barriers
	SERIALISE_ELEMENT_ARR(VkMemoryBarrier, memBarriers, pMemoryBarriers, memCount);
	SERIALISE_ELEMENT_ARR(VkBufferMemoryBarrier, bufMemBarriers, pBufferMemoryBarriers, bufCount);
	SERIALISE_ELEMENT_ARR(VkImageMemoryBarrier, imgMemBarriers, pImageMemoryBarriers, imgCount);

	vector<VkImageMemoryBarrier> imgBarriers;
	vector<VkBufferMemoryBarrier> bufBarriers;

	// it's possible for buffer or image to be NULL if it refers to a resource that is otherwise
	// not in the log (barriers do not mark resources referenced). If the resource in question does
	// not exist, then it's safe to skip this barrier.
	
	if(m_State < WRITING)
	{
		for(uint32_t i=0; i < bufCount; i++)
			if(bufMemBarriers[i].buffer != VK_NULL_HANDLE)
				bufBarriers.push_back(bufMemBarriers[i]);
		
		for(uint32_t i=0; i < imgCount; i++)
		{
			if(imgMemBarriers[i].image != VK_NULL_HANDLE)
			{
				imgBarriers.push_back(imgMemBarriers[i]);
				ReplacePresentableImageLayout(imgBarriers.back().oldLayout);
				ReplacePresentableImageLayout(imgBarriers.back().newLayout);
			}
		}
	}

	SAFE_DELETE_ARRAY(bufMemBarriers);
	SAFE_DELETE_ARRAY(imgMemBarriers);

	// see top of this file for current event/fence handling

	if(m_State == EXECUTING)
	{
		if(ShouldRerecordCmd(cmdid) && InRerecordRange())
		{
			cmdBuffer = RerecordCmdBuf(cmdid);

			VkEventCreateInfo evInfo = {
				VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, NULL, 0,
			};

			VkEvent ev = VK_NULL_HANDLE;
			ObjDisp(cmdBuffer)->CreateEvent(Unwrap(GetDev()), &evInfo, NULL, &ev);
			// don't wrap this event

			ObjDisp(cmdBuffer)->ResetEvent(Unwrap(GetDev()), ev);
			ObjDisp(cmdBuffer)->CmdSetEvent(Unwrap(cmdBuffer), ev, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);

			ObjDisp(cmdBuffer)->CmdWaitEvents(Unwrap(cmdBuffer), 1, &ev, (VkPipelineStageFlags)srcStages, (VkPipelineStageFlags)destStages,
				memCount, memBarriers,
				(uint32_t)bufBarriers.size(), &bufBarriers[0],
				(uint32_t)imgBarriers.size(), &imgBarriers[0]);

			// register to clean this event up once we're done replaying this section of the log
			m_CleanupEvents.push_back(ev);

			ResourceId cmd = GetResID(RerecordCmdBuf(cmdid));
			GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts, (uint32_t)imgBarriers.size(), &imgBarriers[0]);
		}
	}
	else if(m_State == READING)
	{
		cmdBuffer = GetResourceManager()->GetLiveHandle<VkCommandBuffer>(cmdid);

		VkEventCreateInfo evInfo = {
			VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, NULL, 0,
		};

		VkEvent ev = VK_NULL_HANDLE;
		ObjDisp(cmdBuffer)->CreateEvent(Unwrap(GetDev()), &evInfo, NULL, &ev);
		// don't wrap this event

		ObjDisp(cmdBuffer)->ResetEvent(Unwrap(GetDev()), ev);
		ObjDisp(cmdBuffer)->CmdSetEvent(Unwrap(cmdBuffer), ev, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);

		ObjDisp(cmdBuffer)->CmdWaitEvents(Unwrap(cmdBuffer), 1, &ev, (VkPipelineStageFlags)srcStages, (VkPipelineStageFlags)destStages,
				memCount, memBarriers,
				(uint32_t)bufBarriers.size(), &bufBarriers[0],
				(uint32_t)imgBarriers.size(), &imgBarriers[0]);

		// register to clean this event up once we're done replaying this section of the log
		m_CleanupEvents.push_back(ev);
		
		ResourceId cmd = GetResID(cmdBuffer);
		GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts, (uint32_t)imgBarriers.size(), &imgBarriers[0]);
	}

	SAFE_DELETE_ARRAY(memBarriers);

	return true;
}
Exemplo n.º 3
0
bool WrappedVulkan::Serialise_vkCreateRenderPass(
			Serialiser*                                 localSerialiser,
			VkDevice                                    device,
			const VkRenderPassCreateInfo*               pCreateInfo,
			const VkAllocationCallbacks*                pAllocator,
			VkRenderPass*                               pRenderPass)
{
	SERIALISE_ELEMENT(ResourceId, devId, GetResID(device));
	SERIALISE_ELEMENT(VkRenderPassCreateInfo, info, *pCreateInfo);
	SERIALISE_ELEMENT(ResourceId, id, GetResID(*pRenderPass));

	if(m_State == READING)
	{
		device = GetResourceManager()->GetLiveHandle<VkDevice>(devId);
		VkRenderPass rp = VK_NULL_HANDLE;

		VulkanCreationInfo::RenderPass rpinfo;
		rpinfo.Init(GetResourceManager(), m_CreationInfo, &info);

		// we want to store off the data so we can display it after the pass.
		// override any user-specified DONT_CARE.
		VkAttachmentDescription *att = (VkAttachmentDescription *)info.pAttachments;
		for(uint32_t i=0; i < info.attachmentCount; i++)
		{
			att[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
			att[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;

			// renderpass can't start or end in presentable layout on replay
			ReplacePresentableImageLayout(att[i].initialLayout);
			ReplacePresentableImageLayout(att[i].finalLayout);
		}

		VkResult ret = ObjDisp(device)->CreateRenderPass(Unwrap(device), &info, NULL, &rp);

		if(ret != VK_SUCCESS)
		{
			RDCERR("Failed on resource serialise-creation, VkResult: 0x%08x", ret);
		}
		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(id, GetResourceManager()->GetOriginalID(live));
			}
			else
			{
				live = GetResourceManager()->WrapResource(Unwrap(device), rp);
				GetResourceManager()->AddLiveResource(id, 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 < info.attachmentCount; i++)
				{
					att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
					att[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
				}

				ret = ObjDisp(device)->CreateRenderPass(Unwrap(device), &info, NULL, &rpinfo.loadRP);
				RDCASSERTEQUAL(ret, VK_SUCCESS);
				
				// handle the loadRP being a duplicate
				if(GetResourceManager()->HasWrapper(ToTypedHandle(rpinfo.loadRP)))
				{
					// just fetch the existing wrapped object
					rpinfo.loadRP = (VkRenderPass)(uint64_t)GetResourceManager()->GetNonDispWrapper(rpinfo.loadRP);

					// 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.loadRP, NULL);

					// don't need to ReplaceResource as no IDs are involved
				}
				else
				{
					ResourceId loadRPid = GetResourceManager()->WrapResource(Unwrap(device), rpinfo.loadRP);

					// register as a live-only resource, so it is cleaned up properly
					GetResourceManager()->AddLiveResource(loadRPid, rpinfo.loadRP);
				}
				
				m_CreationInfo.m_RenderPass[live] = rpinfo;
			}
		}
	}

	return true;
}