Do not use template updates for buffer textures and buffer images
This commit is contained in:
parent
1a0a351a15
commit
8a12c113f9
2 changed files with 185 additions and 2 deletions
|
@ -684,12 +684,26 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Texture))
|
if (_dirty.HasFlag(DirtyFlags.Texture))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, program, PipelineBase.TextureSetIndex, pbp);
|
if (program.UpdateTexturesWithoutTemplate)
|
||||||
|
{
|
||||||
|
UpdateAndBindTexturesWithoutTemplate(cbs, program, pbp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateAndBind(cbs, program, PipelineBase.TextureSetIndex, pbp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Image))
|
if (_dirty.HasFlag(DirtyFlags.Image))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, program, PipelineBase.ImageSetIndex, pbp);
|
if (program.UpdateImagesWithoutTemplate)
|
||||||
|
{
|
||||||
|
UpdateAndBindImagesWithoutTemplate(cbs, program, pbp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateAndBind(cbs, program, PipelineBase.ImageSetIndex, pbp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (program.BindingSegments.Length > PipelineBase.DescriptorSetLayouts)
|
if (program.BindingSegments.Length > PipelineBase.DescriptorSetLayouts)
|
||||||
|
@ -918,6 +932,152 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateAndBindTexturesWithoutTemplate(CommandBufferScoped cbs, ShaderCollection program, PipelineBindPoint pbp)
|
||||||
|
{
|
||||||
|
int setIndex = PipelineBase.TextureSetIndex;
|
||||||
|
var bindingSegments = program.BindingSegments[setIndex];
|
||||||
|
|
||||||
|
if (bindingSegments.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_updateDescriptorCacheCbIndex)
|
||||||
|
{
|
||||||
|
_updateDescriptorCacheCbIndex = false;
|
||||||
|
program.UpdateDescriptorCacheCommandBufferIndex(cbs.CommandBufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dsc = program.GetNewDescriptorSetCollection(setIndex, out _).Get(cbs);
|
||||||
|
|
||||||
|
foreach (ResourceBindingSegment segment in bindingSegments)
|
||||||
|
{
|
||||||
|
int binding = segment.Binding;
|
||||||
|
int count = segment.Count;
|
||||||
|
|
||||||
|
if (!segment.IsArray)
|
||||||
|
{
|
||||||
|
if (segment.Type != ResourceType.BufferTexture)
|
||||||
|
{
|
||||||
|
Span<DescriptorImageInfo> textures = _textures;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ref var texture = ref textures[i];
|
||||||
|
ref var refs = ref _textureRefs[binding + i];
|
||||||
|
|
||||||
|
texture.ImageView = refs.View?.Get(cbs).Value ?? default;
|
||||||
|
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
||||||
|
|
||||||
|
if (texture.ImageView.Handle == 0)
|
||||||
|
{
|
||||||
|
texture.ImageView = _dummyTexture.GetImageView().Get(cbs).Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture.Sampler.Handle == 0)
|
||||||
|
{
|
||||||
|
texture.Sampler = _dummySampler.GetSampler().Get(cbs).Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dsc.UpdateImages(0, binding, textures[..count], DescriptorType.CombinedImageSampler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Span<BufferView> bufferTextures = _bufferTextures;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
bufferTextures[i] = _bufferTextureRefs[binding + i]?.GetBufferView(cbs, false) ?? default;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsc.UpdateBufferImages(0, binding, bufferTextures[..count], DescriptorType.UniformTexelBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (segment.Type != ResourceType.BufferTexture)
|
||||||
|
{
|
||||||
|
dsc.UpdateImages(0, binding, _textureArrayRefs[binding].Array.GetImageInfos(_gd, cbs, _dummyTexture, _dummySampler), DescriptorType.CombinedImageSampler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dsc.UpdateBufferImages(0, binding, _textureArrayRefs[binding].Array.GetBufferViews(cbs), DescriptorType.UniformTexelBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sets = dsc.GetSets();
|
||||||
|
|
||||||
|
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAndBindImagesWithoutTemplate(CommandBufferScoped cbs, ShaderCollection program, PipelineBindPoint pbp)
|
||||||
|
{
|
||||||
|
int setIndex = PipelineBase.ImageSetIndex;
|
||||||
|
var bindingSegments = program.BindingSegments[setIndex];
|
||||||
|
|
||||||
|
if (bindingSegments.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_updateDescriptorCacheCbIndex)
|
||||||
|
{
|
||||||
|
_updateDescriptorCacheCbIndex = false;
|
||||||
|
program.UpdateDescriptorCacheCommandBufferIndex(cbs.CommandBufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dsc = program.GetNewDescriptorSetCollection(setIndex, out _).Get(cbs);
|
||||||
|
|
||||||
|
foreach (ResourceBindingSegment segment in bindingSegments)
|
||||||
|
{
|
||||||
|
int binding = segment.Binding;
|
||||||
|
int count = segment.Count;
|
||||||
|
|
||||||
|
if (!segment.IsArray)
|
||||||
|
{
|
||||||
|
if (segment.Type != ResourceType.BufferImage)
|
||||||
|
{
|
||||||
|
Span<DescriptorImageInfo> images = _images;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
images[i].ImageView = _imageRefs[binding + i].View?.Get(cbs).Value ?? default;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsc.UpdateImages(0, binding, images[..count], DescriptorType.StorageImage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Span<BufferView> bufferImages = _bufferImages;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
bufferImages[i] = _bufferImageRefs[binding + i]?.GetBufferView(cbs, _bufferImageFormats[binding + i], true) ?? default;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsc.UpdateBufferImages(0, binding, bufferImages[..count], DescriptorType.StorageTexelBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (segment.Type != ResourceType.BufferTexture)
|
||||||
|
{
|
||||||
|
dsc.UpdateImages(0, binding, _imageArrayRefs[binding].Array.GetImageInfos(_gd, cbs, _dummyTexture), DescriptorType.StorageImage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dsc.UpdateBufferImages(0, binding, _imageArrayRefs[binding].Array.GetBufferViews(cbs), DescriptorType.StorageTexelBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sets = dsc.GetSets();
|
||||||
|
|
||||||
|
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
private unsafe void UpdateBuffers(
|
private unsafe void UpdateBuffers(
|
||||||
CommandBufferScoped cbs,
|
CommandBufferScoped cbs,
|
||||||
PipelineBindPoint pbp,
|
PipelineBindPoint pbp,
|
||||||
|
|
|
@ -23,6 +23,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
public bool IsCompute { get; }
|
public bool IsCompute { get; }
|
||||||
public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0;
|
public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0;
|
||||||
|
|
||||||
|
public bool UpdateTexturesWithoutTemplate { get; }
|
||||||
|
public bool UpdateImagesWithoutTemplate { get; }
|
||||||
|
|
||||||
public uint Stages { get; }
|
public uint Stages { get; }
|
||||||
|
|
||||||
public ResourceBindingSegment[][] ClearSegments { get; }
|
public ResourceBindingSegment[][] ClearSegments { get; }
|
||||||
|
@ -130,6 +133,26 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
BindingSegments = BuildBindingSegments(resourceLayout.SetUsages);
|
BindingSegments = BuildBindingSegments(resourceLayout.SetUsages);
|
||||||
Templates = BuildTemplates(usePushDescriptors);
|
Templates = BuildTemplates(usePushDescriptors);
|
||||||
|
|
||||||
|
if (gd.Vendor == Vendor.Qualcomm)
|
||||||
|
{
|
||||||
|
// Updating buffer bindings using template updates crashes the Adreno driver on Windows.
|
||||||
|
|
||||||
|
foreach (ResourceBindingSegment[] stageSegments in BindingSegments)
|
||||||
|
{
|
||||||
|
foreach (ResourceBindingSegment bindingSegment in stageSegments)
|
||||||
|
{
|
||||||
|
if (bindingSegment.Type == ResourceType.BufferTexture)
|
||||||
|
{
|
||||||
|
UpdateTexturesWithoutTemplate = true;
|
||||||
|
}
|
||||||
|
else if (bindingSegment.Type == ResourceType.BufferImage)
|
||||||
|
{
|
||||||
|
UpdateImagesWithoutTemplate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_compileTask = Task.CompletedTask;
|
_compileTask = Task.CompletedTask;
|
||||||
_firstBackgroundUse = false;
|
_firstBackgroundUse = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue