mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-05 06:11:05 +00:00
1248 lines
40 KiB
C++
1248 lines
40 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 "d3d12_common.h"
|
|
#include "driver/dxgi/dxgi_common.h"
|
|
#include "driver/dxgi/dxgi_wrapped.h"
|
|
#include "d3d12_manager.h"
|
|
#include "d3d12_resources.h"
|
|
|
|
D3D12MarkerRegion::D3D12MarkerRegion(ID3D12GraphicsCommandList *l, const rdcstr &marker)
|
|
{
|
|
list = l;
|
|
queue = NULL;
|
|
|
|
D3D12MarkerRegion::Begin(list, marker);
|
|
}
|
|
|
|
D3D12MarkerRegion::D3D12MarkerRegion(ID3D12CommandQueue *q, const rdcstr &marker)
|
|
{
|
|
list = NULL;
|
|
queue = q;
|
|
|
|
D3D12MarkerRegion::Begin(queue, marker);
|
|
}
|
|
|
|
D3D12MarkerRegion::~D3D12MarkerRegion()
|
|
{
|
|
if(list)
|
|
D3D12MarkerRegion::End(list);
|
|
if(queue)
|
|
D3D12MarkerRegion::End(queue);
|
|
}
|
|
|
|
void D3D12MarkerRegion::Begin(ID3D12GraphicsCommandList *list, const rdcstr &marker)
|
|
{
|
|
if(list)
|
|
{
|
|
// Some debuggers (but not all) will assume the event string is null-terminated, and
|
|
// display one less character than specified by the size. Append a space to pad the
|
|
// output without visibly changing the event marker for other debuggers.
|
|
rdcwstr text = StringFormat::UTF82Wide(marker + " ");
|
|
UINT size = UINT(text.length() * sizeof(wchar_t));
|
|
list->BeginEvent(0, text.c_str(), size);
|
|
}
|
|
}
|
|
|
|
void D3D12MarkerRegion::Begin(ID3D12CommandQueue *queue, const rdcstr &marker)
|
|
{
|
|
if(queue)
|
|
{
|
|
rdcwstr text = StringFormat::UTF82Wide(marker + " ");
|
|
UINT size = UINT(text.length() * sizeof(wchar_t));
|
|
queue->BeginEvent(0, text.c_str(), size);
|
|
}
|
|
}
|
|
|
|
void D3D12MarkerRegion::Set(ID3D12GraphicsCommandList *list, const rdcstr &marker)
|
|
{
|
|
if(list)
|
|
{
|
|
rdcwstr text = StringFormat::UTF82Wide(marker + " ");
|
|
UINT size = UINT(text.length() * sizeof(wchar_t));
|
|
list->SetMarker(0, text.c_str(), size);
|
|
}
|
|
}
|
|
|
|
void D3D12MarkerRegion::Set(ID3D12CommandQueue *queue, const rdcstr &marker)
|
|
{
|
|
if(queue)
|
|
{
|
|
rdcwstr text = StringFormat::UTF82Wide(marker + " ");
|
|
UINT size = UINT(text.length() * sizeof(wchar_t));
|
|
queue->SetMarker(0, text.c_str(), size);
|
|
}
|
|
}
|
|
|
|
void D3D12MarkerRegion::End(ID3D12GraphicsCommandList *list)
|
|
{
|
|
list->EndEvent();
|
|
}
|
|
|
|
void D3D12MarkerRegion::End(ID3D12CommandQueue *queue)
|
|
{
|
|
queue->EndEvent();
|
|
}
|
|
|
|
bool EnableD3D12DebugLayer(PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface)
|
|
{
|
|
if(!getDebugInterface)
|
|
getDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(GetModuleHandleA("d3d12.dll"),
|
|
"D3D12GetDebugInterface");
|
|
|
|
if(!getDebugInterface)
|
|
{
|
|
RDCERR("Couldn't find D3D12GetDebugInterface!");
|
|
return false;
|
|
}
|
|
|
|
ID3D12Debug *debug = NULL;
|
|
HRESULT hr = getDebugInterface(__uuidof(ID3D12Debug), (void **)&debug);
|
|
|
|
if(SUCCEEDED(hr) && debug)
|
|
{
|
|
debug->EnableDebugLayer();
|
|
|
|
RDCDEBUG("Enabling debug layer");
|
|
|
|
// enable this to get GPU-based validation, where available, whenever we enable API validation
|
|
#if 0
|
|
ID3D12Debug1 *debug1 = NULL;
|
|
hr = debug->QueryInterface(__uuidof(ID3D12Debug1), (void **)&debug1);
|
|
|
|
if(SUCCEEDED(hr) && debug1)
|
|
{
|
|
RDCDEBUG("Enabling GPU-based validation");
|
|
debug1->SetEnableGPUBasedValidation(true);
|
|
SAFE_RELEASE(debug1);
|
|
}
|
|
else
|
|
{
|
|
RDCDEBUG("GPU-based validation not available");
|
|
}
|
|
#endif
|
|
|
|
SAFE_RELEASE(debug);
|
|
|
|
return true;
|
|
}
|
|
else if(hr == DXGI_ERROR_SDK_COMPONENT_MISSING)
|
|
{
|
|
RDCWARN("Debug layer not available: DXGI_ERROR_SDK_COMPONENT_MISSING");
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Couldn't enable debug layer: %x", hr);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
HRESULT EnumAdapterByLuid(IDXGIFactory1 *factory, LUID luid, IDXGIAdapter **pAdapter)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
*pAdapter = NULL;
|
|
|
|
for(UINT i = 0; i < 10; i++)
|
|
{
|
|
IDXGIAdapter *adapter = NULL;
|
|
hr = factory->EnumAdapters(i, &adapter);
|
|
if(hr == S_OK && adapter)
|
|
{
|
|
DXGI_ADAPTER_DESC desc;
|
|
adapter->GetDesc(&desc);
|
|
|
|
if(desc.AdapterLuid.LowPart == luid.LowPart && desc.AdapterLuid.HighPart == luid.HighPart)
|
|
{
|
|
*pAdapter = adapter;
|
|
return S_OK;
|
|
}
|
|
|
|
adapter->Release();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
bool D3D12InitParams::IsSupportedVersion(uint64_t ver)
|
|
{
|
|
if(ver == CurrentVersion)
|
|
return true;
|
|
|
|
// 0x4 -> 0x5 - CPU_DESCRIPTOR_HANDLE serialised inline as D3D12Descriptor in appropriate
|
|
// list-recording functions
|
|
if(ver == 0x4)
|
|
return true;
|
|
|
|
// 0x5 -> 0x6 - Multiply by number of planes in format when serialising initial states -
|
|
// i.e. stencil is saved with depth in initial states.
|
|
if(ver == 0x5)
|
|
return true;
|
|
|
|
// 0x6 -> 0x7 - Fixed serialisation of D3D12_WRITEBUFFERIMMEDIATE_PARAMETER to properly replay the
|
|
// GPU address
|
|
if(ver == 0x6)
|
|
return true;
|
|
|
|
// 0x7 -> 0x8 - Added serialisation of adapter descriptor in D3D12InitParams
|
|
if(ver == 0x7)
|
|
return true;
|
|
|
|
// 0x8 -> 0x9 - Added serialisation of usedDXIL in D3D12InitParams
|
|
if(ver == 0x8)
|
|
return true;
|
|
|
|
// 0x9 -> 0xA - Added serialisation of vendor extension use in D3D12InitParams
|
|
if(ver == 0x9)
|
|
return true;
|
|
|
|
// 0xA -> 0xB - Added support for sparse/reserved/tiled resources
|
|
if(ver == 0x9)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
template <typename SerialiserType>
|
|
void DoSerialise(SerialiserType &ser, D3D12InitParams &el)
|
|
{
|
|
SERIALISE_MEMBER(MinimumFeatureLevel);
|
|
|
|
if(ser.VersionAtLeast(0x8))
|
|
{
|
|
SERIALISE_MEMBER(AdapterDesc);
|
|
}
|
|
else
|
|
{
|
|
RDCEraseEl(el.AdapterDesc);
|
|
}
|
|
|
|
if(ser.VersionAtLeast(0x9))
|
|
{
|
|
SERIALISE_MEMBER(usedDXIL);
|
|
}
|
|
|
|
if(ser.VersionAtLeast(0xA))
|
|
{
|
|
SERIALISE_MEMBER(VendorExtensions);
|
|
SERIALISE_MEMBER(VendorUAV);
|
|
SERIALISE_MEMBER(VendorUAVSpace);
|
|
}
|
|
else
|
|
{
|
|
el.VendorExtensions = GPUVendor::Unknown;
|
|
el.VendorUAV = ~0U;
|
|
el.VendorUAVSpace = ~0U;
|
|
}
|
|
}
|
|
|
|
INSTANTIATE_SERIALISE_TYPE(D3D12InitParams);
|
|
|
|
TextureType MakeTextureDim(D3D12_SRV_DIMENSION dim)
|
|
{
|
|
switch(dim)
|
|
{
|
|
case D3D12_SRV_DIMENSION_UNKNOWN: return TextureType::Unknown;
|
|
case D3D12_SRV_DIMENSION_BUFFER: return TextureType::Buffer;
|
|
case D3D12_SRV_DIMENSION_TEXTURE1D: return TextureType::Texture1D;
|
|
case D3D12_SRV_DIMENSION_TEXTURE1DARRAY: return TextureType::Texture1DArray;
|
|
case D3D12_SRV_DIMENSION_TEXTURE2D: return TextureType::Texture2D;
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: return TextureType::Texture2DArray;
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DMS: return TextureType::Texture2DMS;
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY: return TextureType::Texture2DMSArray;
|
|
case D3D12_SRV_DIMENSION_TEXTURE3D: return TextureType::Texture3D;
|
|
case D3D12_SRV_DIMENSION_TEXTURECUBE: return TextureType::TextureCube;
|
|
case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: return TextureType::TextureCubeArray;
|
|
default: break;
|
|
}
|
|
|
|
return TextureType::Unknown;
|
|
}
|
|
|
|
TextureType MakeTextureDim(D3D12_RTV_DIMENSION dim)
|
|
{
|
|
switch(dim)
|
|
{
|
|
case D3D12_RTV_DIMENSION_UNKNOWN: return TextureType::Unknown;
|
|
case D3D12_RTV_DIMENSION_BUFFER: return TextureType::Buffer;
|
|
case D3D12_RTV_DIMENSION_TEXTURE1D: return TextureType::Texture1D;
|
|
case D3D12_RTV_DIMENSION_TEXTURE1DARRAY: return TextureType::Texture1DArray;
|
|
case D3D12_RTV_DIMENSION_TEXTURE2D: return TextureType::Texture2D;
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DARRAY: return TextureType::Texture2DArray;
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DMS: return TextureType::Texture2DMS;
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY: return TextureType::Texture2DMSArray;
|
|
case D3D12_RTV_DIMENSION_TEXTURE3D: return TextureType::Texture3D;
|
|
default: break;
|
|
}
|
|
|
|
return TextureType::Unknown;
|
|
}
|
|
|
|
TextureType MakeTextureDim(D3D12_DSV_DIMENSION dim)
|
|
{
|
|
switch(dim)
|
|
{
|
|
case D3D12_DSV_DIMENSION_UNKNOWN: return TextureType::Unknown;
|
|
case D3D12_DSV_DIMENSION_TEXTURE1D: return TextureType::Texture1D;
|
|
case D3D12_DSV_DIMENSION_TEXTURE1DARRAY: return TextureType::Texture1DArray;
|
|
case D3D12_DSV_DIMENSION_TEXTURE2D: return TextureType::Texture2D;
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DARRAY: return TextureType::Texture2DArray;
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DMS: return TextureType::Texture2DMS;
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY: return TextureType::Texture2DMSArray;
|
|
default: break;
|
|
}
|
|
|
|
return TextureType::Unknown;
|
|
}
|
|
|
|
TextureType MakeTextureDim(D3D12_UAV_DIMENSION dim)
|
|
{
|
|
switch(dim)
|
|
{
|
|
case D3D12_UAV_DIMENSION_UNKNOWN: return TextureType::Unknown;
|
|
case D3D12_UAV_DIMENSION_BUFFER: return TextureType::Buffer;
|
|
case D3D12_UAV_DIMENSION_TEXTURE1D: return TextureType::Texture1D;
|
|
case D3D12_UAV_DIMENSION_TEXTURE1DARRAY: return TextureType::Texture1DArray;
|
|
case D3D12_UAV_DIMENSION_TEXTURE2D: return TextureType::Texture2D;
|
|
case D3D12_UAV_DIMENSION_TEXTURE2DARRAY: return TextureType::Texture2DArray;
|
|
case D3D12_UAV_DIMENSION_TEXTURE3D: return TextureType::Texture3D;
|
|
default: break;
|
|
}
|
|
|
|
return TextureType::Unknown;
|
|
}
|
|
|
|
AddressMode MakeAddressMode(D3D12_TEXTURE_ADDRESS_MODE addr)
|
|
{
|
|
switch(addr)
|
|
{
|
|
case D3D12_TEXTURE_ADDRESS_MODE_WRAP: return AddressMode::Wrap;
|
|
case D3D12_TEXTURE_ADDRESS_MODE_MIRROR: return AddressMode::Mirror;
|
|
case D3D12_TEXTURE_ADDRESS_MODE_CLAMP: return AddressMode::ClampEdge;
|
|
case D3D12_TEXTURE_ADDRESS_MODE_BORDER: return AddressMode::ClampBorder;
|
|
case D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE: return AddressMode::MirrorOnce;
|
|
default: break;
|
|
}
|
|
|
|
return AddressMode::Wrap;
|
|
}
|
|
|
|
CompareFunction MakeCompareFunc(D3D12_COMPARISON_FUNC func)
|
|
{
|
|
switch(func)
|
|
{
|
|
case D3D12_COMPARISON_FUNC_NEVER: return CompareFunction::Never;
|
|
case D3D12_COMPARISON_FUNC_LESS: return CompareFunction::Less;
|
|
case D3D12_COMPARISON_FUNC_EQUAL: return CompareFunction::Equal;
|
|
case D3D12_COMPARISON_FUNC_LESS_EQUAL: return CompareFunction::LessEqual;
|
|
case D3D12_COMPARISON_FUNC_GREATER: return CompareFunction::Greater;
|
|
case D3D12_COMPARISON_FUNC_NOT_EQUAL: return CompareFunction::NotEqual;
|
|
case D3D12_COMPARISON_FUNC_GREATER_EQUAL: return CompareFunction::GreaterEqual;
|
|
case D3D12_COMPARISON_FUNC_ALWAYS: return CompareFunction::AlwaysTrue;
|
|
default: break;
|
|
}
|
|
|
|
return CompareFunction::AlwaysTrue;
|
|
}
|
|
|
|
TextureFilter MakeFilter(D3D12_FILTER filter)
|
|
{
|
|
TextureFilter ret;
|
|
|
|
ret.filter = FilterFunction::Normal;
|
|
|
|
if(filter >= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT &&
|
|
filter <= D3D12_FILTER_COMPARISON_ANISOTROPIC)
|
|
{
|
|
ret.filter = FilterFunction::Comparison;
|
|
// the first 0x7f is the min/mag/mip filtering
|
|
filter = D3D12_FILTER(filter & 0x7f);
|
|
}
|
|
else if(filter >= D3D12_FILTER_MINIMUM_MIN_MAG_MIP_POINT &&
|
|
filter <= D3D12_FILTER_MINIMUM_ANISOTROPIC)
|
|
{
|
|
ret.filter = FilterFunction::Minimum;
|
|
// the first 0x7f is the min/mag/mip filtering
|
|
filter = D3D12_FILTER(filter & 0x7f);
|
|
}
|
|
else if(filter >= D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_POINT &&
|
|
filter <= D3D12_FILTER_MAXIMUM_ANISOTROPIC)
|
|
{
|
|
ret.filter = FilterFunction::Maximum;
|
|
// the first 0x7f is the min/mag/mip filtering
|
|
filter = D3D12_FILTER(filter & 0x7f);
|
|
}
|
|
|
|
switch(filter)
|
|
{
|
|
case D3D12_FILTER_ANISOTROPIC:
|
|
ret.minify = ret.magnify = ret.mip = FilterMode::Anisotropic;
|
|
break;
|
|
case D3D12_FILTER_MIN_MAG_MIP_POINT:
|
|
ret.minify = ret.magnify = ret.mip = FilterMode::Point;
|
|
break;
|
|
case D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR:
|
|
ret.minify = ret.magnify = FilterMode::Point;
|
|
ret.mip = FilterMode::Linear;
|
|
break;
|
|
case D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT:
|
|
ret.minify = FilterMode::Point;
|
|
ret.magnify = FilterMode::Linear;
|
|
ret.mip = FilterMode::Point;
|
|
break;
|
|
case D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR:
|
|
ret.minify = FilterMode::Point;
|
|
ret.magnify = ret.mip = FilterMode::Linear;
|
|
break;
|
|
case D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT:
|
|
ret.minify = FilterMode::Linear;
|
|
ret.magnify = ret.mip = FilterMode::Point;
|
|
break;
|
|
case D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
|
|
ret.minify = FilterMode::Linear;
|
|
ret.magnify = FilterMode::Point;
|
|
ret.mip = FilterMode::Linear;
|
|
break;
|
|
case D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT:
|
|
ret.minify = ret.magnify = FilterMode::Linear;
|
|
ret.mip = FilterMode::Point;
|
|
break;
|
|
case D3D12_FILTER_MIN_MAG_MIP_LINEAR:
|
|
ret.minify = ret.magnify = ret.mip = FilterMode::Linear;
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
D3DBufferViewFlags MakeBufferFlags(D3D12_BUFFER_SRV_FLAGS flags)
|
|
{
|
|
D3DBufferViewFlags ret = D3DBufferViewFlags::NoFlags;
|
|
|
|
if(flags & D3D12_BUFFER_SRV_FLAG_RAW)
|
|
ret |= D3DBufferViewFlags::Raw;
|
|
|
|
return ret;
|
|
}
|
|
|
|
D3DBufferViewFlags MakeBufferFlags(D3D12_BUFFER_UAV_FLAGS flags)
|
|
{
|
|
D3DBufferViewFlags ret = D3DBufferViewFlags::NoFlags;
|
|
|
|
if(flags & D3D12_BUFFER_UAV_FLAG_RAW)
|
|
ret |= D3DBufferViewFlags::Raw;
|
|
|
|
return ret;
|
|
}
|
|
|
|
LogicOperation MakeLogicOp(D3D12_LOGIC_OP op)
|
|
{
|
|
switch(op)
|
|
{
|
|
case D3D12_LOGIC_OP_CLEAR: return LogicOperation::Clear;
|
|
case D3D12_LOGIC_OP_AND: return LogicOperation::And;
|
|
case D3D12_LOGIC_OP_AND_REVERSE: return LogicOperation::AndReverse;
|
|
case D3D12_LOGIC_OP_COPY: return LogicOperation::Copy;
|
|
case D3D12_LOGIC_OP_AND_INVERTED: return LogicOperation::AndInverted;
|
|
case D3D12_LOGIC_OP_NOOP: return LogicOperation::NoOp;
|
|
case D3D12_LOGIC_OP_XOR: return LogicOperation::Xor;
|
|
case D3D12_LOGIC_OP_OR: return LogicOperation::Or;
|
|
case D3D12_LOGIC_OP_NOR: return LogicOperation::Nor;
|
|
case D3D12_LOGIC_OP_EQUIV: return LogicOperation::Equivalent;
|
|
case D3D12_LOGIC_OP_INVERT: return LogicOperation::Invert;
|
|
case D3D12_LOGIC_OP_OR_REVERSE: return LogicOperation::OrReverse;
|
|
case D3D12_LOGIC_OP_COPY_INVERTED: return LogicOperation::CopyInverted;
|
|
case D3D12_LOGIC_OP_OR_INVERTED: return LogicOperation::OrInverted;
|
|
case D3D12_LOGIC_OP_NAND: return LogicOperation::Nand;
|
|
case D3D12_LOGIC_OP_SET: return LogicOperation::Set;
|
|
default: break;
|
|
}
|
|
|
|
return LogicOperation::NoOp;
|
|
}
|
|
|
|
BlendMultiplier MakeBlendMultiplier(D3D12_BLEND blend, bool alpha)
|
|
{
|
|
switch(blend)
|
|
{
|
|
case D3D12_BLEND_ZERO: return BlendMultiplier::Zero;
|
|
case D3D12_BLEND_ONE: return BlendMultiplier::One;
|
|
case D3D12_BLEND_SRC_COLOR: return BlendMultiplier::SrcCol;
|
|
case D3D12_BLEND_INV_SRC_COLOR: return BlendMultiplier::InvSrcCol;
|
|
case D3D12_BLEND_DEST_COLOR: return BlendMultiplier::DstCol;
|
|
case D3D12_BLEND_INV_DEST_COLOR: return BlendMultiplier::InvDstCol;
|
|
case D3D12_BLEND_SRC_ALPHA: return BlendMultiplier::SrcAlpha;
|
|
case D3D12_BLEND_INV_SRC_ALPHA: return BlendMultiplier::InvSrcAlpha;
|
|
case D3D12_BLEND_DEST_ALPHA: return BlendMultiplier::DstAlpha;
|
|
case D3D12_BLEND_INV_DEST_ALPHA: return BlendMultiplier::InvDstAlpha;
|
|
case D3D12_BLEND_BLEND_FACTOR:
|
|
return alpha ? BlendMultiplier::FactorAlpha : BlendMultiplier::FactorRGB;
|
|
case D3D12_BLEND_INV_BLEND_FACTOR:
|
|
return alpha ? BlendMultiplier::InvFactorAlpha : BlendMultiplier::InvFactorRGB;
|
|
case D3D12_BLEND_SRC_ALPHA_SAT: return BlendMultiplier::SrcAlphaSat;
|
|
case D3D12_BLEND_SRC1_COLOR: return BlendMultiplier::Src1Col;
|
|
case D3D12_BLEND_INV_SRC1_COLOR: return BlendMultiplier::InvSrc1Col;
|
|
case D3D12_BLEND_SRC1_ALPHA: return BlendMultiplier::Src1Alpha;
|
|
case D3D12_BLEND_INV_SRC1_ALPHA: return BlendMultiplier::InvSrc1Alpha;
|
|
default: break;
|
|
}
|
|
|
|
return BlendMultiplier::One;
|
|
}
|
|
|
|
BlendOperation MakeBlendOp(D3D12_BLEND_OP op)
|
|
{
|
|
switch(op)
|
|
{
|
|
case D3D12_BLEND_OP_ADD: return BlendOperation::Add;
|
|
case D3D12_BLEND_OP_SUBTRACT: return BlendOperation::Subtract;
|
|
case D3D12_BLEND_OP_REV_SUBTRACT: return BlendOperation::ReversedSubtract;
|
|
case D3D12_BLEND_OP_MIN: return BlendOperation::Minimum;
|
|
case D3D12_BLEND_OP_MAX: return BlendOperation::Maximum;
|
|
default: break;
|
|
}
|
|
|
|
return BlendOperation::Add;
|
|
}
|
|
|
|
StencilOperation MakeStencilOp(D3D12_STENCIL_OP op)
|
|
{
|
|
switch(op)
|
|
{
|
|
case D3D12_STENCIL_OP_KEEP: return StencilOperation::Keep;
|
|
case D3D12_STENCIL_OP_ZERO: return StencilOperation::Zero;
|
|
case D3D12_STENCIL_OP_REPLACE: return StencilOperation::Replace;
|
|
case D3D12_STENCIL_OP_INCR_SAT: return StencilOperation::IncSat;
|
|
case D3D12_STENCIL_OP_DECR_SAT: return StencilOperation::DecSat;
|
|
case D3D12_STENCIL_OP_INVERT: return StencilOperation::Invert;
|
|
case D3D12_STENCIL_OP_INCR: return StencilOperation::IncWrap;
|
|
case D3D12_STENCIL_OP_DECR: return StencilOperation::DecWrap;
|
|
default: break;
|
|
}
|
|
|
|
return StencilOperation::Keep;
|
|
}
|
|
|
|
UINT GetResourceNumMipLevels(const D3D12_RESOURCE_DESC *desc)
|
|
{
|
|
switch(desc->Dimension)
|
|
{
|
|
default:
|
|
case D3D12_RESOURCE_DIMENSION_UNKNOWN:
|
|
RDCERR("Unexpected resource dimension! %d", desc->Dimension);
|
|
break;
|
|
case D3D12_RESOURCE_DIMENSION_BUFFER: return 1;
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
|
{
|
|
if(desc->MipLevels)
|
|
return desc->MipLevels;
|
|
UINT w = RDCMAX(1U, UINT(desc->Width));
|
|
UINT count = 1;
|
|
while(w > 1)
|
|
{
|
|
++count;
|
|
w = RDCMAX(1U, w >> 1U);
|
|
}
|
|
return count;
|
|
}
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
|
{
|
|
if(desc->MipLevels)
|
|
return desc->MipLevels;
|
|
UINT w = RDCMAX(1U, UINT(desc->Width));
|
|
UINT h = RDCMAX(1U, desc->Height);
|
|
UINT count = 1;
|
|
while(w > 1 || h > 1)
|
|
{
|
|
++count;
|
|
w = RDCMAX(1U, w >> 1U);
|
|
h = RDCMAX(1U, h >> 1U);
|
|
}
|
|
return count;
|
|
}
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
|
{
|
|
if(desc->MipLevels)
|
|
return desc->MipLevels;
|
|
UINT w = RDCMAX(1U, UINT(desc->Width));
|
|
UINT h = RDCMAX(1U, desc->Height);
|
|
UINT d = RDCMAX(1U, UINT(desc->DepthOrArraySize));
|
|
UINT count = 1;
|
|
while(w > 1 || h > 1 || d > 1)
|
|
{
|
|
++count;
|
|
w = RDCMAX(1U, w >> 1U);
|
|
h = RDCMAX(1U, h >> 1U);
|
|
d = RDCMAX(1U, d >> 1U);
|
|
}
|
|
return count;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
UINT GetNumSubresources(ID3D12Device *dev, const D3D12_RESOURCE_DESC *desc)
|
|
{
|
|
D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {};
|
|
formatInfo.Format = desc->Format;
|
|
dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo));
|
|
|
|
UINT planes = RDCMAX((UINT8)1, formatInfo.PlaneCount);
|
|
|
|
switch(desc->Dimension)
|
|
{
|
|
default:
|
|
case D3D12_RESOURCE_DIMENSION_UNKNOWN:
|
|
RDCERR("Unexpected resource dimension! %d", desc->Dimension);
|
|
break;
|
|
case D3D12_RESOURCE_DIMENSION_BUFFER: return planes;
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
|
return RDCMAX((UINT16)1, desc->DepthOrArraySize) * GetResourceNumMipLevels(desc) * planes;
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE3D: return GetResourceNumMipLevels(desc) * planes;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
ShaderStageMask ConvertVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility)
|
|
{
|
|
switch(ShaderVisibility)
|
|
{
|
|
case D3D12_SHADER_VISIBILITY_ALL: return ShaderStageMask::All;
|
|
case D3D12_SHADER_VISIBILITY_VERTEX: return ShaderStageMask::Vertex;
|
|
case D3D12_SHADER_VISIBILITY_HULL: return ShaderStageMask::Hull;
|
|
case D3D12_SHADER_VISIBILITY_DOMAIN: return ShaderStageMask::Domain;
|
|
case D3D12_SHADER_VISIBILITY_GEOMETRY: return ShaderStageMask::Geometry;
|
|
case D3D12_SHADER_VISIBILITY_PIXEL: return ShaderStageMask::Pixel;
|
|
case D3D12_SHADER_VISIBILITY_AMPLIFICATION:
|
|
case D3D12_SHADER_VISIBILITY_MESH:
|
|
default: RDCERR("Unexpected visibility %u", ShaderVisibility); break;
|
|
}
|
|
|
|
return ShaderStageMask::Unknown;
|
|
}
|
|
|
|
// from PIXEventsCommon.h of winpixeventruntime
|
|
enum PIXEventType
|
|
{
|
|
ePIXEvent_EndEvent = 0x000,
|
|
ePIXEvent_BeginEvent_VarArgs = 0x001,
|
|
ePIXEvent_BeginEvent_NoArgs = 0x002,
|
|
ePIXEvent_SetMarker_VarArgs = 0x007,
|
|
ePIXEvent_SetMarker_NoArgs = 0x008,
|
|
|
|
ePIXEvent_EndEvent_OnContext = 0x010,
|
|
ePIXEvent_BeginEvent_OnContext_VarArgs = 0x011,
|
|
ePIXEvent_BeginEvent_OnContext_NoArgs = 0x012,
|
|
ePIXEvent_SetMarker_OnContext_VarArgs = 0x017,
|
|
ePIXEvent_SetMarker_OnContext_NoArgs = 0x018,
|
|
};
|
|
|
|
inline void PIX3DecodeEventInfo(const UINT64 BlobData, UINT64 &Timestamp, PIXEventType &EventType)
|
|
{
|
|
static const UINT64 PIXEventsBlockEndMarker = 0x00000000000FFF80;
|
|
|
|
static const UINT64 PIXEventsTypeReadMask = 0x00000000000FFC00;
|
|
static const UINT64 PIXEventsTypeWriteMask = 0x00000000000003FF;
|
|
static const UINT64 PIXEventsTypeBitShift = 10;
|
|
|
|
static const UINT64 PIXEventsTimestampReadMask = 0xFFFFFFFFFFF00000;
|
|
static const UINT64 PIXEventsTimestampWriteMask = 0x00000FFFFFFFFFFF;
|
|
static const UINT64 PIXEventsTimestampBitShift = 20;
|
|
|
|
Timestamp = (BlobData >> PIXEventsTimestampBitShift) & PIXEventsTimestampWriteMask;
|
|
EventType = PIXEventType((BlobData >> PIXEventsTypeBitShift) & PIXEventsTypeWriteMask);
|
|
}
|
|
|
|
inline void PIX3DecodeStringInfo(const UINT64 BlobData, UINT64 &Alignment, UINT64 &CopyChunkSize,
|
|
bool &IsANSI, bool &IsShortcut)
|
|
{
|
|
static const UINT64 PIXEventsStringAlignmentWriteMask = 0x000000000000000F;
|
|
static const UINT64 PIXEventsStringAlignmentReadMask = 0xF000000000000000;
|
|
static const UINT64 PIXEventsStringAlignmentBitShift = 60;
|
|
|
|
static const UINT64 PIXEventsStringCopyChunkSizeWriteMask = 0x000000000000001F;
|
|
static const UINT64 PIXEventsStringCopyChunkSizeReadMask = 0x0F80000000000000;
|
|
static const UINT64 PIXEventsStringCopyChunkSizeBitShift = 55;
|
|
|
|
static const UINT64 PIXEventsStringIsANSIWriteMask = 0x0000000000000001;
|
|
static const UINT64 PIXEventsStringIsANSIReadMask = 0x0040000000000000;
|
|
static const UINT64 PIXEventsStringIsANSIBitShift = 54;
|
|
|
|
static const UINT64 PIXEventsStringIsShortcutWriteMask = 0x0000000000000001;
|
|
static const UINT64 PIXEventsStringIsShortcutReadMask = 0x0020000000000000;
|
|
static const UINT64 PIXEventsStringIsShortcutBitShift = 53;
|
|
|
|
Alignment = (BlobData >> PIXEventsStringAlignmentBitShift) & PIXEventsStringAlignmentWriteMask;
|
|
CopyChunkSize =
|
|
(BlobData >> PIXEventsStringCopyChunkSizeBitShift) & PIXEventsStringCopyChunkSizeWriteMask;
|
|
IsANSI = (BlobData >> PIXEventsStringIsANSIBitShift) & PIXEventsStringIsANSIWriteMask;
|
|
IsShortcut = (BlobData >> PIXEventsStringIsShortcutBitShift) & PIXEventsStringIsShortcutWriteMask;
|
|
}
|
|
|
|
const UINT64 *PIX3DecodeStringParam(const UINT64 *pData, rdcstr &DecodedString)
|
|
{
|
|
UINT64 alignment;
|
|
UINT64 copyChunkSize;
|
|
bool isANSI;
|
|
bool isShortcut;
|
|
PIX3DecodeStringInfo(*pData, alignment, copyChunkSize, isANSI, isShortcut);
|
|
++pData;
|
|
|
|
UINT totalStringBytes = 0;
|
|
if(isANSI)
|
|
{
|
|
const char *c = (const char *)pData;
|
|
UINT formatStringCharCount = UINT(strlen((const char *)pData));
|
|
DecodedString = rdcstr(c, formatStringCharCount);
|
|
totalStringBytes = formatStringCharCount + 1;
|
|
}
|
|
else
|
|
{
|
|
const wchar_t *w = (const wchar_t *)pData;
|
|
UINT formatStringCharCount = UINT(wcslen((const wchar_t *)pData));
|
|
DecodedString = StringFormat::Wide2UTF8(rdcwstr(w, formatStringCharCount));
|
|
totalStringBytes = (formatStringCharCount + 1) * sizeof(wchar_t);
|
|
}
|
|
|
|
UINT64 byteChunks = ((totalStringBytes + copyChunkSize - 1) / copyChunkSize) * copyChunkSize;
|
|
UINT64 stringQWordCount = (byteChunks + 7) / 8;
|
|
pData += stringQWordCount;
|
|
|
|
return pData;
|
|
}
|
|
|
|
rdcstr PIX3SprintfParams(const rdcstr &Format, const UINT64 *pData)
|
|
{
|
|
rdcstr finalString;
|
|
rdcstr formatPart;
|
|
int32_t lastFind = 0;
|
|
|
|
for(int32_t found = Format.indexOf('%'); found >= 0;)
|
|
{
|
|
finalString += Format.substr(lastFind, found - lastFind);
|
|
|
|
int32_t endOfFormat = Format.find_first_of("%diufFeEgGxXoscpaAn", found + 1);
|
|
if(endOfFormat < 0)
|
|
{
|
|
finalString += "<FORMAT_ERROR>";
|
|
break;
|
|
}
|
|
|
|
formatPart = Format.substr(found, (endOfFormat - found) + 1);
|
|
|
|
// strings
|
|
if(formatPart.back() == 's')
|
|
{
|
|
rdcstr stringParam;
|
|
pData = PIX3DecodeStringParam(pData, stringParam);
|
|
finalString += stringParam;
|
|
}
|
|
// numerical values
|
|
else
|
|
{
|
|
finalString += StringFormat::Fmt(formatPart.c_str(), *pData);
|
|
++pData;
|
|
}
|
|
|
|
lastFind = endOfFormat + 1;
|
|
found = Format.indexOf('%', lastFind);
|
|
}
|
|
|
|
finalString += Format.substr(lastFind);
|
|
|
|
return finalString;
|
|
}
|
|
|
|
rdcstr PIX3DecodeEventString(const UINT64 *pData)
|
|
{
|
|
// event header
|
|
UINT64 timestamp;
|
|
PIXEventType eventType;
|
|
PIX3DecodeEventInfo(*pData, timestamp, eventType);
|
|
++pData;
|
|
|
|
// convert setmarker event types to beginevent event types because they're identical and it makes
|
|
// for easier processing.
|
|
if(eventType == ePIXEvent_SetMarker_NoArgs)
|
|
eventType = ePIXEvent_BeginEvent_NoArgs;
|
|
|
|
if(eventType == ePIXEvent_SetMarker_VarArgs)
|
|
eventType = ePIXEvent_BeginEvent_VarArgs;
|
|
|
|
if(eventType != ePIXEvent_BeginEvent_NoArgs && eventType != ePIXEvent_BeginEvent_VarArgs)
|
|
{
|
|
RDCERR("Unexpected/unsupported PIX3Event %u type in PIXDecodeMarkerEventString", eventType);
|
|
return "";
|
|
}
|
|
|
|
// color
|
|
// UINT64 color = *pData;
|
|
++pData;
|
|
|
|
// format string
|
|
rdcstr formatString;
|
|
pData = PIX3DecodeStringParam(pData, formatString);
|
|
|
|
if(eventType == ePIXEvent_BeginEvent_NoArgs)
|
|
return formatString;
|
|
|
|
// sprintf remaining args
|
|
formatString = PIX3SprintfParams(formatString, pData);
|
|
return formatString;
|
|
}
|
|
|
|
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC::D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC(
|
|
const D3D12_GRAPHICS_PIPELINE_STATE_DESC &graphics)
|
|
{
|
|
pRootSignature = graphics.pRootSignature;
|
|
VS = graphics.VS;
|
|
PS = graphics.PS;
|
|
DS = graphics.DS;
|
|
HS = graphics.HS;
|
|
GS = graphics.GS;
|
|
StreamOutput = graphics.StreamOutput;
|
|
BlendState = graphics.BlendState;
|
|
SampleMask = graphics.SampleMask;
|
|
RasterizerState = graphics.RasterizerState;
|
|
{
|
|
DepthStencilState.DepthEnable = graphics.DepthStencilState.DepthEnable;
|
|
DepthStencilState.DepthWriteMask = graphics.DepthStencilState.DepthWriteMask;
|
|
DepthStencilState.DepthFunc = graphics.DepthStencilState.DepthFunc;
|
|
DepthStencilState.StencilEnable = graphics.DepthStencilState.StencilEnable;
|
|
DepthStencilState.StencilReadMask = graphics.DepthStencilState.StencilReadMask;
|
|
DepthStencilState.StencilWriteMask = graphics.DepthStencilState.StencilWriteMask;
|
|
DepthStencilState.FrontFace = graphics.DepthStencilState.FrontFace;
|
|
DepthStencilState.BackFace = graphics.DepthStencilState.BackFace;
|
|
|
|
// DepthBounds defaults to disabled
|
|
DepthStencilState.DepthBoundsTestEnable = FALSE;
|
|
}
|
|
InputLayout = graphics.InputLayout;
|
|
IBStripCutValue = graphics.IBStripCutValue;
|
|
PrimitiveTopologyType = graphics.PrimitiveTopologyType;
|
|
RTVFormats.NumRenderTargets = graphics.NumRenderTargets;
|
|
memcpy(RTVFormats.RTFormats, graphics.RTVFormats, 8 * sizeof(DXGI_FORMAT));
|
|
DSVFormat = graphics.DSVFormat;
|
|
SampleDesc = graphics.SampleDesc;
|
|
NodeMask = graphics.NodeMask;
|
|
CachedPSO = graphics.CachedPSO;
|
|
Flags = graphics.Flags;
|
|
|
|
// default state
|
|
ViewInstancing.Flags = D3D12_VIEW_INSTANCING_FLAG_NONE;
|
|
ViewInstancing.pViewInstanceLocations = NULL;
|
|
ViewInstancing.ViewInstanceCount = 0;
|
|
}
|
|
|
|
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC::D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC(
|
|
const D3D12_COMPUTE_PIPELINE_STATE_DESC &compute)
|
|
{
|
|
pRootSignature = compute.pRootSignature;
|
|
CS = compute.CS;
|
|
NodeMask = compute.NodeMask;
|
|
CachedPSO = compute.CachedPSO;
|
|
Flags = compute.Flags;
|
|
}
|
|
|
|
// this awkward construction is to account for UINT and pointer aligned data on both 32-bit and
|
|
// 64-bit.
|
|
struct D3D12_PSO_SUBOBJECT
|
|
{
|
|
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE type;
|
|
};
|
|
|
|
struct D3D12_U32_PSO_SUBOBJECT
|
|
{
|
|
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE type;
|
|
|
|
union U32Data
|
|
{
|
|
UINT SampleMask;
|
|
DXGI_FORMAT DSVFormat;
|
|
UINT NodeMask;
|
|
D3D12_BLEND_DESC BlendState;
|
|
D3D12_RASTERIZER_DESC RasterizerState;
|
|
D3D12_DEPTH_STENCIL_DESC DepthStencilState;
|
|
D3D12_DEPTH_STENCIL_DESC1 DepthStencilState1;
|
|
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue;
|
|
D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;
|
|
D3D12_RT_FORMAT_ARRAY RTVFormats;
|
|
DXGI_SAMPLE_DESC SampleDesc;
|
|
D3D12_PIPELINE_STATE_FLAGS Flags;
|
|
} data;
|
|
};
|
|
|
|
struct D3D12_PTR_PSO_SUBOBJECT
|
|
{
|
|
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE type;
|
|
|
|
#if ENABLED(RDOC_X64)
|
|
UINT padding;
|
|
#endif
|
|
|
|
union PTRData
|
|
{
|
|
ID3D12RootSignature *pRootSignature;
|
|
D3D12_SHADER_BYTECODE shader;
|
|
D3D12_STREAM_OUTPUT_DESC StreamOutput;
|
|
D3D12_INPUT_LAYOUT_DESC InputLayout;
|
|
D3D12_CACHED_PIPELINE_STATE CachedPSO;
|
|
D3D12_VIEW_INSTANCING_DESC ViewInstancing;
|
|
} data;
|
|
};
|
|
|
|
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC::D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC(
|
|
const D3D12_PIPELINE_STATE_STREAM_DESC &stream)
|
|
{
|
|
// ensure data is naturally aligned.
|
|
RDCCOMPILE_ASSERT(offsetof(D3D12_U32_PSO_SUBOBJECT, data.SampleMask) == 4,
|
|
"D3D12_U32_PSO_SUBOBJECT UINT data is misaligned");
|
|
RDCCOMPILE_ASSERT(offsetof(D3D12_PTR_PSO_SUBOBJECT, data.pRootSignature) == sizeof(void *),
|
|
"D3D12_PTR_PSO_SUBOBJECT Pointer data is misaligned");
|
|
RDCCOMPILE_ASSERT(offsetof(D3D12_PSO_SUBOBJECT, type) == 0,
|
|
"D3D12_PSO_SUBOBJECT type member is misaligned");
|
|
RDCCOMPILE_ASSERT(offsetof(D3D12_U32_PSO_SUBOBJECT, type) == 0,
|
|
"D3D12_U32_PSO_SUBOBJECT type member is misaligned");
|
|
RDCCOMPILE_ASSERT(offsetof(D3D12_PTR_PSO_SUBOBJECT, type) == 0,
|
|
"D3D12_PTR_PSO_SUBOBJECT type member is misaligned");
|
|
|
|
// first set default state
|
|
pRootSignature = NULL;
|
|
RDCEraseEl(VS);
|
|
RDCEraseEl(HS);
|
|
RDCEraseEl(DS);
|
|
RDCEraseEl(GS);
|
|
RDCEraseEl(PS);
|
|
RDCEraseEl(CS);
|
|
NodeMask = 0;
|
|
RDCEraseEl(CachedPSO);
|
|
Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
|
|
SampleMask = ~0U;
|
|
RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
|
RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
|
|
RasterizerState.FrontCounterClockwise = FALSE;
|
|
RasterizerState.DepthBias = 0;
|
|
RasterizerState.DepthBiasClamp = 0.0f;
|
|
RasterizerState.SlopeScaledDepthBias = 0.0f;
|
|
RasterizerState.DepthClipEnable = TRUE;
|
|
RasterizerState.MultisampleEnable = FALSE;
|
|
RasterizerState.AntialiasedLineEnable = FALSE;
|
|
RasterizerState.ForcedSampleCount = 0;
|
|
RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
|
|
|
RDCEraseEl(StreamOutput);
|
|
|
|
BlendState.AlphaToCoverageEnable = FALSE;
|
|
BlendState.IndependentBlendEnable = FALSE;
|
|
|
|
for(int i = 0; i < 8; i++)
|
|
{
|
|
BlendState.RenderTarget[i].BlendEnable = FALSE;
|
|
BlendState.RenderTarget[i].LogicOpEnable = FALSE;
|
|
BlendState.RenderTarget[i].SrcBlend = D3D12_BLEND_ONE;
|
|
BlendState.RenderTarget[i].DestBlend = D3D12_BLEND_ZERO;
|
|
BlendState.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD;
|
|
BlendState.RenderTarget[i].SrcBlendAlpha = D3D12_BLEND_ONE;
|
|
BlendState.RenderTarget[i].DestBlendAlpha = D3D12_BLEND_ZERO;
|
|
BlendState.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP;
|
|
BlendState.RenderTarget[i].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
|
}
|
|
|
|
{
|
|
DepthStencilState.DepthEnable = TRUE;
|
|
DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
|
DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
|
|
DepthStencilState.StencilEnable = FALSE;
|
|
DepthStencilState.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
|
|
DepthStencilState.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
|
|
DepthStencilState.FrontFace.StencilFunc = DepthStencilState.BackFace.StencilFunc =
|
|
D3D12_COMPARISON_FUNC_ALWAYS;
|
|
DepthStencilState.FrontFace.StencilDepthFailOp = DepthStencilState.BackFace.StencilDepthFailOp =
|
|
D3D12_STENCIL_OP_KEEP;
|
|
DepthStencilState.FrontFace.StencilPassOp = DepthStencilState.BackFace.StencilPassOp =
|
|
D3D12_STENCIL_OP_KEEP;
|
|
DepthStencilState.FrontFace.StencilFailOp = DepthStencilState.BackFace.StencilFailOp =
|
|
D3D12_STENCIL_OP_KEEP;
|
|
|
|
// DepthBounds defaults to disabled
|
|
DepthStencilState.DepthBoundsTestEnable = FALSE;
|
|
}
|
|
|
|
RDCEraseEl(InputLayout);
|
|
IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
|
|
PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED;
|
|
RDCEraseEl(RTVFormats);
|
|
DSVFormat = DXGI_FORMAT_UNKNOWN;
|
|
SampleDesc.Count = 1;
|
|
SampleDesc.Quality = 0;
|
|
|
|
ViewInstancing.Flags = D3D12_VIEW_INSTANCING_FLAG_NONE;
|
|
ViewInstancing.pViewInstanceLocations = NULL;
|
|
ViewInstancing.ViewInstanceCount = 0;
|
|
|
|
#define ITER_ADV(objtype) \
|
|
iter = iter + sizeof(obj->type); \
|
|
iter = AlignUpPtr(iter, alignof(objtype)); \
|
|
iter += sizeof(objtype);
|
|
|
|
byte *iter = (byte *)stream.pPipelineStateSubobjectStream;
|
|
byte *end = iter + stream.SizeInBytes;
|
|
while(iter < end)
|
|
{
|
|
D3D12_PSO_SUBOBJECT *obj = (D3D12_PSO_SUBOBJECT *)iter;
|
|
D3D12_U32_PSO_SUBOBJECT *u32 = (D3D12_U32_PSO_SUBOBJECT *)obj;
|
|
D3D12_PTR_PSO_SUBOBJECT *ptr = (D3D12_PTR_PSO_SUBOBJECT *)obj;
|
|
switch(obj->type)
|
|
{
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE:
|
|
{
|
|
pRootSignature = ptr->data.pRootSignature;
|
|
ITER_ADV(ID3D12RootSignature *);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS:
|
|
{
|
|
VS = ptr->data.shader;
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS:
|
|
{
|
|
PS = ptr->data.shader;
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS:
|
|
{
|
|
HS = ptr->data.shader;
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS:
|
|
{
|
|
DS = ptr->data.shader;
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS:
|
|
{
|
|
GS = ptr->data.shader;
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS:
|
|
{
|
|
CS = ptr->data.shader;
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT:
|
|
{
|
|
StreamOutput = ptr->data.StreamOutput;
|
|
ITER_ADV(D3D12_STREAM_OUTPUT_DESC);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND:
|
|
{
|
|
BlendState = u32->data.BlendState;
|
|
ITER_ADV(D3D12_BLEND_DESC);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK:
|
|
{
|
|
SampleMask = u32->data.SampleMask;
|
|
ITER_ADV(UINT);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER:
|
|
{
|
|
RasterizerState = u32->data.RasterizerState;
|
|
ITER_ADV(D3D12_RASTERIZER_DESC);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL:
|
|
{
|
|
const D3D12_DEPTH_STENCIL_DESC &dsdesc = u32->data.DepthStencilState;
|
|
DepthStencilState.DepthEnable = dsdesc.DepthEnable;
|
|
DepthStencilState.DepthWriteMask = dsdesc.DepthWriteMask;
|
|
DepthStencilState.DepthFunc = dsdesc.DepthFunc;
|
|
DepthStencilState.StencilEnable = dsdesc.StencilEnable;
|
|
DepthStencilState.StencilReadMask = dsdesc.StencilReadMask;
|
|
DepthStencilState.StencilWriteMask = dsdesc.StencilWriteMask;
|
|
DepthStencilState.FrontFace = dsdesc.FrontFace;
|
|
DepthStencilState.BackFace = dsdesc.BackFace;
|
|
ITER_ADV(D3D12_DEPTH_STENCIL_DESC);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT:
|
|
{
|
|
InputLayout = ptr->data.InputLayout;
|
|
ITER_ADV(D3D12_INPUT_LAYOUT_DESC);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE:
|
|
{
|
|
IBStripCutValue = u32->data.IBStripCutValue;
|
|
ITER_ADV(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY:
|
|
{
|
|
PrimitiveTopologyType = u32->data.PrimitiveTopologyType;
|
|
ITER_ADV(D3D12_PRIMITIVE_TOPOLOGY_TYPE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS:
|
|
{
|
|
RTVFormats = u32->data.RTVFormats;
|
|
ITER_ADV(D3D12_RT_FORMAT_ARRAY);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT:
|
|
{
|
|
DSVFormat = u32->data.DSVFormat;
|
|
ITER_ADV(DXGI_FORMAT);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC:
|
|
{
|
|
SampleDesc = u32->data.SampleDesc;
|
|
ITER_ADV(DXGI_SAMPLE_DESC);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK:
|
|
{
|
|
NodeMask = u32->data.NodeMask;
|
|
ITER_ADV(UINT);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO:
|
|
{
|
|
CachedPSO = ptr->data.CachedPSO;
|
|
ITER_ADV(D3D12_CACHED_PIPELINE_STATE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS:
|
|
{
|
|
Flags = u32->data.Flags;
|
|
ITER_ADV(D3D12_PIPELINE_STATE_FLAGS);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1:
|
|
{
|
|
DepthStencilState = u32->data.DepthStencilState1;
|
|
ITER_ADV(D3D12_DEPTH_STENCIL_DESC1);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING:
|
|
{
|
|
ViewInstancing = ptr->data.ViewInstancing;
|
|
ITER_ADV(D3D12_VIEW_INSTANCING_DESC);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS:
|
|
{
|
|
if(ptr->data.shader.BytecodeLength > 0)
|
|
{
|
|
RDCERR("AS passed to D3D12_PIPELINE_STATE_STREAM_DESC but mesh shaders not supported");
|
|
errored = true;
|
|
}
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS:
|
|
{
|
|
if(ptr->data.shader.BytecodeLength > 0)
|
|
{
|
|
RDCERR("MS passed to D3D12_PIPELINE_STATE_STREAM_DESC but mesh shaders not supported");
|
|
errored = true;
|
|
}
|
|
ITER_ADV(D3D12_SHADER_BYTECODE);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
RDCERR("Unknown subobject type %d", obj->type);
|
|
break;
|
|
}
|
|
}
|
|
iter = AlignUpPtr(iter, sizeof(void *));
|
|
}
|
|
}
|
|
|
|
void D3D12_PACKED_PIPELINE_STATE_STREAM_DESC::Unwrap()
|
|
{
|
|
m_GraphicsStreamData.pRootSignature = ::Unwrap(m_GraphicsStreamData.pRootSignature);
|
|
m_ComputeStreamData.pRootSignature = ::Unwrap(m_ComputeStreamData.pRootSignature);
|
|
}
|
|
|
|
D3D12_PACKED_PIPELINE_STATE_STREAM_DESC &D3D12_PACKED_PIPELINE_STATE_STREAM_DESC::operator=(
|
|
const D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &expanded)
|
|
{
|
|
if(expanded.CS.BytecodeLength > 0)
|
|
{
|
|
m_ComputeStreamData.pRootSignature = expanded.pRootSignature;
|
|
m_ComputeStreamData.CS = expanded.CS;
|
|
m_ComputeStreamData.NodeMask = expanded.NodeMask;
|
|
m_ComputeStreamData.CachedPSO = expanded.CachedPSO;
|
|
m_ComputeStreamData.Flags = expanded.Flags;
|
|
}
|
|
else
|
|
{
|
|
m_GraphicsStreamData.pRootSignature = expanded.pRootSignature;
|
|
m_GraphicsStreamData.VS = expanded.VS;
|
|
m_GraphicsStreamData.PS = expanded.PS;
|
|
m_GraphicsStreamData.DS = expanded.DS;
|
|
m_GraphicsStreamData.HS = expanded.HS;
|
|
m_GraphicsStreamData.GS = expanded.GS;
|
|
m_GraphicsStreamData.StreamOutput = expanded.StreamOutput;
|
|
m_GraphicsStreamData.BlendState = expanded.BlendState;
|
|
m_GraphicsStreamData.SampleMask = expanded.SampleMask;
|
|
m_GraphicsStreamData.RasterizerState = expanded.RasterizerState;
|
|
m_GraphicsStreamData.DepthStencilState = expanded.DepthStencilState;
|
|
m_GraphicsStreamData.InputLayout = expanded.InputLayout;
|
|
m_GraphicsStreamData.IBStripCutValue = expanded.IBStripCutValue;
|
|
m_GraphicsStreamData.PrimitiveTopologyType = expanded.PrimitiveTopologyType;
|
|
m_GraphicsStreamData.RTVFormats = expanded.RTVFormats;
|
|
m_GraphicsStreamData.DSVFormat = expanded.DSVFormat;
|
|
m_GraphicsStreamData.SampleDesc = expanded.SampleDesc;
|
|
m_GraphicsStreamData.NodeMask = expanded.NodeMask;
|
|
m_GraphicsStreamData.CachedPSO = expanded.CachedPSO;
|
|
m_GraphicsStreamData.Flags = expanded.Flags;
|
|
m_GraphicsStreamData.ViewInstancing = expanded.ViewInstancing;
|
|
}
|
|
|
|
return *this;
|
|
}
|