Exemplo n.º 1
0
void D3D12ResourceManager::SerialiseResourceStates(vector<D3D12_RESOURCE_BARRIER> &barriers,
                                                   map<ResourceId, SubresourceStateVector> &states)
{
  SERIALISE_ELEMENT(uint32_t, NumMems, (uint32_t)states.size());

  auto srcit = states.begin();

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

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

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

      if(m_State < WRITING && liveid != ResourceId() && srcit != states.end())
      {
        D3D12_RESOURCE_BARRIER b;
        b.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
        b.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
        b.Transition.pResource = (ID3D12Resource *)GetCurrentResource(liveid);
        b.Transition.Subresource = m;
        b.Transition.StateBefore = states[liveid][m];
        b.Transition.StateAfter = state;

        barriers.push_back(b);
      }
    }

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

  // erase any do-nothing barriers
  for(auto it = barriers.begin(); it != barriers.end();)
  {
    if(it->Transition.StateBefore == it->Transition.StateAfter)
      it = barriers.erase(it);
    else
      ++it;
  }

  ApplyBarriers(barriers, states);
}
Exemplo n.º 2
0
bool D3D12ResourceManager::Serialise_InitialState(ResourceId resid, ID3D12DeviceChild *liveRes)
{
  D3D12ResourceRecord *record = NULL;
  if(m_State >= WRITING)
    record = GetResourceRecord(resid);

  SERIALISE_ELEMENT(ResourceId, id, resid);
  SERIALISE_ELEMENT(D3D12ResourceType, type, record->type);

  if(m_State >= WRITING)
  {
    D3D12ResourceManager::InitialContentData initContents = GetInitialContents(id);

    if(type == Resource_DescriptorHeap)
    {
      D3D12Descriptor *descs = (D3D12Descriptor *)initContents.blob;
      uint32_t numElems = initContents.num;

      m_pSerialiser->SerialiseComplexArray("Descriptors", descs, numElems);
    }
    else if(type == Resource_Resource)
    {
      m_Device->ExecuteLists();
      m_Device->FlushLists();

      ID3D12Resource *copiedBuffer = (ID3D12Resource *)initContents.resource;

      if(initContents.num == 1)
      {
        copiedBuffer = (ID3D12Resource *)liveRes;
      }

      if(initContents.num == 2)
      {
        D3D12NOTIMP("Multisampled initial contents");
        return true;
      }

      byte dummy[4] = {};
      byte *ptr = NULL;
      uint64_t size = 0;

      HRESULT hr = E_NOINTERFACE;

      if(copiedBuffer)
      {
        hr = copiedBuffer->Map(0, NULL, (void **)&ptr);
        size = (uint64_t)copiedBuffer->GetDesc().Width;
      }

      if(FAILED(hr) || ptr == NULL)
      {
        size = 4;
        ptr = dummy;

        RDCERR("Failed to map buffer for readback! 0x%08x", hr);
      }

      m_pSerialiser->Serialise("NumBytes", size);
      size_t sz = (size_t)size;
      m_pSerialiser->SerialiseBuffer("BufferData", ptr, sz);

      if(SUCCEEDED(hr) && ptr)
        copiedBuffer->Unmap(0, NULL);

      return true;
    }
    else
    {
      RDCERR("Unexpected type needing an initial state serialised out: %d", type);
      return false;
    }
  }
  else
  {
    ID3D12DeviceChild *res = GetLiveResource(id);

    RDCASSERT(res != NULL);

    ResourceId liveid = GetLiveID(id);

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

      uint32_t numElems = 0;
      D3D12Descriptor *descs = NULL;

      m_pSerialiser->SerialiseComplexArray("Descriptors", descs, numElems);

      D3D12_DESCRIPTOR_HEAP_DESC desc = heap->GetDesc();

      // this heap doesn't have to be shader visible, we just use it to copy from
      desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;

      ID3D12DescriptorHeap *copyheap = NULL;
      HRESULT hr = m_Device->GetReal()->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap),
                                                             (void **)&copyheap);

      if(FAILED(hr))
      {
        RDCERR("Failed to create CPU descriptor heap for initial state: 0x%08x", hr);
        return false;
      }

      copyheap = new WrappedID3D12DescriptorHeap(copyheap, m_Device, desc);

      D3D12_CPU_DESCRIPTOR_HANDLE handle = copyheap->GetCPUDescriptorHandleForHeapStart();

      UINT increment = m_Device->GetDescriptorHandleIncrementSize(desc.Type);

      for(uint32_t i = 0; i < numElems; i++)
      {
        descs[i].Create(desc.Type, m_Device, handle);

        handle.ptr += increment;
      }

      SAFE_DELETE_ARRAY(descs);

      SetInitialContents(id, D3D12ResourceManager::InitialContentData(copyheap, 0, NULL));
    }
    else if(type == Resource_Resource)
    {
      D3D12_RESOURCE_DESC resDesc = ((ID3D12Resource *)res)->GetDesc();

      if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && resDesc.SampleDesc.Count > 1)
      {
        D3D12NOTIMP("Multisampled initial contents");
        return true;
      }

      uint64_t size = 0;

      m_pSerialiser->Serialise("NumBytes", size);

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

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

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

      if(FAILED(hr))
      {
        RDCERR("Couldn't create upload buffer: 0x%08x", hr);
        return false;
      }

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

      if(FAILED(hr))
      {
        RDCERR("Couldn't map upload buffer: 0x%08x", hr);
        ptr = NULL;
      }

      size_t sz = (size_t)size;

      m_pSerialiser->SerialiseBuffer("BufferData", ptr, sz);

      if(SUCCEEDED(hr))
        copySrc->Unmap(0, NULL);
      else
        SAFE_DELETE_ARRAY(ptr);

      SetInitialContents(id, D3D12ResourceManager::InitialContentData(copySrc, 1, NULL));

      return true;
    }
    else
    {
      RDCERR("Unexpected type needing an initial state serialised in: %d", type);
      return false;
    }
  }

  return true;
}
Exemplo n.º 3
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;
  }
}