Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions sources/engine/Stride.Graphics/Vulkan/Buffer.Vulkan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ public unsafe void Recreate(IntPtr dataPointer)
NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;
}

if ((ViewFlags & BufferFlags.StructuredBuffer) != 0)
{
createInfo.usage |= VkBufferUsageFlags.StorageBuffer;
NativeAccessMask |= VkAccessFlags.UniformRead;
NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;

if ((ViewFlags & BufferFlags.UnorderedAccess) != 0)
{
NativeAccessMask |= VkAccessFlags.ShaderWrite;
}
}

if ((ViewFlags & BufferFlags.ShaderResource) != 0)
{
createInfo.usage |= VkBufferUsageFlags.UniformTexelBuffer;
Expand Down
55 changes: 38 additions & 17 deletions sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ private unsafe void FlushInternal(bool wait)

if (activePipeline != null)
{
vkCmdBindPipeline(currentCommandList.NativeCommandBuffer, VkPipelineBindPoint.Graphics, activePipeline.NativePipeline);
vkCmdBindPipeline(currentCommandList.NativeCommandBuffer, activePipeline.IsCompute ? VkPipelineBindPoint.Compute : VkPipelineBindPoint.Graphics, activePipeline.NativePipeline);
var descriptorSetCopy = descriptorSet;
vkCmdBindDescriptorSets(currentCommandList.NativeCommandBuffer, VkPipelineBindPoint.Graphics, activePipeline.NativeLayout, firstSet: 0, descriptorSetCount: 1, &descriptorSetCopy, dynamicOffsetCount: 0, dynamicOffsets: null);
vkCmdBindDescriptorSets(currentCommandList.NativeCommandBuffer, activePipeline.IsCompute ? VkPipelineBindPoint.Compute : VkPipelineBindPoint.Graphics, activePipeline.NativeLayout, firstSet: 0, descriptorSetCount: 1, &descriptorSetCopy, dynamicOffsetCount: 0, dynamicOffsets: null);
}
SetRenderTargetsImpl(depthStencilBuffer, renderTargetCount, renderTargets);
}
Expand Down Expand Up @@ -249,7 +249,11 @@ private unsafe void PrepareDraw()

// Lazily set the render pass and frame buffer
EnsureRenderPass();
BindDescriptorSets();
}

private unsafe void BindDescriptorSets()
{
// Keep track of descriptor pool usage
bool isPoolExhausted = ++allocatedSetCount > GraphicsDevice.MaxDescriptorSetCount;
for (int i = 0; i < DescriptorSetLayout.DescriptorTypeCount; i++)
Expand Down Expand Up @@ -328,18 +332,28 @@ private unsafe void PrepareDraw()
sType = VkStructureType.WriteDescriptorSet,
descriptorType = mapping.DescriptorType,
dstSet = localDescriptorSet,
dstBinding = (uint) mapping.DestinationBinding,
dstBinding = (uint)mapping.DestinationBinding,
dstArrayElement = 0,
descriptorCount = 1
};

switch (mapping.DescriptorType)
{
case VkDescriptorType.SampledImage:
var texture = heapObject.Value as Texture;
descriptorData->ImageInfo = new VkDescriptorImageInfo { imageView = texture?.NativeImageView ?? GraphicsDevice.EmptyTexture.NativeImageView, imageLayout = VkImageLayout.ShaderReadOnlyOptimal };
write->pImageInfo = &descriptorData->ImageInfo;
break;
{
var texture = heapObject.Value as Texture;
descriptorData->ImageInfo = new VkDescriptorImageInfo { imageView = texture?.NativeImageView ?? GraphicsDevice.EmptyTexture.NativeImageView, imageLayout = VkImageLayout.ShaderReadOnlyOptimal };
write->pImageInfo = &descriptorData->ImageInfo;
break;
}

case VkDescriptorType.StorageImage:
{
var texture = heapObject.Value as Texture;
descriptorData->ImageInfo = new VkDescriptorImageInfo { imageView = texture?.NativeImageView ?? GraphicsDevice.EmptyTexture.NativeImageView, imageLayout = VkImageLayout.General };
write->pImageInfo = &descriptorData->ImageInfo;
break;
}

case VkDescriptorType.Sampler:
var samplerState = heapObject.Value as SamplerState;
Expand All @@ -349,7 +363,7 @@ private unsafe void PrepareDraw()

case VkDescriptorType.UniformBuffer:
var buffer = heapObject.Value as Buffer;
descriptorData->BufferInfo = new VkDescriptorBufferInfo { buffer = buffer?.NativeBuffer ?? VkBuffer.Null, offset = (ulong) heapObject.Offset, range = (ulong) heapObject.Size };
descriptorData->BufferInfo = new VkDescriptorBufferInfo { buffer = buffer?.NativeBuffer ?? VkBuffer.Null, offset = (ulong)heapObject.Offset, range = (ulong)heapObject.Size };
write->pBufferInfo = &descriptorData->BufferInfo;
break;

Expand All @@ -359,14 +373,20 @@ private unsafe void PrepareDraw()
write->pTexelBufferView = &descriptorData->BufferView;
break;

case VkDescriptorType.StorageBuffer:
buffer = heapObject.Value as Buffer;
descriptorData->BufferInfo = new VkDescriptorBufferInfo { buffer = buffer?.NativeBuffer ?? VkBuffer.Null, offset = (ulong)heapObject.Offset, range = (ulong)(buffer?.SizeInBytes ?? 0)};
write->pBufferInfo = &descriptorData->BufferInfo;
break;

default:
throw new InvalidOperationException();
}
}

