Beispiel #1
0
void D3D12ResourceManager::Create_InitialState(ResourceId id, ID3D12DeviceChild *live, bool hasData)
{
  D3D12ResourceType type = IdentifyTypeByPtr(live);

  if(type == Resource_DescriptorHeap)
  {
    // set a NULL heap, if there are no initial contents for a descriptor heap we just leave
    // it all entirely undefined.
    SetInitialContents(id, D3D12ResourceManager::InitialContentData(NULL, 1, NULL));
  }
  else if(type == Resource_Resource)
  {
    D3D12NOTIMP("Creating init states for resources");

    // not handling any missing states at the moment
  }
  else
  {
    RDCERR("Unexpected type needing an initial state created: %d", type);
  }
}
Beispiel #2
0
bool D3D11ResourceManager::Need_InitialStateChunk(ID3D11DeviceChild *res)
{
  return IdentifyTypeByPtr(res) != Resource_Buffer;
}
Beispiel #3
0
bool D3D11ResourceManager::Force_InitialState(ID3D11DeviceChild *res, bool prepare)
{
  return IdentifyTypeByPtr(res) == Resource_UnorderedAccessView;
}
Beispiel #4
0
bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
{
  ResourceId id = GetResID(res);
  D3D12ResourceType type = IdentifyTypeByPtr(res);

  if(type == Resource_DescriptorHeap)
  {
    WrappedID3D12DescriptorHeap *heap = (WrappedID3D12DescriptorHeap *)res;

    UINT numElems = heap->GetDesc().NumDescriptors;

    D3D12Descriptor *descs =
        (D3D12Descriptor *)Serialiser::AllocAlignedBuffer(sizeof(D3D12Descriptor) * numElems);

    memcpy(descs, heap->GetDescriptors(), sizeof(D3D12Descriptor) * numElems);

    SetInitialContents(heap->GetResourceID(),
                       D3D12ResourceManager::InitialContentData(NULL, numElems, (byte *)descs));
    return true;
  }
  else if(type == Resource_Resource)
  {
    WrappedID3D12Resource *r = (WrappedID3D12Resource *)res;
    ID3D12Pageable *pageable = r;

    bool nonresident = false;
    if(!r->Resident())
      nonresident = true;

    D3D12_RESOURCE_DESC desc = r->GetDesc();

    if(desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && desc.SampleDesc.Count > 1)
    {
      D3D12NOTIMP("Multisampled initial contents");

      SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(NULL, 2, NULL));
      return true;
    }
    else if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
    {
      D3D12_HEAP_PROPERTIES heapProps;
      r->GetHeapProperties(&heapProps, NULL);

      if(heapProps.Type == D3D12_HEAP_TYPE_READBACK)
      {
        // already on readback heap, just mark that we can map it directly and continue
        SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(NULL, 1, NULL));
        return true;
      }

      heapProps.Type = D3D12_HEAP_TYPE_READBACK;
      heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
      heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
      heapProps.CreationNodeMask = 1;
      heapProps.VisibleNodeMask = 1;

      desc.Flags = D3D12_RESOURCE_FLAG_NONE;

      ID3D12Resource *copyDst = NULL;
      HRESULT hr = m_Device->GetReal()->CreateCommittedResource(
          &heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
          __uuidof(ID3D12Resource), (void **)&copyDst);

      if(nonresident)
        m_Device->MakeResident(1, &pageable);

      if(SUCCEEDED(hr))
      {
        ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList());

        list->CopyResource(copyDst, r->GetReal());
      }
      else
      {
        RDCERR("Couldn't create readback buffer: 0x%08x", hr);
      }

      if(nonresident)
      {
        m_Device->CloseInitialStateList();

        m_Device->ExecuteLists();
        m_Device->FlushLists();

        m_Device->Evict(1, &pageable);
      }

      SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(copyDst, 0, NULL));
      return true;
    }
    else
    {
      D3D12_HEAP_PROPERTIES heapProps;
      heapProps.Type = D3D12_HEAP_TYPE_READBACK;
      heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
      heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
      heapProps.CreationNodeMask = 1;
      heapProps.VisibleNodeMask = 1;

      D3D12_RESOURCE_DESC bufDesc;

      bufDesc.Alignment = 0;
      bufDesc.DepthOrArraySize = 1;
      bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
      bufDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
      bufDesc.Format = DXGI_FORMAT_UNKNOWN;
      bufDesc.Height = 1;
      bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
      bufDesc.MipLevels = 1;
      bufDesc.SampleDesc.Count = 1;
      bufDesc.SampleDesc.Quality = 0;
      bufDesc.Width = 1;

      UINT numSubresources = desc.MipLevels;
      if(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
        numSubresources *= desc.DepthOrArraySize;

      D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts =
          new D3D12_PLACED_SUBRESOURCE_FOOTPRINT[numSubresources];

      m_Device->GetCopyableFootprints(&desc, 0, numSubresources, 0, layouts, NULL, NULL,
                                      &bufDesc.Width);

      ID3D12Resource *copyDst = NULL;
      HRESULT hr = m_Device->GetReal()->CreateCommittedResource(
          &heapProps, D3D12_HEAP_FLAG_NONE, &bufDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
          __uuidof(ID3D12Resource), (void **)&copyDst);

      if(nonresident)
        m_Device->MakeResident(1, &pageable);

      if(SUCCEEDED(hr))
      {
        ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList());

        vector<D3D12_RESOURCE_BARRIER> barriers;

        const vector<D3D12_RESOURCE_STATES> &states = m_Device->GetSubresourceStates(GetResID(r));

        barriers.reserve(states.size());

        for(size_t i = 0; i < states.size(); i++)
        {
          if(states[i] & D3D12_RESOURCE_STATE_COPY_SOURCE)
            continue;

          D3D12_RESOURCE_BARRIER barrier;
          barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
          barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
          barrier.Transition.pResource = r->GetReal();
          barrier.Transition.Subresource = (UINT)i;
          barrier.Transition.StateBefore = states[i];
          barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;

          barriers.push_back(barrier);
        }

        // transition to copy dest
        if(!barriers.empty())
          list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);

        for(UINT i = 0; i < numSubresources; i++)
        {
          D3D12_TEXTURE_COPY_LOCATION dst, src;

          src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
          src.pResource = r->GetReal();
          src.SubresourceIndex = i;

          dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
          dst.pResource = copyDst;
          dst.PlacedFootprint = layouts[i];

          list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);
        }

        // transition back
        for(size_t i = 0; i < barriers.size(); i++)
          std::swap(barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter);

        if(!barriers.empty())
          list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);
      }
      else
      {
        RDCERR("Couldn't create readback buffer: 0x%08x", hr);
      }

      if(nonresident)
      {
        m_Device->CloseInitialStateList();

        m_Device->ExecuteLists();
        m_Device->FlushLists();

        m_Device->Evict(1, &pageable);
      }

      SAFE_DELETE_ARRAY(layouts);

      SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(copyDst, 0, NULL));
      return true;
    }
  }
  else
  {
    RDCERR("Unexpected type needing an initial state prepared: %d", type);
  }

  return false;
}
Beispiel #5
0
void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, InitialContentData data)
{
  D3D12ResourceType type = IdentifyTypeByPtr(live);

  if(type == Resource_DescriptorHeap)
  {
    ID3D12DescriptorHeap *dstheap = (ID3D12DescriptorHeap *)live;
    ID3D12DescriptorHeap *srcheap = (ID3D12DescriptorHeap *)data.resource;

    if(srcheap)
    {
      // copy the whole heap
      m_Device->CopyDescriptorsSimple(
          srcheap->GetDesc().NumDescriptors, dstheap->GetCPUDescriptorHandleForHeapStart(),
          srcheap->GetCPUDescriptorHandleForHeapStart(), srcheap->GetDesc().Type);
    }
  }
  else if(type == Resource_Resource)
  {
    if(data.num == 1 && data.resource)
    {
      ID3D12Resource *copyDst = Unwrap((ID3D12Resource *)live);
      ID3D12Resource *copySrc = (ID3D12Resource *)data.resource;

      D3D12_HEAP_PROPERTIES heapProps = {};
      copyDst->GetHeapProperties(&heapProps, NULL);

      // if destination is on the upload heap, it's impossible to copy via the device,
      // so we have to map both sides and CPU copy.
      if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD)
      {
        byte *src = NULL, *dst = NULL;

        HRESULT hr = S_OK;

        hr = copySrc->Map(0, NULL, (void **)&src);

        if(FAILED(hr))
        {
          RDCERR("Doing CPU-side copy, couldn't map source: 0x%08x", hr);
          src = NULL;
        }

        if(copyDst->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
        {
          hr = copyDst->Map(0, NULL, (void **)&dst);

          if(FAILED(hr))
          {
            RDCERR("Doing CPU-side copy, couldn't map source: 0x%08x", hr);
            dst = NULL;
          }

          if(src && dst)
          {
            memcpy(dst, src, (size_t)copySrc->GetDesc().Width);
          }

          if(dst)
            copyDst->Unmap(0, NULL);
        }
        else
        {
          D3D12_RESOURCE_DESC desc = copyDst->GetDesc();

          UINT numSubresources = desc.MipLevels;
          if(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
            numSubresources *= desc.DepthOrArraySize;

          D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts =
              new D3D12_PLACED_SUBRESOURCE_FOOTPRINT[numSubresources];
          UINT *numrows = new UINT[numSubresources];
          UINT64 *rowsizes = new UINT64[numSubresources];

          m_Device->GetCopyableFootprints(&desc, 0, numSubresources, 0, layouts, numrows, rowsizes,
                                          NULL);

          for(UINT i = 0; i < numSubresources; i++)
          {
            hr = copyDst->Map(i, NULL, (void **)&dst);

            if(FAILED(hr))
            {
              RDCERR("Doing CPU-side copy, couldn't map source: 0x%08x", hr);
              dst = NULL;
            }

            if(src && dst)
            {
              byte *bufPtr = src + layouts[i].Offset;
              byte *texPtr = dst;

              for(UINT d = 0; d < layouts[i].Footprint.Depth; d++)
              {
                for(UINT r = 0; r < numrows[i]; r++)
                {
                  memcpy(bufPtr, texPtr, (size_t)rowsizes[i]);

                  bufPtr += layouts[i].Footprint.RowPitch;
                  texPtr += rowsizes[i];
                }
              }
            }

            if(dst)
              copyDst->Unmap(0, NULL);
          }

          delete[] layouts;
          delete[] numrows;
          delete[] rowsizes;
        }

        if(src)
          copySrc->Unmap(0, NULL);
      }
      else
      {
        ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList());

        vector<D3D12_RESOURCE_BARRIER> barriers;

        const vector<D3D12_RESOURCE_STATES> &states = m_Device->GetSubresourceStates(GetResID(live));

        barriers.reserve(states.size());

        for(size_t i = 0; i < states.size(); i++)
        {
          if(states[i] & D3D12_RESOURCE_STATE_COPY_DEST)
            continue;

          D3D12_RESOURCE_BARRIER barrier;
          barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
          barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
          barrier.Transition.pResource = copyDst;
          barrier.Transition.Subresource = (UINT)i;
          barrier.Transition.StateBefore = states[i];
          barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;

          barriers.push_back(barrier);
        }

        // transition to copy dest
        if(!barriers.empty())
          list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);

        if(copyDst->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
        {
          list->CopyBufferRegion(copyDst, 0, copySrc, 0, copySrc->GetDesc().Width);
        }
        else
        {
          D3D12_RESOURCE_DESC desc = copyDst->GetDesc();

          UINT numSubresources = desc.MipLevels;
          if(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
            numSubresources *= desc.DepthOrArraySize;

          D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts =
              new D3D12_PLACED_SUBRESOURCE_FOOTPRINT[numSubresources];

          m_Device->GetCopyableFootprints(&desc, 0, numSubresources, 0, layouts, NULL, NULL, NULL);

          for(UINT i = 0; i < numSubresources; i++)
          {
            D3D12_TEXTURE_COPY_LOCATION dst, src;

            dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
            dst.pResource = copyDst;
            dst.SubresourceIndex = i;

            src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
            src.pResource = copySrc;
            src.PlacedFootprint = layouts[i];

            list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);
          }

          delete[] layouts;
        }

        // transition back to whatever it was before
        for(size_t i = 0; i < barriers.size(); i++)
          std::swap(barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter);

        if(!barriers.empty())
          list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);

#if ENABLED(SINGLE_FLUSH_VALIDATE)
        m_Device->CloseInitialStateList();
        m_Device->ExecuteLists();
        m_Device->FlushLists(true);
#endif
      }
    }
    else
    {
      RDCERR("Unexpected num or NULL resource: %d, %p", data.num, data.resource);
    }
  }
  else
  {
    RDCERR("Unexpected type needing an initial state created: %d", type);
  }
}
Beispiel #6
0
bool WrappedVulkan::ReleaseResource(WrappedVkRes *res)
{
	if(res == NULL) return true;

	// MULTIDEVICE need to get the actual device that created this object
	VkDevice dev = GetDev();
	const VkLayerDispatchTable *vt = ObjDisp(dev);

	WrappedVkNonDispRes *nondisp = (WrappedVkNonDispRes *)res;
	WrappedVkDispRes *disp = (WrappedVkDispRes *)res;
	uint64_t handle = (uint64_t)nondisp;

	switch(IdentifyTypeByPtr(res))
	{
		case eResSurface:
		case eResSwapchain:
			if(m_State >= WRITING)
				RDCERR("Swapchain/swapchain object is leaking");
			else
				RDCERR("Should be no swapchain/surface objects created on replay");
			break;

		case eResUnknown:
			RDCERR("Unknown resource type!");
			break;
			
		case eResCommandBuffer:
			// special case here, on replay we don't have the tracking
			// to remove these with the parent object so do it here.
			// This ensures we clean up after ourselves with a well-
			// behaved application.
			if(m_State < WRITING)
				GetResourceManager()->ReleaseWrappedResource((VkCommandBuffer)res);
			break;
		case eResDescriptorSet:
			if(m_State < WRITING)
				GetResourceManager()->ReleaseWrappedResource(VkDescriptorSet(handle));
			break;
		case eResPhysicalDevice:
			if(m_State < WRITING)
				GetResourceManager()->ReleaseWrappedResource((VkPhysicalDevice)disp);
			break;
		case eResQueue:
			if(m_State < WRITING)
				GetResourceManager()->ReleaseWrappedResource((VkQueue)disp);
			break;
			
		case eResDevice:
			// these are explicitly released elsewhere, do not need to destroy
			// any API objects.
			// On replay though we do need to tidy up book-keeping for these.
			if(m_State < WRITING)
			{
				GetResourceManager()->ReleaseCurrentResource(disp->id);
				GetResourceManager()->RemoveWrapper(ToTypedHandle(disp->real.As<VkDevice>()));
			}
			break;
		case eResInstance:
			if(m_State < WRITING)
			{
				GetResourceManager()->ReleaseCurrentResource(disp->id);
				GetResourceManager()->RemoveWrapper(ToTypedHandle(disp->real.As<VkInstance>()));
			}
			break;

		case eResDeviceMemory:
		{
			VkDeviceMemory real = nondisp->real.As<VkDeviceMemory>();
			GetResourceManager()->ReleaseWrappedResource(VkDeviceMemory(handle));
			vt->FreeMemory(Unwrap(dev), real, NULL);
			break;
		}
		case eResBuffer:
		{
			VkBuffer real = nondisp->real.As<VkBuffer>();
			GetResourceManager()->ReleaseWrappedResource(VkBuffer(handle));
			vt->DestroyBuffer(Unwrap(dev), real, NULL);
			break;
		}
		case eResBufferView:
		{
			VkBufferView real = nondisp->real.As<VkBufferView>();
			GetResourceManager()->ReleaseWrappedResource(VkBufferView(handle));
			vt->DestroyBufferView(Unwrap(dev), real, NULL);
			break;
		}
		case eResImage:
		{
			VkImage real = nondisp->real.As<VkImage>();
			GetResourceManager()->ReleaseWrappedResource(VkImage(handle));
			vt->DestroyImage(Unwrap(dev), real, NULL);
			break;
		}
		case eResImageView:
		{
			VkImageView real = nondisp->real.As<VkImageView>();
			GetResourceManager()->ReleaseWrappedResource(VkImageView(handle));
			vt->DestroyImageView(Unwrap(dev), real, NULL);
			break;
		}
		case eResFramebuffer:
		{
			VkFramebuffer real = nondisp->real.As<VkFramebuffer>();
			GetResourceManager()->ReleaseWrappedResource(VkFramebuffer(handle));
			vt->DestroyFramebuffer(Unwrap(dev), real, NULL);
			break;
		}
		case eResRenderPass:
		{
			VkRenderPass real = nondisp->real.As<VkRenderPass>();
			GetResourceManager()->ReleaseWrappedResource(VkRenderPass(handle));
			vt->DestroyRenderPass(Unwrap(dev), real, NULL);
			break;
		}
		case eResShaderModule:
		{
			VkShaderModule real = nondisp->real.As<VkShaderModule>();
			GetResourceManager()->ReleaseWrappedResource(VkShaderModule(handle));
			vt->DestroyShaderModule(Unwrap(dev), real, NULL);
			break;
		}
		case eResPipelineCache:
		{
			VkPipelineCache real = nondisp->real.As<VkPipelineCache>();
			GetResourceManager()->ReleaseWrappedResource(VkPipelineCache(handle));
			vt->DestroyPipelineCache(Unwrap(dev), real, NULL);
			break;
		}
		case eResPipelineLayout:
		{
			VkPipelineLayout real = nondisp->real.As<VkPipelineLayout>();
			GetResourceManager()->ReleaseWrappedResource(VkPipelineLayout(handle));
			vt->DestroyPipelineLayout(Unwrap(dev), real, NULL);
			break;
		}
		case eResPipeline:
		{
			VkPipeline real = nondisp->real.As<VkPipeline>();
			GetResourceManager()->ReleaseWrappedResource(VkPipeline(handle));
			vt->DestroyPipeline(Unwrap(dev), real, NULL);
			break;
		}
		case eResSampler:
		{
			VkSampler real = nondisp->real.As<VkSampler>();
			GetResourceManager()->ReleaseWrappedResource(VkSampler(handle));
			vt->DestroySampler(Unwrap(dev), real, NULL);
			break;
		}
		case eResDescriptorPool:
		{
			VkDescriptorPool real = nondisp->real.As<VkDescriptorPool>();
			GetResourceManager()->ReleaseWrappedResource(VkDescriptorPool(handle));
			vt->DestroyDescriptorPool(Unwrap(dev), real, NULL);
			break;
		}
		case eResDescriptorSetLayout:
		{
			VkDescriptorSetLayout real = nondisp->real.As<VkDescriptorSetLayout>();
			GetResourceManager()->ReleaseWrappedResource(VkDescriptorSetLayout(handle));
			vt->DestroyDescriptorSetLayout(Unwrap(dev), real, NULL);
			break;
		}
		case eResCommandPool:
		{
			VkCommandPool real = nondisp->real.As<VkCommandPool>();
			GetResourceManager()->ReleaseWrappedResource(VkCommandPool(handle));
			vt->DestroyCommandPool(Unwrap(dev), real, NULL);
			break;
		}
		case eResFence:
		{
			VkFence real = nondisp->real.As<VkFence>();
			GetResourceManager()->ReleaseWrappedResource(VkFence(handle));
			vt->DestroyFence(Unwrap(dev), real, NULL);
			break;
		}
		case eResEvent:
		{
			VkEvent real = nondisp->real.As<VkEvent>();
			GetResourceManager()->ReleaseWrappedResource(VkEvent(handle));
			vt->DestroyEvent(Unwrap(dev), real, NULL);
			break;
		}
		case eResQueryPool:
		{
			VkQueryPool real = nondisp->real.As<VkQueryPool>();
			GetResourceManager()->ReleaseWrappedResource(VkQueryPool(handle));
			vt->DestroyQueryPool(Unwrap(dev), real, NULL);
			break;
		}
		case eResSemaphore:
		{
			VkSemaphore real = nondisp->real.As<VkSemaphore>();
			GetResourceManager()->ReleaseWrappedResource(VkSemaphore(handle));
			vt->DestroySemaphore(Unwrap(dev), real, NULL);
			break;
		}
	}

	return true;
}