Files
renderdoc/renderdoc/driver/d3d11/d3d11_replay.cpp
T
baldurk edbd1ce89b Pass through view format as a type hint to texture display/sampling
* This is only applicable really on D3D11 where the underlying texture
  can be typeless, and a default interpretation as unorm/float won't
  necessarily how the texture is actually being used.
2016-06-27 12:10:21 +02:00

2099 lines
68 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015-2016 Baldur Karlsson
* Copyright (c) 2014 Crytek
*
* 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_replay.h"
#include "driver/shaders/dxbc/dxbc_debug.h"
#include "official/d3dcompiler.h"
#include "serialise/string_utils.h"
#include "d3d11_context.h"
#include "d3d11_debug.h"
#include "d3d11_device.h"
#include "d3d11_renderstate.h"
#include "d3d11_resources.h"
D3D11Replay::D3D11Replay()
{
m_pDevice = NULL;
m_Proxy = false;
m_WARP = false;
}
void D3D11Replay::Shutdown()
{
for(size_t i = 0; i < m_ProxyResources.size(); i++)
m_ProxyResources[i]->Release();
m_ProxyResources.clear();
m_pDevice->Release();
D3D11DebugManager::PostDeviceShutdownCounters();
}
FetchTexture D3D11Replay::GetTexture(ResourceId id)
{
FetchTexture tex;
tex.ID = ResourceId();
auto it1D = WrappedID3D11Texture1D::m_TextureList.find(id);
if(it1D != WrappedID3D11Texture1D::m_TextureList.end())
{
WrappedID3D11Texture1D *d3dtex = (WrappedID3D11Texture1D *)it1D->second.m_Texture;
string str = GetDebugName(d3dtex);
D3D11_TEXTURE1D_DESC desc;
d3dtex->GetDesc(&desc);
tex.ID = m_pDevice->GetResourceManager()->GetOriginalID(it1D->first);
tex.dimension = 1;
tex.width = desc.Width;
tex.height = 1;
tex.depth = 1;
tex.cubemap = false;
tex.format = MakeResourceFormat(desc.Format);
tex.numSubresources = desc.MipLevels;
tex.creationFlags = 0;
if(desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
tex.creationFlags |= eTextureCreate_SRV;
if(desc.BindFlags & D3D11_BIND_RENDER_TARGET)
tex.creationFlags |= eTextureCreate_RTV;
if(desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
tex.creationFlags |= eTextureCreate_DSV;
if(desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
tex.creationFlags |= eTextureCreate_UAV;
if(desc.MipLevels == 0)
tex.numSubresources = CalcNumMips(desc.Width, 1, 1);
tex.mips = tex.numSubresources;
tex.arraysize = desc.ArraySize;
tex.resType = tex.arraysize > 1 ? eResType_Texture1DArray : eResType_Texture1D;
tex.msQual = 0;
tex.msSamp = 1;
tex.numSubresources *= desc.ArraySize;
tex.customName = true;
if(str == "")
{
const char *suffix = "";
if(tex.creationFlags & eTextureCreate_RTV)
suffix = " RTV";
if(tex.creationFlags & eTextureCreate_DSV)
suffix = " DSV";
tex.customName = false;
if(tex.arraysize > 1)
str = StringFormat::Fmt("Texture1DArray%s %llu", suffix, tex.ID);
else
str = StringFormat::Fmt("Texture1D%s %llu", suffix, tex.ID);
}
tex.name = str;
tex.byteSize = 0;
for(uint32_t s = 0; s < tex.numSubresources; s++)
tex.byteSize += GetByteSize(d3dtex, s);
return tex;
}
auto it2D = WrappedID3D11Texture2D1::m_TextureList.find(id);
if(it2D != WrappedID3D11Texture2D1::m_TextureList.end())
{
WrappedID3D11Texture2D1 *d3dtex = (WrappedID3D11Texture2D1 *)it2D->second.m_Texture;
string str = GetDebugName(d3dtex);
D3D11_TEXTURE2D_DESC desc;
d3dtex->GetDesc(&desc);
if(d3dtex->m_RealDescriptor)
desc.Format = d3dtex->m_RealDescriptor->Format;
tex.ID = m_pDevice->GetResourceManager()->GetOriginalID(it2D->first);
tex.dimension = 2;
tex.width = desc.Width;
tex.height = desc.Height;
tex.depth = 1;
tex.format = MakeResourceFormat(desc.Format);
tex.numSubresources = desc.MipLevels;
tex.creationFlags = 0;
if(desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
tex.creationFlags |= eTextureCreate_SRV;
if(desc.BindFlags & D3D11_BIND_RENDER_TARGET)
tex.creationFlags |= eTextureCreate_RTV;
if(desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
tex.creationFlags |= eTextureCreate_DSV;
if(desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
tex.creationFlags |= eTextureCreate_UAV;
if(d3dtex->m_RealDescriptor)
tex.creationFlags |= eTextureCreate_SwapBuffer;
tex.cubemap = false;
if(desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
tex.cubemap = true;
if(desc.MipLevels == 0)
tex.numSubresources = CalcNumMips(desc.Width, desc.Height, 1);
tex.mips = tex.numSubresources;
tex.arraysize = desc.ArraySize;
tex.msQual = desc.SampleDesc.Quality;
tex.msSamp = desc.SampleDesc.Count;
tex.resType = tex.arraysize > 1 ? eResType_Texture2DArray : eResType_Texture2D;
if(tex.cubemap)
tex.resType = tex.arraysize > 1 ? eResType_TextureCubeArray : eResType_TextureCube;
if(tex.msSamp > 1)
tex.resType = tex.arraysize > 1 ? eResType_Texture2DMSArray : eResType_Texture2DMS;
tex.numSubresources *= desc.ArraySize;
tex.customName = true;
if(str == "")
{
const char *suffix = "";
const char *ms = "";
if(tex.msSamp > 1)
ms = "MS";
if(tex.creationFlags & eTextureCreate_RTV)
suffix = " RTV";
if(tex.creationFlags & eTextureCreate_DSV)
suffix = " DSV";
tex.customName = false;
if(tex.cubemap)
{
if(tex.arraysize > 6)
str = StringFormat::Fmt("TextureCube%sArray%s %llu", ms, suffix, tex.ID);
else
str = StringFormat::Fmt("TextureCube%s%s %llu", ms, suffix, tex.ID);
}
else
{
if(tex.arraysize > 1)
str = StringFormat::Fmt("Texture2D%sArray%s %llu", ms, suffix, tex.ID);
else
str = StringFormat::Fmt("Texture2D%s%s %llu", ms, suffix, tex.ID);
}
}
tex.name = str;
tex.byteSize = 0;
for(uint32_t s = 0; s < tex.numSubresources; s++)
tex.byteSize += GetByteSize(d3dtex, s);
return tex;
}
auto it3D = WrappedID3D11Texture3D1::m_TextureList.find(id);
if(it3D != WrappedID3D11Texture3D1::m_TextureList.end())
{
WrappedID3D11Texture3D1 *d3dtex = (WrappedID3D11Texture3D1 *)it3D->second.m_Texture;
string str = GetDebugName(d3dtex);
D3D11_TEXTURE3D_DESC desc;
d3dtex->GetDesc(&desc);
tex.ID = m_pDevice->GetResourceManager()->GetOriginalID(it3D->first);
tex.dimension = 3;
tex.width = desc.Width;
tex.height = desc.Height;
tex.depth = desc.Depth;
tex.cubemap = false;
tex.format = MakeResourceFormat(desc.Format);
tex.numSubresources = desc.MipLevels;
tex.resType = eResType_Texture3D;
tex.creationFlags = 0;
if(desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
tex.creationFlags |= eTextureCreate_SRV;
if(desc.BindFlags & D3D11_BIND_RENDER_TARGET)
tex.creationFlags |= eTextureCreate_RTV;
if(desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
tex.creationFlags |= eTextureCreate_DSV;
if(desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
tex.creationFlags |= eTextureCreate_UAV;
if(desc.MipLevels == 0)
tex.numSubresources = CalcNumMips(desc.Width, desc.Height, desc.Depth);
tex.msQual = 0;
tex.msSamp = 1;
tex.mips = tex.numSubresources;
tex.arraysize = 1;
tex.customName = true;
if(str == "")
{
const char *suffix = "";
if(tex.creationFlags & eTextureCreate_RTV)
suffix = " RTV";
if(tex.creationFlags & eTextureCreate_DSV)
suffix = " DSV";
tex.customName = false;
str = StringFormat::Fmt("Texture3D%s %llu", suffix, tex.ID);
}
tex.name = str;
tex.byteSize = 0;
for(uint32_t s = 0; s < tex.numSubresources; s++)
tex.byteSize += GetByteSize(d3dtex, s);
return tex;
}
return tex;
}
ShaderReflection *D3D11Replay::GetShader(ResourceId shader, string entryPoint)
{
auto it = WrappedShader::m_ShaderList.find(shader);
if(it == WrappedShader::m_ShaderList.end())
return NULL;
ShaderReflection *ret = it->second->GetDetails();
RDCASSERT(ret);
return ret;
}
void D3D11Replay::FreeTargetResource(ResourceId id)
{
if(m_pDevice->GetResourceManager()->HasLiveResource(id))
{
ID3D11DeviceChild *resource = m_pDevice->GetResourceManager()->GetLiveResource(id);
SAFE_RELEASE(resource);
}
}
void D3D11Replay::FreeCustomShader(ResourceId id)
{
if(m_pDevice->GetResourceManager()->HasLiveResource(id))
{
ID3D11DeviceChild *resource = m_pDevice->GetResourceManager()->GetLiveResource(id);
SAFE_RELEASE(resource);
}
}
FetchFrameRecord D3D11Replay::GetFrameRecord()
{
return m_pDevice->GetFrameRecord();
}
vector<EventUsage> D3D11Replay::GetUsage(ResourceId id)
{
return m_pDevice->GetImmediateContext()->GetUsage(id);
}
vector<DebugMessage> D3D11Replay::GetDebugMessages()
{
return m_pDevice->GetDebugMessages();
}
APIProperties D3D11Replay::GetAPIProperties()
{
APIProperties ret;
ret.pipelineType = ePipelineState_D3D11;
ret.degraded = m_WARP;
return ret;
}
vector<ResourceId> D3D11Replay::GetBuffers()
{
vector<ResourceId> ret;
ret.reserve(WrappedID3D11Buffer::m_BufferList.size());
for(auto it = WrappedID3D11Buffer::m_BufferList.begin();
it != WrappedID3D11Buffer::m_BufferList.end(); ++it)
ret.push_back(it->first);
return ret;
}
FetchBuffer D3D11Replay::GetBuffer(ResourceId id)
{
FetchBuffer ret;
ret.ID = ResourceId();
auto it = WrappedID3D11Buffer::m_BufferList.find(id);
if(it == WrappedID3D11Buffer::m_BufferList.end())
return ret;
WrappedID3D11Buffer *d3dbuf = it->second.m_Buffer;
string str = GetDebugName(d3dbuf);
ret.ID = m_pDevice->GetResourceManager()->GetOriginalID(it->first);
ret.customName = true;
if(str == "")
{
ret.customName = false;
str = StringFormat::Fmt("Buffer %llu", ret.ID);
}
D3D11_BUFFER_DESC desc;
it->second.m_Buffer->GetDesc(&desc);
ret.name = str;
ret.length = it->second.length;
ret.structureSize = 0;
if(desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)
ret.structureSize = desc.StructureByteStride;
ret.byteSize = desc.ByteWidth;
ret.creationFlags = 0;
if(desc.BindFlags & D3D11_BIND_VERTEX_BUFFER)
ret.creationFlags |= eBufferCreate_VB;
if(desc.BindFlags & D3D11_BIND_INDEX_BUFFER)
ret.creationFlags |= eBufferCreate_IB;
if(desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
ret.creationFlags |= eBufferCreate_UAV;
if(desc.MiscFlags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS)
ret.creationFlags |= eBufferCreate_Indirect;
return ret;
}
vector<ResourceId> D3D11Replay::GetTextures()
{
vector<ResourceId> ret;
ret.reserve(WrappedID3D11Texture1D::m_TextureList.size() +
WrappedID3D11Texture2D1::m_TextureList.size() +
WrappedID3D11Texture3D1::m_TextureList.size());
for(auto it = WrappedID3D11Texture1D::m_TextureList.begin();
it != WrappedID3D11Texture1D::m_TextureList.end(); ++it)
ret.push_back(it->first);
for(auto it = WrappedID3D11Texture2D1::m_TextureList.begin();
it != WrappedID3D11Texture2D1::m_TextureList.end(); ++it)
ret.push_back(it->first);
for(auto it = WrappedID3D11Texture3D1::m_TextureList.begin();
it != WrappedID3D11Texture3D1::m_TextureList.end(); ++it)
ret.push_back(it->first);
return ret;
}
D3D11PipelineState D3D11Replay::MakePipelineState()
{
D3D11RenderState *rs = m_pDevice->GetImmediateContext()->GetCurrentPipelineState();
D3D11PipelineState ret;
/////////////////////////////////////////////////
// Input Assembler
/////////////////////////////////////////////////
D3D11ResourceManager *rm = m_pDevice->GetResourceManager();
ret.m_IA.Bytecode = NULL;
if(rs->IA.Layout)
{
const vector<D3D11_INPUT_ELEMENT_DESC> &vec = m_pDevice->GetLayoutDesc(rs->IA.Layout);
ResourceId layoutId = GetIDForResource(rs->IA.Layout);
ret.m_IA.layout = rm->GetOriginalID(layoutId);
ret.m_IA.Bytecode = GetShader(layoutId, "");
string str = GetDebugName(rs->IA.Layout);
ret.m_IA.customName = true;
if(str == "" && ret.m_IA.layout != ResourceId())
{
ret.m_IA.customName = false;
str = StringFormat::Fmt("Input Layout %llu", ret.m_IA.layout);
}
ret.m_IA.LayoutName = str;
create_array_uninit(ret.m_IA.layouts, vec.size());
for(size_t i = 0; i < vec.size(); i++)
{
D3D11PipelineState::InputAssembler::LayoutInput &l = ret.m_IA.layouts[i];
l.ByteOffset = vec[i].AlignedByteOffset;
l.Format = MakeResourceFormat(vec[i].Format);
l.InputSlot = vec[i].InputSlot;
l.PerInstance = vec[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA;
l.InstanceDataStepRate = vec[i].InstanceDataStepRate;
l.SemanticIndex = vec[i].SemanticIndex;
l.SemanticName = vec[i].SemanticName;
}
}
create_array_uninit(ret.m_IA.vbuffers, ARRAY_COUNT(rs->IA.VBs));
for(size_t i = 0; i < ARRAY_COUNT(rs->IA.VBs); i++)
{
D3D11PipelineState::InputAssembler::VertexBuffer &vb = ret.m_IA.vbuffers[i];
vb.Buffer = rm->GetOriginalID(GetIDForResource(rs->IA.VBs[i]));
vb.Offset = rs->IA.Offsets[i];
vb.Stride = rs->IA.Strides[i];
}
ret.m_IA.ibuffer.Buffer = rm->GetOriginalID(GetIDForResource(rs->IA.IndexBuffer));
ret.m_IA.ibuffer.Offset = rs->IA.IndexOffset;
/////////////////////////////////////////////////
// Shaders
/////////////////////////////////////////////////
{
D3D11PipelineState::ShaderStage *dstArr = &ret.m_VS;
const D3D11RenderState::shader *srcArr = &rs->VS;
const char *stageNames[] = {"Vertex", "Hull", "Domain", "Geometry", "Pixel", "Compute"};
for(size_t stage = 0; stage < 6; stage++)
{
D3D11PipelineState::ShaderStage &dst = dstArr[stage];
const D3D11RenderState::shader &src = srcArr[stage];
dst.stage = (ShaderStageType)stage;
ResourceId id = GetIDForResource(src.Shader);
WrappedShader *shad = (WrappedShader *)(WrappedID3D11Shader<ID3D11VertexShader> *)src.Shader;
ShaderReflection *refl = NULL;
if(shad != NULL)
refl = shad->GetDetails();
dst.Shader = rm->GetOriginalID(id);
dst.ShaderDetails = NULL;
string str = GetDebugName(src.Shader);
dst.customName = true;
if(str == "" && dst.Shader != ResourceId())
{
dst.customName = false;
str = StringFormat::Fmt("%s Shader %llu", stageNames[stage], dst.Shader);
}
dst.ShaderName = str;
// create identity bindpoint mapping
create_array_uninit(dst.BindpointMapping.InputAttributes,
D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT);
for(int s = 0; s < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; s++)
{
// TODO: this should do any semantic rematching as defined by the bytecode
// the input layout was built with (not necessarily the vertex shader's bytecode -
// in the case of a mismatch). It's commonly, but not always the identity mapping
dst.BindpointMapping.InputAttributes[s] = s;
}
create_array_uninit(dst.BindpointMapping.ConstantBlocks,
D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
for(int s = 0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++)
{
dst.BindpointMapping.ConstantBlocks[s].bindset = 0;
dst.BindpointMapping.ConstantBlocks[s].bind = s;
dst.BindpointMapping.ConstantBlocks[s].used = false;
dst.BindpointMapping.ConstantBlocks[s].arraySize = 1;
}
create_array_uninit(dst.BindpointMapping.ReadOnlyResources,
D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
for(int32_t s = 0; s < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; s++)
{
dst.BindpointMapping.ReadOnlyResources[s].bindset = 0;
dst.BindpointMapping.ReadOnlyResources[s].bind = s;
dst.BindpointMapping.ReadOnlyResources[s].used = false;
dst.BindpointMapping.ReadOnlyResources[s].arraySize = 1;
}
create_array_uninit(dst.BindpointMapping.ReadWriteResources, D3D11_1_UAV_SLOT_COUNT);
for(int32_t s = 0; s < D3D11_1_UAV_SLOT_COUNT; s++)
{
dst.BindpointMapping.ReadWriteResources[s].bindset = 0;
dst.BindpointMapping.ReadWriteResources[s].bind = s;
dst.BindpointMapping.ReadWriteResources[s].used = false;
dst.BindpointMapping.ReadWriteResources[s].arraySize = 1;
}
// mark resources as used if they are referenced by the shader
if(refl)
{
for(int32_t i = 0; i < refl->ConstantBlocks.count; i++)
if(refl->ConstantBlocks[i].bufferBacked)
dst.BindpointMapping.ConstantBlocks[refl->ConstantBlocks[i].bindPoint].used = true;
for(int32_t i = 0; i < refl->ReadOnlyResources.count; i++)
if(!refl->ReadOnlyResources[i].IsSampler)
dst.BindpointMapping.ReadOnlyResources[refl->ReadOnlyResources[i].bindPoint].used = true;
for(int32_t i = 0; i < refl->ReadWriteResources.count; i++)
dst.BindpointMapping.ReadWriteResources[refl->ReadWriteResources[i].bindPoint].used = true;
}
create_array_uninit(dst.ConstantBuffers, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
for(size_t s = 0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++)
{
dst.ConstantBuffers[s].Buffer = rm->GetOriginalID(GetIDForResource(src.ConstantBuffers[s]));
dst.ConstantBuffers[s].VecOffset = src.CBOffsets[s];
dst.ConstantBuffers[s].VecCount = src.CBCounts[s];
}
create_array_uninit(dst.Samplers, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT);
for(size_t s = 0; s < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; s++)
{
D3D11PipelineState::ShaderStage::Sampler &samp = dst.Samplers[s];
samp.Samp = rm->GetOriginalID(GetIDForResource(src.Samplers[s]));
if(samp.Samp != ResourceId())
{
samp.SamplerName = GetDebugName(src.Samplers[s]);
samp.customSamplerName = true;
if(samp.SamplerName.count == 0)
{
samp.customSamplerName = false;
samp.SamplerName = StringFormat::Fmt("Sampler %llu", samp.Samp);
}
D3D11_SAMPLER_DESC desc;
src.Samplers[s]->GetDesc(&desc);
samp.AddressU = ToStr::Get(desc.AddressU);
samp.AddressV = ToStr::Get(desc.AddressV);
samp.AddressW = ToStr::Get(desc.AddressW);
memcpy(samp.BorderColor, desc.BorderColor, sizeof(FLOAT) * 4);
samp.Comparison = ToStr::Get(desc.ComparisonFunc);
samp.Filter = ToStr::Get(desc.Filter);
samp.MaxAniso = 0;
if(desc.Filter == D3D11_FILTER_ANISOTROPIC ||
desc.Filter == D3D11_FILTER_COMPARISON_ANISOTROPIC)
samp.MaxAniso = desc.MaxAnisotropy;
samp.MaxLOD = desc.MaxLOD;
samp.MinLOD = desc.MinLOD;
samp.MipLODBias = desc.MipLODBias;
samp.UseComparison = (desc.Filter >= D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT);
samp.UseBorder = (desc.AddressU == D3D11_TEXTURE_ADDRESS_BORDER ||
desc.AddressV == D3D11_TEXTURE_ADDRESS_BORDER ||
desc.AddressW == D3D11_TEXTURE_ADDRESS_BORDER);
}
}
create_array_uninit(dst.SRVs, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
for(size_t s = 0; s < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; s++)
{
D3D11PipelineState::ShaderStage::ResourceView &view = dst.SRVs[s];
view.View = rm->GetOriginalID(GetIDForResource(src.SRVs[s]));
if(view.View != ResourceId())
{
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
src.SRVs[s]->GetDesc(&desc);
view.Format = MakeResourceFormat(desc.Format);
ID3D11Resource *res = NULL;
src.SRVs[s]->GetResource(&res);
view.Structured = false;
view.BufferStructCount = 0;
view.ElementSize =
desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0);
view.Resource = rm->GetOriginalID(GetIDForResource(res));
view.Type = ToStr::Get(desc.ViewDimension);
if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER)
{
view.FirstElement = desc.Buffer.FirstElement;
view.NumElements = desc.Buffer.NumElements;
view.ElementOffset = desc.Buffer.ElementOffset;
view.ElementWidth = desc.Buffer.ElementWidth;
D3D11_BUFFER_DESC bufdesc;
((ID3D11Buffer *)res)->GetDesc(&bufdesc);
view.Structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN;
if(view.Structured)
view.ElementSize = bufdesc.StructureByteStride;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX)
{
view.FirstElement = desc.BufferEx.FirstElement;
view.NumElements = desc.BufferEx.NumElements;
view.Flags = desc.BufferEx.Flags;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1D)
{
view.HighestMip = desc.Texture1D.MostDetailedMip;
view.NumMipLevels = desc.Texture1D.MipLevels;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY)
{
view.ArraySize = desc.Texture1DArray.ArraySize;
view.FirstArraySlice = desc.Texture1DArray.FirstArraySlice;
view.HighestMip = desc.Texture1DArray.MostDetailedMip;
view.NumMipLevels = desc.Texture1DArray.MipLevels;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2D)
{
view.HighestMip = desc.Texture2D.MostDetailedMip;
view.NumMipLevels = desc.Texture2D.MipLevels;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY)
{
view.ArraySize = desc.Texture2DArray.ArraySize;
view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice;
view.HighestMip = desc.Texture2DArray.MostDetailedMip;
view.NumMipLevels = desc.Texture2DArray.MipLevels;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMS)
{
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY)
{
view.ArraySize = desc.Texture2DArray.ArraySize;
view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D)
{
view.HighestMip = desc.Texture3D.MostDetailedMip;
view.NumMipLevels = desc.Texture3D.MipLevels;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBE)
{
view.ArraySize = 6;
view.HighestMip = desc.TextureCube.MostDetailedMip;
view.NumMipLevels = desc.TextureCube.MipLevels;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY)
{
view.ArraySize = desc.TextureCubeArray.NumCubes * 6;
view.FirstArraySlice = desc.TextureCubeArray.First2DArrayFace;
view.HighestMip = desc.TextureCubeArray.MostDetailedMip;
view.NumMipLevels = desc.TextureCubeArray.MipLevels;
}
SAFE_RELEASE(res);
}
}
create_array(dst.UAVs, D3D11_1_UAV_SLOT_COUNT);
for(size_t s = 0; dst.stage == eShaderStage_Compute && s < D3D11_1_UAV_SLOT_COUNT; s++)
{
D3D11PipelineState::ShaderStage::ResourceView &view = dst.UAVs[s];
view.View = rm->GetOriginalID(GetIDForResource(rs->CSUAVs[s]));
if(view.View != ResourceId())
{
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
rs->CSUAVs[s]->GetDesc(&desc);
ID3D11Resource *res = NULL;
rs->CSUAVs[s]->GetResource(&res);
view.Structured = false;
view.BufferStructCount = 0;
view.ElementSize =
desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0);
if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER &&
(desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER)))
{
view.BufferStructCount = m_pDevice->GetDebugManager()->GetStructCount(rs->CSUAVs[s]);
}
view.Resource = rm->GetOriginalID(GetIDForResource(res));
view.Format = MakeResourceFormat(desc.Format);
view.Type = ToStr::Get(desc.ViewDimension);
if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER)
{
view.FirstElement = desc.Buffer.FirstElement;
view.NumElements = desc.Buffer.NumElements;
view.Flags = desc.Buffer.Flags;
D3D11_BUFFER_DESC bufdesc;
((ID3D11Buffer *)res)->GetDesc(&bufdesc);
view.Structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN;
if(view.Structured)
view.ElementSize = bufdesc.StructureByteStride;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1D)
{
view.HighestMip = desc.Texture1D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY)
{
view.ArraySize = desc.Texture1DArray.ArraySize;
view.FirstArraySlice = desc.Texture1DArray.FirstArraySlice;
view.HighestMip = desc.Texture1DArray.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D)
{
view.HighestMip = desc.Texture2D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY)
{
view.ArraySize = desc.Texture2DArray.ArraySize;
view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice;
view.HighestMip = desc.Texture2DArray.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE3D)
{
view.ArraySize = desc.Texture3D.WSize;
view.FirstArraySlice = desc.Texture3D.FirstWSlice;
view.HighestMip = desc.Texture3D.MipSlice;
view.NumMipLevels = 1;
}
SAFE_RELEASE(res);
}
}
create_array_uninit(dst.ClassInstances, src.NumInstances);
for(UINT s = 0; s < src.NumInstances; s++)
{
D3D11_CLASS_INSTANCE_DESC desc;
src.Instances[s]->GetDesc(&desc);
char typeName[256] = {0};
SIZE_T count = 255;
src.Instances[s]->GetTypeName(typeName, &count);
char instName[256] = {0};
count = 255;
src.Instances[s]->GetInstanceName(instName, &count);
dst.ClassInstances[s] = instName;
}
}
}
/////////////////////////////////////////////////
// Stream Out
/////////////////////////////////////////////////
{
create_array_uninit(ret.m_SO.Outputs, D3D11_SO_BUFFER_SLOT_COUNT);
for(size_t s = 0; s < D3D11_SO_BUFFER_SLOT_COUNT; s++)
{
ret.m_SO.Outputs[s].Buffer = rm->GetOriginalID(GetIDForResource(rs->SO.Buffers[s]));
ret.m_SO.Outputs[s].Offset = rs->SO.Offsets[s];
}
}
/////////////////////////////////////////////////
// Rasterizer
/////////////////////////////////////////////////
{
D3D11_RASTERIZER_DESC desc;
if(rs->RS.State)
{
rs->RS.State->GetDesc(&desc);
ret.m_RS.m_State.AntialiasedLineEnable = desc.AntialiasedLineEnable == TRUE;
ret.m_RS.m_State.CullMode = eCull_None;
if(desc.CullMode == D3D11_CULL_FRONT)
ret.m_RS.m_State.CullMode = eCull_Front;
if(desc.CullMode == D3D11_CULL_BACK)
ret.m_RS.m_State.CullMode = eCull_Back;
ret.m_RS.m_State.FillMode = eFill_Solid;
if(desc.FillMode == D3D11_FILL_WIREFRAME)
ret.m_RS.m_State.FillMode = eFill_Wireframe;
ret.m_RS.m_State.DepthBias = desc.DepthBias;
ret.m_RS.m_State.DepthBiasClamp = desc.DepthBiasClamp;
ret.m_RS.m_State.DepthClip = desc.DepthClipEnable == TRUE;
ret.m_RS.m_State.FrontCCW = desc.FrontCounterClockwise == TRUE;
ret.m_RS.m_State.MultisampleEnable = desc.MultisampleEnable == TRUE;
ret.m_RS.m_State.ScissorEnable = desc.ScissorEnable == TRUE;
ret.m_RS.m_State.SlopeScaledDepthBias = desc.SlopeScaledDepthBias;
ret.m_RS.m_State.ForcedSampleCount = 0;
D3D11_RASTERIZER_DESC1 desc1;
RDCEraseEl(desc1);
if(CanQuery<ID3D11RasterizerState1>(rs->RS.State))
{
((ID3D11RasterizerState1 *)rs->RS.State)->GetDesc1(&desc1);
ret.m_RS.m_State.ForcedSampleCount = desc1.ForcedSampleCount;
}
D3D11_RASTERIZER_DESC2 desc2;
RDCEraseEl(desc2);
if(CanQuery<ID3D11RasterizerState2>(rs->RS.State))
{
((ID3D11RasterizerState2 *)rs->RS.State)->GetDesc2(&desc2);
ret.m_RS.m_State.ConservativeRasterization =
desc2.ConservativeRaster == D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON;
}
ret.m_RS.m_State.State = rm->GetOriginalID(GetIDForResource(rs->RS.State));
}
else
{
ret.m_RS.m_State.AntialiasedLineEnable = FALSE;
ret.m_RS.m_State.CullMode = eCull_Back;
ret.m_RS.m_State.DepthBias = 0;
ret.m_RS.m_State.DepthBiasClamp = 0.0f;
ret.m_RS.m_State.DepthClip = TRUE;
ret.m_RS.m_State.FillMode = eFill_Solid;
ret.m_RS.m_State.FrontCCW = FALSE;
ret.m_RS.m_State.MultisampleEnable = FALSE;
ret.m_RS.m_State.ScissorEnable = FALSE;
ret.m_RS.m_State.SlopeScaledDepthBias = 0.0f;
ret.m_RS.m_State.ForcedSampleCount = 0;
ret.m_RS.m_State.State = ResourceId();
}
size_t i = 0;
create_array_uninit(ret.m_RS.Scissors, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE);
for(i = 0; i < rs->RS.NumScissors; i++)
ret.m_RS.Scissors[i] = D3D11PipelineState::Rasterizer::Scissor(
rs->RS.Scissors[i].left, rs->RS.Scissors[i].top, rs->RS.Scissors[i].right,
rs->RS.Scissors[i].bottom, true);
for(; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; i++)
ret.m_RS.Scissors[i] = D3D11PipelineState::Rasterizer::Scissor(0, 0, 0, 0, false);
create_array_uninit(ret.m_RS.Viewports, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE);
for(i = 0; i < rs->RS.NumViews; i++)
ret.m_RS.Viewports[i] = D3D11PipelineState::Rasterizer::Viewport(
rs->RS.Viewports[i].TopLeftX, rs->RS.Viewports[i].TopLeftY, rs->RS.Viewports[i].Width,
rs->RS.Viewports[i].Height, rs->RS.Viewports[i].MinDepth, rs->RS.Viewports[i].MaxDepth,
true);
for(; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; i++)
ret.m_RS.Viewports[i] = D3D11PipelineState::Rasterizer::Viewport(0, 0, 0, 0, 0, 0, false);
}
/////////////////////////////////////////////////
// Output Merger
/////////////////////////////////////////////////
{
create_array_uninit(ret.m_OM.RenderTargets, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
for(size_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
D3D11PipelineState::ShaderStage::ResourceView &view = ret.m_OM.RenderTargets[i];
view.View = rm->GetOriginalID(GetIDForResource(rs->OM.RenderTargets[i]));
if(view.View != ResourceId())
{
D3D11_RENDER_TARGET_VIEW_DESC desc;
rs->OM.RenderTargets[i]->GetDesc(&desc);
ID3D11Resource *res = NULL;
rs->OM.RenderTargets[i]->GetResource(&res);
view.Structured = false;
view.BufferStructCount = 0;
view.ElementSize =
desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0);
view.Resource = rm->GetOriginalID(GetIDForResource(res));
view.Format = MakeResourceFormat(desc.Format);
view.Type = ToStr::Get(desc.ViewDimension);
if(desc.ViewDimension == D3D11_RTV_DIMENSION_BUFFER)
{
view.FirstElement = desc.Buffer.FirstElement;
view.NumElements = desc.Buffer.NumElements;
}
else if(desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1D)
{
view.HighestMip = desc.Texture1D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY)
{
view.ArraySize = desc.Texture1DArray.ArraySize;
view.FirstArraySlice = desc.Texture1DArray.FirstArraySlice;
view.HighestMip = desc.Texture1DArray.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2D)
{
view.HighestMip = desc.Texture2D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY)
{
view.ArraySize = desc.Texture2DArray.ArraySize;
view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice;
view.HighestMip = desc.Texture2DArray.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE3D)
{
view.ArraySize = desc.Texture3D.WSize;
view.FirstArraySlice = desc.Texture3D.FirstWSlice;
view.HighestMip = desc.Texture3D.MipSlice;
view.NumMipLevels = 1;
}
SAFE_RELEASE(res);
}
}
ret.m_OM.UAVStartSlot = rs->OM.UAVStartSlot;
create_array_uninit(ret.m_OM.UAVs, D3D11_1_UAV_SLOT_COUNT);
for(size_t s = 0; s < D3D11_1_UAV_SLOT_COUNT; s++)
{
D3D11PipelineState::ShaderStage::ResourceView view;
view.View = rm->GetOriginalID(GetIDForResource(rs->OM.UAVs[s]));
if(view.View != ResourceId())
{
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
rs->OM.UAVs[s]->GetDesc(&desc);
ID3D11Resource *res = NULL;
rs->OM.UAVs[s]->GetResource(&res);
view.Structured = false;
view.BufferStructCount = 0;
view.ElementSize =
desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0);
if(desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))
{
view.Structured = true;
view.BufferStructCount = m_pDevice->GetDebugManager()->GetStructCount(rs->OM.UAVs[s]);
}
view.Resource = rm->GetOriginalID(GetIDForResource(res));
view.Format = MakeResourceFormat(desc.Format);
view.Type = ToStr::Get(desc.ViewDimension);
if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER)
{
view.FirstElement = desc.Buffer.FirstElement;
view.NumElements = desc.Buffer.NumElements;
view.Flags = desc.Buffer.Flags;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1D)
{
view.HighestMip = desc.Texture1D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY)
{
view.ArraySize = desc.Texture1DArray.ArraySize;
view.FirstArraySlice = desc.Texture1DArray.FirstArraySlice;
view.HighestMip = desc.Texture1DArray.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D)
{
view.HighestMip = desc.Texture2D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY)
{
view.ArraySize = desc.Texture2DArray.ArraySize;
view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice;
view.HighestMip = desc.Texture2DArray.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE3D)
{
view.ArraySize = desc.Texture3D.WSize;
view.FirstArraySlice = desc.Texture3D.FirstWSlice;
view.HighestMip = desc.Texture3D.MipSlice;
view.NumMipLevels = 1;
}
SAFE_RELEASE(res);
}
ret.m_OM.UAVs[s] = view;
}
{
D3D11PipelineState::ShaderStage::ResourceView &view = ret.m_OM.DepthTarget;
view.View = rm->GetOriginalID(GetIDForResource(rs->OM.DepthView));
if(view.View != ResourceId())
{
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
rs->OM.DepthView->GetDesc(&desc);
ID3D11Resource *res = NULL;
rs->OM.DepthView->GetResource(&res);
view.Structured = false;
view.BufferStructCount = 0;
view.ElementSize =
desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0);
ret.m_OM.DepthReadOnly = false;
ret.m_OM.StencilReadOnly = false;
if(desc.Flags & D3D11_DSV_READ_ONLY_DEPTH)
ret.m_OM.DepthReadOnly = true;
if(desc.Flags & D3D11_DSV_READ_ONLY_STENCIL)
ret.m_OM.StencilReadOnly = true;
view.Resource = rm->GetOriginalID(GetIDForResource(res));
view.Format = MakeResourceFormat(desc.Format);
view.Type = ToStr::Get(desc.ViewDimension);
if(desc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE1D)
{
view.HighestMip = desc.Texture1D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE1DARRAY)
{
view.ArraySize = desc.Texture1DArray.ArraySize;
view.FirstArraySlice = desc.Texture1DArray.FirstArraySlice;
view.HighestMip = desc.Texture1DArray.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2D)
{
view.HighestMip = desc.Texture2D.MipSlice;
view.NumMipLevels = 1;
}
else if(desc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2DARRAY)
{
view.ArraySize = desc.Texture2DArray.ArraySize;
view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice;
view.HighestMip = desc.Texture2DArray.MipSlice;
view.NumMipLevels = 1;
}
SAFE_RELEASE(res);
}
}
if(rs->OM.BlendState)
{
D3D11_BLEND_DESC desc;
rs->OM.BlendState->GetDesc(&desc);
ret.m_OM.m_BlendState.State = GetIDForResource(rs->OM.BlendState);
ret.m_OM.m_BlendState.SampleMask = rs->OM.SampleMask;
memcpy(ret.m_OM.m_BlendState.BlendFactor, rs->OM.BlendFactor, sizeof(FLOAT) * 4);
ret.m_OM.m_BlendState.AlphaToCoverage = desc.AlphaToCoverageEnable == TRUE;
ret.m_OM.m_BlendState.IndependentBlend = desc.IndependentBlendEnable == TRUE;
bool state1 = false;
D3D11_BLEND_DESC1 desc1;
RDCEraseEl(desc1);
if(CanQuery<ID3D11BlendState1>(rs->OM.BlendState))
{
((WrappedID3D11BlendState1 *)rs->OM.BlendState)->GetDesc1(&desc1);
state1 = true;
}
create_array_uninit(ret.m_OM.m_BlendState.Blends, 8);
for(size_t i = 0; i < 8; i++)
{
D3D11PipelineState::OutputMerger::BlendState::RTBlend &blend =
ret.m_OM.m_BlendState.Blends[i];
blend.Enabled = desc.RenderTarget[i].BlendEnable == TRUE;
blend.LogicEnabled = state1 && desc1.RenderTarget[i].LogicOpEnable == TRUE;
blend.LogicOp = state1 ? ToStr::Get(desc1.RenderTarget[i].LogicOp) : "NOOP";
blend.m_AlphaBlend.Source = ToStr::Get(desc.RenderTarget[i].SrcBlendAlpha);
blend.m_AlphaBlend.Destination = ToStr::Get(desc.RenderTarget[i].DestBlendAlpha);
blend.m_AlphaBlend.Operation = ToStr::Get(desc.RenderTarget[i].BlendOpAlpha);
blend.m_Blend.Source = ToStr::Get(desc.RenderTarget[i].SrcBlend);
blend.m_Blend.Destination = ToStr::Get(desc.RenderTarget[i].DestBlend);
blend.m_Blend.Operation = ToStr::Get(desc.RenderTarget[i].BlendOp);
blend.WriteMask = desc.RenderTarget[i].RenderTargetWriteMask;
}
}
else
{
ret.m_OM.m_BlendState.State = ResourceId();
ret.m_OM.m_BlendState.SampleMask = ~0U;
ret.m_OM.m_BlendState.BlendFactor[0] = ret.m_OM.m_BlendState.BlendFactor[1] =
ret.m_OM.m_BlendState.BlendFactor[2] = ret.m_OM.m_BlendState.BlendFactor[3] = 1.0f;
ret.m_OM.m_BlendState.AlphaToCoverage = false;
ret.m_OM.m_BlendState.IndependentBlend = false;
D3D11PipelineState::OutputMerger::BlendState::RTBlend blend;
blend.Enabled = false;
blend.m_AlphaBlend.Source = ToStr::Get(D3D11_BLEND_ONE);
blend.m_AlphaBlend.Destination = ToStr::Get(D3D11_BLEND_ZERO);
blend.m_AlphaBlend.Operation = ToStr::Get(D3D11_BLEND_OP_ADD);
blend.m_Blend.Source = ToStr::Get(D3D11_BLEND_ONE);
blend.m_Blend.Destination = ToStr::Get(D3D11_BLEND_ZERO);
blend.m_Blend.Operation = ToStr::Get(D3D11_BLEND_OP_ADD);
blend.LogicEnabled = false;
blend.LogicOp = ToStr::Get(D3D11_LOGIC_OP_NOOP);
blend.WriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
create_array_uninit(ret.m_OM.m_BlendState.Blends, 8);
for(size_t i = 0; i < 8; i++)
ret.m_OM.m_BlendState.Blends[i] = blend;
}
if(rs->OM.DepthStencilState)
{
D3D11_DEPTH_STENCIL_DESC desc;
rs->OM.DepthStencilState->GetDesc(&desc);
ret.m_OM.m_State.DepthEnable = desc.DepthEnable == TRUE;
ret.m_OM.m_State.DepthFunc = ToStr::Get(desc.DepthFunc);
ret.m_OM.m_State.DepthWrites = desc.DepthWriteMask == D3D11_DEPTH_WRITE_MASK_ALL;
ret.m_OM.m_State.StencilEnable = desc.StencilEnable == TRUE;
ret.m_OM.m_State.StencilRef = rs->OM.StencRef;
ret.m_OM.m_State.StencilReadMask = desc.StencilReadMask;
ret.m_OM.m_State.StencilWriteMask = desc.StencilWriteMask;
ret.m_OM.m_State.State = rm->GetOriginalID(GetIDForResource(rs->OM.DepthStencilState));
ret.m_OM.m_State.m_FrontFace.Func = ToStr::Get(desc.FrontFace.StencilFunc);
ret.m_OM.m_State.m_FrontFace.DepthFailOp = ToStr::Get(desc.FrontFace.StencilDepthFailOp);
ret.m_OM.m_State.m_FrontFace.PassOp = ToStr::Get(desc.FrontFace.StencilPassOp);
ret.m_OM.m_State.m_FrontFace.FailOp = ToStr::Get(desc.FrontFace.StencilFailOp);
ret.m_OM.m_State.m_BackFace.Func = ToStr::Get(desc.BackFace.StencilFunc);
ret.m_OM.m_State.m_BackFace.DepthFailOp = ToStr::Get(desc.BackFace.StencilDepthFailOp);
ret.m_OM.m_State.m_BackFace.PassOp = ToStr::Get(desc.BackFace.StencilPassOp);
ret.m_OM.m_State.m_BackFace.FailOp = ToStr::Get(desc.BackFace.StencilFailOp);
}
else
{
ret.m_OM.m_State.DepthEnable = true;
ret.m_OM.m_State.DepthFunc = ToStr::Get(D3D11_COMPARISON_LESS);
ret.m_OM.m_State.DepthWrites = true;
ret.m_OM.m_State.StencilEnable = false;
ret.m_OM.m_State.StencilRef = rs->OM.StencRef;
ret.m_OM.m_State.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
ret.m_OM.m_State.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
ret.m_OM.m_State.State = ResourceId();
ret.m_OM.m_State.m_FrontFace.Func = ToStr::Get(D3D11_COMPARISON_ALWAYS);
ret.m_OM.m_State.m_FrontFace.DepthFailOp = ToStr::Get(D3D11_STENCIL_OP_KEEP);
ret.m_OM.m_State.m_FrontFace.PassOp = ToStr::Get(D3D11_STENCIL_OP_KEEP);
ret.m_OM.m_State.m_FrontFace.FailOp = ToStr::Get(D3D11_STENCIL_OP_KEEP);
ret.m_OM.m_State.m_BackFace.Func = ToStr::Get(D3D11_COMPARISON_ALWAYS);
ret.m_OM.m_State.m_BackFace.DepthFailOp = ToStr::Get(D3D11_STENCIL_OP_KEEP);
ret.m_OM.m_State.m_BackFace.PassOp = ToStr::Get(D3D11_STENCIL_OP_KEEP);
ret.m_OM.m_State.m_BackFace.FailOp = ToStr::Get(D3D11_STENCIL_OP_KEEP);
}
}
return ret;
}
void D3D11Replay::ReadLogInitialisation()
{
m_pDevice->ReadLogInitialisation();
}
void D3D11Replay::SetContextFilter(ResourceId id, uint32_t firstDefEv, uint32_t lastDefEv)
{
m_pDevice->SetContextFilter(id, firstDefEv, lastDefEv);
}
void D3D11Replay::ReplayLog(uint32_t endEventID, ReplayLogType replayType)
{
m_pDevice->ReplayLog(0, endEventID, replayType);
}
vector<uint32_t> D3D11Replay::GetPassEvents(uint32_t eventID)
{
vector<uint32_t> passEvents;
const FetchDrawcall *draw = m_pDevice->GetDrawcall(eventID);
const FetchDrawcall *start = draw;
while(start && start->previous != 0 &&
(m_pDevice->GetDrawcall((uint32_t)start->previous)->flags & eDraw_Clear) == 0)
{
const FetchDrawcall *prev = m_pDevice->GetDrawcall((uint32_t)start->previous);
if(memcmp(start->outputs, prev->outputs, sizeof(start->outputs)) ||
start->depthOut != prev->depthOut)
break;
start = prev;
}
while(start)
{
if(start == draw)
break;
if(start->flags & eDraw_Drawcall)
passEvents.push_back(start->eventID);
start = m_pDevice->GetDrawcall((uint32_t)start->next);
}
return passEvents;
}
uint64_t D3D11Replay::MakeOutputWindow(void *w, bool depth)
{
return m_pDevice->GetDebugManager()->MakeOutputWindow(w, depth);
}
void D3D11Replay::DestroyOutputWindow(uint64_t id)
{
m_pDevice->GetDebugManager()->DestroyOutputWindow(id);
}
bool D3D11Replay::CheckResizeOutputWindow(uint64_t id)
{
return m_pDevice->GetDebugManager()->CheckResizeOutputWindow(id);
}
void D3D11Replay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
{
m_pDevice->GetDebugManager()->GetOutputWindowDimensions(id, w, h);
}
void D3D11Replay::ClearOutputWindowColour(uint64_t id, float col[4])
{
m_pDevice->GetDebugManager()->ClearOutputWindowColour(id, col);
}
void D3D11Replay::ClearOutputWindowDepth(uint64_t id, float depth, uint8_t stencil)
{
m_pDevice->GetDebugManager()->ClearOutputWindowDepth(id, depth, stencil);
}
void D3D11Replay::BindOutputWindow(uint64_t id, bool depth)
{
m_pDevice->GetDebugManager()->BindOutputWindow(id, depth);
}
bool D3D11Replay::IsOutputWindowVisible(uint64_t id)
{
return m_pDevice->GetDebugManager()->IsOutputWindowVisible(id);
}
void D3D11Replay::FlipOutputWindow(uint64_t id)
{
m_pDevice->GetDebugManager()->FlipOutputWindow(id);
}
void D3D11Replay::InitPostVSBuffers(uint32_t eventID)
{
m_pDevice->GetDebugManager()->InitPostVSBuffers(eventID);
}
void D3D11Replay::InitPostVSBuffers(const vector<uint32_t> &passEvents)
{
uint32_t prev = 0;
// since we can always replay between drawcalls, just loop through all the events
// doing partial replays and calling InitPostVSBuffers for each
for(size_t i = 0; i < passEvents.size(); i++)
{
if(prev != passEvents[i])
{
m_pDevice->ReplayLog(prev, passEvents[i], eReplay_WithoutDraw);
prev = passEvents[i];
}
const FetchDrawcall *d = m_pDevice->GetDrawcall(passEvents[i]);
if(d)
m_pDevice->GetDebugManager()->InitPostVSBuffers(passEvents[i]);
}
}
ResourceId D3D11Replay::GetLiveID(ResourceId id)
{
return m_pDevice->GetResourceManager()->GetLiveID(id);
}
bool D3D11Replay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample,
FormatComponentType typeHint, float *minval, float *maxval)
{
return m_pDevice->GetDebugManager()->GetMinMax(texid, sliceFace, mip, sample, typeHint, minval,
maxval);
}
bool D3D11Replay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample,
FormatComponentType typeHint, float minval, float maxval,
bool channels[4], vector<uint32_t> &histogram)
{
return m_pDevice->GetDebugManager()->GetHistogram(texid, sliceFace, mip, sample, typeHint, minval,
maxval, channels, histogram);
}
MeshFormat D3D11Replay::GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage)
{
return m_pDevice->GetDebugManager()->GetPostVSBuffers(eventID, instID, stage);
}
void D3D11Replay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector<byte> &retData)
{
m_pDevice->GetDebugManager()->GetBufferData(buff, offset, len, retData);
}
byte *D3D11Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm,
float blackPoint, float whitePoint, size_t &dataSize)
{
return m_pDevice->GetDebugManager()->GetTextureData(
tex, arrayIdx, mip, typeHint, resolve, forceRGBA8unorm, blackPoint, whitePoint, dataSize);
}
void D3D11Replay::ReplaceResource(ResourceId from, ResourceId to)
{
m_pDevice->GetResourceManager()->ReplaceResource(from, to);
}
void D3D11Replay::RemoveReplacement(ResourceId id)
{
m_pDevice->GetResourceManager()->RemoveReplacement(id);
}
vector<uint32_t> D3D11Replay::EnumerateCounters()
{
return m_pDevice->GetDebugManager()->EnumerateCounters();
}
void D3D11Replay::DescribeCounter(uint32_t counterID, CounterDescription &desc)
{
m_pDevice->GetDebugManager()->DescribeCounter(counterID, desc);
}
vector<CounterResult> D3D11Replay::FetchCounters(const vector<uint32_t> &counters)
{
return m_pDevice->GetDebugManager()->FetchCounters(counters);
}
void D3D11Replay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &secondaryDraws,
const MeshDisplay &cfg)
{
return m_pDevice->GetDebugManager()->RenderMesh(eventID, secondaryDraws, cfg);
}
void D3D11Replay::BuildTargetShader(string source, string entry, const uint32_t compileFlags,
ShaderStageType type, ResourceId *id, string *errors)
{
m_pDevice->GetDebugManager()->BuildShader(source, entry, D3DCOMPILE_DEBUG | compileFlags, type,
id, errors);
}
void D3D11Replay::BuildCustomShader(string source, string entry, const uint32_t compileFlags,
ShaderStageType type, ResourceId *id, string *errors)
{
m_pDevice->GetDebugManager()->BuildShader(source, entry, compileFlags, type, id, errors);
}
bool D3D11Replay::RenderTexture(TextureDisplay cfg)
{
return m_pDevice->GetDebugManager()->RenderTexture(cfg, true);
}
void D3D11Replay::RenderCheckerboard(Vec3f light, Vec3f dark)
{
m_pDevice->GetDebugManager()->RenderCheckerboard(light, dark);
}
void D3D11Replay::RenderHighlightBox(float w, float h, float scale)
{
m_pDevice->GetDebugManager()->RenderHighlightBox(w, h, scale);
}
void D3D11Replay::FillCBufferVariables(ResourceId shader, string entryPoint, uint32_t cbufSlot,
vector<ShaderVariable> &outvars, const vector<byte> &data)
{
auto it = WrappedShader::m_ShaderList.find(shader);
if(it == WrappedShader::m_ShaderList.end())
return;
DXBC::DXBCFile *dxbc = it->second->GetDXBC();
RDCASSERT(dxbc);
if(cbufSlot < dxbc->m_CBuffers.size())
m_pDevice->GetDebugManager()->FillCBufferVariables(dxbc->m_CBuffers[cbufSlot].variables,
outvars, false, data);
return;
}
vector<PixelModification> D3D11Replay::PixelHistory(vector<EventUsage> events, ResourceId target,
uint32_t x, uint32_t y, uint32_t slice,
uint32_t mip, uint32_t sampleIdx,
FormatComponentType typeHint)
{
return m_pDevice->GetDebugManager()->PixelHistory(events, target, x, y, slice, mip, sampleIdx,
typeHint);
}
ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventID, uint32_t vertid, uint32_t instid,
uint32_t idx, uint32_t instOffset, uint32_t vertOffset)
{
return m_pDevice->GetDebugManager()->DebugVertex(eventID, vertid, instid, idx, instOffset,
vertOffset);
}
ShaderDebugTrace D3D11Replay::DebugPixel(uint32_t eventID, uint32_t x, uint32_t y, uint32_t sample,
uint32_t primitive)
{
return m_pDevice->GetDebugManager()->DebugPixel(eventID, x, y, sample, primitive);
}
ShaderDebugTrace D3D11Replay::DebugThread(uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3])
{
return m_pDevice->GetDebugManager()->DebugThread(eventID, groupid, threadid);
}
uint32_t D3D11Replay::PickVertex(uint32_t eventID, const MeshDisplay &cfg, uint32_t x, uint32_t y)
{
return m_pDevice->GetDebugManager()->PickVertex(eventID, cfg, x, y);
}
void D3D11Replay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace,
uint32_t mip, uint32_t sample, FormatComponentType typeHint,
float pixel[4])
{
m_pDevice->GetDebugManager()->PickPixel(texture, x, y, sliceFace, mip, sample, typeHint, pixel);
}
ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FormatComponentType typeHint,
TextureDisplayOverlay overlay, uint32_t eventID,
const vector<uint32_t> &passEvents)
{
return m_pDevice->GetDebugManager()->RenderOverlay(texid, typeHint, overlay, eventID, passEvents);
}
ResourceId D3D11Replay::ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip,
FormatComponentType typeHint)
{
return m_pDevice->GetDebugManager()->ApplyCustomShader(shader, texid, mip, typeHint);
}
bool D3D11Replay::IsRenderOutput(ResourceId id)
{
for(size_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
if(m_CurPipelineState.m_OM.RenderTargets[i].View == id ||
m_CurPipelineState.m_OM.RenderTargets[i].Resource == id)
return true;
}
if(m_CurPipelineState.m_OM.DepthTarget.View == id ||
m_CurPipelineState.m_OM.DepthTarget.Resource == id)
return true;
return false;
}
void D3D11Replay::InitCallstackResolver()
{
m_pDevice->GetSerialiser()->InitCallstackResolver();
}
bool D3D11Replay::HasCallstacks()
{
return m_pDevice->GetSerialiser()->HasCallstacks();
}
Callstack::StackResolver *D3D11Replay::GetCallstackResolver()
{
return m_pDevice->GetSerialiser()->GetCallstackResolver();
}
ResourceId D3D11Replay::CreateProxyTexture(const FetchTexture &templateTex)
{
ResourceId ret;
ID3D11Resource *resource = NULL;
if(templateTex.dimension == 1)
{
ID3D11Texture1D *throwaway = NULL;
D3D11_TEXTURE1D_DESC desc;
desc.ArraySize = templateTex.arraysize;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
if(templateTex.creationFlags & eTextureCreate_DSV)
desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
desc.CPUAccessFlags = 0;
desc.Format = MakeDXGIFormat(templateTex.format);
desc.MipLevels = templateTex.mips;
desc.MiscFlags = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.Width = templateTex.width;
HRESULT hr = m_pDevice->CreateTexture1D(&desc, NULL, &throwaway);
if(FAILED(hr))
{
RDCERR("Failed to create 1D proxy texture");
return ResourceId();
}
resource = throwaway;
if(templateTex.creationFlags & eTextureCreate_DSV)
desc.Format = GetTypelessFormat(desc.Format);
ret = ((WrappedID3D11Texture1D *)throwaway)->GetResourceID();
if(templateTex.creationFlags & eTextureCreate_DSV)
WrappedID3D11Texture1D::m_TextureList[ret].m_Type = TEXDISPLAY_DEPTH_TARGET;
}
else if(templateTex.dimension == 2)
{
ID3D11Texture2D *throwaway = NULL;
D3D11_TEXTURE2D_DESC desc;
desc.ArraySize = templateTex.arraysize;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.Format = MakeDXGIFormat(templateTex.format);
desc.MipLevels = templateTex.mips;
desc.MiscFlags = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.Width = templateTex.width;
desc.Height = templateTex.height;
desc.SampleDesc.Count = templateTex.msSamp;
desc.SampleDesc.Quality = templateTex.msQual;
if(templateTex.creationFlags & eTextureCreate_DSV)
{
desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
desc.Format = GetTypelessFormat(desc.Format);
}
if(templateTex.cubemap)
desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
HRESULT hr = m_pDevice->CreateTexture2D(&desc, NULL, &throwaway);
if(FAILED(hr))
{
RDCERR("Failed to create 2D proxy texture");
return ResourceId();
}
resource = throwaway;
ret = ((WrappedID3D11Texture2D1 *)throwaway)->GetResourceID();
if(templateTex.creationFlags & eTextureCreate_DSV)
WrappedID3D11Texture2D1::m_TextureList[ret].m_Type = TEXDISPLAY_DEPTH_TARGET;
}
else if(templateTex.dimension == 3)
{
ID3D11Texture3D *throwaway = NULL;
D3D11_TEXTURE3D_DESC desc;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
if(templateTex.creationFlags & eTextureCreate_DSV)
desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
desc.CPUAccessFlags = 0;
desc.Format = MakeDXGIFormat(templateTex.format);
desc.MipLevels = templateTex.mips;
desc.MiscFlags = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.Width = templateTex.width;
desc.Height = templateTex.height;
desc.Depth = templateTex.depth;
HRESULT hr = m_pDevice->CreateTexture3D(&desc, NULL, &throwaway);
if(FAILED(hr))
{
RDCERR("Failed to create 3D proxy texture");
return ResourceId();
}
resource = throwaway;
ret = ((WrappedID3D11Texture3D1 *)throwaway)->GetResourceID();
}
else
{
RDCERR("Invalid texture dimension: %d", templateTex.dimension);
}
if(resource != NULL && templateTex.customName)
{
string name = templateTex.name.elems;
SetDebugName(resource, templateTex.name.elems);
}
m_ProxyResources.push_back(resource);
return ret;
}
void D3D11Replay::SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data,
size_t dataSize)
{
if(texid == ResourceId())
return;
ID3D11DeviceContext *ctx = m_pDevice->GetImmediateContext()->GetReal();
if(WrappedID3D11Texture1D::m_TextureList.find(texid) != WrappedID3D11Texture1D::m_TextureList.end())
{
WrappedID3D11Texture1D *tex =
(WrappedID3D11Texture1D *)WrappedID3D11Texture1D::m_TextureList[texid].m_Texture;
D3D11_TEXTURE1D_DESC desc;
tex->GetDesc(&desc);
uint32_t mips = desc.MipLevels ? desc.MipLevels : CalcNumMips(desc.Width, 1, 1);
if(mip >= mips || arrayIdx >= desc.ArraySize)
{
RDCERR("arrayIdx %d and mip %d invalid for tex", arrayIdx, mip);
return;
}
uint32_t sub = arrayIdx * mips + mip;
if(dataSize < GetByteSize(desc.Width, 1, 1, desc.Format, mip))
{
RDCERR("Insufficient data provided to SetProxyTextureData");
return;
}
ctx->UpdateSubresource(tex->GetReal(), sub, NULL, data,
GetByteSize(desc.Width, 1, 1, desc.Format, mip),
GetByteSize(desc.Width, 1, 1, desc.Format, mip));
}
else if(WrappedID3D11Texture2D1::m_TextureList.find(texid) !=
WrappedID3D11Texture2D1::m_TextureList.end())
{
WrappedID3D11Texture2D1 *tex =
(WrappedID3D11Texture2D1 *)WrappedID3D11Texture2D1::m_TextureList[texid].m_Texture;
D3D11_TEXTURE2D_DESC desc;
tex->GetDesc(&desc);
uint32_t mips = desc.MipLevels ? desc.MipLevels : CalcNumMips(desc.Width, desc.Height, 1);
if(mip >= mips || arrayIdx >= desc.ArraySize)
{
RDCERR("arrayIdx %d and mip %d invalid for tex", arrayIdx, mip);
return;
}
uint32_t sub = arrayIdx * mips + mip;
if(dataSize < GetByteSize(desc.Width, desc.Height, 1, desc.Format, mip))
{
RDCERR("Insufficient data provided to SetProxyTextureData");
return;
}
ctx->UpdateSubresource(tex->GetReal(), sub, NULL, data,
GetByteSize(desc.Width, 1, 1, desc.Format, mip),
GetByteSize(desc.Width, desc.Height, 1, desc.Format, mip));
}
else if(WrappedID3D11Texture3D1::m_TextureList.find(texid) !=
WrappedID3D11Texture3D1::m_TextureList.end())
{
WrappedID3D11Texture3D1 *tex =
(WrappedID3D11Texture3D1 *)WrappedID3D11Texture3D1::m_TextureList[texid].m_Texture;
D3D11_TEXTURE3D_DESC desc;
tex->GetDesc(&desc);
uint32_t mips =
desc.MipLevels ? desc.MipLevels : CalcNumMips(desc.Width, desc.Height, desc.Depth);
if(mip >= mips)
{
RDCERR("arrayIdx %d and mip %d invalid for tex", arrayIdx, mip);
return;
}
if(dataSize < GetByteSize(desc.Width, desc.Height, desc.Depth, desc.Format, mip))
{
RDCERR("Insufficient data provided to SetProxyTextureData");
return;
}
ctx->UpdateSubresource(tex->GetReal(), mip, NULL, data,
GetByteSize(desc.Width, 1, 1, desc.Format, mip),
GetByteSize(desc.Width, desc.Height, 1, desc.Format, mip));
}
else
{
RDCERR("Invalid texture id passed to SetProxyTextureData");
}
}
ResourceId D3D11Replay::CreateProxyBuffer(const FetchBuffer &templateBuf)
{
ResourceId ret;
ID3D11Resource *resource = NULL;
{
ID3D11Buffer *throwaway = NULL;
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (UINT)templateBuf.byteSize;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
if(templateBuf.structureSize > 0)
{
desc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.StructureByteStride = templateBuf.structureSize;
}
if(templateBuf.creationFlags & eBufferCreate_Indirect)
{
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
}
if(templateBuf.creationFlags & eBufferCreate_IB)
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
if(templateBuf.creationFlags & eBufferCreate_CB)
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
if(templateBuf.creationFlags & eBufferCreate_UAV)
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
HRESULT hr = m_pDevice->CreateBuffer(&desc, NULL, &throwaway);
if(FAILED(hr))
{
RDCERR("Failed to create proxy buffer");
return ResourceId();
}
resource = throwaway;
ret = ((WrappedID3D11Buffer *)throwaway)->GetResourceID();
}
if(resource != NULL && templateBuf.customName)
{
string name = templateBuf.name.elems;
SetDebugName(resource, templateBuf.name.elems);
}
m_ProxyResources.push_back(resource);
return ret;
}
void D3D11Replay::SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize)
{
if(bufid == ResourceId())
return;
ID3D11DeviceContext *ctx = m_pDevice->GetImmediateContext()->GetReal();
if(WrappedID3D11Buffer::m_BufferList.find(bufid) != WrappedID3D11Buffer::m_BufferList.end())
{
WrappedID3D11Buffer *buf =
(WrappedID3D11Buffer *)WrappedID3D11Buffer::m_BufferList[bufid].m_Buffer;
D3D11_BUFFER_DESC desc;
buf->GetDesc(&desc);
if(dataSize < desc.ByteWidth)
{
RDCERR("Insufficient data provided to SetProxyBufferData");
return;
}
ctx->UpdateSubresource(buf->GetReal(), 0, NULL, data, (UINT)dataSize, (UINT)dataSize);
}
else
{
RDCERR("Invalid buffer id passed to SetProxyBufferData");
}
}
ReplayCreateStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
{
RDCDEBUG("Creating a D3D11 replay device");
HMODULE lib = NULL;
lib = LoadLibraryA("d3d11.dll");
if(lib == NULL)
{
RDCERR("Failed to load d3d11.dll");
return eReplayCreate_APIInitFailed;
}
lib = LoadLibraryA("d3d9.dll");
if(lib == NULL)
{
RDCERR("Failed to load d3d9.dll");
return eReplayCreate_APIInitFailed;
}
lib = LoadLibraryA("dxgi.dll");
if(lib == NULL)
{
RDCERR("Failed to load dxgi.dll");
return eReplayCreate_APIInitFailed;
}
if(GetD3DCompiler() == NULL)
{
RDCERR("Failed to load d3dcompiler_??.dll");
return eReplayCreate_APIInitFailed;
}
typedef HRESULT(__cdecl * PFN_RENDERDOC_CREATE_DEVICE_AND_SWAP_CHAIN)(
__in_opt IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT,
__in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL *, UINT FeatureLevels, UINT,
__in_opt CONST DXGI_SWAP_CHAIN_DESC *, __out_opt IDXGISwapChain **, __out_opt ID3D11Device **,
__out_opt D3D_FEATURE_LEVEL *, __out_opt ID3D11DeviceContext **);
PFN_RENDERDOC_CREATE_DEVICE_AND_SWAP_CHAIN createDevice =
(PFN_RENDERDOC_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(
GetModuleHandleA("renderdoc.dll"), "RENDERDOC_CreateWrappedD3D11DeviceAndSwapChain");
RDCASSERT(createDevice);
ID3D11Device *device = NULL;
D3D11InitParams initParams;
RDCDriver driverFileType = RDC_D3D11;
string driverName = "D3D11";
if(logfile)
{
auto status = RenderDoc::Inst().FillInitParams(logfile, driverFileType, driverName,
(RDCInitParams *)&initParams);
if(status != eReplayCreate_Success)
return status;
}
// initParams.SerialiseVersion is guaranteed to be valid/supported since otherwise the
// FillInitParams
// (which calls D3D11InitParams::Serialise) would have failed above, so no need to check it here.
if(initParams.SDKVersion != D3D11_SDK_VERSION)
{
RDCWARN(
"Capture file used a different SDK version %lu from replay app %lu. Results may be "
"undefined",
initParams.SDKVersion, D3D11_SDK_VERSION);
}
if(initParams.DriverType == D3D_DRIVER_TYPE_UNKNOWN)
initParams.DriverType = D3D_DRIVER_TYPE_HARDWARE;
int i = -2;
// force using our feature levels as we require >= 11_0 for analysis
D3D_FEATURE_LEVEL featureLevelArray11_1[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
UINT numFeatureLevels11_1 = ARRAY_COUNT(featureLevelArray11_1);
D3D_FEATURE_LEVEL featureLevelArray11_0[] = {D3D_FEATURE_LEVEL_11_0};
UINT numFeatureLevels11_0 = ARRAY_COUNT(featureLevelArray11_0);
D3D_DRIVER_TYPE driverTypes[] = {D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE};
int numDrivers = ARRAY_COUNT(driverTypes);
D3D_FEATURE_LEVEL *featureLevelArray = featureLevelArray11_1;
UINT numFeatureLevels = numFeatureLevels11_1;
D3D_DRIVER_TYPE driverType = initParams.DriverType;
UINT flags = initParams.Flags;
HRESULT hr = E_FAIL;
D3D_FEATURE_LEVEL maxFeatureLevel = D3D_FEATURE_LEVEL_9_1;
// check for feature level 11 support - passing NULL feature level array implicitly checks for
// 11_0 before others
hr = createDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL,
NULL, &maxFeatureLevel, NULL);
bool warpFallback = false;
if(SUCCEEDED(hr) && maxFeatureLevel < D3D_FEATURE_LEVEL_11_0)
{
RDCWARN(
"Couldn't create FEATURE_LEVEL_11_0 device - RenderDoc requires FEATURE_LEVEL_11_0 "
"availability - falling back to WARP rasterizer");
driverTypes[0] = driverType = D3D_DRIVER_TYPE_WARP;
warpFallback = true;
}
D3D11DebugManager::PreDeviceInitCounters();
hr = E_FAIL;
for(;;)
{
hr = createDevice(
/*pAdapter=*/NULL, driverType, /*Software=*/NULL, flags,
/*pFeatureLevels=*/featureLevelArray, /*nFeatureLevels=*/numFeatureLevels, D3D11_SDK_VERSION,
/*pSwapChainDesc=*/NULL, (IDXGISwapChain **)NULL, (ID3D11Device **)&device,
(D3D_FEATURE_LEVEL *)NULL, (ID3D11DeviceContext **)NULL);
if(SUCCEEDED(hr))
{
WrappedID3D11Device *wrappedDev = (WrappedID3D11Device *)device;
if(logfile)
wrappedDev->SetLogFile(logfile);
wrappedDev->SetLogVersion(initParams.SerialiseVersion);
RDCLOG("Created device.");
D3D11Replay *replay = wrappedDev->GetReplay();
replay->SetProxy(logfile == NULL, warpFallback);
if(warpFallback)
{
wrappedDev->AddDebugMessage(
eDbgCategory_Initialization, eDbgSeverity_High, eDbgSource_RuntimeWarning,
"Couldn't create FEATURE_LEVEL_11_0 device - RenderDoc requires FEATURE_LEVEL_11_0 "
"availability - falling back to WARP rasterizer.\n"
"Performance and usability will be significantly degraded.");
}
*driver = (IReplayDriver *)replay;
return eReplayCreate_Success;
}
if(i == -1)
{
RDCWARN("Couldn't create device with similar settings to capture.");
}
SAFE_RELEASE(device);
i++;
if(i >= numDrivers * 2)
break;
if(i >= 0)
initParams.DriverType = driverTypes[i / 2];
if(i % 2 == 0)
{
featureLevelArray = featureLevelArray11_1;
numFeatureLevels = numFeatureLevels11_1;
}
else
{
featureLevelArray = featureLevelArray11_0;
numFeatureLevels = numFeatureLevels11_0;
}
}
D3D11DebugManager::PostDeviceShutdownCounters();
RDCERR("Couldn't create any compatible d3d11 device :(.");
return eReplayCreate_APIHardwareUnsupported;
}
static DriverRegistration D3D11DriverRegistration(RDC_D3D11, "D3D11", &D3D11_CreateReplayDevice);