Change D3D11.3 device wrapping to new serialisation system

This commit is contained in:
baldurk
2017-09-18 15:34:33 +01:00
parent 37ef704a3b
commit 545c7831d4
+129 -100
View File
@@ -29,20 +29,29 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////
// ID3D11Device3 interface
bool WrappedID3D11Device::Serialise_CreateTexture2D1(const D3D11_TEXTURE2D_DESC1 *pDesc,
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_CreateTexture2D1(SerialiserType &ser,
const D3D11_TEXTURE2D_DESC1 *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData,
ID3D11Texture2D1 **ppTexture2D)
{
SERIALISE_ELEMENT_PTR(D3D11_TEXTURE2D_DESC1, Descriptor, pDesc);
SERIALISE_ELEMENT(ResourceId, pTexture, GetIDForResource(*ppTexture2D));
SERIALISE_ELEMENT_LOCAL(Descriptor, *pDesc);
SERIALISE_ELEMENT_LOCAL(pTexture, GetIDForResource(*ppTexture2D));
SERIALISE_ELEMENT(bool, HasInitialData, pInitialData != NULL);
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);
}
vector<D3D11_SUBRESOURCE_DATA> descs = Serialise_CreateTextureData(
ppTexture2D ? *ppTexture2D : NULL, pTexture, pInitialData, Descriptor.Width, Descriptor.Height,
1, Descriptor.Format, Descriptor.MipLevels, Descriptor.ArraySize, HasInitialData);
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(m_State == READING)
if(IsReplayingAndReading())
{
ID3D11Texture2D1 *ret = NULL;
HRESULT hr = E_NOINTERFACE;
@@ -76,10 +85,11 @@ bool WrappedID3D11Device::Serialise_CreateTexture2D1(const D3D11_TEXTURE2D_DESC1
GetResourceManager()->AddLiveResource(pTexture, ret);
}
}
for(size_t i = 0; i < descs.size(); i++)
SAFE_DELETE_ARRAY(descs[i].pSysMem);
// 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;
}
@@ -105,13 +115,14 @@ HRESULT WrappedID3D11Device::CreateTexture2D1(const D3D11_TEXTURE2D_DESC1 *pDesc
wrapped = new WrappedID3D11Texture2D1((ID3D11Texture2D *)real, this);
if(m_State >= WRITING)
if(IsCaptureMode(m_State))
{
Chunk *chunk = NULL;
{
SCOPED_SERIALISE_CONTEXT(CREATE_TEXTURE_2D1);
Serialise_CreateTexture2D1(pDesc1, pInitialData, &wrapped);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateTexture2D1);
Serialise_CreateTexture2D1(GET_SERIALISER, pDesc1, pInitialData, &wrapped);
chunk = scope.Get();
}
@@ -136,20 +147,29 @@ HRESULT WrappedID3D11Device::CreateTexture2D1(const D3D11_TEXTURE2D_DESC1 *pDesc
return ret;
}
bool WrappedID3D11Device::Serialise_CreateTexture3D1(const D3D11_TEXTURE3D_DESC1 *pDesc,
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_CreateTexture3D1(SerialiserType &ser,
const D3D11_TEXTURE3D_DESC1 *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData,
ID3D11Texture3D1 **ppTexture3D)
{
SERIALISE_ELEMENT_PTR(D3D11_TEXTURE3D_DESC1, Descriptor, pDesc);
SERIALISE_ELEMENT(ResourceId, pTexture, GetIDForResource(*ppTexture3D));
SERIALISE_ELEMENT_LOCAL(Descriptor, *pDesc);
SERIALISE_ELEMENT_LOCAL(pTexture, GetIDForResource(*ppTexture3D));
SERIALISE_ELEMENT(bool, HasInitialData, pInitialData != NULL);
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);
}
vector<D3D11_SUBRESOURCE_DATA> descs = Serialise_CreateTextureData(
ppTexture3D ? *ppTexture3D : NULL, pTexture, pInitialData, Descriptor.Width, Descriptor.Height,
Descriptor.Depth, Descriptor.Format, Descriptor.MipLevels, 1, HasInitialData);
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(m_State == READING)
if(IsReplayingAndReading())
{
ID3D11Texture3D1 *ret = NULL;
HRESULT hr = E_NOINTERFACE;
@@ -183,10 +203,11 @@ bool WrappedID3D11Device::Serialise_CreateTexture3D1(const D3D11_TEXTURE3D_DESC1
GetResourceManager()->AddLiveResource(pTexture, ret);
}
}
for(size_t i = 0; i < descs.size(); i++)
SAFE_DELETE_ARRAY(descs[i].pSysMem);
// 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;
}
@@ -212,13 +233,14 @@ HRESULT WrappedID3D11Device::CreateTexture3D1(const D3D11_TEXTURE3D_DESC1 *pDesc
wrapped = new WrappedID3D11Texture3D1((ID3D11Texture3D *)real, this);
if(m_State >= WRITING)
if(IsCaptureMode(m_State))
{
Chunk *chunk = NULL;
{
SCOPED_SERIALISE_CONTEXT(CREATE_TEXTURE_3D1);
Serialise_CreateTexture3D1(pDesc1, pInitialData, &wrapped);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateTexture3D1);
Serialise_CreateTexture3D1(GET_SERIALISER, pDesc1, pInitialData, &wrapped);
chunk = scope.Get();
}
@@ -243,32 +265,28 @@ HRESULT WrappedID3D11Device::CreateTexture3D1(const D3D11_TEXTURE3D_DESC1 *pDesc
return ret;
}
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_CreateShaderResourceView1(
ID3D11Resource *pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC1 *pDesc,
SerialiserType &ser, ID3D11Resource *pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC1 *pDesc,
ID3D11ShaderResourceView1 **ppSRView)
{
SERIALISE_ELEMENT(ResourceId, Resource, GetIDForResource(pResource));
SERIALISE_ELEMENT(bool, HasDesc, pDesc != NULL);
SERIALISE_ELEMENT_PTR_OPT(D3D11_SHADER_RESOURCE_VIEW_DESC1, Descriptor, pDesc, HasDesc);
SERIALISE_ELEMENT(ResourceId, pView, GetIDForResource(*ppSRView));
SERIALISE_ELEMENT(pResource);
SERIALISE_ELEMENT_OPT(pDesc);
SERIALISE_ELEMENT_LOCAL(pView, GetIDForResource(*ppSRView));
if(m_State == READING && GetResourceManager()->HasLiveResource(Resource))
if(IsReplayingAndReading() && pResource)
{
ID3D11ShaderResourceView1 *ret = NULL;
D3D11_SHADER_RESOURCE_VIEW_DESC1 *pSRVDesc = NULL;
if(HasDesc)
pSRVDesc = &Descriptor;
D3D11_SHADER_RESOURCE_VIEW_DESC1 *pSRVDesc = (D3D11_SHADER_RESOURCE_VIEW_DESC1 *)pDesc;
ID3D11Resource *live = (ID3D11Resource *)GetResourceManager()->GetLiveResource(Resource);
WrappedID3D11Texture2D1 *tex2d = (WrappedID3D11Texture2D1 *)live;
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(!HasDesc && WrappedID3D11Texture2D1::IsAlloc(live) && tex2d->m_RealDescriptor)
if(!pDesc && WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
{
backbufferTypedDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
@@ -290,7 +308,7 @@ bool WrappedID3D11Device::Serialise_CreateShaderResourceView1(
// 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(live) && tex2d->m_RealDescriptor)
WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
{
pSRVDesc->Format = tex2d->m_RealDescriptor->Format;
}
@@ -299,7 +317,7 @@ bool WrappedID3D11Device::Serialise_CreateShaderResourceView1(
if(m_pDevice3)
{
hr = m_pDevice3->CreateShaderResourceView1(GetResourceManager()->UnwrapResource(live),
hr = m_pDevice3->CreateShaderResourceView1(GetResourceManager()->UnwrapResource(pResource),
pSRVDesc, &ret);
}
else
@@ -313,7 +331,7 @@ bool WrappedID3D11Device::Serialise_CreateShaderResourceView1(
}
else
{
ret = new WrappedID3D11ShaderResourceView1(ret, live, this);
ret = new WrappedID3D11ShaderResourceView1(ret, pResource, this);
GetResourceManager()->AddLiveResource(pView, ret);
}
@@ -347,10 +365,11 @@ HRESULT WrappedID3D11Device::CreateShaderResourceView1(ID3D11Resource *pResource
Chunk *chunk = NULL;
if(m_State >= WRITING)
if(IsCaptureMode(m_State))
{
SCOPED_SERIALISE_CONTEXT(CREATE_SRV1);
Serialise_CreateShaderResourceView1(pResource, pDesc, &wrapped);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateShaderResourceView1);
Serialise_CreateShaderResourceView1(GET_SERIALISER, pResource, pDesc, &wrapped);
chunk = scope.Get();
@@ -387,32 +406,29 @@ HRESULT WrappedID3D11Device::CreateShaderResourceView1(ID3D11Resource *pResource
return ret;
}
bool WrappedID3D11Device::Serialise_CreateRenderTargetView1(ID3D11Resource *pResource,
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_CreateRenderTargetView1(SerialiserType &ser,
ID3D11Resource *pResource,
const D3D11_RENDER_TARGET_VIEW_DESC1 *pDesc,
ID3D11RenderTargetView1 **ppRTView)
{
SERIALISE_ELEMENT(ResourceId, Resource, GetIDForResource(pResource));
SERIALISE_ELEMENT(bool, HasDesc, pDesc != NULL);
SERIALISE_ELEMENT_PTR_OPT(D3D11_RENDER_TARGET_VIEW_DESC1, Descriptor, pDesc, HasDesc);
SERIALISE_ELEMENT(ResourceId, pView, GetIDForResource(*ppRTView));
SERIALISE_ELEMENT(pResource);
SERIALISE_ELEMENT_OPT(pDesc);
SERIALISE_ELEMENT_LOCAL(pView, GetIDForResource(*ppRTView));
if(m_State == READING && GetResourceManager()->HasLiveResource(Resource))
if(IsReplayingAndReading() && pResource)
{
ID3D11RenderTargetView1 *ret = NULL;
D3D11_RENDER_TARGET_VIEW_DESC1 *pRTVDesc = NULL;
if(HasDesc)
pRTVDesc = &Descriptor;
D3D11_RENDER_TARGET_VIEW_DESC1 *pRTVDesc = (D3D11_RENDER_TARGET_VIEW_DESC1 *)pDesc;
ID3D11Resource *live = (ID3D11Resource *)GetResourceManager()->GetLiveResource(Resource);
WrappedID3D11Texture2D1 *tex2d = (WrappedID3D11Texture2D1 *)live;
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(!HasDesc && WrappedID3D11Texture2D1::IsAlloc(live) && tex2d->m_RealDescriptor)
if(!pDesc && WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
{
backbufferTypedDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
@@ -430,7 +446,7 @@ bool WrappedID3D11Device::Serialise_CreateRenderTargetView1(ID3D11Resource *pRes
// 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(live) && tex2d->m_RealDescriptor)
WrappedID3D11Texture2D1::IsAlloc(pResource) && tex2d->m_RealDescriptor)
{
pRTVDesc->Format = tex2d->m_RealDescriptor->Format;
}
@@ -439,8 +455,8 @@ bool WrappedID3D11Device::Serialise_CreateRenderTargetView1(ID3D11Resource *pRes
if(m_pDevice3)
{
hr = m_pDevice3->CreateRenderTargetView1(GetResourceManager()->UnwrapResource(live), pRTVDesc,
&ret);
hr = m_pDevice3->CreateRenderTargetView1(GetResourceManager()->UnwrapResource(pResource),
pRTVDesc, &ret);
}
else
{
@@ -453,7 +469,7 @@ bool WrappedID3D11Device::Serialise_CreateRenderTargetView1(ID3D11Resource *pRes
}
else
{
ret = new WrappedID3D11RenderTargetView1(ret, live, this);
ret = new WrappedID3D11RenderTargetView1(ret, pResource, this);
GetResourceManager()->AddLiveResource(pView, ret);
}
@@ -487,10 +503,11 @@ HRESULT WrappedID3D11Device::CreateRenderTargetView1(ID3D11Resource *pResource,
Chunk *chunk = NULL;
if(m_State >= WRITING)
if(IsCaptureMode(m_State))
{
SCOPED_SERIALISE_CONTEXT(CREATE_RTV1);
Serialise_CreateRenderTargetView1(pResource, pDesc, &wrapped);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateRenderTargetView1);
Serialise_CreateRenderTargetView1(GET_SERIALISER, pResource, pDesc, &wrapped);
chunk = scope.Get();
@@ -528,31 +545,25 @@ HRESULT WrappedID3D11Device::CreateRenderTargetView1(ID3D11Resource *pResource,
return ret;
}
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_CreateUnorderedAccessView1(
ID3D11Resource *pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC1 *pDesc,
SerialiserType &ser, ID3D11Resource *pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC1 *pDesc,
ID3D11UnorderedAccessView1 **ppUAView)
{
SERIALISE_ELEMENT(ResourceId, Resource, GetIDForResource(pResource));
SERIALISE_ELEMENT(bool, HasDesc, pDesc != NULL);
SERIALISE_ELEMENT_PTR_OPT(D3D11_UNORDERED_ACCESS_VIEW_DESC1, Descriptor, pDesc, HasDesc);
SERIALISE_ELEMENT(ResourceId, pView, GetIDForResource(*ppUAView));
SERIALISE_ELEMENT(pResource);
SERIALISE_ELEMENT_OPT(pDesc);
SERIALISE_ELEMENT_LOCAL(pView, GetIDForResource(*ppUAView));
if(m_State == READING && GetResourceManager()->HasLiveResource(Resource))
if(IsReplayingAndReading() && pResource)
{
ID3D11UnorderedAccessView1 *ret = NULL;
D3D11_UNORDERED_ACCESS_VIEW_DESC1 *pUAVDesc = NULL;
if(HasDesc)
pUAVDesc = &Descriptor;
ID3D11Resource *live = (ID3D11Resource *)GetResourceManager()->GetLiveResource(Resource);
HRESULT hr = E_NOINTERFACE;
if(m_pDevice3)
{
hr = m_pDevice3->CreateUnorderedAccessView1(GetResourceManager()->UnwrapResource(live),
pUAVDesc, &ret);
hr = m_pDevice3->CreateUnorderedAccessView1(GetResourceManager()->UnwrapResource(pResource),
pDesc, &ret);
}
else
{
@@ -565,7 +576,7 @@ bool WrappedID3D11Device::Serialise_CreateUnorderedAccessView1(
}
else
{
ret = new WrappedID3D11UnorderedAccessView1(ret, live, this);
ret = new WrappedID3D11UnorderedAccessView1(ret, pResource, this);
GetResourceManager()->AddLiveResource(pView, ret);
}
@@ -599,10 +610,11 @@ HRESULT WrappedID3D11Device::CreateUnorderedAccessView1(ID3D11Resource *pResourc
Chunk *chunk = NULL;
if(m_State >= WRITING)
if(IsCaptureMode(m_State))
{
SCOPED_SERIALISE_CONTEXT(CREATE_UAV1);
Serialise_CreateUnorderedAccessView1(pResource, pDesc, &wrapped);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateUnorderedAccessView1);
Serialise_CreateUnorderedAccessView1(GET_SERIALISER, pResource, pDesc, &wrapped);
chunk = scope.Get();
@@ -639,13 +651,15 @@ HRESULT WrappedID3D11Device::CreateUnorderedAccessView1(ID3D11Resource *pResourc
return ret;
}
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_CreateRasterizerState2(
const D3D11_RASTERIZER_DESC2 *pRasterizerDesc, ID3D11RasterizerState2 **ppRasterizerState)
SerialiserType &ser, const D3D11_RASTERIZER_DESC2 *pRasterizerDesc,
ID3D11RasterizerState2 **ppRasterizerState)
{
SERIALISE_ELEMENT_PTR(D3D11_RASTERIZER_DESC2, Descriptor, pRasterizerDesc);
SERIALISE_ELEMENT(ResourceId, State, GetIDForResource(*ppRasterizerState));
SERIALISE_ELEMENT_LOCAL(Descriptor, *pRasterizerDesc);
SERIALISE_ELEMENT_LOCAL(pState, GetIDForResource(*ppRasterizerState));
if(m_State == READING)
if(IsReplayingAndReading())
{
ID3D11RasterizerState2 *ret = NULL;
HRESULT hr = E_NOINTERFACE;
@@ -667,13 +681,13 @@ bool WrappedID3D11Device::Serialise_CreateRasterizerState2(
ret = (ID3D11RasterizerState2 *)GetResourceManager()->GetWrapper(ret);
ret->AddRef();
GetResourceManager()->AddLiveResource(State, ret);
GetResourceManager()->AddLiveResource(pState, ret);
}
else
{
ret = new WrappedID3D11RasterizerState2(ret, this);
GetResourceManager()->AddLiveResource(State, ret);
GetResourceManager()->AddLiveResource(pState, ret);
}
}
}
@@ -717,10 +731,11 @@ HRESULT WrappedID3D11Device::CreateRasterizerState2(const D3D11_RASTERIZER_DESC2
m_CachedStateObjects.insert(wrapped);
}
if(m_State >= WRITING)
if(IsCaptureMode(m_State))
{
SCOPED_SERIALISE_CONTEXT(CREATE_RASTER_STATE2);
Serialise_CreateRasterizerState2(pRasterizerDesc, &wrapped);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateRasterizerState2);
Serialise_CreateRasterizerState2(GET_SERIALISER, pRasterizerDesc, &wrapped);
m_DeviceRecord->AddChunk(scope.Get());
}
@@ -731,13 +746,15 @@ HRESULT WrappedID3D11Device::CreateRasterizerState2(const D3D11_RASTERIZER_DESC2
return ret;
}
bool WrappedID3D11Device::Serialise_CreateQuery1(const D3D11_QUERY_DESC1 *pQueryDesc,
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_CreateQuery1(SerialiserType &ser,
const D3D11_QUERY_DESC1 *pQueryDesc,
ID3D11Query1 **ppQuery)
{
SERIALISE_ELEMENT_PTR(D3D11_QUERY_DESC1, Descriptor, pQueryDesc);
SERIALISE_ELEMENT(ResourceId, Query, GetIDForResource(*ppQuery));
SERIALISE_ELEMENT_LOCAL(Descriptor, *pQueryDesc);
SERIALISE_ELEMENT_LOCAL(pQuery, GetIDForResource(*ppQuery));
if(m_State == READING)
if(IsReplayingAndReading())
{
ID3D11Query1 *ret = NULL;
HRESULT hr = E_NOINTERFACE;
@@ -755,7 +772,7 @@ bool WrappedID3D11Device::Serialise_CreateQuery1(const D3D11_QUERY_DESC1 *pQuery
{
ret = new WrappedID3D11Query1(ret, this);
GetResourceManager()->AddLiveResource(Query, ret);
GetResourceManager()->AddLiveResource(pQuery, ret);
}
}
@@ -772,13 +789,25 @@ HRESULT WrappedID3D11Device::CreateQuery1(const D3D11_QUERY_DESC1 *pQueryDesc, I
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);
*ppQuery = new WrappedID3D11Query1(real, this);
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;