vkUpdateDescriptorSets(GraphicsDevice.NativeDevice, (uint) bindingCount, writes, descriptorCopyCount: 0, descriptorCopies: null);
vkUpdateDescriptorSets(GraphicsDevice.NativeDevice, (uint)bindingCount, writes, descriptorCopyCount: 0, descriptorCopies: null);
#endif
vkCmdBindDescriptorSets(currentCommandList.NativeCommandBuffer, VkPipelineBindPoint.Graphics, activePipeline.NativeLayout, firstSet: 0, descriptorSetCount: 1, &localDescriptorSet, dynamicOffsetCount: 0, dynamicOffsets: null);
vkCmdBindDescriptorSets(currentCommandList.NativeCommandBuffer, activePipeline.IsCompute ? VkPipelineBindPoint.Compute : VkPipelineBindPoint.Graphics, activePipeline.NativeLayout, firstSet: 0, descriptorSetCount: 1, &localDescriptorSet, dynamicOffsetCount: 0, dynamicOffsets: null);
}

private readonly FastList<VkCopyDescriptorSet> copies = new();
Expand All @@ -390,7 +410,7 @@ public void SetPipelineState(PipelineState pipelineState)

activePipeline = pipelineState;

vkCmdBindPipeline(currentCommandList.NativeCommandBuffer, VkPipelineBindPoint.Graphics, pipelineState.NativePipeline);
vkCmdBindPipeline(currentCommandList.NativeCommandBuffer, activePipeline.IsCompute ? VkPipelineBindPoint.Compute : VkPipelineBindPoint.Graphics, pipelineState.NativePipeline);
}

