Refactor render state to use cached resource ranges for views

* We also check for null resources and early out before fetching or
  constructing the range and doing the intersection test.
This commit is contained in:
baldurk
2017-06-08 12:51:37 +01:00
parent eba2c65870
commit d27c15a0ab
3 changed files with 229 additions and 562 deletions
+4 -4
View File
@@ -2517,15 +2517,15 @@ void WrappedID3D11Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap
{
ResourceRange range(wrapped11);
GetImmediateContext()->GetCurrentPipelineState()->UnbindIUnknownForWrite(range);
GetImmediateContext()->GetCurrentPipelineState()->UnbindIUnknownForRead(range, false, false);
GetImmediateContext()->GetCurrentPipelineState()->UnbindRangeForWrite(range);
GetImmediateContext()->GetCurrentPipelineState()->UnbindRangeForRead(range);
{
SCOPED_LOCK(WrappedID3DDeviceContextState::m_Lock);
for(size_t s = 0; s < WrappedID3DDeviceContextState::m_List.size(); s++)
{
WrappedID3DDeviceContextState::m_List[s]->state->UnbindIUnknownForWrite(range);
WrappedID3DDeviceContextState::m_List[s]->state->UnbindIUnknownForRead(range, false, false);
WrappedID3DDeviceContextState::m_List[s]->state->UnbindRangeForWrite(range);
WrappedID3DDeviceContextState::m_List[s]->state->UnbindRangeForRead(range);
}
}
+171 -346
View File
@@ -974,12 +974,11 @@ void D3D11RenderState::ReleaseRef(ID3D11DeviceChild *p)
}
}
bool D3D11RenderState::IsBoundIUnknownForWrite(const ResourceRange &range, bool readDepthOnly,
bool readStencilOnly)
bool D3D11RenderState::IsRangeBoundForWrite(const ResourceRange &range)
{
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(CSUAVs[i])))
if(CSUAVs[i] && range.Intersects(GetResourceRange(CSUAVs[i])))
{
// RDCDEBUG("Resource was bound on CS UAV %u", i);
return true;
@@ -988,7 +987,7 @@ bool D3D11RenderState::IsBoundIUnknownForWrite(const ResourceRange &range, bool
for(UINT i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(SO.Buffers[i])))
if(SO.Buffers[i] && range.Intersects(ResourceRange(SO.Buffers[i])))
{
// RDCDEBUG("Resource was bound on SO buffer %u", i);
return true;
@@ -997,7 +996,7 @@ bool D3D11RenderState::IsBoundIUnknownForWrite(const ResourceRange &range, bool
for(UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
if(range.Intersects(ResourceRange(OM.RenderTargets[i])))
if(OM.RenderTargets[i] && range.Intersects(GetResourceRange(OM.RenderTargets[i])))
{
// RDCDEBUG("Resource was bound on RTV %u", i);
return true;
@@ -1006,39 +1005,32 @@ bool D3D11RenderState::IsBoundIUnknownForWrite(const ResourceRange &range, bool
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(OM.UAVs[i])))
if(OM.UAVs[i] && range.Intersects(GetResourceRange(OM.UAVs[i])))
{
// RDCDEBUG("Resource was bound on OM UAV %d", i);
return true;
}
}
if(OM.DepthView)
{
UINT depthFlags = 0;
const ResourceRange &depthRange = GetResourceRange(OM.DepthView);
if(OM.DepthView)
{
D3D11_DEPTH_STENCIL_VIEW_DESC d;
OM.DepthView->GetDesc(&d);
depthFlags = d.Flags;
}
if(range.Intersects(ResourceRange(OM.DepthView)))
if(range.Intersects(depthRange))
{
// RDCDEBUG("Resource was bound on OM DSV");
if(depthFlags == (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL))
if(depthRange.IsDepthReadOnly() && depthRange.IsStencilReadOnly())
{
// RDCDEBUG("but it's a readonly DSV, so that's fine");
}
else if(depthFlags == D3D11_DSV_READ_ONLY_DEPTH && readDepthOnly)
else if(depthRange.IsDepthReadOnly() && range.IsDepthReadOnly())
{
// RDCDEBUG("but it's a depth readonly DSV and we're only reading depth, so that's fine");
}
else if(depthFlags == D3D11_DSV_READ_ONLY_STENCIL && readStencilOnly)
else if(depthRange.IsStencilReadOnly() && range.IsStencilReadOnly())
{
// RDCDEBUG("but it's a depth readonly DSV and we're only reading depth, so that's fine");
// RDCDEBUG("but it's a stencil readonly DSV and we're only reading stencil, so that's OK");
}
else
{
@@ -1050,11 +1042,11 @@ bool D3D11RenderState::IsBoundIUnknownForWrite(const ResourceRange &range, bool
return false;
}
void D3D11RenderState::UnbindIUnknownForWrite(const ResourceRange &range)
void D3D11RenderState::UnbindRangeForWrite(const ResourceRange &range)
{
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(CSUAVs[i])))
if(CSUAVs[i] && range.Intersects(GetResourceRange(CSUAVs[i])))
{
ReleaseRef(CSUAVs[i]);
CSUAVs[i] = NULL;
@@ -1063,7 +1055,7 @@ void D3D11RenderState::UnbindIUnknownForWrite(const ResourceRange &range)
for(UINT i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(SO.Buffers[i])))
if(SO.Buffers[i] && range.Intersects(ResourceRange(SO.Buffers[i])))
{
ReleaseRef(SO.Buffers[i]);
SO.Buffers[i] = NULL;
@@ -1072,7 +1064,7 @@ void D3D11RenderState::UnbindIUnknownForWrite(const ResourceRange &range)
for(UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
if(range.Intersects(ResourceRange(OM.RenderTargets[i])))
if(OM.RenderTargets[i] && range.Intersects(GetResourceRange(OM.RenderTargets[i])))
{
ReleaseRef(OM.RenderTargets[i]);
OM.RenderTargets[i] = NULL;
@@ -1081,26 +1073,25 @@ void D3D11RenderState::UnbindIUnknownForWrite(const ResourceRange &range)
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(OM.UAVs[i])))
if(OM.UAVs[i] && range.Intersects(GetResourceRange(OM.UAVs[i])))
{
ReleaseRef(OM.UAVs[i]);
OM.UAVs[i] = NULL;
}
}
if(range.Intersects(ResourceRange(OM.DepthView)))
if(OM.DepthView && range.Intersects(GetResourceRange(OM.DepthView)))
{
ReleaseRef(OM.DepthView);
OM.DepthView = NULL;
}
}
void D3D11RenderState::UnbindIUnknownForRead(const ResourceRange &range, bool allowDepthOnly,
bool allowStencilOnly)
void D3D11RenderState::UnbindRangeForRead(const ResourceRange &range)
{
for(int i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(IA.VBs[i])))
if(IA.VBs[i] && range.Intersects(ResourceRange(IA.VBs[i])))
{
// RDCDEBUG("Resource was bound on IA VB %u", i);
ReleaseRef(IA.VBs[i]);
@@ -1108,7 +1099,7 @@ void D3D11RenderState::UnbindIUnknownForRead(const ResourceRange &range, bool al
}
}
if(range.Intersects(ResourceRange(IA.IndexBuffer)))
if(IA.IndexBuffer && range.Intersects(ResourceRange(IA.IndexBuffer)))
{
// RDCDEBUG("Resource was bound on IA IB");
ReleaseRef(IA.IndexBuffer);
@@ -1123,7 +1114,7 @@ void D3D11RenderState::UnbindIUnknownForRead(const ResourceRange &range, bool al
for(UINT i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
{
if(range.Intersects(ResourceRange(sh->ConstantBuffers[i])))
if(sh->ConstantBuffers[i] && range.Intersects(ResourceRange(sh->ConstantBuffers[i])))
{
// RDCDEBUG("Resource was bound on %s CB %u", names[s], i);
ReleaseRef(sh->ConstantBuffers[i]);
@@ -1133,79 +1124,22 @@ void D3D11RenderState::UnbindIUnknownForRead(const ResourceRange &range, bool al
for(UINT i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++)
{
bool readDepthOnly = false;
bool readStencilOnly = false;
if(!sh->SRVs[i])
continue;
D3D11_RESOURCE_DIMENSION dim;
DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN;
const ResourceRange &srvRange = GetResourceRange(sh->SRVs[i]);
ID3D11Resource *res = NULL;
// we only need to fetch the information about depth/stencil
// read-only status if we're actually going to care about it.
if(sh->SRVs[i] && (allowDepthOnly || allowStencilOnly))
{
sh->SRVs[i]->GetResource(&res);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
sh->SRVs[i]->GetDesc(&srvDesc);
fmt = srvDesc.Format;
res->GetType(&dim);
if(fmt == DXGI_FORMAT_UNKNOWN)
{
if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE1D)
{
D3D11_TEXTURE1D_DESC d;
((ID3D11Texture1D *)res)->GetDesc(&d);
fmt = d.Format;
}
else if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D)
{
D3D11_TEXTURE2D_DESC d;
((ID3D11Texture2D *)res)->GetDesc(&d);
fmt = d.Format;
}
}
if(fmt == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT || fmt == DXGI_FORMAT_X24_TYPELESS_G8_UINT)
{
readStencilOnly = true;
}
else if(fmt == DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS ||
fmt == DXGI_FORMAT_R24_UNORM_X8_TYPELESS)
{
readDepthOnly = true;
}
else
{
fmt = GetTypelessFormat(fmt);
// any format that could be depth-only, treat it as reading depth only.
// this only applies for conflicts detected with the depth target.
if(fmt == DXGI_FORMAT_R32_TYPELESS || fmt == DXGI_FORMAT_R16_TYPELESS)
{
readDepthOnly = true;
}
}
SAFE_RELEASE(res);
}
if(range.Intersects(ResourceRange(sh->SRVs[i])))
if(range.Intersects(srvRange))
{
// RDCDEBUG("Resource was bound on %s SRV %u", names[s], i);
if(allowDepthOnly && readDepthOnly)
if(range.IsDepthReadOnly() && srvRange.IsDepthReadOnly())
{
// RDCDEBUG("but it's a depth readonly DSV and we're only reading depth, so that's fine");
}
else if(allowStencilOnly && readStencilOnly)
else if(range.IsStencilReadOnly() && srvRange.IsStencilReadOnly())
{
// RDCDEBUG("but it's a depth readonly DSV and we're only reading depth, so that's fine");
// RDCDEBUG("but it's a stencil readonly DSV and we're only reading stenc, so that's OK");
}
else
{
@@ -1284,13 +1218,13 @@ bool D3D11RenderState::ValidOutputMerger(ID3D11RenderTargetView **RTs, ID3D11Dep
for(int i = 0; RTs && i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
if(RTs[i])
rtvRanges[i] = ResourceRange(RTs[i]);
rtvRanges[i] = GetResourceRange(RTs[i]);
else
break;
}
if(depth)
depthRange = ResourceRange(depth);
depthRange = GetResourceRange(depth);
int numUAVs = 0;
@@ -1298,7 +1232,7 @@ bool D3D11RenderState::ValidOutputMerger(ID3D11RenderTargetView **RTs, ID3D11Dep
{
if(uavs[i])
{
uavRanges[i] = ResourceRange(uavs[i]);
uavRanges[i] = GetResourceRange(uavs[i]);
numUAVs = i + 1;
}
}
@@ -1694,6 +1628,145 @@ bool D3D11RenderState::shader::Used_UAV(uint32_t slot) const
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11InputLayout *resource)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11ClassInstance *resource)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11DeviceChild *shader)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11SamplerState *resource)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11BlendState *state)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11RasterizerState *state)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11DepthStencilState *state)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11Buffer *buffer)
{
if(buffer == NULL)
return false;
return IsRangeBoundForWrite(ResourceRange(buffer));
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11ShaderResourceView *srv)
{
if(srv == NULL)
return false;
return IsRangeBoundForWrite(GetResourceRange(srv));
}
template <>
void D3D11RenderState::UnbindForRead(ID3D11Buffer *buffer)
{
if(buffer == NULL)
return;
UnbindRangeForRead(ResourceRange(buffer));
}
template <>
void D3D11RenderState::UnbindForRead(ID3D11RenderTargetView *rtv)
{
if(rtv == NULL)
return;
UnbindRangeForRead(GetResourceRange(rtv));
}
template <>
void D3D11RenderState::UnbindForRead(ID3D11DepthStencilView *dsv)
{
if(dsv == NULL)
return;
const ResourceRange &dsvRange = GetResourceRange(dsv);
if(dsvRange.IsDepthReadOnly() && dsvRange.IsStencilReadOnly())
{
// don't need to.
}
else
{
UnbindRangeForRead(dsvRange);
}
}
template <>
void D3D11RenderState::UnbindForRead(ID3D11UnorderedAccessView *uav)
{
if(uav == NULL)
return;
UnbindRangeForRead(GetResourceRange(uav));
}
template <>
void D3D11RenderState::UnbindForWrite(ID3D11Buffer *buffer)
{
if(buffer == NULL)
return;
UnbindRangeForWrite(ResourceRange(buffer));
}
template <>
void D3D11RenderState::UnbindForWrite(ID3D11RenderTargetView *rtv)
{
if(rtv == NULL)
return;
UnbindRangeForWrite(GetResourceRange(rtv));
}
template <>
void D3D11RenderState::UnbindForWrite(ID3D11DepthStencilView *dsv)
{
if(dsv == NULL)
return;
UnbindRangeForWrite(GetResourceRange(dsv));
}
template <>
void D3D11RenderState::UnbindForWrite(ID3D11UnorderedAccessView *uav)
{
if(uav == NULL)
return;
UnbindRangeForWrite(GetResourceRange(uav));
}
D3D11RenderStateTracker::D3D11RenderStateTracker(WrappedID3D11DeviceContext *ctx)
: m_RS(*ctx->GetCurrentPipelineState())
{
@@ -1704,251 +1777,3 @@ D3D11RenderStateTracker::~D3D11RenderStateTracker()
{
m_RS.ApplyState(m_pContext);
}
D3D11RenderState::ResourceRange D3D11RenderState::ResourceRange::Null =
D3D11RenderState::ResourceRange(NULL, 0, 0);
D3D11RenderState::ResourceRange::ResourceRange(ID3D11ShaderResourceView *srv)
{
minMip = minSlice = 0;
if(srv == NULL)
{
resource = NULL;
maxMip = maxSlice = ~0U;
fullRange = true;
return;
}
ID3D11Resource *res = NULL;
srv->GetResource(&res);
res->Release();
resource = (IUnknown *)res;
UINT numMips = ~0U, numSlices = ~0U;
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
srv->GetDesc(&srvd);
switch(srvd.ViewDimension)
{
case D3D11_SRV_DIMENSION_TEXTURE1D:
minMip = srvd.Texture1D.MostDetailedMip;
numMips = srvd.Texture1D.MipLevels;
break;
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
minMip = srvd.Texture1DArray.MostDetailedMip;
numMips = srvd.Texture1DArray.MipLevels;
minSlice = srvd.Texture1DArray.FirstArraySlice;
numSlices = srvd.Texture1DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2D:
minMip = srvd.Texture2D.MostDetailedMip;
numMips = srvd.Texture2D.MipLevels;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
minMip = srvd.Texture2DArray.MostDetailedMip;
numMips = srvd.Texture2DArray.MipLevels;
minSlice = srvd.Texture2DArray.FirstArraySlice;
numSlices = srvd.Texture2DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMS: break;
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
minSlice = srvd.Texture2DMSArray.FirstArraySlice;
numSlices = srvd.Texture2DMSArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE3D:
minMip = srvd.Texture3D.MostDetailedMip;
numMips = srvd.Texture3D.MipLevels;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBE:
minMip = srvd.TextureCube.MostDetailedMip;
numMips = srvd.TextureCube.MipLevels;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
minMip = srvd.TextureCubeArray.MostDetailedMip;
numMips = srvd.TextureCubeArray.MipLevels;
minSlice = srvd.TextureCubeArray.First2DArrayFace;
numSlices = srvd.TextureCubeArray.NumCubes * 6;
break;
case D3D11_SRV_DIMENSION_UNKNOWN:
case D3D11_SRV_DIMENSION_BUFFER:
case D3D11_SRV_DIMENSION_BUFFEREX: break;
}
SetMaxes(numMips, numSlices);
}
D3D11RenderState::ResourceRange::ResourceRange(ID3D11UnorderedAccessView *uav)
{
minMip = minSlice = 0;
if(uav == NULL)
{
resource = NULL;
maxMip = maxSlice = ~0U;
fullRange = true;
return;
}
ID3D11Resource *res = NULL;
uav->GetResource(&res);
res->Release();
resource = (IUnknown *)res;
UINT numMips = ~0U, numSlices = ~0U;
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
uav->GetDesc(&desc);
switch(desc.ViewDimension)
{
case D3D11_UAV_DIMENSION_TEXTURE1D:
minMip = desc.Texture1D.MipSlice;
numMips = 1;
break;
case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
minMip = desc.Texture1DArray.MipSlice;
numMips = 1;
minSlice = desc.Texture1DArray.FirstArraySlice;
numSlices = desc.Texture1DArray.ArraySize;
break;
case D3D11_UAV_DIMENSION_TEXTURE2D:
minMip = desc.Texture2D.MipSlice;
numMips = 1;
break;
case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
minMip = desc.Texture2DArray.MipSlice;
numMips = 1;
minSlice = desc.Texture2DArray.FirstArraySlice;
numSlices = desc.Texture2DArray.ArraySize;
break;
case D3D11_UAV_DIMENSION_TEXTURE3D:
minMip = desc.Texture3D.MipSlice;
numMips = 1;
minSlice = desc.Texture3D.FirstWSlice;
numSlices = desc.Texture3D.WSize;
break;
case D3D11_UAV_DIMENSION_UNKNOWN:
case D3D11_UAV_DIMENSION_BUFFER: break;
}
SetMaxes(numMips, numSlices);
}
D3D11RenderState::ResourceRange::ResourceRange(ID3D11RenderTargetView *rtv)
{
minMip = minSlice = 0;
if(rtv == NULL)
{
resource = NULL;
maxMip = maxSlice = ~0U;
fullRange = true;
return;
}
ID3D11Resource *res = NULL;
rtv->GetResource(&res);
res->Release();
resource = (IUnknown *)res;
UINT numMips = ~0U, numSlices = ~0U;
D3D11_RENDER_TARGET_VIEW_DESC desc;
rtv->GetDesc(&desc);
switch(desc.ViewDimension)
{
case D3D11_RTV_DIMENSION_TEXTURE1D:
minMip = desc.Texture1D.MipSlice;
numMips = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
minMip = desc.Texture1DArray.MipSlice;
numMips = 1;
minSlice = desc.Texture1DArray.FirstArraySlice;
numSlices = desc.Texture1DArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2D:
minMip = desc.Texture2D.MipSlice;
numMips = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
minMip = desc.Texture2DArray.MipSlice;
numMips = 1;
minSlice = desc.Texture2DArray.FirstArraySlice;
numSlices = desc.Texture2DArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMS: break;
case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
minSlice = desc.Texture2DMSArray.FirstArraySlice;
numSlices = desc.Texture2DMSArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE3D:
minMip = desc.Texture3D.MipSlice;
numMips = 1;
minSlice = desc.Texture3D.FirstWSlice;
numSlices = desc.Texture3D.WSize;
break;
case D3D11_RTV_DIMENSION_UNKNOWN:
case D3D11_RTV_DIMENSION_BUFFER: break;
}
SetMaxes(numMips, numSlices);
}
D3D11RenderState::ResourceRange::ResourceRange(ID3D11DepthStencilView *dsv)
{
minMip = minSlice = 0;
if(dsv == NULL)
{
resource = NULL;
maxMip = maxSlice = ~0U;
fullRange = true;
return;
}
ID3D11Resource *res = NULL;
dsv->GetResource(&res);
res->Release();
resource = (IUnknown *)res;
UINT numMips = ~0U, numSlices = ~0U;
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
dsv->GetDesc(&desc);
switch(desc.ViewDimension)
{
case D3D11_DSV_DIMENSION_TEXTURE1D:
minMip = desc.Texture1D.MipSlice;
numMips = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
minMip = desc.Texture1DArray.MipSlice;
numMips = 1;
minSlice = desc.Texture1DArray.FirstArraySlice;
numSlices = desc.Texture1DArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_TEXTURE2D:
minMip = desc.Texture2D.MipSlice;
numMips = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
minMip = desc.Texture2DArray.MipSlice;
numMips = 1;
minSlice = desc.Texture2DArray.FirstArraySlice;
numSlices = desc.Texture2DArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMS: break;
case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
minSlice = desc.Texture2DMSArray.FirstArraySlice;
numSlices = desc.Texture2DMSArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_UNKNOWN: break;
}
SetMaxes(numMips, numSlices);
}
+54 -212
View File
@@ -68,235 +68,26 @@ struct D3D11RenderState
// is any part of this range bound for a writing part of the pipeline? if so, read binds will bind
// NULL
bool IsBoundIUnknownForWrite(const ResourceRange &range, bool readDepthOnly, bool readStencilOnly);
bool IsRangeBoundForWrite(const ResourceRange &range);
// this range was bound for writing - find any overlapping read binds and set them to NULL
void UnbindIUnknownForRead(const ResourceRange &range, bool allowDepthOnly, bool allowStencilOnly);
void UnbindRangeForRead(const ResourceRange &range);
// just for utility, not used below
void UnbindIUnknownForWrite(const ResourceRange &range);
void UnbindRangeForWrite(const ResourceRange &range);
// define template but only implement for specific types, so we can more easily reason
// about what types are passing through these functions
template <typename T>
bool IsBoundForWrite(T *resource);
template <>
bool IsBoundForWrite(ID3D11InputLayout *resource)
{
return false;
}
template <>
bool IsBoundForWrite(ID3D11ClassInstance *resource)
{
return false;
}
template <>
bool IsBoundForWrite(ID3D11DeviceChild *shader)
{
return false;
}
template <>
bool IsBoundForWrite(ID3D11SamplerState *resource)
{
return false;
}
template <>
bool IsBoundForWrite(ID3D11BlendState *state)
{
return false;
}
template <>
bool IsBoundForWrite(ID3D11RasterizerState *state)
{
return false;
}
template <>
bool IsBoundForWrite(ID3D11DepthStencilState *state)
{
return false;
}
template <>
bool IsBoundForWrite(ID3D11Buffer *buffer)
{
if(buffer == NULL)
return false;
return IsBoundIUnknownForWrite(ResourceRange(buffer), false, false);
}
template <>
bool IsBoundForWrite(ID3D11ShaderResourceView *srv)
{
if(srv == NULL)
return false;
ID3D11Resource *res = NULL;
srv->GetResource(&res);
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
srv->GetDesc(&srvd);
bool readDepthOnly = false;
bool readStencilOnly = false;
D3D11_RESOURCE_DIMENSION dim;
res->GetType(&dim);
DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN;
if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE1D)
{
D3D11_TEXTURE1D_DESC d;
((ID3D11Texture1D *)res)->GetDesc(&d);
if(d.Format == DXGI_FORMAT_R24G8_TYPELESS || d.Format == DXGI_FORMAT_R32G8X24_TYPELESS)
{
d.Format = srvd.Format;
}
fmt = d.Format;
}
else if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D)
{
D3D11_TEXTURE2D_DESC d;
((ID3D11Texture2D *)res)->GetDesc(&d);
if(d.Format == DXGI_FORMAT_R24G8_TYPELESS || d.Format == DXGI_FORMAT_R32G8X24_TYPELESS)
{
d.Format = srvd.Format;
}
fmt = d.Format;
}
if(fmt == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT || fmt == DXGI_FORMAT_X24_TYPELESS_G8_UINT)
{
readStencilOnly = true;
}
else if(fmt == DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS || fmt == DXGI_FORMAT_R24_UNORM_X8_TYPELESS)
{
readDepthOnly = true;
}
else
{
fmt = GetTypelessFormat(fmt);
// any format that could be depth-only, treat it as reading depth only.
// this only applies for conflicts detected with the depth target.
if(fmt == DXGI_FORMAT_R32_TYPELESS || fmt == DXGI_FORMAT_R16_TYPELESS)
{
readDepthOnly = true;
}
}
SAFE_RELEASE(res);
return IsBoundIUnknownForWrite(ResourceRange(srv), readDepthOnly, readStencilOnly);
}
// same as IsBoundForWrite above
template <typename T>
void UnbindForRead(T *resource);
template <>
void UnbindForRead(ID3D11Buffer *buffer)
{
if(buffer == NULL)
return;
UnbindIUnknownForRead(ResourceRange(buffer), false, false);
}
template <>
void UnbindForRead(ID3D11RenderTargetView *rtv)
{
if(rtv == NULL)
return;
UnbindIUnknownForRead(ResourceRange(rtv), false, false);
}
template <>
void UnbindForRead(ID3D11DepthStencilView *dsv)
{
if(dsv == NULL)
return;
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
dsv->GetDesc(&desc);
if(desc.Flags == (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL))
{
// don't need to.
}
else if(desc.Flags == D3D11_DSV_READ_ONLY_DEPTH)
{
UnbindIUnknownForRead(ResourceRange(dsv), true, false);
}
else if(desc.Flags == D3D11_DSV_READ_ONLY_STENCIL)
{
UnbindIUnknownForRead(ResourceRange(dsv), false, true);
}
else
{
UnbindIUnknownForRead(ResourceRange(dsv), false, false);
}
}
template <>
void UnbindForRead(ID3D11UnorderedAccessView *uav)
{
if(uav == NULL)
return;
UnbindIUnknownForRead(ResourceRange(uav), false, false);
}
template <typename T>
void UnbindForWrite(T *resource);
template <>
void UnbindForWrite(ID3D11Buffer *buffer)
{
if(buffer == NULL)
return;
UnbindIUnknownForWrite(ResourceRange(buffer));
}
template <>
void UnbindForWrite(ID3D11RenderTargetView *rtv)
{
if(rtv == NULL)
return;
UnbindIUnknownForWrite(ResourceRange(rtv));
}
template <>
void UnbindForWrite(ID3D11DepthStencilView *dsv)
{
if(dsv == NULL)
return;
UnbindIUnknownForWrite(ResourceRange(dsv));
}
template <>
void UnbindForWrite(ID3D11UnorderedAccessView *uav)
{
if(uav == NULL)
return;
UnbindIUnknownForWrite(ResourceRange(uav));
}
/////////////////////////////////////////////////////////////////////////
// Utility functions to swap resources around, removing and adding refs
@@ -505,3 +296,54 @@ private:
D3D11RenderState m_RS;
WrappedID3D11DeviceContext *m_pContext;
};
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11InputLayout *resource);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11ClassInstance *resource);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11DeviceChild *shader);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11SamplerState *resource);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11BlendState *state);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11RasterizerState *state);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11DepthStencilState *state);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11Buffer *buffer);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11ShaderResourceView *srv);
template <>
void D3D11RenderState::UnbindForRead(ID3D11Buffer *buffer);
template <>
void D3D11RenderState::UnbindForRead(ID3D11RenderTargetView *rtv);
template <>
void D3D11RenderState::UnbindForRead(ID3D11DepthStencilView *dsv);
template <>
void D3D11RenderState::UnbindForRead(ID3D11UnorderedAccessView *uav);
template <>
void D3D11RenderState::UnbindForWrite(ID3D11Buffer *buffer);
template <>
void D3D11RenderState::UnbindForWrite(ID3D11RenderTargetView *rtv);
template <>
void D3D11RenderState::UnbindForWrite(ID3D11DepthStencilView *dsv);
template <>
void D3D11RenderState::UnbindForWrite(ID3D11UnorderedAccessView *uav);