diff --git a/Source/Core/VideoBackends/D3D/D3DGfx.cpp b/Source/Core/VideoBackends/D3D/D3DGfx.cpp index a4d1f5b8b9..27b4f0a4a0 100644 --- a/Source/Core/VideoBackends/D3D/D3DGfx.cpp +++ b/Source/Core/VideoBackends/D3D/D3DGfx.cpp @@ -239,9 +239,10 @@ void Gfx::SetSamplerState(u32 index, const SamplerState& state) D3D::stateman->SetSampler(index, m_state_cache.Get(state)); } -void Gfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) +void Gfx::SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write) { - D3D::stateman->SetComputeUAV(texture ? static_cast(texture)->GetD3DUAV() : nullptr); + D3D::stateman->SetComputeUAV(index, + texture ? static_cast(texture)->GetD3DUAV() : nullptr); } void Gfx::UnbindTexture(const AbstractTexture* texture) diff --git a/Source/Core/VideoBackends/D3D/D3DGfx.h b/Source/Core/VideoBackends/D3D/D3DGfx.h index e23867e73b..07c47e93af 100644 --- a/Source/Core/VideoBackends/D3D/D3DGfx.h +++ b/Source/Core/VideoBackends/D3D/D3DGfx.h @@ -52,7 +52,7 @@ public: void SetScissorRect(const MathUtil::Rectangle& 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; diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp index 06f01792f5..0372252b9a 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -222,13 +222,14 @@ void StateManager::SetTextureByMask(u32 textureSlotMask, ID3D11ShaderResourceVie } } -void StateManager::SetComputeUAV(ID3D11UnorderedAccessView* uav) +void StateManager::SetComputeUAV(u32 index, ID3D11UnorderedAccessView* uav) { - if (m_compute_image == uav) + if (m_compute_images[index] == uav) return; - m_compute_image = uav; - D3D::context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr); + m_compute_images[index] = uav; + D3D::context->CSSetUnorderedAccessViews(0, static_cast(m_compute_images.size()), + m_compute_images.data(), nullptr); } void StateManager::SetComputeShader(ID3D11ComputeShader* shader) diff --git a/Source/Core/VideoBackends/D3D/D3DState.h b/Source/Core/VideoBackends/D3D/D3DState.h index eba58c2431..0893220e71 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.h +++ b/Source/Core/VideoBackends/D3D/D3DState.h @@ -218,7 +218,7 @@ public: // Binds constant buffers/textures/samplers to the compute shader stage. // We don't track these explicitly because it's not often-used. - void SetComputeUAV(ID3D11UnorderedAccessView* uav); + void SetComputeUAV(u32 index, ID3D11UnorderedAccessView* uav); void SetComputeShader(ID3D11ComputeShader* shader); void SyncComputeBindings(); @@ -277,9 +277,11 @@ private: // Compute resources are synced with the graphics resources when we need them. ID3D11Buffer* m_compute_constants = nullptr; - std::array m_compute_textures{}; - std::array m_compute_samplers{}; - ID3D11UnorderedAccessView* m_compute_image = nullptr; + std::array + m_compute_textures{}; + std::array m_compute_samplers{}; + std::array + m_compute_images{}; ID3D11ComputeShader* m_compute_shader = nullptr; }; diff --git a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp index 3f8e6ae4f3..3f6035feda 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp +++ b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp @@ -263,7 +263,7 @@ void Gfx::SetSamplerState(u32 index, const SamplerState& state) m_dirty_bits |= DirtyState_Samplers; } -void Gfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) +void Gfx::SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write) { const DXTexture* dxtex = static_cast(texture); if (m_state.compute_image_texture == dxtex) diff --git a/Source/Core/VideoBackends/D3D12/D3D12Gfx.h b/Source/Core/VideoBackends/D3D12/D3D12Gfx.h index 77ce4da899..b3426cb95e 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12Gfx.h +++ b/Source/Core/VideoBackends/D3D12/D3D12Gfx.h @@ -60,7 +60,7 @@ public: void SetScissorRect(const MathUtil::Rectangle& 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; diff --git a/Source/Core/VideoBackends/Metal/MTLGfx.h b/Source/Core/VideoBackends/Metal/MTLGfx.h index c1a698711a..e92ae285e6 100644 --- a/Source/Core/VideoBackends/Metal/MTLGfx.h +++ b/Source/Core/VideoBackends/Metal/MTLGfx.h @@ -59,7 +59,7 @@ public: void SetScissorRect(const MathUtil::Rectangle& 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; diff --git a/Source/Core/VideoBackends/Metal/MTLGfx.mm b/Source/Core/VideoBackends/Metal/MTLGfx.mm index 1137c45e5f..f37dce39c7 100644 --- a/Source/Core/VideoBackends/Metal/MTLGfx.mm +++ b/Source/Core/VideoBackends/Metal/MTLGfx.mm @@ -386,7 +386,7 @@ void Metal::Gfx::SetSamplerState(u32 index, const SamplerState& state) g_state_tracker->SetSampler(index, state); } -void Metal::Gfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) +void Metal::Gfx::SetComputeImageTexture(u32, AbstractTexture* texture, bool read, bool write) { g_state_tracker->SetComputeTexture(static_cast(texture)); } diff --git a/Source/Core/VideoBackends/OGL/OGLGfx.cpp b/Source/Core/VideoBackends/OGL/OGLGfx.cpp index e545ed7f4b..fb773a6a2d 100644 --- a/Source/Core/VideoBackends/OGL/OGLGfx.cpp +++ b/Source/Core/VideoBackends/OGL/OGLGfx.cpp @@ -22,6 +22,7 @@ #include "VideoCommon/Present.h" #include "VideoCommon/VideoConfig.h" +#include #include namespace OGL @@ -303,8 +304,11 @@ void OGLGfx::DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x static_cast(m_current_pipeline)->GetProgram()->shader.Bind(); // Barrier to texture can be used for reads. - if (m_bound_image_texture) + if (std::any_of(m_bound_image_textures.begin(), m_bound_image_textures.end(), + [](auto image) { return image != nullptr; })) + { glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); + } } void OGLGfx::SelectLeftBuffer() @@ -652,23 +656,23 @@ void OGLGfx::SetSamplerState(u32 index, const SamplerState& state) g_sampler_cache->SetSamplerState(index, state); } -void OGLGfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) +void OGLGfx::SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write) { - if (m_bound_image_texture == texture) + if (m_bound_image_textures[index] == texture) return; if (texture) { const GLenum access = read ? (write ? GL_READ_WRITE : GL_READ_ONLY) : GL_WRITE_ONLY; - glBindImageTexture(0, static_cast(texture)->GetGLTextureId(), 0, GL_TRUE, 0, + glBindImageTexture(index, static_cast(texture)->GetGLTextureId(), 0, GL_TRUE, 0, access, static_cast(texture)->GetGLFormatForImageTexture()); } else { - glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); + glBindImageTexture(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); } - m_bound_image_texture = texture; + m_bound_image_textures[index] = texture; } void OGLGfx::UnbindTexture(const AbstractTexture* texture) @@ -683,10 +687,13 @@ void OGLGfx::UnbindTexture(const AbstractTexture* texture) m_bound_textures[i] = nullptr; } - if (m_bound_image_texture == texture) + for (size_t i = 0; i < m_bound_image_textures.size(); i++) { - glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); - m_bound_image_texture = nullptr; + if (m_bound_image_textures[i] != texture) + continue; + + glBindImageTexture(static_cast(i), 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); + m_bound_image_textures[i] = nullptr; } } diff --git a/Source/Core/VideoBackends/OGL/OGLGfx.h b/Source/Core/VideoBackends/OGL/OGLGfx.h index 8d552a661b..1f392c7296 100644 --- a/Source/Core/VideoBackends/OGL/OGLGfx.h +++ b/Source/Core/VideoBackends/OGL/OGLGfx.h @@ -49,7 +49,7 @@ public: void SetScissorRect(const MathUtil::Rectangle& 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; @@ -103,6 +103,8 @@ private: std::unique_ptr m_main_gl_context; std::unique_ptr m_system_framebuffer; std::array m_bound_textures{}; + std::array + m_bound_image_textures{}; AbstractTexture* m_bound_image_texture = nullptr; RasterizationState m_current_rasterization_state; DepthState m_current_depth_state; diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp index be02034f67..3aa05dbaf0 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp @@ -157,8 +157,9 @@ VkDescriptorPool CommandBufferManager::CreateDescriptorPool(u32 max_descriptor_s const std::array 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}, diff --git a/Source/Core/VideoBackends/Vulkan/Constants.h b/Source/Core/VideoBackends/Vulkan/Constants.h index 255cfe4929..2bdceefe3b 100644 --- a/Source/Core/VideoBackends/Vulkan/Constants.h +++ b/Source/Core/VideoBackends/Vulkan/Constants.h @@ -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. diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 6b8f66ae80..d899191614 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -148,13 +148,26 @@ bool ObjectCache::CreateDescriptorSetLayouts() {8, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, }}; - static const std::array compute_set_bindings{{ + static const std::array 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 ubo_bindings = standard_ubo_bindings; diff --git a/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp b/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp index 3555a6c9b7..ab9b015cec 100644 --- a/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp +++ b/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp @@ -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 diff --git a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp index edf57ae3b1..d6e4e3c422 100644 --- a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp +++ b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp @@ -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}; diff --git a/Source/Core/VideoBackends/Vulkan/StateTracker.h b/Source/Core/VideoBackends/Vulkan/StateTracker.h index 1113cfc994..8de5fd54cc 100644 --- a/Source/Core/VideoBackends/Vulkan/StateTracker.h +++ b/Source/Core/VideoBackends/Vulkan/StateTracker.h @@ -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 texel_buffers; VkDescriptorBufferInfo ssbo; VkDescriptorBufferInfo gx_uber_vertex_ssbo; - VkDescriptorImageInfo image_texture; + std::array image_textures; } m_bindings = {}; std::array m_gx_descriptor_sets = {}; std::array m_utility_descriptor_sets = {}; @@ -158,6 +158,7 @@ private: // uniform buffers std::unique_ptr m_dummy_texture; + std::unique_ptr m_dummy_compute_texture; VKFramebuffer* m_framebuffer = nullptr; VkRenderPass m_current_render_pass = VK_NULL_HANDLE; diff --git a/Source/Core/VideoBackends/Vulkan/VKGfx.cpp b/Source/Core/VideoBackends/Vulkan/VKGfx.cpp index e514979c65..fdfeb5713b 100644 --- a/Source/Core/VideoBackends/Vulkan/VKGfx.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKGfx.cpp @@ -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(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); } } diff --git a/Source/Core/VideoBackends/Vulkan/VKGfx.h b/Source/Core/VideoBackends/Vulkan/VKGfx.h index c6d6201714..539b427a9d 100644 --- a/Source/Core/VideoBackends/Vulkan/VKGfx.h +++ b/Source/Core/VideoBackends/Vulkan/VKGfx.h @@ -66,7 +66,7 @@ public: void SetScissorRect(const MathUtil::Rectangle& 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; diff --git a/Source/Core/VideoCommon/AbstractGfx.h b/Source/Core/VideoCommon/AbstractGfx.h index 952369e11e..5d2679f68f 100644 --- a/Source/Core/VideoCommon/AbstractGfx.h +++ b/Source/Core/VideoCommon/AbstractGfx.h @@ -61,7 +61,7 @@ public: virtual void SetScissorRect(const MathUtil::Rectangle& rc) {} virtual void SetTexture(u32 index, const AbstractTexture* texture) {} virtual void SetSamplerState(u32 index, const SamplerState& state) {} - virtual void SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) {} + virtual void SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write) {} virtual void UnbindTexture(const AbstractTexture* texture) {} virtual void SetViewport(float x, float y, float width, float height, float near_depth, float far_depth) diff --git a/Source/Core/VideoCommon/Constants.h b/Source/Core/VideoCommon/Constants.h index 8da73e8054..bd939b1f3c 100644 --- a/Source/Core/VideoCommon/Constants.h +++ b/Source/Core/VideoCommon/Constants.h @@ -8,4 +8,5 @@ namespace VideoCommon { constexpr u32 MAX_PIXEL_SHADER_SAMPLERS = 8; -} +constexpr u32 MAX_COMPUTE_SHADER_SAMPLERS = 8; +} // namespace VideoCommon diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index c26cbb5f4c..6198eea0ff 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -3009,7 +3009,7 @@ bool TextureCacheBase::DecodeTextureOnGPU(RcTcacheEntry& entry, u32 dst_level, c aligned_height, src_offset, row_stride / bytes_per_buffer_elem, palette_offset}; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); - g_gfx->SetComputeImageTexture(m_decoding_texture.get(), false, true); + g_gfx->SetComputeImageTexture(0, m_decoding_texture.get(), false, true); auto dispatch_groups = TextureConversionShaderTiled::GetDispatchCount(info, aligned_width, aligned_height);