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 _ => 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 var desc = new D3D12_RENDER_PASS_DEPTH_STENCIL_DESC
{ {
cpuDescriptor = cpuHandle, 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 resourceDesc = pResource->GetDesc();
var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC 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 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) switch (resourceDesc.Dimension)
{ {
case D3D12_RESOURCE_DIMENSION_TEXTURE1D: case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
@@ -251,7 +260,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator
return rtvDesc; 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 resourceDesc = pResource->GetDesc();
var dsvDesc = new D3D12_DEPTH_STENCIL_VIEW_DESC var dsvDesc = new D3D12_DEPTH_STENCIL_VIEW_DESC
@@ -276,7 +285,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator
break; break;
} }
dsvDesc.Format = resourceDesc.Format; dsvDesc.Format = originalFormat == TextureFormat.Unknown ? resourceDesc.Format : originalFormat.ToDXGIFormat();
var isArray = var isArray =
dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DARRAY || dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DARRAY ||
@@ -644,7 +653,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv); var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv);
var isCubeMap = desc.Dimension == TextureDimension.TextureCube || desc.Dimension == TextureDimension.TextureCubeArray; 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); _device.NativeObject.Get()->CreateShaderResourceView(pResource, &srvDesc, cpuHandle);
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.srv); _descriptorAllocator.CopyToShaderVisible(resourceDescriptor.srv);
@@ -663,7 +672,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
{ {
resourceDescriptor.dsv = _descriptorAllocator.AllocateDSV(); resourceDescriptor.dsv = _descriptorAllocator.AllocateDSV();
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.dsv); 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); _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.R32G32B32A32_Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT_D24_UNORM_S8_UINT, TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT_D24_UNORM_S8_UINT,
TextureFormat.D32_Float => DXGI_FORMAT_D32_FLOAT, 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."), _ => 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_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float,
DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt, DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt,
DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float, 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.") _ => 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) public static D3D12_RESOURCE_DESC ToD3D12ResourceDesc(this in TextureDesc desc)
{ {
var dxgiFormat = desc.Format.ToDXGIFormat(); 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 maxDimension = Math.Max(desc.Width, Math.Max(desc.Height, desc.Slice));
var mipLevels = desc.MipLevels == 0 var mipLevels = desc.MipLevels == 0
? (ushort)(1 + Math.Floor(Math.Log2(maxDimension))) ? (ushort)(1 + Math.Floor(Math.Log2(maxDimension)))

View File

@@ -454,6 +454,10 @@ public struct PassDepthStencilDesc
get; set; get; set;
} }
public bool HasStencil
{
get; set;
}
} }
@@ -1287,7 +1291,10 @@ public enum TextureFormat
R16G16B16A16_Float, R16G16B16A16_Float,
R32G32B32A32_Float, R32G32B32A32_Float,
D24_UNorm_S8_UInt, D24_UNorm_S8_UInt,
D32_Float D32_Float,
R32_Typeless,
R24G8_Typeless,
} }
[Flags] [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(); ThrowIfDisposed();

View File

@@ -144,11 +144,13 @@ internal sealed class RenderGraphExecutor
? nativePass.depthAttachment.storeOp ? nativePass.depthAttachment.storeOp
: AttachmentStoreOp.DontCare, : AttachmentStoreOp.DontCare,
StencilLoadOp = nativePass.hasDepthAttachment StencilLoadOp = nativePass.hasDepthAttachment
? nativePass.depthAttachment.loadOp ? nativePass.depthAttachment.stencilLoadOp
: AttachmentLoadOp.DontCare, : AttachmentLoadOp.DontCare,
StencilStoreOp = nativePass.hasDepthAttachment StencilStoreOp = nativePass.hasDepthAttachment
? nativePass.depthAttachment.storeOp ? nativePass.depthAttachment.stencilStoreOp
: AttachmentStoreOp.DontCare : 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); commandBuffer.BeginRenderPass(new Span<PassRenderTargetDesc>(pPassRTDescs, nativePass.colorAttachmentCount), depthDesc);

View File

@@ -365,6 +365,18 @@ internal sealed class RenderGraphNativePassBuilder
attachment.storeOp = AttachmentStoreOp.Store; 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 AccessFlags access;
public AttachmentLoadOp loadOp; public AttachmentLoadOp loadOp;
public AttachmentStoreOp storeOp; public AttachmentStoreOp storeOp;
public AttachmentLoadOp stencilLoadOp;
public AttachmentStoreOp stencilStoreOp;
public float clearDepth; public float clearDepth;
public byte clearStencil; public byte clearStencil;
} }