Fix D3D12 depth format and stencil barrier issues in Render Graph

This commit is contained in:
2026-04-01 15:28:25 +09:00
parent a00cb27529
commit 3157596b5d
8 changed files with 65 additions and 10 deletions

View File

@@ -537,6 +537,12 @@ internal unsafe class D3D12CommandBuffer : D3D12Object<ID3D12GraphicsCommandList
_ => D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE
};
if (!depthDesc.HasStencil)
{
stencilLoadAccessType = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS;
stencilStoreAccessType = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS;
}
var desc = new D3D12_RENDER_PASS_DEPTH_STENCIL_DESC
{
cpuDescriptor = cpuHandle,

View File

@@ -39,7 +39,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator
}
}
private static D3D12_SHADER_RESOURCE_VIEW_DESC CreateTextureSrvDesc(ID3D12Resource* pResource, uint mipLevels, uint arraySize, bool isCubeMap)
private static D3D12_SHADER_RESOURCE_VIEW_DESC CreateTextureSrvDesc(ID3D12Resource* pResource, uint mipLevels, uint arraySize, bool isCubeMap, TextureFormat originalFormat)
{
var resourceDesc = pResource->GetDesc();
var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC
@@ -48,6 +48,15 @@ internal sealed unsafe partial class D3D12ResourceAllocator
Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING
};
if (originalFormat == TextureFormat.D32_Float)
{
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
}
else if (originalFormat == TextureFormat.D24_UNorm_S8_UInt)
{
srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
}
switch (resourceDesc.Dimension)
{
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
@@ -251,7 +260,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator
return rtvDesc;
}
private static D3D12_DEPTH_STENCIL_VIEW_DESC CreateDsvDesc(ID3D12Resource* pResource, uint mipSlice = 0, uint firstArraySlice = 0, D3D12_DSV_FLAGS flags = D3D12_DSV_FLAG_NONE)
private static D3D12_DEPTH_STENCIL_VIEW_DESC CreateDsvDesc(ID3D12Resource* pResource, uint mipSlice = 0, uint firstArraySlice = 0, D3D12_DSV_FLAGS flags = D3D12_DSV_FLAG_NONE, TextureFormat originalFormat = TextureFormat.Unknown)
{
var resourceDesc = pResource->GetDesc();
var dsvDesc = new D3D12_DEPTH_STENCIL_VIEW_DESC
@@ -276,7 +285,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator
break;
}
dsvDesc.Format = resourceDesc.Format;
dsvDesc.Format = originalFormat == TextureFormat.Unknown ? resourceDesc.Format : originalFormat.ToDXGIFormat();
var isArray =
dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DARRAY ||
@@ -644,7 +653,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv);
var isCubeMap = desc.Dimension == TextureDimension.TextureCube || desc.Dimension == TextureDimension.TextureCubeArray;
var srvDesc = CreateTextureSrvDesc(pResource, resourceDesc.MipLevels, resourceDesc.DepthOrArraySize, isCubeMap);
var srvDesc = CreateTextureSrvDesc(pResource, resourceDesc.MipLevels, resourceDesc.DepthOrArraySize, isCubeMap, desc.Format);
_device.NativeObject.Get()->CreateShaderResourceView(pResource, &srvDesc, cpuHandle);
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.srv);
@@ -663,7 +672,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
{
resourceDescriptor.dsv = _descriptorAllocator.AllocateDSV();
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.dsv);
var dsvDesc = CreateDsvDesc(pResource);
var dsvDesc = CreateDsvDesc(pResource, 0, 0, D3D12_DSV_FLAG_NONE, desc.Format);
_device.NativeObject.Get()->CreateDepthStencilView(pResource, &dsvDesc, cpuHandle);
}

View File

