Fixed bugs in rendering.

This commit is contained in:
2025-11-12 20:31:37 +09:00
parent 6cf2e35a9b
commit 708b8cd065
18 changed files with 102 additions and 90 deletions

View File

@@ -6,12 +6,7 @@ using TerraFX.Interop.Windows;
namespace Ghost.Core.Utilities;
internal static partial class Win32Utility
{
public const string OS_SUPPORTED_VERSION = "windows10.0.19041.0";
}
[SupportedOSPlatform(OS_SUPPORTED_VERSION)]
[SupportedOSPlatform("windows10.0.19041.0")]
internal static unsafe partial class Win32Utility
{
[EditorBrowsable(EditorBrowsableState.Never)]

View File

@@ -6,7 +6,7 @@ namespace Ghost.Entities.Query;
public struct QueryFilter : IDisposable
{
private readonly Stack.Scope _scope;
//private readonly Stack.Scope _scope;
internal UnsafeList<TypeHandle> _all;
internal UnsafeList<TypeHandle> _any;
@@ -15,7 +15,7 @@ public struct QueryFilter : IDisposable
public QueryFilter()
{
_scope = AllocationManager.CreateStackScope();
//_scope = AllocationManager.CreateStackScope();
_all = new UnsafeList<TypeHandle>(4, Allocator.Stack);
_any = new UnsafeList<TypeHandle>(4, Allocator.Stack);
@@ -92,6 +92,6 @@ public struct QueryFilter : IDisposable
public readonly void Dispose()
{
_scope.Dispose();
//_scope.Dispose();
}
}

View File

@@ -2,6 +2,7 @@ using Ghost.Graphics.Test.Windows;
using Microsoft.UI.Xaml;
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
using System.Runtime.InteropServices;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
@@ -23,12 +24,31 @@ public partial class UnitTestApp : Application
InitializeComponent();
}
private static void LoadDll()
{
var currentDir = AppContext.BaseDirectory;
var platform = OperatingSystem.IsWindows() ? "win" :
OperatingSystem.IsLinux() ? "linux" :
OperatingSystem.IsMacOS() ? "osx" : "unknown";
var arch = Environment.Is64BitProcess ? "x64" : "x86";
var nativeDllDir = Path.Combine(currentDir, "runtime", platform + "-" + arch, "native");
if (Directory.Exists(nativeDllDir))
{
foreach (var dll in Directory.EnumerateFiles(nativeDllDir, "*.dll"))
{
NativeLibrary.Load(dll);
}
}
}
/// <summary>
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
LoadDll();
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
_window = new GraphicsTestWindow();

View File

@@ -4,11 +4,15 @@ global using static TerraFX.Interop.DirectX.DXGI;
global using static TerraFX.Interop.Windows.Windows;
using Ghost.Core.Attributes;
using Ghost.Core.Utilities;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
[assembly: InternalsVisibleTo("Ghost.Engine")]
[assembly: InternalsVisibleTo("Ghost.Editor")]
[assembly: InternalsVisibleTo("Ghost.Editor.Core")]
[assembly: InternalsVisibleTo("Ghost.Graphics.Test")]
[assembly: SupportedOSPlatform("windows10.0.19041.0")]
[assembly: EngineAssembly]

View File

@@ -1,12 +1,10 @@
using Ghost.Core;
using Ghost.Core.Graphics;
using Ghost.Core.Utilities;
using Ghost.Graphics.Core;
using Ghost.Graphics.D3D12.Utilities;
using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows;
using static TerraFX.Aliases.D3D_Alias;
@@ -15,7 +13,6 @@ using static TerraFX.Aliases.DXGI_Alias;
namespace Ghost.Graphics.D3D12;
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal unsafe class D3D12CommandBuffer : ICommandBuffer
{
private ComPtr<ID3D12CommandAllocator> _allocator;

View File

@@ -49,6 +49,8 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
CommandBufferType.Copy);
_renderers = ImmutableArray<IRenderer>.Empty;
_pipelineLibrary.InitializeLibrary(null);
}
~D3D12GraphicsEngine()
@@ -59,10 +61,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(D3D12GraphicsEngine));
}
ObjectDisposedException.ThrowIf(_disposed, this);
}
public IRenderer CreateRenderer()

