mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-10 08:41:04 +00:00
851 lines
28 KiB
C++
851 lines
28 KiB
C++
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2019-2021 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_context.h"
|
|
#include "d3d11_debug.h"
|
|
#include "d3d11_renderstate.h"
|
|
#include "d3d11_resources.h"
|
|
|
|
struct Tex2DMSToArrayStateTracker
|
|
{
|
|
Tex2DMSToArrayStateTracker(WrappedID3D11DeviceContext *wrappedContext)
|
|
{
|
|
m_WrappedContext = wrappedContext;
|
|
D3D11RenderState *rs = wrappedContext->GetCurrentPipelineState();
|
|
|
|
// first copy the properties. We don't need to keep refs as the objects won't be deleted by
|
|
// being unbound and we won't do anything with them
|
|
Layout = rs->IA.Layout;
|
|
memcpy(&VS, &rs->VS, sizeof(VS));
|
|
memcpy(&PS, &rs->PS, sizeof(PS));
|
|
|
|
memcpy(CSUAVs, rs->CSUAVs, sizeof(CSUAVs));
|
|
|
|
memcpy(&RS, &rs->RS, sizeof(RS));
|
|
memcpy(&OM, &rs->OM, sizeof(OM));
|
|
|
|
RDCCOMPILE_ASSERT(sizeof(VS) == sizeof(rs->VS), "Struct sizes have changed, ensure full copy");
|
|
RDCCOMPILE_ASSERT(sizeof(RS) == sizeof(rs->RS), "Struct sizes have changed, ensure full copy");
|
|
RDCCOMPILE_ASSERT(sizeof(OM) == sizeof(rs->OM), "Struct sizes have changed, ensure full copy");
|
|
|
|
// now unwrap everything in place.
|
|
Layout = UNWRAP(WrappedID3D11InputLayout, Layout);
|
|
VS.Shader = UNWRAP(WrappedID3D11Shader<ID3D11VertexShader>, VS.Shader);
|
|
PS.Shader = UNWRAP(WrappedID3D11Shader<ID3D11PixelShader>, PS.Shader);
|
|
|
|
// only need to save/restore constant buffer 0
|
|
PS.ConstantBuffers[0] = UNWRAP(WrappedID3D11Buffer, PS.ConstantBuffers[0]);
|
|
|
|
// same for the first 16 SRVs
|
|
for(int i = 0; i < 16; i++)
|
|
PS.SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, PS.SRVs[i]);
|
|
|
|
for(int i = 0; i < D3D11_SHADER_MAX_INTERFACES; i++)
|
|
{
|
|
VS.Instances[i] = UNWRAP(WrappedID3D11ClassInstance, VS.Instances[i]);
|
|
PS.Instances[i] = UNWRAP(WrappedID3D11ClassInstance, PS.Instances[i]);
|
|
}
|
|
|
|
for(int i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
|
|
CSUAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView1, CSUAVs[i]);
|
|
|
|
RS.State = UNWRAP(WrappedID3D11RasterizerState2, RS.State);
|
|
OM.DepthStencilState = UNWRAP(WrappedID3D11DepthStencilState, OM.DepthStencilState);
|
|
OM.BlendState = UNWRAP(WrappedID3D11BlendState1, OM.BlendState);
|
|
OM.DepthView = UNWRAP(WrappedID3D11DepthStencilView, OM.DepthView);
|
|
|
|
for(int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
|
|
OM.RenderTargets[i] = UNWRAP(WrappedID3D11RenderTargetView1, OM.RenderTargets[i]);
|
|
|
|
for(int i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
|
|
OM.UAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView1, OM.UAVs[i]);
|
|
}
|
|
~Tex2DMSToArrayStateTracker()
|
|
{
|
|
ID3D11DeviceContext *context = m_WrappedContext->GetReal();
|
|
ID3D11DeviceContext1 *context1 = m_WrappedContext->GetReal1();
|
|
|
|
context->IASetInputLayout(Layout);
|
|
context->VSSetShader((ID3D11VertexShader *)VS.Shader, VS.Instances, VS.NumInstances);
|
|
|
|
context->PSSetShaderResources(0, 16, PS.SRVs);
|
|
context->PSSetShader((ID3D11PixelShader *)PS.Shader, PS.Instances, PS.NumInstances);
|
|
|
|
if(m_WrappedContext->IsFL11_1())
|
|
context1->PSSetConstantBuffers1(0, 1, PS.ConstantBuffers, PS.CBOffsets, PS.CBCounts);
|
|
else
|
|
context->PSSetConstantBuffers(0, 1, PS.ConstantBuffers);
|
|
|
|
UINT UAV_keepcounts[D3D11_1_UAV_SLOT_COUNT] = {(UINT)-1, (UINT)-1, (UINT)-1, (UINT)-1,
|
|
(UINT)-1, (UINT)-1, (UINT)-1, (UINT)-1};
|
|
|
|
if(m_WrappedContext->IsFL11_1())
|
|
context->CSSetUnorderedAccessViews(0, D3D11_1_UAV_SLOT_COUNT, CSUAVs, UAV_keepcounts);
|
|
else
|
|
context->CSSetUnorderedAccessViews(0, D3D11_PS_CS_UAV_REGISTER_COUNT, CSUAVs, UAV_keepcounts);
|
|
|
|
context->RSSetState(RS.State);
|
|
context->RSSetViewports(RS.NumViews, RS.Viewports);
|
|
|
|
context->OMSetBlendState(OM.BlendState, OM.BlendFactor, OM.SampleMask);
|
|
context->OMSetDepthStencilState(OM.DepthStencilState, OM.StencRef);
|
|
|
|
if(m_WrappedContext->IsFL11_1())
|
|
context->OMSetRenderTargetsAndUnorderedAccessViews(
|
|
OM.UAVStartSlot, OM.RenderTargets, OM.DepthView, OM.UAVStartSlot,
|
|
D3D11_1_UAV_SLOT_COUNT - OM.UAVStartSlot, OM.UAVs, UAV_keepcounts);
|
|
else
|
|
context->OMSetRenderTargetsAndUnorderedAccessViews(
|
|
OM.UAVStartSlot, OM.RenderTargets, OM.DepthView, OM.UAVStartSlot,
|
|
D3D11_PS_CS_UAV_REGISTER_COUNT - OM.UAVStartSlot, OM.UAVs, UAV_keepcounts);
|
|
}
|
|
|
|
WrappedID3D11DeviceContext *m_WrappedContext;
|
|
|
|
ID3D11InputLayout *Layout;
|
|
|
|
struct shader
|
|
{
|
|
ID3D11DeviceChild *Shader;
|
|
ID3D11Buffer *ConstantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
|
|
UINT CBOffsets[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
|
|
UINT CBCounts[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
|
|
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
|
|
ID3D11SamplerState *Samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
|
|
ID3D11ClassInstance *Instances[D3D11_SHADER_MAX_INTERFACES];
|
|
UINT NumInstances;
|
|
|
|
bool Used_CB(uint32_t slot) const;
|
|
bool Used_SRV(uint32_t slot) const;
|
|
bool Used_UAV(uint32_t slot) const;
|
|
} VS, PS;
|
|
|
|
ID3D11UnorderedAccessView *CSUAVs[D3D11_1_UAV_SLOT_COUNT];
|
|
|
|
struct rasterizer
|
|
{
|
|
UINT NumViews, NumScissors;
|
|
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
|
D3D11_RECT Scissors[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
|
ID3D11RasterizerState *State;
|
|
} RS;
|
|
|
|
struct outmerger
|
|
{
|
|
ID3D11DepthStencilState *DepthStencilState;
|
|
UINT StencRef;
|
|
|
|
ID3D11BlendState *BlendState;
|
|
FLOAT BlendFactor[4];
|
|
UINT SampleMask;
|
|
|
|
ID3D11DepthStencilView *DepthView;
|
|
|
|
ID3D11RenderTargetView *RenderTargets[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
|
|
|
|
UINT UAVStartSlot;
|
|
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT];
|
|
} OM;
|
|
};
|
|
|
|
void D3D11DebugManager::CopyArrayToTex2DMS(ID3D11Texture2D *destMS, ID3D11Texture2D *srcArray,
|
|
UINT selectedSlice)
|
|
{
|
|
if(!CopyArrayToMSPS)
|
|
{
|
|
RDCWARN("Can't copy array to MSAA texture, contents will be undefined.");
|
|
return;
|
|
}
|
|
|
|
bool singleSliceMode = (selectedSlice != ~0U);
|
|
|
|
D3D11MarkerRegion copy("CopyArrayToTex2DMS");
|
|
|
|
// unlike CopyTex2DMSToArray we can use the wrapped context here, but for consistency
|
|
// we accept unwrapped parameters.
|
|
|
|
D3D11RenderStateTracker tracker(m_pImmediateContext);
|
|
|
|
// copy to textures with right bind flags for operation
|
|
D3D11_TEXTURE2D_DESC descArr;
|
|
srcArray->GetDesc(&descArr);
|
|
|
|
D3D11_TEXTURE2D_DESC descMS;
|
|
destMS->GetDesc(&descMS);
|
|
|
|
UINT sampleMask = ~0U;
|
|
|
|
if(singleSliceMode)
|
|
{
|
|
sampleMask = 1U << (selectedSlice % descMS.SampleDesc.Count);
|
|
selectedSlice /= descMS.SampleDesc.Count;
|
|
}
|
|
|
|
bool depthFormat = IsDepthFormat(descMS.Format);
|
|
bool intFormat =
|
|
IsUIntFormat(descMS.Format) || IsIntFormat(descMS.Format) || IsTypelessFormat(descMS.Format);
|
|
|
|
ID3D11Texture2D *rtvResource = NULL;
|
|
ID3D11Texture2D *srvResource = NULL;
|
|
|
|
D3D11_TEXTURE2D_DESC rtvResDesc = descMS;
|
|
D3D11_TEXTURE2D_DESC srvResDesc = descArr;
|
|
|
|
rtvResDesc.BindFlags = depthFormat ? D3D11_BIND_DEPTH_STENCIL : D3D11_BIND_RENDER_TARGET;
|
|
srvResDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
|
|
if(depthFormat)
|
|
{
|
|
rtvResDesc.Format = GetTypelessFormat(rtvResDesc.Format);
|
|
srvResDesc.Format = GetTypelessFormat(srvResDesc.Format);
|
|
}
|
|
|
|
rtvResDesc.Usage = D3D11_USAGE_DEFAULT;
|
|
srvResDesc.Usage = D3D11_USAGE_DEFAULT;
|
|
|
|
rtvResDesc.CPUAccessFlags = 0;
|
|
srvResDesc.CPUAccessFlags = 0;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = m_pDevice->CreateTexture2D(&rtvResDesc, NULL, &rtvResource);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
hr = m_pDevice->CreateTexture2D(&srvResDesc, NULL, &srvResource);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
// if we're doing a partial update, need to preserve what was in the destination texture
|
|
if(singleSliceMode)
|
|
m_pImmediateContext->GetReal()->CopyResource(UNWRAP(WrappedID3D11Texture2D1, rtvResource),
|
|
destMS);
|
|
|
|
m_pImmediateContext->GetReal()->CopyResource(UNWRAP(WrappedID3D11Texture2D1, srvResource),
|
|
srcArray);
|
|
|
|
ID3D11UnorderedAccessView *uavs[D3D11_1_UAV_SLOT_COUNT] = {NULL};
|
|
const UINT numUAVs =
|
|
m_pImmediateContext->IsFL11_1() ? D3D11_1_UAV_SLOT_COUNT : D3D11_PS_CS_UAV_REGISTER_COUNT;
|
|
UINT uavCounts[D3D11_1_UAV_SLOT_COUNT];
|
|
memset(&uavCounts[0], 0xff, sizeof(uavCounts));
|
|
|
|
m_pImmediateContext->CSSetUnorderedAccessViews(0, numUAVs, uavs, uavCounts);
|
|
|
|
m_pImmediateContext->VSSetShader(MSArrayCopyVS, NULL, 0);
|
|
|
|
if(depthFormat)
|
|
m_pImmediateContext->PSSetShader(DepthCopyArrayToMSPS, NULL, 0);
|
|
else if(intFormat)
|
|
m_pImmediateContext->PSSetShader(CopyArrayToMSPS, NULL, 0);
|
|
else
|
|
m_pImmediateContext->PSSetShader(FloatCopyArrayToMSPS, NULL, 0);
|
|
|
|
m_pImmediateContext->HSSetShader(NULL, NULL, 0);
|
|
m_pImmediateContext->DSSetShader(NULL, NULL, 0);
|
|
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
|
|
|
|
D3D11_VIEWPORT view = {0.0f, 0.0f, (float)descArr.Width, (float)descArr.Height, 0.0f, 1.0f};
|
|
|
|
m_pImmediateContext->RSSetState(NULL);
|
|
m_pImmediateContext->RSSetViewports(1, &view);
|
|
|
|
m_pImmediateContext->IASetInputLayout(NULL);
|
|
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
float blendFactor[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
m_pImmediateContext->OMSetBlendState(NULL, blendFactor, sampleMask);
|
|
|
|
{
|
|
D3D11_DEPTH_STENCIL_DESC dsDesc;
|
|
ID3D11DepthStencilState *dsState = NULL;
|
|
RDCEraseEl(dsDesc);
|
|
|
|
dsDesc.DepthEnable = TRUE;
|
|
dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
|
if(depthFormat)
|
|
dsDesc.StencilEnable = FALSE;
|
|
else
|
|
dsDesc.StencilEnable = TRUE;
|
|
|
|
dsDesc.BackFace.StencilFailOp = dsDesc.BackFace.StencilPassOp =
|
|
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
|
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.FrontFace.StencilFailOp = dsDesc.FrontFace.StencilPassOp =
|
|
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
|
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.StencilReadMask = dsDesc.StencilWriteMask = 0xff;
|
|
|
|
m_pDevice->CreateDepthStencilState(&dsDesc, &dsState);
|
|
m_pImmediateContext->OMSetDepthStencilState(dsState, 0);
|
|
SAFE_RELEASE(dsState);
|
|
}
|
|
|
|
ID3D11DepthStencilView *dsvMS = NULL;
|
|
ID3D11RenderTargetView *rtvMS = NULL;
|
|
ID3D11ShaderResourceView *srvArray = NULL;
|
|
|
|
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
|
rtvDesc.Format = depthFormat ? GetUIntTypedFormat(descMS.Format)
|
|
: GetTypedFormat(descMS.Format, CompType::UInt);
|
|
rtvDesc.Texture2DMSArray.ArraySize = descMS.ArraySize;
|
|
rtvDesc.Texture2DMSArray.FirstArraySlice = 0;
|
|
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
|
dsvDesc.Flags = 0;
|
|
dsvDesc.Format = GetDepthTypedFormat(descMS.Format);
|
|
dsvDesc.Texture2DMSArray.ArraySize = descMS.ArraySize;
|
|
dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
|
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
srvDesc.Format = depthFormat ? GetUIntTypedFormat(descArr.Format)
|
|
: GetTypedFormat(descArr.Format, CompType::UInt);
|
|
srvDesc.Texture2DArray.ArraySize = descArr.ArraySize;
|
|
srvDesc.Texture2DArray.FirstArraySlice = 0;
|
|
srvDesc.Texture2DArray.MipLevels = descArr.MipLevels;
|
|
srvDesc.Texture2DArray.MostDetailedMip = 0;
|
|
|
|
bool stencil = false;
|
|
DXGI_FORMAT stencilFormat = DXGI_FORMAT_UNKNOWN;
|
|
|
|
if(depthFormat)
|
|
{
|
|
switch(descArr.Format)
|
|
{
|
|
case DXGI_FORMAT_D32_FLOAT:
|
|
case DXGI_FORMAT_R32_FLOAT:
|
|
case DXGI_FORMAT_R32_TYPELESS: srvDesc.Format = DXGI_FORMAT_R32_FLOAT; break;
|
|
|
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
|
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
|
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
|
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
|
|
srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
|
stencilFormat = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
|
stencil = true;
|
|
break;
|
|
|
|
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
|
case DXGI_FORMAT_R24G8_TYPELESS:
|
|
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
|
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
|
|
srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
|
stencilFormat = DXGI_FORMAT_X24_TYPELESS_G8_UINT;
|
|
stencil = true;
|
|
break;
|
|
|
|
case DXGI_FORMAT_D16_UNORM:
|
|
case DXGI_FORMAT_R16_TYPELESS: srvDesc.Format = DXGI_FORMAT_R16_UNORM; break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
hr = m_pDevice->CreateShaderResourceView(srvResource, &srvDesc, &srvArray);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
ID3D11ShaderResourceView *srvs[10] = {NULL};
|
|
srvs[0] = srvArray;
|
|
|
|
m_pImmediateContext->PSSetShaderResources(1, 10, srvs);
|
|
|
|
// loop over every array slice in MS texture
|
|
for(UINT slice = 0; slice < descMS.ArraySize; slice++)
|
|
{
|
|
if(singleSliceMode)
|
|
slice = selectedSlice;
|
|
|
|
uint32_t cdata[4] = {descMS.SampleDesc.Count, 1000, 0, slice};
|
|
|
|
ID3D11Buffer *cbuf = MakeCBuffer(cdata, sizeof(cdata));
|
|
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &cbuf);
|
|
|
|
rtvDesc.Texture2DMSArray.FirstArraySlice = slice;
|
|
rtvDesc.Texture2DMSArray.ArraySize = 1;
|
|
dsvDesc.Texture2DMSArray.FirstArraySlice = slice;
|
|
dsvDesc.Texture2DMSArray.ArraySize = 1;
|
|
|
|
if(depthFormat)
|
|
hr = m_pDevice->CreateDepthStencilView(rtvResource, &dsvDesc, &dsvMS);
|
|
else
|
|
hr = m_pDevice->CreateRenderTargetView(rtvResource, &rtvDesc, &rtvMS);
|
|
if(FAILED(hr))
|
|
{
|
|
SAFE_RELEASE(srvArray);
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
if(depthFormat)
|
|
m_pImmediateContext->OMSetRenderTargetsAndUnorderedAccessViews(0, NULL, dsvMS, 0, 0, NULL,
|
|
NULL);
|
|
else
|
|
m_pImmediateContext->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtvMS, NULL, 0, 0, NULL,
|
|
NULL);
|
|
|
|
m_pImmediateContext->Draw(3, 0);
|
|
|
|
SAFE_RELEASE(rtvMS);
|
|
SAFE_RELEASE(dsvMS);
|
|
|
|
if(singleSliceMode)
|
|
break;
|
|
}
|
|
|
|
SAFE_RELEASE(srvArray);
|
|
|
|
if(stencil)
|
|
{
|
|
srvDesc.Format = stencilFormat;
|
|
|
|
hr = m_pDevice->CreateShaderResourceView(srvResource, &srvDesc, &srvArray);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
m_pImmediateContext->PSSetShaderResources(11, 1, &srvArray);
|
|
|
|
D3D11_DEPTH_STENCIL_DESC dsDesc;
|
|
ID3D11DepthStencilState *dsState = NULL;
|
|
RDCEraseEl(dsDesc);
|
|
|
|
dsDesc.DepthEnable = FALSE;
|
|
dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
|
dsDesc.StencilEnable = TRUE;
|
|
|
|
dsDesc.BackFace.StencilFailOp = dsDesc.BackFace.StencilPassOp =
|
|
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
|
|
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.FrontFace.StencilFailOp = dsDesc.FrontFace.StencilPassOp =
|
|
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
|
|
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.StencilReadMask = dsDesc.StencilWriteMask = 0xff;
|
|
|
|
dsvDesc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
|
|
dsvDesc.Texture2DArray.ArraySize = 1;
|
|
|
|
m_pDevice->CreateDepthStencilState(&dsDesc, &dsState);
|
|
|
|
// loop over every array slice in MS texture
|
|
for(UINT slice = 0; slice < descMS.ArraySize; slice++)
|
|
{
|
|
if(singleSliceMode)
|
|
slice = selectedSlice;
|
|
|
|
dsvDesc.Texture2DMSArray.FirstArraySlice = slice;
|
|
|
|
hr = m_pDevice->CreateDepthStencilView(rtvResource, &dsvDesc, &dsvMS);
|
|
if(FAILED(hr))
|
|
{
|
|
SAFE_RELEASE(srvArray);
|
|
SAFE_RELEASE(dsState);
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
m_pImmediateContext->OMSetRenderTargetsAndUnorderedAccessViews(0, NULL, dsvMS, 0, 0, NULL,
|
|
NULL);
|
|
|
|
// loop over every stencil value (zzzzzz, no shader stencil read/write)
|
|
for(UINT stencilval = 0; stencilval < 256; stencilval++)
|
|
{
|
|
uint32_t cdata[4] = {descMS.SampleDesc.Count, stencilval, 0, slice};
|
|
|
|
ID3D11Buffer *cbuf = MakeCBuffer(cdata, sizeof(cdata));
|
|
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &cbuf);
|
|
|
|
m_pImmediateContext->OMSetDepthStencilState(dsState, stencilval);
|
|
|
|
m_pImmediateContext->Draw(3, 0);
|
|
}
|
|
|
|
SAFE_RELEASE(dsvMS);
|
|
|
|
m_pImmediateContext->Flush();
|
|
|
|
if(singleSliceMode)
|
|
break;
|
|
}
|
|
|
|
SAFE_RELEASE(srvArray);
|
|
SAFE_RELEASE(dsState);
|
|
}
|
|
|
|
m_pImmediateContext->GetReal()->CopyResource(destMS, UNWRAP(WrappedID3D11Texture2D1, rtvResource));
|
|
|
|
SAFE_RELEASE(rtvResource);
|
|
SAFE_RELEASE(srvResource);
|
|
}
|
|
|
|
void D3D11DebugManager::CopyTex2DMSToArray(ID3D11Texture2D *destArray, ID3D11Texture2D *srcMS)
|
|
{
|
|
if(!CopyMSToArrayPS)
|
|
{
|
|
RDCWARN("Can't copy array to MSAA texture, contents will be undefined.");
|
|
return;
|
|
}
|
|
|
|
// we have to use exclusively the unwrapped context here as this might be happening during
|
|
// capture and we don't want to serialise any of this work, and the parameters might not exist
|
|
// as wrapped objects for that reason
|
|
|
|
// use the wrapped context's state tracked to avoid needing our own tracking, just restore it to
|
|
// the unwrapped context
|
|
Tex2DMSToArrayStateTracker tracker(m_pImmediateContext);
|
|
|
|
D3D11MarkerRegion copy("CopyTex2DMSToArray");
|
|
|
|
ID3D11Device *dev = m_pDevice->GetReal();
|
|
ID3D11DeviceContext *ctx = m_pImmediateContext->GetReal();
|
|
|
|
// copy to textures with right bind flags for operation
|
|
D3D11_TEXTURE2D_DESC descMS;
|
|
srcMS->GetDesc(&descMS);
|
|
|
|
D3D11_TEXTURE2D_DESC descArr;
|
|
destArray->GetDesc(&descArr);
|
|
|
|
ID3D11Texture2D *rtvResource = NULL;
|
|
ID3D11Texture2D *srvResource = NULL;
|
|
|
|
D3D11_TEXTURE2D_DESC rtvResDesc = descArr;
|
|
D3D11_TEXTURE2D_DESC srvResDesc = descMS;
|
|
|
|
bool depthFormat = IsDepthFormat(descMS.Format);
|
|
bool intFormat =
|
|
IsUIntFormat(descMS.Format) || IsIntFormat(descMS.Format) || IsTypelessFormat(descMS.Format);
|
|
|
|
rtvResDesc.BindFlags = depthFormat ? D3D11_BIND_DEPTH_STENCIL : D3D11_BIND_RENDER_TARGET;
|
|
srvResDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
|
|
if(depthFormat)
|
|
{
|
|
rtvResDesc.Format = GetTypelessFormat(rtvResDesc.Format);
|
|
srvResDesc.Format = GetTypelessFormat(srvResDesc.Format);
|
|
}
|
|
|
|
rtvResDesc.Usage = D3D11_USAGE_DEFAULT;
|
|
srvResDesc.Usage = D3D11_USAGE_DEFAULT;
|
|
|
|
rtvResDesc.CPUAccessFlags = 0;
|
|
srvResDesc.CPUAccessFlags = 0;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = dev->CreateTexture2D(&rtvResDesc, NULL, &rtvResource);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
hr = dev->CreateTexture2D(&srvResDesc, NULL, &srvResource);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
ctx->CopyResource(srvResource, srcMS);
|
|
|
|
ID3D11UnorderedAccessView *uavs[D3D11_1_UAV_SLOT_COUNT] = {NULL};
|
|
UINT uavCounts[D3D11_1_UAV_SLOT_COUNT];
|
|
memset(&uavCounts[0], 0xff, sizeof(uavCounts));
|
|
const UINT numUAVs =
|
|
m_pImmediateContext->IsFL11_1() ? D3D11_1_UAV_SLOT_COUNT : D3D11_PS_CS_UAV_REGISTER_COUNT;
|
|
|
|
ctx->CSSetUnorderedAccessViews(0, numUAVs, uavs, uavCounts);
|
|
|
|
ctx->VSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11VertexShader>, MSArrayCopyVS), NULL, 0);
|
|
if(depthFormat)
|
|
ctx->PSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11PixelShader>, DepthCopyMSToArrayPS), NULL, 0);
|
|
else if(intFormat)
|
|
ctx->PSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11PixelShader>, CopyMSToArrayPS), NULL, 0);
|
|
else
|
|
ctx->PSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11PixelShader>, FloatCopyMSToArrayPS), NULL, 0);
|
|
|
|
D3D11_VIEWPORT view = {0.0f, 0.0f, (float)descArr.Width, (float)descArr.Height, 0.0f, 1.0f};
|
|
|
|
ctx->RSSetState(NULL);
|
|
ctx->RSSetViewports(1, &view);
|
|
|
|
ctx->IASetInputLayout(NULL);
|
|
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
float blendFactor[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
ctx->OMSetBlendState(NULL, blendFactor, ~0U);
|
|
|
|
{
|
|
D3D11_DEPTH_STENCIL_DESC dsDesc;
|
|
ID3D11DepthStencilState *dsState = NULL;
|
|
RDCEraseEl(dsDesc);
|
|
|
|
dsDesc.DepthEnable = TRUE;
|
|
dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
|
if(depthFormat)
|
|
dsDesc.StencilEnable = FALSE;
|
|
else
|
|
dsDesc.StencilEnable = TRUE;
|
|
|
|
dsDesc.BackFace.StencilFailOp = dsDesc.BackFace.StencilPassOp =
|
|
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
|
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.FrontFace.StencilFailOp = dsDesc.FrontFace.StencilPassOp =
|
|
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
|
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.StencilReadMask = dsDesc.StencilWriteMask = 0xff;
|
|
|
|
dev->CreateDepthStencilState(&dsDesc, &dsState);
|
|
ctx->OMSetDepthStencilState(dsState, 0);
|
|
SAFE_RELEASE(dsState);
|
|
}
|
|
|
|
ID3D11RenderTargetView *rtvArray = NULL;
|
|
ID3D11DepthStencilView *dsvArray = NULL;
|
|
ID3D11ShaderResourceView *srvMS = NULL;
|
|
|
|
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtvDesc.Format = depthFormat ? GetUIntTypedFormat(descArr.Format)
|
|
: GetTypedFormat(descArr.Format, CompType::UInt);
|
|
rtvDesc.Texture2DArray.FirstArraySlice = 0;
|
|
rtvDesc.Texture2DArray.ArraySize = 1;
|
|
rtvDesc.Texture2DArray.MipSlice = 0;
|
|
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsvDesc.Format = GetDepthTypedFormat(descArr.Format);
|
|
dsvDesc.Flags = 0;
|
|
dsvDesc.Texture2DArray.FirstArraySlice = 0;
|
|
dsvDesc.Texture2DArray.ArraySize = 1;
|
|
dsvDesc.Texture2DArray.MipSlice = 0;
|
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
|
|
srvDesc.Format = depthFormat ? GetUIntTypedFormat(descMS.Format)
|
|
: GetTypedFormat(descMS.Format, CompType::UInt);
|
|
srvDesc.Texture2DMSArray.ArraySize = descMS.ArraySize;
|
|
srvDesc.Texture2DMSArray.FirstArraySlice = 0;
|
|
|
|
bool stencil = false;
|
|
DXGI_FORMAT stencilFormat = DXGI_FORMAT_UNKNOWN;
|
|
|
|
if(depthFormat)
|
|
{
|
|
switch(descMS.Format)
|
|
{
|
|
case DXGI_FORMAT_D32_FLOAT:
|
|
case DXGI_FORMAT_R32_FLOAT:
|
|
case DXGI_FORMAT_R32_TYPELESS: srvDesc.Format = DXGI_FORMAT_R32_FLOAT; break;
|
|
|
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
|
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
|
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
|
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
|
|
srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
|
stencilFormat = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
|
stencil = true;
|
|
break;
|
|
|
|
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
|
case DXGI_FORMAT_R24G8_TYPELESS:
|
|
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
|
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
|
|
srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
|
stencilFormat = DXGI_FORMAT_X24_TYPELESS_G8_UINT;
|
|
stencil = true;
|
|
break;
|
|
|
|
case DXGI_FORMAT_D16_UNORM:
|
|
case DXGI_FORMAT_R16_TYPELESS: srvDesc.Format = DXGI_FORMAT_R16_UNORM; break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
hr = dev->CreateShaderResourceView(srvResource, &srvDesc, &srvMS);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
ID3D11ShaderResourceView *srvs[16] = {NULL};
|
|
|
|
int srvIndex = 0;
|
|
|
|
for(int i = 0; i < 8; i++)
|
|
if(descMS.SampleDesc.Count == UINT(1 << i))
|
|
srvIndex = i;
|
|
|
|
srvs[srvIndex] = srvMS;
|
|
|
|
ctx->PSSetShaderResources(0, 16, srvs);
|
|
|
|
// loop over every array slice in MS texture
|
|
for(UINT slice = 0; slice < descMS.ArraySize; slice++)
|
|
{
|
|
// loop over every multi sample
|
|
for(UINT sample = 0; sample < descMS.SampleDesc.Count; sample++)
|
|
{
|
|
uint32_t cdata[4] = {descMS.SampleDesc.Count, 1000, sample, slice};
|
|
|
|
ID3D11Buffer *cbuf = UNWRAP(WrappedID3D11Buffer, MakeCBuffer(cdata, sizeof(cdata)));
|
|
|
|
ctx->PSSetConstantBuffers(0, 1, &cbuf);
|
|
|
|
rtvDesc.Texture2DArray.FirstArraySlice = slice * descMS.SampleDesc.Count + sample;
|
|
dsvDesc.Texture2DArray.FirstArraySlice = slice * descMS.SampleDesc.Count + sample;
|
|
|
|
if(depthFormat)
|
|
hr = dev->CreateDepthStencilView(rtvResource, &dsvDesc, &dsvArray);
|
|
else
|
|
hr = dev->CreateRenderTargetView(rtvResource, &rtvDesc, &rtvArray);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
SAFE_RELEASE(rtvArray);
|
|
SAFE_RELEASE(dsvArray);
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
if(depthFormat)
|
|
ctx->OMSetRenderTargetsAndUnorderedAccessViews(0, NULL, dsvArray, 0, 0, NULL, NULL);
|
|
else
|
|
ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtvArray, NULL, 0, 0, NULL, NULL);
|
|
|
|
ctx->Draw(3, 0);
|
|
|
|
SAFE_RELEASE(rtvArray);
|
|
SAFE_RELEASE(dsvArray);
|
|
|
|
ctx->Flush();
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE(srvMS);
|
|
|
|
if(stencil)
|
|
{
|
|
srvDesc.Format = stencilFormat;
|
|
|
|
hr = dev->CreateShaderResourceView(srvResource, &srvDesc, &srvMS);
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
ctx->PSSetShaderResources(10 + srvIndex, 1, &srvMS);
|
|
|
|
D3D11_DEPTH_STENCIL_DESC dsDesc;
|
|
ID3D11DepthStencilState *dsState = NULL;
|
|
RDCEraseEl(dsDesc);
|
|
|
|
dsDesc.DepthEnable = FALSE;
|
|
dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
|
dsDesc.StencilEnable = TRUE;
|
|
|
|
dsDesc.BackFace.StencilFailOp = dsDesc.BackFace.StencilPassOp =
|
|
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
|
|
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.FrontFace.StencilFailOp = dsDesc.FrontFace.StencilPassOp =
|
|
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
|
|
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
dsDesc.StencilReadMask = dsDesc.StencilWriteMask = 0xff;
|
|
|
|
dsvDesc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
|
|
dsvDesc.Texture2DArray.ArraySize = 1;
|
|
|
|
dev->CreateDepthStencilState(&dsDesc, &dsState);
|
|
|
|
// loop over every array slice in MS texture
|
|
for(UINT slice = 0; slice < descMS.ArraySize; slice++)
|
|
{
|
|
// loop over every multi sample
|
|
for(UINT sample = 0; sample < descMS.SampleDesc.Count; sample++)
|
|
{
|
|
dsvDesc.Texture2DArray.FirstArraySlice = slice * descMS.SampleDesc.Count + sample;
|
|
|
|
hr = dev->CreateDepthStencilView(rtvResource, &dsvDesc, &dsvArray);
|
|
if(FAILED(hr))
|
|
{
|
|
SAFE_RELEASE(dsState);
|
|
SAFE_RELEASE(srvMS);
|
|
RDCERR("0xHRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
ctx->OMSetRenderTargetsAndUnorderedAccessViews(0, NULL, dsvArray, 0, 0, NULL, NULL);
|
|
|
|
// loop over every stencil value (zzzzzz, no shader stencil read/write)
|
|
for(UINT stencilval = 0; stencilval < 256; stencilval++)
|
|
{
|
|
uint32_t cdata[4] = {descMS.SampleDesc.Count, stencilval, sample, slice};
|
|
|
|
ID3D11Buffer *cbuf = UNWRAP(WrappedID3D11Buffer, MakeCBuffer(cdata, sizeof(cdata)));
|
|
|
|
ctx->PSSetConstantBuffers(0, 1, &cbuf);
|
|
|
|
ctx->OMSetDepthStencilState(dsState, stencilval);
|
|
|
|
ctx->Draw(3, 0);
|
|
}
|
|
|
|
ctx->Flush();
|
|
|
|
SAFE_RELEASE(dsvArray);
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE(dsState);
|
|
SAFE_RELEASE(srvMS);
|
|
}
|
|
|
|
ctx->CopyResource(destArray, rtvResource);
|
|
|
|
SAFE_RELEASE(rtvResource);
|
|
SAFE_RELEASE(srvResource);
|
|
}
|