@@ -140,6 +140,8 @@ internal static unsafe class D3D12Utility
TextureFormat.R32G32B32A32_Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT_D24_UNORM_S8_UINT,
TextureFormat.D32_Float => DXGI_FORMAT_D32_FLOAT,
TextureFormat.R32_Typeless => DXGI_FORMAT_R32_TYPELESS,
TextureFormat.R24G8_Typeless => DXGI_FORMAT_R24G8_TYPELESS,
_ => throw new NotSupportedException($"Texture format {format} is not supported."),
};
}
@@ -154,6 +156,8 @@ internal static unsafe class D3D12Utility
DXGI_FORMAT_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float,
DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt,
DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float,
DXGI_FORMAT_R32_TYPELESS => TextureFormat.R32_Typeless,
DXGI_FORMAT_R24G8_TYPELESS => TextureFormat.R24G8_Typeless,
_ => throw new NotSupportedException($"DXGI format {format} is not supported.")
};
}
@@ -385,6 +389,19 @@ internal static unsafe class D3D12Utility
public static D3D12_RESOURCE_DESC ToD3D12ResourceDesc(this in TextureDesc desc)
{
var dxgiFormat = desc.Format.ToDXGIFormat();
if (desc.Usage.HasFlag(TextureUsage.DepthStencil) && desc.Usage.HasFlag(TextureUsage.ShaderResource))
{
if (dxgiFormat == DXGI_FORMAT_D32_FLOAT)
{
dxgiFormat = DXGI_FORMAT_R32_TYPELESS;
}
else if (dxgiFormat == DXGI_FORMAT_D24_UNORM_S8_UINT)
{
dxgiFormat = DXGI_FORMAT_R24G8_TYPELESS;
}
}
var maxDimension = Math.Max(desc.Width, Math.Max(desc.Height, desc.Slice));
var mipLevels = desc.MipLevels == 0
? (ushort)(1 + Math.Floor(Math.Log2(maxDimension)))

View File

@@ -454,6 +454,10 @@ public struct PassDepthStencilDesc
get; set;
}
public bool HasStencil
{
get; set;
}
}
@@ -1287,7 +1291,10 @@ public enum TextureFormat
R16G16B16A16_Float,
R32G32B32A32_Float,
D24_UNorm_S8_UInt,
D32_Float
D32_Float,
R32_Typeless,
R24G8_Typeless,
}
[Flags]

View File

@@ -294,7 +294,7 @@ internal class RenderGraphBuilder : IRasterRenderGraphBuilder, IComputeRenderGra
}
}
public void SetDepthAttachment(Identifier<RGTexture> texture, AccessFlags flags = AccessFlags.ReadWrite)
public void SetDepthAttachment(Identifier<RGTexture> texture, AccessFlags flags = AccessFlags.WriteAll)
{
ThrowIfDisposed();

View File

@@ -144,11 +144,13 @@ internal sealed class RenderGraphExecutor
? nativePass.depthAttachment.storeOp
: AttachmentStoreOp.DontCare,
StencilLoadOp = nativePass.hasDepthAttachment
? nativePass.depthAttachment.loadOp
? nativePass.depthAttachment.stencilLoadOp
: AttachmentLoadOp.DontCare,
StencilStoreOp = nativePass.hasDepthAttachment
? nativePass.depthAttachment.storeOp
: AttachmentStoreOp.DontCare
? nativePass.depthAttachment.stencilStoreOp
: AttachmentStoreOp.DontCare,
HasStencil = nativePass.hasDepthAttachment &&
(_resources.GetResource(nativePass.depthAttachment.texture).rgTextureDesc.format == TextureFormat.D24_UNorm_S8_UInt)
};
commandBuffer.BeginRenderPass(new Span<PassRenderTargetDesc>(pPassRTDescs, nativePass.colorAttachmentCount), depthDesc);

View File

@@ -365,6 +365,18 @@ internal sealed class RenderGraphNativePassBuilder
attachment.storeOp = AttachmentStoreOp.Store;
}
var hasStencil = resource.rgTextureDesc.format == TextureFormat.D24_UNorm_S8_UInt;
if (hasStencil)
{
attachment.stencilLoadOp = attachment.loadOp;
attachment.stencilStoreOp = attachment.storeOp;
}
else
{
attachment.stencilLoadOp = AttachmentLoadOp.DontCare;
attachment.stencilStoreOp = AttachmentStoreOp.DontCare;
}
}
}
}

View File

@@ -384,6 +384,8 @@ internal struct DepthStencilInfo
public AccessFlags access;
public AttachmentLoadOp loadOp;
public AttachmentStoreOp storeOp;
public AttachmentLoadOp stencilLoadOp;
public AttachmentStoreOp stencilStoreOp;
public float clearDepth;
public byte clearStencil;
}