[ShaderCompiler] Reserve portable buffer descriptor words in the binding layout
This commit is contained in:
parent
2e507d4e08
commit
b8d86c27bf
|
|
@ -336,11 +336,14 @@ public sealed class BindingLayout : IEquatable<BindingLayout>
|
|||
public uint ShaderBaseDword { get; init; } = NoShaderBase;
|
||||
public uint MemoryOffsetDword { get; init; }
|
||||
public uint MemoryOffsetCount { get; init; }
|
||||
public uint BufferWordCount { get; init; }
|
||||
public bool UsesDispatchThreadLimits { get; init; }
|
||||
public IReadOnlyList<uint> UserDataRegisters { get; init; } = [];
|
||||
public IReadOnlyList<DescriptorBinding> Descriptors { get; init; } = [];
|
||||
|
||||
public uint DispatchThreadLimitsDword => MemoryOffsetDword + (MemoryOffsetCount + 3) / 4;
|
||||
public uint BufferWordDword => MemoryOffsetDword + (MemoryOffsetCount + 3) / 4;
|
||||
|
||||
public uint DispatchThreadLimitsDword => BufferWordDword + BufferWordCount;
|
||||
|
||||
public uint ShaderDataDwordCount => DispatchThreadLimitsDword + (UsesDispatchThreadLimits ? 3u : 0u);
|
||||
|
||||
|
|
@ -561,12 +564,14 @@ public sealed class BindingLayout : IEquatable<BindingLayout>
|
|||
bool usesFlattenedTable,
|
||||
bool usesShaderBase,
|
||||
uint pushDataStartDword = 0,
|
||||
bool usesDispatchThreadLimits = false)
|
||||
bool usesDispatchThreadLimits = false,
|
||||
bool portableBuffers = false)
|
||||
{
|
||||
var shaderBaseDword = usesShaderBase ? (uint)userDataRegisters.Count : NoShaderBase;
|
||||
var memoryOffsetDword = (uint)userDataRegisters.Count + (usesShaderBase ? ShaderBaseDwordCount : 0);
|
||||
var memoryOffsetCount = (uint)info.Buffers.Count;
|
||||
var shaderDataDwords = memoryOffsetDword + (memoryOffsetCount + 3) / 4 + (usesDispatchThreadLimits ? 3u : 0u);
|
||||
var bufferWordCount = portableBuffers ? memoryOffsetCount * PortableBufferWord.DwordCount : 0;
|
||||
var shaderDataDwords = memoryOffsetDword + (memoryOffsetCount + 3) / 4 + bufferWordCount + (usesDispatchThreadLimits ? 3u : 0u);
|
||||
var pushStart = PushData.StartFor(pushDataStartDword, shaderDataDwords);
|
||||
var descriptors = new List<DescriptorBinding>();
|
||||
if (info.Buffers.Count != 0)
|
||||
|
|
@ -643,6 +648,7 @@ public sealed class BindingLayout : IEquatable<BindingLayout>
|
|||
ShaderBaseDword = shaderBaseDword,
|
||||
MemoryOffsetDword = memoryOffsetDword,
|
||||
MemoryOffsetCount = memoryOffsetCount,
|
||||
BufferWordCount = bufferWordCount,
|
||||
UsesDispatchThreadLimits = usesDispatchThreadLimits,
|
||||
UserDataRegisters = userDataRegisters,
|
||||
Descriptors = descriptors,
|
||||
|
|
@ -656,6 +662,7 @@ public sealed class BindingLayout : IEquatable<BindingLayout>
|
|||
ShaderBaseDword == other.ShaderBaseDword &&
|
||||
MemoryOffsetDword == other.MemoryOffsetDword &&
|
||||
MemoryOffsetCount == other.MemoryOffsetCount &&
|
||||
BufferWordCount == other.BufferWordCount &&
|
||||
UsesDispatchThreadLimits == other.UsesDispatchThreadLimits &&
|
||||
UserDataRegisters.SequenceEqual(other.UserDataRegisters) &&
|
||||
Descriptors.Count == other.Descriptors.Count &&
|
||||
|
|
@ -663,7 +670,7 @@ public sealed class BindingLayout : IEquatable<BindingLayout>
|
|||
|
||||
public override bool Equals(object? obj) => Equals(obj as BindingLayout);
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(PushDataStartDword, MemoryOffsetDword, MemoryOffsetCount, Descriptors.Count, UsesDispatchThreadLimits);
|
||||
public override int GetHashCode() => HashCode.Combine(PushDataStartDword, MemoryOffsetDword, MemoryOffsetCount, BufferWordCount, Descriptors.Count, UsesDispatchThreadLimits);
|
||||
}
|
||||
|
||||
// Recomputes the layout an emitter was given from the same inputs and the same push
|
||||
|
|
@ -685,7 +692,8 @@ public static class BindingLayoutValidator
|
|||
throw new ResourcePlanException("Only a compute shader can use dispatch thread limits.");
|
||||
}
|
||||
|
||||
var expected = BindingLayout.Allocate(info, userDataRegisters, usesGlobalDataShare, usesFlattenedTable, usesShaderBase, layout.AllocationCursor, layout.UsesDispatchThreadLimits);
|
||||
var expected = BindingLayout.Allocate(info, userDataRegisters, usesGlobalDataShare, usesFlattenedTable, usesShaderBase,
|
||||
layout.AllocationCursor, layout.UsesDispatchThreadLimits, portableBuffers: layout.BufferWordCount != 0);
|
||||
if (!expected.Equals(layout))
|
||||
{
|
||||
throw new ResourcePlanException(
|
||||
|
|
@ -696,6 +704,7 @@ public static class BindingLayoutValidator
|
|||
|
||||
private static string Describe(BindingLayout layout) =>
|
||||
$"push={layout.PushDataStartDword} base={layout.ShaderBaseDword} offsets={layout.MemoryOffsetDword}+{layout.MemoryOffsetCount} " +
|
||||
$"words={layout.BufferWordCount} " +
|
||||
$"user=[{string.Join(",", layout.UserDataRegisters)}] " +
|
||||
string.Join(" ", layout.Descriptors.Select(binding => $"{binding.Kind}:{string.Join(",", binding.Resources)}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
namespace SharpEmu.ShaderCompiler.Resources;
|
||||
|
||||
public static class PortableBufferWord
|
||||
{
|
||||
public const int DwordCount = 2;
|
||||
public const uint StrideMask = 0x3FFF;
|
||||
|
||||
public static bool ReadsFormatAtRuntime(BufferResource buffer) => buffer.Formatted && !buffer.Written;
|
||||
|
||||
public static (uint Stride, uint DescriptorWord3) Pack(ReadOnlySpan<uint> descriptor)
|
||||
{
|
||||
if (descriptor.Length != 4 || (descriptor[3] >> 30) != 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return ((descriptor[1] >> 16) & StrideMask, descriptor[3]);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue