Merge pull request #11923 from iwubcode/multi-texture-compute-support

VideoBackends: support multiple compute images for some backends
This commit is contained in:
Admiral H. Curtiss
2023-07-01 17:47:55 +02:00
committed by GitHub
21 changed files with 107 additions and 59 deletions

View File

@ -157,8 +157,9 @@ VkDescriptorPool CommandBufferManager::CreateDescriptorPool(u32 max_descriptor_s
const std::array<VkDescriptorPoolSize, 5> pool_sizes{{
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, max_descriptor_sets * 3},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
max_descriptor_sets * (VideoCommon::MAX_PIXEL_SHADER_SAMPLERS + NUM_COMPUTE_SHADER_SAMPLERS +
NUM_UTILITY_PIXEL_SAMPLERS)},
max_descriptor_sets *
(VideoCommon::MAX_PIXEL_SHADER_SAMPLERS + VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS +
NUM_UTILITY_PIXEL_SAMPLERS)},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, max_descriptor_sets * 2},
{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, max_descriptor_sets * 3},
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, max_descriptor_sets * 1},

View File

@ -49,9 +49,9 @@ enum DESCRIPTOR_SET_LAYOUT
// - 1 texel buffer (accessible from PS) [set=1, binding=8]
// - Compute
// - 1 uniform buffer [set=0, binding=0]
// - 2 combined image samplers [set=0, binding=1-2]
// - 2 texel buffers [set=0, binding=3-4]
// - 1 storage image [set=0, binding=5]
// - 8 combined image samplers [set=0, binding=1-8]
// - 2 texel buffers [set=0, binding=9-10]
// - 8 storage image [set=0, binding=11-18]
//
// All four pipeline layout share the first two descriptor sets (uniform buffers, PS samplers).
// The third descriptor set (see bind points above) is used for storage or texel buffers.
@ -78,7 +78,6 @@ enum UNIFORM_BUFFER_DESCRIPTOR_SET_BINDING
constexpr u32 MAX_VERTEX_ATTRIBUTES = 16;
// Number of pixel shader texture slots
constexpr u32 NUM_COMPUTE_SHADER_SAMPLERS = 2;
constexpr u32 NUM_UTILITY_PIXEL_SAMPLERS = 8;
// Number of texel buffer binding points.

View File

@ -148,13 +148,26 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{8, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
}};
static const std::array<VkDescriptorSetLayoutBinding, 6> compute_set_bindings{{
static const std::array<VkDescriptorSetLayoutBinding, 19> compute_set_bindings{{
{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{3, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{4, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{5, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{6, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{7, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{8, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{9, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{10, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{11, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{12, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{13, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{14, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{15, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{16, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{17, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{18, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
}};
std::array<VkDescriptorSetLayoutBinding, 3> ubo_bindings = standard_ubo_bindings;

View File

@ -58,8 +58,8 @@ static const char COMPUTE_SHADER_HEADER[] = R"(
// All resources are packed into one descriptor set for compute.
#define UBO_BINDING(packing, x) layout(packing, set = 0, binding = (x - 1))
#define SAMPLER_BINDING(x) layout(set = 0, binding = (1 + x))
#define TEXEL_BUFFER_BINDING(x) layout(set = 0, binding = (3 + x))
#define IMAGE_BINDING(format, x) layout(format, set = 0, binding = (5 + x))
#define TEXEL_BUFFER_BINDING(x) layout(set = 0, binding = (9 + x))
#define IMAGE_BINDING(format, x) layout(format, set = 0, binding = (11 + x))
// hlsl to glsl function translation
#define API_VULKAN 1

View File

@ -49,8 +49,10 @@ void StateTracker::DestroyInstance()
// Clear everything out so this doesn't happen.
for (auto& it : s_state_tracker->m_bindings.samplers)
it.imageView = VK_NULL_HANDLE;
s_state_tracker->m_bindings.image_texture.imageView = VK_NULL_HANDLE;
for (auto& it : s_state_tracker->m_bindings.image_textures)
it.imageView = VK_NULL_HANDLE;
s_state_tracker->m_dummy_texture.reset();
s_state_tracker->m_dummy_compute_texture.reset();
s_state_tracker.reset();
}
@ -64,6 +66,14 @@ bool StateTracker::Initialize()
return false;
m_dummy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Create a dummy compute texture which can be used in place of a real binding
m_dummy_compute_texture = VKTexture::Create(
TextureConfig(1, 1, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_ComputeImage),
"");
if (!m_dummy_compute_texture)
return false;
m_dummy_compute_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_IMAGE_LAYOUT_GENERAL);
// Initialize all samplers to point by default
for (size_t i = 0; i < VideoCommon::MAX_PIXEL_SHADER_SAMPLERS; i++)
@ -73,6 +83,13 @@ bool StateTracker::Initialize()
m_bindings.samplers[i].sampler = g_object_cache->GetPointSampler();
}
for (size_t i = 0; i < VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS; i++)
{
m_bindings.image_textures[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
m_bindings.image_textures[i].imageView = m_dummy_compute_texture->GetView();
m_bindings.image_textures[i].sampler = g_object_cache->GetPointSampler();
}
// Default dirty flags include all descriptors
InvalidateCachedState();
return true;
@ -217,13 +234,13 @@ void StateTracker::SetTexelBuffer(u32 index, VkBufferView view)
m_dirty_flags |= DIRTY_FLAG_UTILITY_BINDINGS | DIRTY_FLAG_COMPUTE_BINDINGS;
}
void StateTracker::SetImageTexture(VkImageView view)
void StateTracker::SetImageTexture(u32 index, VkImageView view)
{
if (m_bindings.image_texture.imageView == view)
if (m_bindings.image_textures[index].imageView == view)
return;
m_bindings.image_texture.imageView = view;
m_bindings.image_texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
m_bindings.image_textures[index].imageView = view;
m_bindings.image_textures[index].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
m_dirty_flags |= DIRTY_FLAG_COMPUTE_BINDINGS;
}
@ -238,10 +255,13 @@ void StateTracker::UnbindTexture(VkImageView view)
}
}
if (m_bindings.image_texture.imageView == view)
for (VkDescriptorImageInfo& it : m_bindings.image_textures)
{
m_bindings.image_texture.imageView = m_dummy_texture->GetView();
m_bindings.image_texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
if (it.imageView == view)
{
it.imageView = m_dummy_compute_texture->GetView();
it.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
}
}
@ -667,7 +687,7 @@ void StateTracker::UpdateComputeDescriptorSet()
m_compute_descriptor_set,
1,
0,
NUM_COMPUTE_SHADER_SAMPLERS,
VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
m_bindings.samplers.data(),
nullptr,
@ -675,7 +695,7 @@ void StateTracker::UpdateComputeDescriptorSet()
dswrites[2] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
m_compute_descriptor_set,
3,
1 + VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS,
0,
NUM_COMPUTE_TEXEL_BUFFERS,
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
@ -685,11 +705,11 @@ void StateTracker::UpdateComputeDescriptorSet()
dswrites[3] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
m_compute_descriptor_set,
5,
1 + VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS + NUM_COMPUTE_TEXEL_BUFFERS,
0,
1,
VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
&m_bindings.image_texture,
m_bindings.image_textures.data(),
nullptr,
nullptr};

View File

@ -43,7 +43,7 @@ public:
void SetSampler(u32 index, VkSampler sampler);
void SetSSBO(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range);
void SetTexelBuffer(u32 index, VkBufferView view);
void SetImageTexture(VkImageView view);
void SetImageTexture(u32 index, VkImageView view);
void UnbindTexture(VkImageView view);
@ -146,7 +146,7 @@ private:
std::array<VkBufferView, NUM_COMPUTE_TEXEL_BUFFERS> texel_buffers;
VkDescriptorBufferInfo ssbo;
VkDescriptorBufferInfo gx_uber_vertex_ssbo;
VkDescriptorImageInfo image_texture;
std::array<VkDescriptorImageInfo, VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS> image_textures;
} m_bindings = {};
std::array<VkDescriptorSet, NUM_GX_DESCRIPTOR_SETS> m_gx_descriptor_sets = {};
std::array<VkDescriptorSet, NUM_UTILITY_DESCRIPTOR_SETS> m_utility_descriptor_sets = {};
@ -158,6 +158,7 @@ private:
// uniform buffers
std::unique_ptr<VKTexture> m_dummy_texture;
std::unique_ptr<VKTexture> m_dummy_compute_texture;
VKFramebuffer* m_framebuffer = nullptr;
VkRenderPass m_current_render_pass = VK_NULL_HANDLE;

View File

@ -512,13 +512,13 @@ void VKGfx::SetSamplerState(u32 index, const SamplerState& state)
m_sampler_states[index] = state;
}
void VKGfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write)
void VKGfx::SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write)
{
VKTexture* vk_texture = static_cast<VKTexture*>(texture);
if (vk_texture)
{
StateTracker::GetInstance()->EndRenderPass();
StateTracker::GetInstance()->SetImageTexture(vk_texture->GetView());
StateTracker::GetInstance()->SetImageTexture(index, vk_texture->GetView());
vk_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
read ? (write ? VKTexture::ComputeImageLayout::ReadWrite :
VKTexture::ComputeImageLayout::ReadOnly) :
@ -526,7 +526,7 @@ void VKGfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool wri
}
else
{
StateTracker::GetInstance()->SetImageTexture(VK_NULL_HANDLE);
StateTracker::GetInstance()->SetImageTexture(index, VK_NULL_HANDLE);
}
}

View File

@ -66,7 +66,7 @@ public:
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
void SetTexture(u32 index, const AbstractTexture* texture) override;
void SetSamplerState(u32 index, const SamplerState& state) override;
void SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) override;
void SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write) override;
void UnbindTexture(const AbstractTexture* texture) override;
void SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) override;