View File

@@ -9,7 +9,6 @@ using Misaki.HighPerformance.LowLevel.Utilities;
using Misaki.HighPerformance.Utilities;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows;
@@ -32,7 +31,6 @@ internal struct D3D12GraphicsCompiledResult : IDisposable
}
}
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal struct D3D12PipelineState : IDisposable
{
// NOTE: This is just a temporary cache for compiled shader code. We will implement a proper disk cache later.
@@ -47,10 +45,9 @@ internal struct D3D12PipelineState : IDisposable
}
}
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
{
private const int _ROOT_PARAM_COUNT =
private const int rootParamCount =
#if USE_TRADITIONAL_BINDLESS
6
#else
@@ -83,7 +80,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
_defaultRootSignature = default;
// NOTE: Since we are targeting SM 6.6, we can use ResourceDescriptorHeap and SamplerDescriptorHeap directly without needing to set up viewGroup tables.
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[_ROOT_PARAM_COUNT];
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[rootParamCount];
rootParameters[0] = new D3D12_ROOT_PARAMETER1
{
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
@@ -146,7 +143,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1
{
NumParameters = _ROOT_PARAM_COUNT,
NumParameters = rootParamCount,
pParameters = rootParameters,
NumStaticSamplers = 0,
pStaticSamplers = null,
@@ -180,7 +177,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
_defaultRootSignature.Attach(pRootSignature);
}
public void LoadLibraryFromDisk(string? filePath)
public void InitializeLibrary(string? filePath)
{
ID3D12PipelineLibrary1* pLibrary = default;
@@ -219,9 +216,9 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
private static void ValidateReflectionData(ShaderReflectionData reflectionData)
{
if (reflectionData.ConstantBuffers.Count != _ROOT_PARAM_COUNT)
if (reflectionData.ConstantBuffers.Count != rootParamCount)
{
throw new InvalidOperationException($"Shader reflection data has {reflectionData.ConstantBuffers.Count} constant buffers, expected {_ROOT_PARAM_COUNT}");
throw new InvalidOperationException($"Shader reflection data has {reflectionData.ConstantBuffers.Count} constant buffers, expected {rootParamCount}");
}
if (reflectionData.OtherResources.Count != 0)
@@ -240,13 +237,16 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
try
{
// TODO: This does not include generated code. This will cause a root signature mismatch.
var result = D3D12ShaderCompiler.Compile(ref config, Allocator.Persistent, &reflectionBlob).GetValueOrThrow();
#if false
if (reflectionBlob != null)
{
var reflection = D3D12ShaderCompiler.PerformDXCReflection(reflectionBlob).GetValueOrThrow();
ValidateReflectionData(reflection);
}
#endif
return result;
}
@@ -415,15 +415,16 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
existing.compileResult = compiled;
existing.psoDesc = desc;
var meshStream = new CD3DX12_PIPELINE_MESH_STATE_STREAM(in desc);
var streamDesc = new D3D12_PIPELINE_STATE_STREAM_DESC
{
pPipelineStateSubobjectStream = &desc,
SizeInBytes = (nuint)sizeof(D3DX12_MESH_SHADER_PIPELINE_STATE_DESC)
pPipelineStateSubobjectStream = &meshStream,
SizeInBytes = (nuint)sizeof(CD3DX12_PIPELINE_MESH_STATE_STREAM)
};
ID3D12PipelineState* pPipelineState = default;
char* pKeyStr = stackalloc char[GraphicsPipelineKey.KEY_STRING_LENGTH];
var pKeyStr = stackalloc char[GraphicsPipelineKey.KEY_STRING_LENGTH];
var keySpan = new Span<char>(pKeyStr, GraphicsPipelineKey.KEY_STRING_LENGTH);
key.GetString(keySpan).ThrowIfFailed();

View File

@@ -11,7 +11,6 @@ namespace Ghost.Graphics.D3D12;
/// <summary>
/// D3D12 implementation of the render device interface
/// </summary>
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal unsafe class D3D12RenderDevice : IRenderDevice
{
private ComPtr<IDXGIFactory7> _dxgiFactory;

View File

@@ -6,7 +6,6 @@ using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.Mathematics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows;
using static TerraFX.Aliases.D3D12_Alias;
@@ -16,8 +15,7 @@ using static TerraFX.Interop.DirectX.D3D12MemAlloc;
namespace Ghost.Graphics.D3D12;
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal unsafe sealed partial class D3D12ResourceAllocator
internal sealed unsafe partial class D3D12ResourceAllocator
{
// NOTE: _MAX_BYTES may not be accurate, we need to verify it with feature level checks.
private const uint _MAX_BYTES = D3D12_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM * 1024u * 1024u;
@@ -593,7 +591,7 @@ internal unsafe sealed partial class D3D12ResourceAllocator
// TODO: Thread safety for resource allocator
// A common solution is to use ticket. Each allocation request create a ticket and put it into a thread-safe queue. A dedicated thread process the queue and fulfill the requests.
internal unsafe sealed partial class D3D12ResourceAllocator : IResourceAllocator, IDisposable
internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator, IDisposable
{
private readonly IFenceSynchronizer _fenceSynchronizer;
private readonly D3D12RenderDevice _device;

View File

@@ -1,5 +1,4 @@
using Ghost.Core;
using Ghost.Core.Utilities;
using Ghost.Graphics.Core;
using Ghost.Graphics.RHI;
using Misaki.HighPerformance.Collections;
@@ -7,13 +6,11 @@ using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows;
namespace Ghost.Graphics.D3D12;
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
{
internal unsafe struct ResourceRecord
@@ -100,8 +97,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
private readonly Dictionary<Handle<GPUResource>, string> _resourceName;
#endif
private readonly UnsafeSlotMap<Mesh> _meshes;
private readonly UnsafeSlotMap<Material> _materials;
private UnsafeSlotMap<Mesh> _meshes;
private UnsafeSlotMap<Material> _materials;
private readonly DynamicArray<Shader?> _shaders; // NOTE: We use a simple list since shader is not frequently added/removed. This can save 4 bytes for each ecs component.
private readonly Dictionary<ShaderPassKey, ShaderPass> _shaderPasses; // NOTE: The reason we use Dictionary here is that ShaderPassKey is a presistence identifier across multiple application sessions.

View File

@@ -3,7 +3,6 @@ using Ghost.Core.Utilities;
using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX;
@@ -11,7 +10,7 @@ using TerraFX.Interop.Windows;
namespace Ghost.Graphics.D3D12;
internal unsafe struct CompileResult : IDisposable
internal struct CompileResult : IDisposable
{
public UnsafeArray<byte> bytecode;
@@ -120,7 +119,6 @@ internal readonly struct ShaderReflectionData
}
}
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal static unsafe class D3D12ShaderCompiler
{
private static string GetProfileString(ShaderStage stage, CompilerTier version)
@@ -209,8 +207,8 @@ internal static unsafe class D3D12ShaderCompiler
var dxccID = CLSID.CLSID_DxcCompiler;
var dxcuID = CLSID.CLSID_DxcUtils;
ThrowIfFailed(DxcCreateInstance(&dxccID, pCompiler->IID(), (void**)&pCompiler));
ThrowIfFailed(DxcCreateInstance(&dxcuID, pUtils->IID(), (void**)&pUtils));
ThrowIfFailed(DxcCreateInstance(&dxccID, __uuidof(pCompiler), (void**)&pCompiler));
ThrowIfFailed(DxcCreateInstance(&dxcuID, __uuidof(pUtils), (void**)&pUtils));
//pIncludeHandler.Get()->LoadSource();
pUtils->CreateDefaultIncludeHandler(&pIncludeHandler);
@@ -244,7 +242,7 @@ internal static unsafe class D3D12ShaderCompiler
Encoding = DXC.DXC_CP_UTF8
};
ThrowIfFailed(pCompiler->Compile(&buffer, argPtrs, (uint)argsArray.Count, pIncludeHandler, pResult->IID(), (void**)&pResult));
ThrowIfFailed(pCompiler->Compile(&buffer, argPtrs, (uint)argsArray.Count, pIncludeHandler, __uuidof(pResult), (void**)&pResult));
// Check compilation pResult
HRESULT hrStatus;
@@ -257,7 +255,7 @@ internal static unsafe class D3D12ShaderCompiler
if (errorBlob.Get() != null)
{
var errorMessage = Marshal.PtrToStringUni((IntPtr)errorBlob.Get()->GetBufferPointer());
var errorMessage = Marshal.PtrToStringUTF8((IntPtr)errorBlob.Get()->GetBufferPointer());
return Result.Fail($"DXC shader compilation failed:\n{errorMessage}");
}
else

View File

@@ -2,6 +2,7 @@ using Ghost.Graphics.RHI;
using TerraFX.Interop.DirectX;
using static TerraFX.Aliases.D3D12_Alias;
using static TerraFX.Aliases.DXGI_Alias;
namespace Ghost.Graphics.D3D12.Utilities;
@@ -31,12 +32,13 @@ internal unsafe static class D3D12Utility
{
return format switch
{
TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM,
TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM,
TextureFormat.R16G16B16A16_Float => DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT,
TextureFormat.R32G32B32A32_Float => DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT,
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT,
TextureFormat.D32_Float => DXGI_FORMAT.DXGI_FORMAT_D32_FLOAT,
TextureFormat.Unknown => DXGI_FORMAT_UNKNOWN,
TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT_R8G8B8A8_UNORM,
TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT_B8G8R8A8_UNORM,
TextureFormat.R16G16B16A16_Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
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,
_ => throw new NotSupportedException($"Texture format {format} is not supported."),
};
}
@@ -45,12 +47,12 @@ internal unsafe static class D3D12Utility
{
return format switch
{
DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM => TextureFormat.R8G8B8A8_UNorm,
DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM => TextureFormat.B8G8R8A8_UNorm,
DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT => TextureFormat.R16G16B16A16_Float,
DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float,
DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt,
DXGI_FORMAT.DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float,
DXGI_FORMAT_R8G8B8A8_UNORM => TextureFormat.R8G8B8A8_UNorm,
DXGI_FORMAT_B8G8R8A8_UNORM => TextureFormat.B8G8R8A8_UNorm,
DXGI_FORMAT_R16G16B16A16_FLOAT => TextureFormat.R16G16B16A16_Float,
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,
_ => TextureFormat.Unknown,
};
}
@@ -59,16 +61,16 @@ internal unsafe static class D3D12Utility
{
return state switch
{
ResourceState.Common or ResourceState.Present => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON,
ResourceState.VertexAndConstantBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
ResourceState.IndexBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_INDEX_BUFFER,
ResourceState.RenderTarget => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_RENDER_TARGET,
ResourceState.UnorderedAccess => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
ResourceState.DepthWrite => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_WRITE,
ResourceState.DepthRead => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_READ,
ResourceState.PixelShaderResource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
ResourceState.CopyDest => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
ResourceState.CopySource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE,
ResourceState.Common or ResourceState.Present => D3D12_RESOURCE_STATE_COMMON,
ResourceState.VertexAndConstantBuffer => D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
ResourceState.IndexBuffer => D3D12_RESOURCE_STATE_INDEX_BUFFER,
ResourceState.RenderTarget => D3D12_RESOURCE_STATE_RENDER_TARGET,
ResourceState.UnorderedAccess => D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
ResourceState.DepthWrite => D3D12_RESOURCE_STATE_DEPTH_WRITE,
ResourceState.DepthRead => D3D12_RESOURCE_STATE_DEPTH_READ,
ResourceState.PixelShaderResource => D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
ResourceState.CopyDest => D3D12_RESOURCE_STATE_COPY_DEST,
ResourceState.CopySource => D3D12_RESOURCE_STATE_COPY_SOURCE,
_ => throw new ArgumentException($"Unknown resource state: {state}")
};
}

View File

@@ -16,6 +16,20 @@
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<None Remove="runtime\win-x64\native\dxcompiler.dll" />
<None Remove="runtime\win-x64\native\dxil.dll" />
</ItemGroup>
<ItemGroup>
<Content Include="runtime\win-x64\native\dxcompiler.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="runtime\win-x64\native\dxil.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Misaki.HighPerformance.Image" Version="1.0.0" />
<PackageReference Include="TerraFX.Interop.D3D12MemoryAllocator" Version="2.0.1.5" />

View File

@@ -19,7 +19,7 @@ public interface IPipelineLibrary
/// Load pipeline library from disk.
/// </summary>
/// <param name="filePath">File path. If null, load default library.</param>
void LoadLibraryFromDisk(string? filePath);
void InitializeLibrary(string? filePath);
void SaveLibraryToDisk(string filePath);
GraphicsPipelineKey CompilePassPSO(IPassDescriptor descriptor, ReadOnlySpan<TextureFormat> rtvs, TextureFormat dsv);
}

View File

@@ -28,7 +28,7 @@ internal unsafe class MeshRenderPass : IRenderPass
public void Initialize(ref readonly RenderingContext ctx)
{
var shaderDescriptor = SDLCompiler.CompileShader("F:\\csharp\\GhostEngine\\Ghost.Graphics\\RenderPasses\\ShaderCode.hlsl").GetValueOrThrow();
var shaderDescriptor = SDLCompiler.CompileShader("F:\\csharp\\GhostEngine\\Ghost.Graphics\\test.gshader").GetValueOrThrow();
var key = ctx.PipelineLibrary.CompilePassPSO(shaderDescriptor.passes[0], [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown);

View File

@@ -1,4 +1,4 @@
cbuffer ConstantBuffer : register(b0)
cbuffer ConstantBuffer : register(b0)
{
float4 _Color;
uint _TextureIndex1;
@@ -9,9 +9,6 @@
uint _IndexBufferIndex;
};
// SM 6.6 approach - direct access to global descriptor heap
SamplerState _MainSampler : register(s0);
struct Vertex
{
float4 position;
@@ -54,6 +51,8 @@ void MSMain(
v.color = asfloat(vertexBuffer.Load4(vertexOffset + 48));
v.uv = asfloat(vertexBuffer.Load4(vertexOffset + 64));
SetMeshOutputCounts(3, 1);
// Write vertex output
outVerts[vertexId].position = v.position;
outVerts[vertexId].color = v.color;
@@ -62,28 +61,17 @@ void MSMain(
// Thread 0 defines topology
if (vertexId == 0)
{
SetMeshOutputCounts(3, 1);
outTris[0] = uint3(0, 1, 2);
}
}
float4 PSMain(PixelInput input) : SV_TARGET
{
// SM 6.6 Modern Bindless Approach:
// ResourceDescriptorHeap[index] directly accesses any texture in the heap
Texture2D tex1 = ResourceDescriptorHeap[_TextureIndex1];
Texture2D tex2 = ResourceDescriptorHeap[_TextureIndex2];
Texture2D tex3 = ResourceDescriptorHeap[_TextureIndex3];
Texture2D tex4 = ResourceDescriptorHeap[_TextureIndex4];
float4 color1 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex1, 0, input.uv.xy);
float4 color2 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex2, 0, input.uv.xy);
float4 color3 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex3, 0, input.uv.xy);
float4 color4 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex4, 0, input.uv.xy);
// Sample the textures
float4 color1 = tex1.Sample(_MainSampler, input.uv.xy);
float4 color2 = tex2.Sample(_MainSampler, input.uv.xy);
float4 color3 = tex3.Sample(_MainSampler, input.uv.xy);
float4 color4 = tex4.Sample(_MainSampler, input.uv.xy);
// Blend all textures together (simple average)
float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
return blendedColor * _Color;
}

Binary file not shown.

Binary file not shown.