public unsafe void SetVertexBuffer(int index, Buffer buffer, int offset, int stride)
Expand Down Expand Up @@ -446,7 +466,7 @@ public unsafe void ResourceBarrierTransition(GraphicsResource resource, Graphics
case GraphicsResourceState.PixelShaderResource:
texture.NativeLayout = VkImageLayout.ShaderReadOnlyOptimal;
texture.NativeAccessMask = VkAccessFlags.ShaderRead;
texture.NativePipelineStageMask = VkPipelineStageFlags.FragmentShader;
texture.NativePipelineStageMask = VkPipelineStageFlags.FragmentShader | VkPipelineStageFlags.ComputeShader;
break;
case GraphicsResourceState.GenericRead:
texture.NativeLayout = VkImageLayout.General;
Expand Down Expand Up @@ -503,6 +523,9 @@ public void SetDescriptorSets(int index, DescriptorSet[] descriptorSets)
/// <inheritdoc />
public void Dispatch(int threadCountX, int threadCountY, int threadCountZ)
{
CleanupRenderPass();
BindDescriptorSets();
vkCmdDispatch(currentCommandList.NativeCommandBuffer, (uint)threadCountX, (uint)threadCountY, (uint)threadCountZ);
}

/// <summary>
Expand All @@ -512,6 +535,9 @@ public void Dispatch(int threadCountX, int threadCountY, int threadCountZ)
/// <param name="offsetInBytes">The offset information bytes.</param>
public void Dispatch(Buffer indirectBuffer, int offsetInBytes)
{
CleanupRenderPass();
BindDescriptorSets();
vkCmdDispatchIndirect(currentCommandList.NativeCommandBuffer, indirectBuffer.NativeBuffer, (ulong)offsetInBytes);
}

/// <summary>
Expand Down Expand Up @@ -1301,11 +1327,6 @@ public unsafe MappedResource MapSubresource(GraphicsResource resource, int subRe
throw new InvalidOperationException();
}

if (mapMode == MapMode.WriteDiscard)
{
throw new InvalidOperationException("Can't use WriteDiscard on Graphics API that doesn't support renaming");
}

if (mapMode != MapMode.WriteNoOverwrite && mapMode != MapMode.Write)
{
// Need to wait?
Expand Down
41 changes: 35 additions & 6 deletions sources/engine/Stride.Graphics/Vulkan/GraphicsDevice.Vulkan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,20 @@ public partial class GraphicsDevice

internal HeapPool DescriptorPools;
internal const uint MaxDescriptorSetCount = 256;
internal readonly uint[] MaxDescriptorTypeCounts = new uint[DescriptorSetLayout.DescriptorTypeCount]
{
internal readonly uint[] MaxDescriptorTypeCounts =
[
256, // Sampler
0, // CombinedImageSampler
512, // SampledImage
0, // StorageImage
64, // StorageImage
64, // UniformTexelBuffer
0, // StorageTexelBuffer
64, // StorageTexelBuffer
512, // UniformBuffer
0, // StorageBuffer
64, // StorageBuffer
0, // UniformBufferDynamic
0, // StorageBufferDynamic
0 // InputAttachment
};
];

internal Buffer EmptyTexelBufferInt, EmptyTexelBufferFloat;
internal Texture EmptyTexture;
Expand Down Expand Up @@ -264,6 +264,22 @@ private unsafe void InitializePlatformDevice(GraphicsProfile[] graphicsProfiles,
ConstantBufferDataPlacementAlignment = (int)physicalDeviceProperties.limits.minUniformBufferOffsetAlignment;
TimestampFrequency = (long)(1.0e9 / physicalDeviceProperties.limits.timestampPeriod); // Resolution in nanoseconds

// Configure descriptor type max counts
void SetMaxDescriptorTypeCount(VkDescriptorType type, uint limit)
=> MaxDescriptorTypeCounts[(int)type] = Math.Min(MaxDescriptorTypeCounts[(int)type], limit);

SetMaxDescriptorTypeCount(VkDescriptorType.Sampler, physicalDeviceProperties.limits.maxDescriptorSetSamplers);
SetMaxDescriptorTypeCount(VkDescriptorType.CombinedImageSampler, 0); // Not defined.
SetMaxDescriptorTypeCount(VkDescriptorType.SampledImage, physicalDeviceProperties.limits.maxDescriptorSetSampledImages);
SetMaxDescriptorTypeCount(VkDescriptorType.StorageImage, physicalDeviceProperties.limits.maxDescriptorSetStorageImages);
SetMaxDescriptorTypeCount(VkDescriptorType.UniformTexelBuffer, physicalDeviceProperties.limits.maxDescriptorSetSampledImages); // No individual limit
SetMaxDescriptorTypeCount(VkDescriptorType.StorageTexelBuffer, physicalDeviceProperties.limits.maxDescriptorSetStorageImages); // No individual limit
SetMaxDescriptorTypeCount(VkDescriptorType.UniformBuffer, physicalDeviceProperties.limits.maxDescriptorSetUniformBuffers);
SetMaxDescriptorTypeCount(VkDescriptorType.StorageBuffer, physicalDeviceProperties.limits.maxDescriptorSetStorageBuffers);
SetMaxDescriptorTypeCount(VkDescriptorType.UniformBufferDynamic, physicalDeviceProperties.limits.maxDescriptorSetUniformBuffersDynamic);
SetMaxDescriptorTypeCount(VkDescriptorType.StorageBufferDynamic, physicalDeviceProperties.limits.maxDescriptorSetStorageBuffersDynamic);
SetMaxDescriptorTypeCount(VkDescriptorType.InputAttachment, physicalDeviceProperties.limits.maxDescriptorSetInputAttachments);

RequestedProfile = graphicsProfiles.First();

var queueProperties = vkGetPhysicalDeviceQueueFamilyProperties(NativePhysicalDevice);
Expand Down Expand Up @@ -292,11 +308,24 @@ private unsafe void InitializePlatformDevice(GraphicsProfile[] graphicsProfiles,
depthClamp = true,
};

vkGetPhysicalDeviceFeatures(NativePhysicalDevice, out var deviceFeatures);

if (deviceFeatures.shaderStorageImageReadWithoutFormat)
{
enabledFeature.shaderStorageImageReadWithoutFormat = true;
}

if (deviceFeatures.shaderStorageImageWriteWithoutFormat)
{
enabledFeature.shaderStorageImageWriteWithoutFormat = true;
}

Span<VkUtf8String> supportedExtensionProperties = stackalloc VkUtf8String[]
{
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
};

var availableExtensionProperties = GetAvailableExtensionProperties(supportedExtensionProperties);
ValidateExtensionPropertiesAvailability(availableExtensionProperties);
var desiredExtensionProperties = new HashSet<VkUtf8String>
Expand Down
Loading