mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-23 07:51:39 +00:00
911 lines
29 KiB
C++
911 lines
29 KiB
C++
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2016-2017 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 "d3d11_device.h"
|
|
#include "d3d11_context.h"
|
|
#include "d3d11_resources.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// ID3D11Device3 interface
|
|
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D11Device::Serialise_CreateTexture2D1(SerialiserType &ser,
|
|
const D3D11_TEXTURE2D_DESC1 *pDesc,
|
|
const D3D11_SUBRESOURCE_DATA *pInitialData,
|
|
ID3D11Texture2D1 **ppTexture2D)
|
|
{
|
|
SERIALISE_ELEMENT_LOCAL(Descriptor, *pDesc);
|
|
SERIALISE_ELEMENT_LOCAL(pTexture, GetIDForResource(*ppTexture2D));
|
|
|
|
SERIALISE_ELEMENT_LOCAL(HasInitialData, bool(pInitialData != NULL));
|
|
// unused, just for the sake of the user
|
|
if(HasInitialData)
|
|
{
|
|
SERIALISE_ELEMENT_LOCAL(SysMemPitch, pInitialData->SysMemPitch);
|
|
SERIALISE_ELEMENT_LOCAL(SysMemSlicePitch, pInitialData->SysMemSlicePitch);
|
|
}
|
|
|
|
std::vector<D3D11_SUBRESOURCE_DATA> descs =
|
|
Serialise_CreateTextureData(ser, ppTexture2D ? *ppTexture2D : NULL, pTexture, pInitialData,
|
|
Descriptor.Width, Descriptor.Height, 1, Descriptor.Format,
|
|
Descriptor.MipLevels, Descriptor.ArraySize, HasInitialData);
|
|
|
|
if(IsReplayingAndReading())
|
|
{
|
|
ID3D11Texture2D1 *ret = NULL;
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
TextureDisplayType dispType = DispTypeForTexture(Descriptor);
|
|
|
|
// unset flags that are unimportant/problematic in replay
|
|
Descriptor.MiscFlags &=
|
|
~(D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX |
|
|
D3D11_RESOURCE_MISC_GDI_COMPATIBLE | D3D11_RESOURCE_MISC_SHARED_NTHANDLE);
|
|
|
|
if(m_pDevice3)
|
|
{
|
|
if(HasInitialData)
|
|
hr = m_pDevice3->CreateTexture2D1(&Descriptor, &descs[0], &ret);
|
|
else
|
|
hr = m_pDevice3->CreateTexture2D1(&Descriptor, NULL, &ret);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Replaying a D3D11.3 device without D3D11.3 available");
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed on resource serialise-creation, HRESULT: %s", ToStr(hr).c_str());
|
|
}
|
|
else
|
|
{
|
|
ret = new WrappedID3D11Texture2D1((ID3D11Texture2D1 *)ret, this, dispType);
|
|
|
|
GetResourceManager()->AddLiveResource(pTexture, ret);
|
|
}
|
|
|
|
// free the serialised buffers we stole in Serialise_CreateTextureData
|
|
for(size_t i = 0; i < descs.size(); i++)
|
|
FreeAlignedBuffer((byte *)descs[i].pSysMem);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateTexture2D1(const D3D11_TEXTURE2D_DESC1 *pDesc1,
|
|
const D3D11_SUBRESOURCE_DATA *pInitialData,
|
|
ID3D11Texture2D1 **ppTexture2D)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
// validation, returns S_FALSE for valid params, or an error code
|
|
if(ppTexture2D == NULL)
|
|
return m_pDevice3->CreateTexture2D1(pDesc1, pInitialData, NULL);
|
|
|
|
ID3D11Texture2D1 *real = NULL;
|
|
ID3D11Texture2D1 *wrapped = NULL;
|
|
HRESULT ret = m_pDevice3->CreateTexture2D1(pDesc1, pInitialData, &real);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
SCOPED_LOCK(m_D3DLock);
|
|
|
|
wrapped = new WrappedID3D11Texture2D1((ID3D11Texture2D *)real, this);
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
Chunk *chunk = NULL;
|
|
|
|
{
|
|
USE_SCRATCH_SERIALISER();
|
|
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateTexture2D1);
|
|
Serialise_CreateTexture2D1(GET_SERIALISER, pDesc1, pInitialData, &wrapped);
|
|
|
|
chunk = scope.Get();
|
|
}
|
|
|
|
D3D11ResourceRecord *record =
|
|
GetResourceManager()->GetResourceRecord(GetIDForResource(wrapped));
|
|
RDCASSERT(record);
|
|
|
|
record->AddChunk(chunk);
|
|
record->SetDataPtr(chunk->GetData());
|
|
}
|
|
else
|
|
{
|
|
WrappedID3D11Texture2D1 *w = (WrappedID3D11Texture2D1 *)wrapped;
|
|
|
|
GetResourceManager()->AddLiveResource(w->GetResourceID(), wrapped);
|
|
}
|
|
|
|
*ppTexture2D = wrapped;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D11Device::Serialise_CreateTexture3D1(SerialiserType &ser,
|
|
const D3D11_TEXTURE3D_DESC1 *pDesc,
|
|
const D3D11_SUBRESOURCE_DATA *pInitialData,
|
|
ID3D11Texture3D1 **ppTexture3D)
|
|
{
|
|
SERIALISE_ELEMENT_LOCAL(Descriptor, *pDesc);
|
|
SERIALISE_ELEMENT_LOCAL(pTexture, GetIDForResource(*ppTexture3D));
|
|
|
|
SERIALISE_ELEMENT_LOCAL(HasInitialData, bool(pInitialData != NULL));
|
|
// unused, just for the sake of the user
|
|
if(HasInitialData)
|
|
{
|
|
SERIALISE_ELEMENT_LOCAL(SysMemPitch, pInitialData->SysMemPitch);
|
|
SERIALISE_ELEMENT_LOCAL(SysMemSlicePitch, pInitialData->SysMemSlicePitch);
|
|
}
|
|
|
|
std::vector<D3D11_SUBRESOURCE_DATA> descs =
|
|
Serialise_CreateTextureData(ser, ppTexture3D ? *ppTexture3D : NULL, pTexture, pInitialData,
|
|
Descriptor.Width, Descriptor.Height, Descriptor.Depth,
|
|
Descriptor.Format, Descriptor.MipLevels, 1, HasInitialData);
|
|
|
|
if(IsReplayingAndReading())
|
|
{
|
|
ID3D11Texture3D1 *ret = NULL;
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
TextureDisplayType dispType = DispTypeForTexture(Descriptor);
|
|
|
|
// unset flags that are unimportant/problematic in replay
|
|
Descriptor.MiscFlags &=
|
|
~(D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX |
|
|
D3D11_RESOURCE_MISC_GDI_COMPATIBLE | D3D11_RESOURCE_MISC_SHARED_NTHANDLE);
|
|
|
|
if(m_pDevice3)
|
|
{
|
|
if(HasInitialData)
|
|
hr = m_pDevice3->CreateTexture3D1(&Descriptor, &descs[0], &ret);
|
|
else
|
|
hr = m_pDevice3->CreateTexture3D1(&Descriptor, NULL, &ret);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Replaying a D3D11.3 device without D3D11.3 available");
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed on resource serialise-creation, HRESULT: %s", ToStr(hr).c_str());
|
|
}
|
|
else
|
|
{
|
|
ret = new WrappedID3D11Texture3D1((ID3D11Texture3D1 *)ret, this, dispType);
|
|
|
|
GetResourceManager()->AddLiveResource(pTexture, ret);
|
|
}
|
|
|
|
// free the serialised buffers we stole in Serialise_CreateTextureData
|
|
for(size_t i = 0; i < descs.size(); i++)
|
|
FreeAlignedBuffer((byte *)descs[i].pSysMem);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateTexture3D1(const D3D11_TEXTURE3D_DESC1 *pDesc1,
|
|
const D3D11_SUBRESOURCE_DATA *pInitialData,
|
|
ID3D11Texture3D1 **ppTexture3D)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
// validation, returns S_FALSE for valid params, or an error code
|
|
if(ppTexture3D == NULL)
|
|
return m_pDevice3->CreateTexture3D1(pDesc1, pInitialData, NULL);
|
|
|
|
ID3D11Texture3D1 *real = NULL;
|
|
ID3D11Texture3D1 *wrapped = NULL;
|
|
HRESULT ret = m_pDevice3->CreateTexture3D1(pDesc1, pInitialData, &real);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
SCOPED_LOCK(m_D3DLock);
|
|
|
|
wrapped = new WrappedID3D11Texture3D1((ID3D11Texture3D *)real, this);
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
Chunk *chunk = NULL;
|
|
|
|
{
|
|
USE_SCRATCH_SERIALISER();
|
|
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateTexture3D1);
|
|
Serialise_CreateTexture3D1(GET_SERIALISER, pDesc1, pInitialData, &wrapped);
|
|
|
|
chunk = scope.Get();
|
|
}
|
|
|
|
D3D11ResourceRecord *record =
|
|
GetResourceManager()->GetResourceRecord(GetIDForResource(wrapped));
|
|
RDCASSERT(record);
|
|
|
|
record->AddChunk(chunk);
|
|
record->SetDataPtr(chunk->GetData());
|
|
}
|
|
else
|
|
{
|
|
WrappedID3D11Texture3D1 *w = (WrappedID3D11Texture3D1 *)wrapped;
|
|
|
|
GetResourceManager()->AddLiveResource(w->GetResourceID(), wrapped);
|
|
}
|
|
|
|
*ppTexture3D = wrapped;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D11Device::Serialise_CreateShaderResourceView1(
|
|
SerialiserType &ser, ID3D11Resource *pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC1 *pDesc,
|
|
ID3D11ShaderResourceView1 **ppSRView)
|
|
{
|
|
SERIALISE_ELEMENT(pResource);
|
|
SERIALISE_ELEMENT_OPT(pDesc);
|
|
SERIALISE_ELEMENT_LOCAL(pView, GetIDForResource(*ppSRView));
|
|
|
|
if(IsReplayingAndReading() && pResource)
|
|
{
|
|
ID3D11ShaderResourceView1 *ret = NULL;
|
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC1 *pSRVDesc = (D3D11_SHADER_RESOURCE_VIEW_DESC1 *)pDesc;
|
|
|
|
WrappedID3D11Texture2D1 *tex2d = (WrappedID3D11Texture2D1 *)pResource;
|
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC1 backbufferTypedDesc = {};
|
|
|
|
// need to fixup typeless backbuffer fudging, if a descriptor isn't specified then
|
|
// we need to make one to give the correct type
|
|
if(!pDesc && WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
|
|
{
|
|
backbufferTypedDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
|
|
if(tex2d->m_RealDescriptor->SampleDesc.Quality > 0 ||
|
|
tex2d->m_RealDescriptor->SampleDesc.Count > 1)
|
|
backbufferTypedDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
|
|
|
backbufferTypedDesc.Format = tex2d->m_RealDescriptor->Format;
|
|
backbufferTypedDesc.Texture2D.MipLevels = 1;
|
|
backbufferTypedDesc.Texture2D.MostDetailedMip = 0;
|
|
backbufferTypedDesc.Texture2D.PlaneSlice = 0;
|
|
pSRVDesc = &backbufferTypedDesc;
|
|
}
|
|
|
|
// if we have a descriptor but it specifies DXGI_FORMAT_UNKNOWN format, that means use
|
|
// the texture's format. But as above, we fudge around the typeless backbuffer so we
|
|
// have to set the correct typed format
|
|
//
|
|
// This behaviour is documented only for render targets, but seems to be used & work for
|
|
// SRVs, so apply it here too.
|
|
if(pSRVDesc && pSRVDesc->Format == DXGI_FORMAT_UNKNOWN &&
|
|
WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
|
|
{
|
|
pSRVDesc->Format = tex2d->m_RealDescriptor->Format;
|
|
}
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if(m_pDevice3)
|
|
{
|
|
hr = m_pDevice3->CreateShaderResourceView1(GetResourceManager()->UnwrapResource(pResource),
|
|
pSRVDesc, &ret);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Replaying a D3D11.3 device without D3D11.3 available");
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed on resource serialise-creation, HRESULT: %s", ToStr(hr).c_str());
|
|
}
|
|
else
|
|
{
|
|
ret = new WrappedID3D11ShaderResourceView1(ret, pResource, this);
|
|
|
|
GetResourceManager()->AddLiveResource(pView, ret);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateShaderResourceView1(ID3D11Resource *pResource,
|
|
const D3D11_SHADER_RESOURCE_VIEW_DESC1 *pDesc,
|
|
ID3D11ShaderResourceView1 **ppSRView)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
// validation, returns S_FALSE for valid params, or an error code
|
|
if(ppSRView == NULL)
|
|
return m_pDevice3->CreateShaderResourceView1(GetResourceManager()->UnwrapResource(pResource),
|
|
pDesc, NULL);
|
|
|
|
ID3D11ShaderResourceView1 *real = NULL;
|
|
ID3D11ShaderResourceView1 *wrapped = NULL;
|
|
HRESULT ret = m_pDevice3->CreateShaderResourceView1(
|
|
GetResourceManager()->UnwrapResource(pResource), pDesc, &real);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
SCOPED_LOCK(m_D3DLock);
|
|
|
|
wrapped = new WrappedID3D11ShaderResourceView1(real, pResource, this);
|
|
|
|
Chunk *chunk = NULL;
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
USE_SCRATCH_SERIALISER();
|
|
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateShaderResourceView1);
|
|
Serialise_CreateShaderResourceView1(GET_SERIALISER, pResource, pDesc, &wrapped);
|
|
|
|
chunk = scope.Get();
|
|
|
|
if(WrappedID3D11Texture1D::IsAlloc(pResource) || WrappedID3D11Texture2D1::IsAlloc(pResource) ||
|
|
WrappedID3D11Texture3D1::IsAlloc(pResource) || WrappedID3D11Buffer::IsAlloc(pResource))
|
|
{
|
|
D3D11ResourceRecord *parent =
|
|
GetResourceManager()->GetResourceRecord(GetIDForResource(pResource));
|
|
|
|
RDCASSERT(parent);
|
|
|
|
WrappedID3D11ShaderResourceView1 *view = (WrappedID3D11ShaderResourceView1 *)wrapped;
|
|
ResourceId id = view->GetResourceID();
|
|
|
|
RDCASSERT(GetResourceManager()->GetResourceRecord(id) == NULL);
|
|
|
|
D3D11ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
|
|
record->Length = 0;
|
|
|
|
record->AddParent(parent);
|
|
|
|
record->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Unexpected resource type in SRV creation");
|
|
|
|
m_DeviceRecord->AddChunk(chunk);
|
|
}
|
|
}
|
|
|
|
*ppSRView = wrapped;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D11Device::Serialise_CreateRenderTargetView1(SerialiserType &ser,
|
|
ID3D11Resource *pResource,
|
|
const D3D11_RENDER_TARGET_VIEW_DESC1 *pDesc,
|
|
ID3D11RenderTargetView1 **ppRTView)
|
|
{
|
|
SERIALISE_ELEMENT(pResource);
|
|
SERIALISE_ELEMENT_OPT(pDesc);
|
|
SERIALISE_ELEMENT_LOCAL(pView, GetIDForResource(*ppRTView));
|
|
|
|
if(IsReplayingAndReading() && pResource)
|
|
{
|
|
ID3D11RenderTargetView1 *ret = NULL;
|
|
|
|
D3D11_RENDER_TARGET_VIEW_DESC1 *pRTVDesc = (D3D11_RENDER_TARGET_VIEW_DESC1 *)pDesc;
|
|
|
|
WrappedID3D11Texture2D1 *tex2d = (WrappedID3D11Texture2D1 *)pResource;
|
|
|
|
D3D11_RENDER_TARGET_VIEW_DESC1 backbufferTypedDesc = {};
|
|
|
|
// need to fixup typeless backbuffer fudging, if a descriptor isn't specified then
|
|
// we need to make one to give the correct type
|
|
if(!pDesc && WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
|
|
{
|
|
backbufferTypedDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
|
|
|
if(tex2d->m_RealDescriptor->SampleDesc.Quality > 0 ||
|
|
tex2d->m_RealDescriptor->SampleDesc.Count > 1)
|
|
backbufferTypedDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
|
|
|
|
backbufferTypedDesc.Format = tex2d->m_RealDescriptor->Format;
|
|
backbufferTypedDesc.Texture2D.MipSlice = 0;
|
|
backbufferTypedDesc.Texture2D.PlaneSlice = 0;
|
|
pRTVDesc = &backbufferTypedDesc;
|
|
}
|
|
|
|
// if we have a descriptor but it specifies DXGI_FORMAT_UNKNOWN format, that means use
|
|
// the texture's format. But as above, we fudge around the typeless backbuffer so we
|
|
// have to set the correct typed format
|
|
if(pRTVDesc && pRTVDesc->Format == DXGI_FORMAT_UNKNOWN &&
|
|
WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
|
|
{
|
|
pRTVDesc->Format = tex2d->m_RealDescriptor->Format;
|
|
}
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if(m_pDevice3)
|
|
{
|
|
hr = m_pDevice3->CreateRenderTargetView1(GetResourceManager()->UnwrapResource(pResource),
|
|
pRTVDesc, &ret);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Replaying a D3D11.3 device without D3D11.3 available");
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed on resource serialise-creation, HRESULT: %s", ToStr(hr).c_str());
|
|
}
|
|
else
|
|
{
|
|
ret = new WrappedID3D11RenderTargetView1(ret, pResource, this);
|
|
|
|
GetResourceManager()->AddLiveResource(pView, ret);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateRenderTargetView1(ID3D11Resource *pResource,
|
|
const D3D11_RENDER_TARGET_VIEW_DESC1 *pDesc,
|
|
ID3D11RenderTargetView1 **ppRTView)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
// validation, returns S_FALSE for valid params, or an error code
|
|
if(ppRTView == NULL)
|
|
return m_pDevice3->CreateRenderTargetView1(GetResourceManager()->UnwrapResource(pResource),
|
|
pDesc, NULL);
|
|
|
|
ID3D11RenderTargetView1 *real = NULL;
|
|
ID3D11RenderTargetView1 *wrapped = NULL;
|
|
HRESULT ret = m_pDevice3->CreateRenderTargetView1(GetResourceManager()->UnwrapResource(pResource),
|
|
pDesc, &real);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
SCOPED_LOCK(m_D3DLock);
|
|
|
|
wrapped = new WrappedID3D11RenderTargetView1(real, pResource, this);
|
|
|
|
Chunk *chunk = NULL;
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
USE_SCRATCH_SERIALISER();
|
|
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateRenderTargetView1);
|
|
Serialise_CreateRenderTargetView1(GET_SERIALISER, pResource, pDesc, &wrapped);
|
|
|
|
chunk = scope.Get();
|
|
|
|
if(WrappedID3D11Texture1D::IsAlloc(pResource) || WrappedID3D11Texture2D1::IsAlloc(pResource) ||
|
|
WrappedID3D11Texture3D1::IsAlloc(pResource) || WrappedID3D11Buffer::IsAlloc(pResource))
|
|
{
|
|
D3D11ResourceRecord *parent =
|
|
GetResourceManager()->GetResourceRecord(GetIDForResource(pResource));
|
|
|
|
RDCASSERT(parent);
|
|
|
|
WrappedID3D11RenderTargetView1 *view = (WrappedID3D11RenderTargetView1 *)wrapped;
|
|
ResourceId id = view->GetResourceID();
|
|
|
|
RDCASSERT(GetResourceManager()->GetResourceRecord(id) == NULL);
|
|
|
|
D3D11ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
|
|
record->Length = 0;
|
|
|
|
record->AddParent(parent);
|
|
|
|
record->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Unexpected resource type in RTV creation");
|
|
|
|
m_DeviceRecord->AddChunk(chunk);
|
|
}
|
|
}
|
|
|
|
*ppRTView = wrapped;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D11Device::Serialise_CreateUnorderedAccessView1(
|
|
SerialiserType &ser, ID3D11Resource *pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC1 *pDesc,
|
|
ID3D11UnorderedAccessView1 **ppUAView)
|
|
{
|
|
SERIALISE_ELEMENT(pResource);
|
|
SERIALISE_ELEMENT_OPT(pDesc);
|
|
SERIALISE_ELEMENT_LOCAL(pView, GetIDForResource(*ppUAView));
|
|
|
|
if(IsReplayingAndReading() && pResource)
|
|
{
|
|
ID3D11UnorderedAccessView1 *ret = NULL;
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if(m_pDevice3)
|
|
{
|
|
hr = m_pDevice3->CreateUnorderedAccessView1(GetResourceManager()->UnwrapResource(pResource),
|
|
pDesc, &ret);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Replaying a D3D11.3 device without D3D11.3 available");
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed on resource serialise-creation, HRESULT: %s", ToStr(hr).c_str());
|
|
}
|
|
else
|
|
{
|
|
ret = new WrappedID3D11UnorderedAccessView1(ret, pResource, this);
|
|
|
|
GetResourceManager()->AddLiveResource(pView, ret);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateUnorderedAccessView1(ID3D11Resource *pResource,
|
|
const D3D11_UNORDERED_ACCESS_VIEW_DESC1 *pDesc,
|
|
ID3D11UnorderedAccessView1 **ppUAView)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
// validation, returns S_FALSE for valid params, or an error code
|
|
if(ppUAView == NULL)
|
|
return m_pDevice3->CreateUnorderedAccessView1(GetResourceManager()->UnwrapResource(pResource),
|
|
pDesc, NULL);
|
|
|
|
ID3D11UnorderedAccessView1 *real = NULL;
|
|
ID3D11UnorderedAccessView1 *wrapped = NULL;
|
|
HRESULT ret = m_pDevice3->CreateUnorderedAccessView1(
|
|
GetResourceManager()->UnwrapResource(pResource), pDesc, &real);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
SCOPED_LOCK(m_D3DLock);
|
|
|
|
wrapped = new WrappedID3D11UnorderedAccessView1(real, pResource, this);
|
|
|
|
Chunk *chunk = NULL;
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
USE_SCRATCH_SERIALISER();
|
|
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateUnorderedAccessView1);
|
|
Serialise_CreateUnorderedAccessView1(GET_SERIALISER, pResource, pDesc, &wrapped);
|
|
|
|
chunk = scope.Get();
|
|
|
|
if(WrappedID3D11Texture1D::IsAlloc(pResource) || WrappedID3D11Texture2D1::IsAlloc(pResource) ||
|
|
WrappedID3D11Texture3D1::IsAlloc(pResource) || WrappedID3D11Buffer::IsAlloc(pResource))
|
|
{
|
|
D3D11ResourceRecord *parent =
|
|
GetResourceManager()->GetResourceRecord(GetIDForResource(pResource));
|
|
|
|
RDCASSERT(parent);
|
|
|
|
WrappedID3D11UnorderedAccessView1 *view = (WrappedID3D11UnorderedAccessView1 *)wrapped;
|
|
ResourceId id = view->GetResourceID();
|
|
|
|
RDCASSERT(GetResourceManager()->GetResourceRecord(id) == NULL);
|
|
|
|
D3D11ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
|
|
record->Length = 0;
|
|
|
|
record->AddParent(parent);
|
|
|
|
record->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Unexpected resource type in UAV creation");
|
|
|
|
m_DeviceRecord->AddChunk(chunk);
|
|
}
|
|
}
|
|
|
|
*ppUAView = wrapped;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D11Device::Serialise_CreateRasterizerState2(
|
|
SerialiserType &ser, const D3D11_RASTERIZER_DESC2 *pRasterizerDesc,
|
|
ID3D11RasterizerState2 **ppRasterizerState)
|
|
{
|
|
SERIALISE_ELEMENT_LOCAL(Descriptor, *pRasterizerDesc);
|
|
SERIALISE_ELEMENT_LOCAL(pState, GetIDForResource(*ppRasterizerState));
|
|
|
|
if(IsReplayingAndReading())
|
|
{
|
|
ID3D11RasterizerState2 *ret = NULL;
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if(m_pDevice3)
|
|
hr = m_pDevice3->CreateRasterizerState2(&Descriptor, &ret);
|
|
else
|
|
RDCERR("Replaying a D3D11.3 device without D3D11.3 available");
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed on resource serialise-creation, HRESULT: %s", ToStr(hr).c_str());
|
|
}
|
|
else
|
|
{
|
|
if(GetResourceManager()->HasWrapper(ret))
|
|
{
|
|
ret->Release();
|
|
ret = (ID3D11RasterizerState2 *)GetResourceManager()->GetWrapper(ret);
|
|
ret->AddRef();
|
|
|
|
GetResourceManager()->AddLiveResource(pState, ret);
|
|
}
|
|
else
|
|
{
|
|
ret = new WrappedID3D11RasterizerState2(ret, this);
|
|
|
|
GetResourceManager()->AddLiveResource(pState, ret);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateRasterizerState2(const D3D11_RASTERIZER_DESC2 *pRasterizerDesc,
|
|
ID3D11RasterizerState2 **ppRasterizerState)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
if(ppRasterizerState == NULL)
|
|
return m_pDevice3->CreateRasterizerState2(pRasterizerDesc, NULL);
|
|
|
|
ID3D11RasterizerState2 *real = NULL;
|
|
HRESULT ret = m_pDevice3->CreateRasterizerState2(pRasterizerDesc, &real);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
SCOPED_LOCK(m_D3DLock);
|
|
|
|
// duplicate states can be returned, if Create is called with a previous descriptor
|
|
if(GetResourceManager()->HasWrapper(real))
|
|
{
|
|
real->Release();
|
|
*ppRasterizerState = (ID3D11RasterizerState2 *)GetResourceManager()->GetWrapper(real);
|
|
(*ppRasterizerState)->AddRef();
|
|
return ret;
|
|
}
|
|
|
|
ID3D11RasterizerState2 *wrapped = new WrappedID3D11RasterizerState2(real, this);
|
|
|
|
CachedObjectsGarbageCollect();
|
|
|
|
{
|
|
RDCASSERT(m_CachedStateObjects.find(wrapped) == m_CachedStateObjects.end());
|
|
wrapped->AddRef();
|
|
InternalRef();
|
|
m_CachedStateObjects.insert(wrapped);
|
|
}
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
USE_SCRATCH_SERIALISER();
|
|
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateRasterizerState2);
|
|
Serialise_CreateRasterizerState2(GET_SERIALISER, pRasterizerDesc, &wrapped);
|
|
|
|
m_DeviceRecord->AddChunk(scope.Get());
|
|
}
|
|
|
|
*ppRasterizerState = wrapped;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D11Device::Serialise_CreateQuery1(SerialiserType &ser,
|
|
const D3D11_QUERY_DESC1 *pQueryDesc,
|
|
ID3D11Query1 **ppQuery)
|
|
{
|
|
SERIALISE_ELEMENT_LOCAL(Descriptor, *pQueryDesc);
|
|
SERIALISE_ELEMENT_LOCAL(pQuery, GetIDForResource(*ppQuery));
|
|
|
|
if(IsReplayingAndReading())
|
|
{
|
|
ID3D11Query1 *ret = NULL;
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if(m_pDevice3)
|
|
hr = m_pDevice3->CreateQuery1(&Descriptor, &ret);
|
|
else
|
|
RDCERR("Replaying a D3D11.3 device without D3D11.3 available");
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed on resource serialise-creation, HRESULT: %s", ToStr(hr).c_str());
|
|
}
|
|
else
|
|
{
|
|
ret = new WrappedID3D11Query1(ret, this);
|
|
|
|
GetResourceManager()->AddLiveResource(pQuery, ret);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateQuery1(const D3D11_QUERY_DESC1 *pQueryDesc, ID3D11Query1 **ppQuery)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
// validation, returns S_FALSE for valid params, or an error code
|
|
if(ppQuery == NULL)
|
|
return m_pDevice3->CreateQuery1(pQueryDesc, NULL);
|
|
|
|
ID3D11Query1 *real = NULL;
|
|
ID3D11Query1 *wrapped = NULL;
|
|
HRESULT ret = m_pDevice3->CreateQuery1(pQueryDesc, &real);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
SCOPED_LOCK(m_D3DLock);
|
|
|
|
wrapped = new WrappedID3D11Query1(real, this);
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
USE_SCRATCH_SERIALISER();
|
|
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateQuery1);
|
|
Serialise_CreateQuery1(GET_SERIALISER, pQueryDesc, &wrapped);
|
|
|
|
m_DeviceRecord->AddChunk(scope.Get());
|
|
}
|
|
|
|
*ppQuery = wrapped;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void WrappedID3D11Device::GetImmediateContext3(ID3D11DeviceContext3 **ppImmediateContext)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return;
|
|
|
|
if(ppImmediateContext)
|
|
{
|
|
m_pImmediateContext->AddRef();
|
|
*ppImmediateContext = (ID3D11DeviceContext3 *)m_pImmediateContext;
|
|
}
|
|
}
|
|
|
|
HRESULT WrappedID3D11Device::CreateDeferredContext3(UINT ContextFlags,
|
|
ID3D11DeviceContext3 **ppDeferredContext)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
if(ppDeferredContext == NULL)
|
|
return m_pDevice3->CreateDeferredContext3(ContextFlags, NULL);
|
|
|
|
ID3D11DeviceContext *defCtx = NULL;
|
|
HRESULT ret = CreateDeferredContext(ContextFlags, &defCtx);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
WrappedID3D11DeviceContext *wrapped = (WrappedID3D11DeviceContext *)defCtx;
|
|
*ppDeferredContext = (ID3D11DeviceContext3 *)wrapped;
|
|
}
|
|
else
|
|
{
|
|
SAFE_RELEASE(defCtx);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void WrappedID3D11Device::WriteToSubresource(ID3D11Resource *pDstResource, UINT DstSubresource,
|
|
const D3D11_BOX *pDstBox, const void *pSrcData,
|
|
UINT SrcRowPitch, UINT SrcDepthPitch)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return;
|
|
|
|
RDCUNIMPLEMENTED(
|
|
"WriteToSubresource is not supported. Please contact me if you have a working example! "
|
|
"https://github.com/baldurk/renderdoc/issues");
|
|
|
|
m_pDevice3->WriteToSubresource(pDstResource, DstSubresource, pDstBox, pSrcData, SrcRowPitch,
|
|
SrcDepthPitch);
|
|
|
|
return;
|
|
}
|
|
|
|
void WrappedID3D11Device::ReadFromSubresource(void *pDstData, UINT DstRowPitch, UINT DstDepthPitch,
|
|
ID3D11Resource *pSrcResource, UINT SrcSubresource,
|
|
const D3D11_BOX *pSrcBox)
|
|
{
|
|
if(m_pDevice3 == NULL)
|
|
return;
|
|
|
|
RDCUNIMPLEMENTED(
|
|
"ReadFromSubresource is not supported. Please contact me if you have a working example! "
|
|
"https://github.com/baldurk/renderdoc/issues");
|
|
|
|
m_pDevice3->ReadFromSubresource(pDstData, DstRowPitch, DstDepthPitch, pSrcResource,
|
|
SrcSubresource, pSrcBox);
|
|
|
|
return;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// ID3D11Device4 interface
|
|
|
|
HRESULT WrappedID3D11Device::RegisterDeviceRemovedEvent(HANDLE hEvent, DWORD *pdwCookie)
|
|
{
|
|
if(m_pDevice4 == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
return m_pDevice4->RegisterDeviceRemovedEvent(hEvent, pdwCookie);
|
|
}
|
|
|
|
void WrappedID3D11Device::UnregisterDeviceRemoved(DWORD dwCookie)
|
|
{
|
|
if(m_pDevice4 == NULL)
|
|
return;
|
|
|
|
return m_pDevice4->UnregisterDeviceRemoved(dwCookie);
|
|
}
|
|
|
|
#undef IMPLEMENT_FUNCTION_SERIALISED
|
|
#define IMPLEMENT_FUNCTION_SERIALISED(ret, func, ...) \
|
|
template bool WrappedID3D11Device::CONCAT(Serialise_, func(ReadSerialiser &ser, __VA_ARGS__)); \
|
|
template bool WrappedID3D11Device::CONCAT(Serialise_, func(WriteSerialiser &ser, __VA_ARGS__));
|
|
|
|
SERIALISED_ID3D11DEVICE3_FUNCTIONS(); |