vulkan: Fix rescaling push constant usage
This commit is contained in:
		| @@ -1006,47 +1006,47 @@ void EmitContext::DefineRescalingInput(const Info& info) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (profile.unified_descriptor_binding) { |     if (profile.unified_descriptor_binding) { | ||||||
|         DefineRescalingInputPushConstant(info); |         DefineRescalingInputPushConstant(); | ||||||
|     } else { |     } else { | ||||||
|         DefineRescalingInputUniformConstant(); |         DefineRescalingInputUniformConstant(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void EmitContext::DefineRescalingInputPushConstant(const Info& info) { | void EmitContext::DefineRescalingInputPushConstant() { | ||||||
|     boost::container::static_vector<Id, 3> members{F32[1]}; |     boost::container::static_vector<Id, 3> members{}; | ||||||
|     u32 member_index{0}; |     u32 member_index{0}; | ||||||
|     if (!info.texture_descriptors.empty()) { |  | ||||||
|         rescaling_textures_type = TypeArray(U32[1], Const(4u)); |     rescaling_textures_type = TypeArray(U32[1], Const(4u)); | ||||||
|         Decorate(rescaling_textures_type, spv::Decoration::ArrayStride, 4u); |     Decorate(rescaling_textures_type, spv::Decoration::ArrayStride, 4u); | ||||||
|         members.push_back(rescaling_textures_type); |     members.push_back(rescaling_textures_type); | ||||||
|         rescaling_textures_member_index = ++member_index; |     rescaling_textures_member_index = member_index++; | ||||||
|     } |  | ||||||
|     if (!info.image_descriptors.empty()) { |     rescaling_images_type = TypeArray(U32[1], Const(NUM_IMAGE_SCALING_WORDS)); | ||||||
|         rescaling_images_type = TypeArray(U32[1], Const(NUM_IMAGE_SCALING_WORDS)); |     Decorate(rescaling_images_type, spv::Decoration::ArrayStride, 4u); | ||||||
|         if (rescaling_textures_type.value != rescaling_images_type.value) { |     members.push_back(rescaling_images_type); | ||||||
|             Decorate(rescaling_images_type, spv::Decoration::ArrayStride, 4u); |     rescaling_images_member_index = member_index++; | ||||||
|         } |  | ||||||
|         members.push_back(rescaling_images_type); |     if (stage != Stage::Compute) { | ||||||
|         rescaling_images_member_index = ++member_index; |         members.push_back(F32[1]); | ||||||
|  |         rescaling_downfactor_member_index = member_index++; | ||||||
|     } |     } | ||||||
|     const Id push_constant_struct{TypeStruct(std::span(members.data(), members.size()))}; |     const Id push_constant_struct{TypeStruct(std::span(members.data(), members.size()))}; | ||||||
|     Decorate(push_constant_struct, spv::Decoration::Block); |     Decorate(push_constant_struct, spv::Decoration::Block); | ||||||
|     Name(push_constant_struct, "ResolutionInfo"); |     Name(push_constant_struct, "ResolutionInfo"); | ||||||
|  |  | ||||||
|     MemberDecorate(push_constant_struct, 0u, spv::Decoration::Offset, 0u); |     MemberDecorate(push_constant_struct, rescaling_textures_member_index, spv::Decoration::Offset, | ||||||
|     MemberName(push_constant_struct, 0u, "down_factor"); |                    static_cast<u32>(offsetof(RescalingLayout, rescaling_textures))); | ||||||
|  |     MemberName(push_constant_struct, rescaling_textures_member_index, "rescaling_textures"); | ||||||
|  |  | ||||||
|     const u32 offset_bias = stage == Stage::Compute ? sizeof(u32) : 0; |     MemberDecorate(push_constant_struct, rescaling_images_member_index, spv::Decoration::Offset, | ||||||
|     if (!info.texture_descriptors.empty()) { |                    static_cast<u32>(offsetof(RescalingLayout, rescaling_images))); | ||||||
|         MemberDecorate( |     MemberName(push_constant_struct, rescaling_images_member_index, "rescaling_images"); | ||||||
|             push_constant_struct, rescaling_textures_member_index, spv::Decoration::Offset, |  | ||||||
|             static_cast<u32>(offsetof(RescalingLayout, rescaling_textures) - offset_bias)); |     if (stage != Stage::Compute) { | ||||||
|         MemberName(push_constant_struct, rescaling_textures_member_index, "rescaling_textures"); |         MemberDecorate(push_constant_struct, rescaling_downfactor_member_index, | ||||||
|     } |                        spv::Decoration::Offset, | ||||||
|     if (!info.image_descriptors.empty()) { |                        static_cast<u32>(offsetof(RescalingLayout, down_factor))); | ||||||
|         MemberDecorate(push_constant_struct, rescaling_images_member_index, spv::Decoration::Offset, |         MemberName(push_constant_struct, rescaling_downfactor_member_index, "down_factor"); | ||||||
|                        static_cast<u32>(offsetof(RescalingLayout, rescaling_images) - offset_bias)); |  | ||||||
|         MemberName(push_constant_struct, rescaling_images_member_index, "rescaling_images"); |  | ||||||
|     } |     } | ||||||
|     const Id pointer_type{TypePointer(spv::StorageClass::PushConstant, push_constant_struct)}; |     const Id pointer_type{TypePointer(spv::StorageClass::PushConstant, push_constant_struct)}; | ||||||
|     rescaling_push_constants = AddGlobalVariable(pointer_type, spv::StorageClass::PushConstant); |     rescaling_push_constants = AddGlobalVariable(pointer_type, spv::StorageClass::PushConstant); | ||||||
|   | |||||||
| @@ -244,6 +244,7 @@ public: | |||||||
|     Id rescaling_images_type{}; |     Id rescaling_images_type{}; | ||||||
|     u32 rescaling_textures_member_index{}; |     u32 rescaling_textures_member_index{}; | ||||||
|     u32 rescaling_images_member_index{}; |     u32 rescaling_images_member_index{}; | ||||||
|  |     u32 rescaling_downfactor_member_index{}; | ||||||
|     u32 texture_rescaling_index{}; |     u32 texture_rescaling_index{}; | ||||||
|     u32 image_rescaling_index{}; |     u32 image_rescaling_index{}; | ||||||
|  |  | ||||||
| @@ -324,7 +325,7 @@ private: | |||||||
|     void DefineAttributeMemAccess(const Info& info); |     void DefineAttributeMemAccess(const Info& info); | ||||||
|     void DefineGlobalMemoryFunctions(const Info& info); |     void DefineGlobalMemoryFunctions(const Info& info); | ||||||
|     void DefineRescalingInput(const Info& info); |     void DefineRescalingInput(const Info& info); | ||||||
|     void DefineRescalingInputPushConstant(const Info& info); |     void DefineRescalingInputPushConstant(); | ||||||
|     void DefineRescalingInputUniformConstant(); |     void DefineRescalingInputUniformConstant(); | ||||||
|  |  | ||||||
|     void DefineInputs(const IR::Program& program); |     void DefineInputs(const IR::Program& program); | ||||||
|   | |||||||
| @@ -22,11 +22,12 @@ constexpr u32 NUM_TEXTURE_AND_IMAGE_SCALING_WORDS = | |||||||
|     NUM_TEXTURE_SCALING_WORDS + NUM_IMAGE_SCALING_WORDS; |     NUM_TEXTURE_SCALING_WORDS + NUM_IMAGE_SCALING_WORDS; | ||||||
|  |  | ||||||
| struct RescalingLayout { | struct RescalingLayout { | ||||||
|     u32 down_factor; |  | ||||||
|     alignas(16) std::array<u32, NUM_TEXTURE_SCALING_WORDS> rescaling_textures; |     alignas(16) std::array<u32, NUM_TEXTURE_SCALING_WORDS> rescaling_textures; | ||||||
|     alignas(16) std::array<u32, NUM_IMAGE_SCALING_WORDS> rescaling_images; |     alignas(16) std::array<u32, NUM_IMAGE_SCALING_WORDS> rescaling_images; | ||||||
|  |     alignas(16) u32 down_factor; | ||||||
| }; | }; | ||||||
| constexpr u32 RESCALING_PUSH_CONSTANT_WORDS_OFFSET = offsetof(RescalingLayout, rescaling_textures); | constexpr u32 RESCALING_LAYOUT_WORDS_OFFSET = offsetof(RescalingLayout, rescaling_textures); | ||||||
|  | constexpr u32 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET = offsetof(RescalingLayout, down_factor); | ||||||
|  |  | ||||||
| [[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, | [[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, | ||||||
|                                          IR::Program& program, Bindings& bindings); |                                          IR::Program& program, Bindings& bindings); | ||||||
|   | |||||||
| @@ -529,8 +529,8 @@ Id EmitYDirection(EmitContext& ctx) { | |||||||
| Id EmitResolutionDownFactor(EmitContext& ctx) { | Id EmitResolutionDownFactor(EmitContext& ctx) { | ||||||
|     if (ctx.profile.unified_descriptor_binding) { |     if (ctx.profile.unified_descriptor_binding) { | ||||||
|         const Id pointer_type{ctx.TypePointer(spv::StorageClass::PushConstant, ctx.F32[1])}; |         const Id pointer_type{ctx.TypePointer(spv::StorageClass::PushConstant, ctx.F32[1])}; | ||||||
|         const Id pointer{ |         const Id index{ctx.Const(ctx.rescaling_downfactor_member_index)}; | ||||||
|             ctx.OpAccessChain(pointer_type, ctx.rescaling_push_constants, ctx.u32_zero_value)}; |         const Id pointer{ctx.OpAccessChain(pointer_type, ctx.rescaling_push_constants, index)}; | ||||||
|         return ctx.OpLoad(ctx.F32[1], pointer); |         return ctx.OpLoad(ctx.F32[1], pointer); | ||||||
|     } else { |     } else { | ||||||
|         const Id composite{ctx.OpLoad(ctx.F32[4], ctx.rescaling_uniform_constant)}; |         const Id composite{ctx.OpLoad(ctx.F32[4], ctx.rescaling_uniform_constant)}; | ||||||
|   | |||||||
| @@ -22,7 +22,6 @@ | |||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
|  |  | ||||||
| using Shader::Backend::SPIRV::NUM_TEXTURE_AND_IMAGE_SCALING_WORDS; | using Shader::Backend::SPIRV::NUM_TEXTURE_AND_IMAGE_SCALING_WORDS; | ||||||
| using Shader::Backend::SPIRV::RESCALING_PUSH_CONSTANT_WORDS_OFFSET; |  | ||||||
|  |  | ||||||
| class DescriptorLayoutBuilder { | class DescriptorLayoutBuilder { | ||||||
| public: | public: | ||||||
| @@ -73,12 +72,12 @@ public: | |||||||
|  |  | ||||||
|     vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const { |     vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const { | ||||||
|         using Shader::Backend::SPIRV::RescalingLayout; |         using Shader::Backend::SPIRV::RescalingLayout; | ||||||
|         const u32 push_offset = is_compute ? RESCALING_PUSH_CONSTANT_WORDS_OFFSET : 0; |         const u32 size_offset = is_compute ? sizeof(RescalingLayout::down_factor) : 0u; | ||||||
|         const VkPushConstantRange range{ |         const VkPushConstantRange range{ | ||||||
|             .stageFlags = static_cast<VkShaderStageFlags>( |             .stageFlags = static_cast<VkShaderStageFlags>( | ||||||
|                 is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS), |                 is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS), | ||||||
|             .offset = 0, |             .offset = 0, | ||||||
|             .size = sizeof(RescalingLayout) - push_offset, |             .size = sizeof(RescalingLayout) - size_offset, | ||||||
|         }; |         }; | ||||||
|         return device->GetLogical().CreatePipelineLayout({ |         return device->GetLogical().CreatePipelineLayout({ | ||||||
|             .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |             .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||||||
| @@ -139,21 +138,21 @@ private: | |||||||
|  |  | ||||||
| class RescalingPushConstant { | class RescalingPushConstant { | ||||||
| public: | public: | ||||||
|     explicit RescalingPushConstant(u32 num_textures) noexcept {} |     explicit RescalingPushConstant() noexcept {} | ||||||
|  |  | ||||||
|     void PushTexture(bool is_rescaled) noexcept { |     void PushTexture(bool is_rescaled) noexcept { | ||||||
|         *texture_ptr |= is_rescaled ? texture_bit : 0; |         *texture_ptr |= is_rescaled ? texture_bit : 0u; | ||||||
|         texture_bit <<= 1; |         texture_bit <<= 1u; | ||||||
|         if (texture_bit == 0) { |         if (texture_bit == 0u) { | ||||||
|             texture_bit = 1u; |             texture_bit = 1u; | ||||||
|             ++texture_ptr; |             ++texture_ptr; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void PushImage(bool is_rescaled) noexcept { |     void PushImage(bool is_rescaled) noexcept { | ||||||
|         *image_ptr |= is_rescaled ? image_bit : 0; |         *image_ptr |= is_rescaled ? image_bit : 0u; | ||||||
|         image_bit <<= 1; |         image_bit <<= 1u; | ||||||
|         if (image_bit == 0) { |         if (image_bit == 0u) { | ||||||
|             image_bit = 1u; |             image_bit = 1u; | ||||||
|             ++image_ptr; |             ++image_ptr; | ||||||
|         } |         } | ||||||
| @@ -176,8 +175,10 @@ inline void PushImageDescriptors(TextureCache& texture_cache, | |||||||
|                                  const Shader::Info& info, RescalingPushConstant& rescaling, |                                  const Shader::Info& info, RescalingPushConstant& rescaling, | ||||||
|                                  const VkSampler*& samplers, |                                  const VkSampler*& samplers, | ||||||
|                                  const VideoCommon::ImageViewInOut*& views) { |                                  const VideoCommon::ImageViewInOut*& views) { | ||||||
|     views += Shader::NumDescriptors(info.texture_buffer_descriptors); |     const u32 num_texture_buffers = Shader::NumDescriptors(info.texture_buffer_descriptors); | ||||||
|     views += Shader::NumDescriptors(info.image_buffer_descriptors); |     const u32 num_image_buffers = Shader::NumDescriptors(info.image_buffer_descriptors); | ||||||
|  |     views += num_texture_buffers; | ||||||
|  |     views += num_image_buffers; | ||||||
|     for (const auto& desc : info.texture_descriptors) { |     for (const auto& desc : info.texture_descriptors) { | ||||||
|         for (u32 index = 0; index < desc.count; ++index) { |         for (u32 index = 0; index < desc.count; ++index) { | ||||||
|             const VideoCommon::ImageViewId image_view_id{(views++)->id}; |             const VideoCommon::ImageViewId image_view_id{(views++)->id}; | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ | |||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
|  |  | ||||||
| using Shader::ImageBufferDescriptor; | using Shader::ImageBufferDescriptor; | ||||||
|  | using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; | ||||||
| using Tegra::Texture::TexturePair; | using Tegra::Texture::TexturePair; | ||||||
|  |  | ||||||
| ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, | ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, | ||||||
| @@ -185,7 +186,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||||||
|     buffer_cache.UpdateComputeBuffers(); |     buffer_cache.UpdateComputeBuffers(); | ||||||
|     buffer_cache.BindHostComputeBuffers(); |     buffer_cache.BindHostComputeBuffers(); | ||||||
|  |  | ||||||
|     RescalingPushConstant rescaling(num_textures); |     RescalingPushConstant rescaling; | ||||||
|     const VkSampler* samplers_it{samplers.data()}; |     const VkSampler* samplers_it{samplers.data()}; | ||||||
|     const VideoCommon::ImageViewInOut* views_it{views.data()}; |     const VideoCommon::ImageViewInOut* views_it{views.data()}; | ||||||
|     PushImageDescriptors(texture_cache, update_descriptor_queue, info, rescaling, samplers_it, |     PushImageDescriptors(texture_cache, update_descriptor_queue, info, rescaling, samplers_it, | ||||||
| @@ -199,21 +200,24 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|     const void* const descriptor_data{update_descriptor_queue.UpdateData()}; |     const void* const descriptor_data{update_descriptor_queue.UpdateData()}; | ||||||
|     scheduler.Record( |     const bool is_rescaling = !info.texture_descriptors.empty() || !info.image_descriptors.empty(); | ||||||
|         [this, descriptor_data, rescaling_data = rescaling.Data()](vk::CommandBuffer cmdbuf) { |     scheduler.Record([this, descriptor_data, is_rescaling, | ||||||
|             cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); |                       rescaling_data = rescaling.Data()](vk::CommandBuffer cmdbuf) { | ||||||
|             if (!descriptor_set_layout) { |         cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); | ||||||
|                 return; |         if (!descriptor_set_layout) { | ||||||
|             } |             return; | ||||||
|             if (num_textures > 0) { |         } | ||||||
|                 cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, rescaling_data); |         if (is_rescaling) { | ||||||
|             } |             cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, | ||||||
|             const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; |                                  RESCALING_LAYOUT_WORDS_OFFSET, sizeof(rescaling_data), | ||||||
|             const vk::Device& dev{device.GetLogical()}; |                                  rescaling_data.data()); | ||||||
|             dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data); |         } | ||||||
|             cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0, |         const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; | ||||||
|                                       descriptor_set, nullptr); |         const vk::Device& dev{device.GetLogical()}; | ||||||
|         }); |         dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data); | ||||||
|  |         cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0, | ||||||
|  |                                   descriptor_set, nullptr); | ||||||
|  |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Vulkan | } // namespace Vulkan | ||||||
|   | |||||||
| @@ -59,7 +59,6 @@ private: | |||||||
|     vk::PipelineLayout pipeline_layout; |     vk::PipelineLayout pipeline_layout; | ||||||
|     vk::DescriptorUpdateTemplateKHR descriptor_update_template; |     vk::DescriptorUpdateTemplateKHR descriptor_update_template; | ||||||
|     vk::Pipeline pipeline; |     vk::Pipeline pipeline; | ||||||
|     u32 num_textures{}; |  | ||||||
|  |  | ||||||
|     std::condition_variable build_condvar; |     std::condition_variable build_condvar; | ||||||
|     std::mutex build_mutex; |     std::mutex build_mutex; | ||||||
|   | |||||||
| @@ -32,6 +32,8 @@ namespace { | |||||||
| using boost::container::small_vector; | using boost::container::small_vector; | ||||||
| using boost::container::static_vector; | using boost::container::static_vector; | ||||||
| using Shader::ImageBufferDescriptor; | using Shader::ImageBufferDescriptor; | ||||||
|  | using Shader::Backend::SPIRV::RESCALING_LAYOUT_DOWN_FACTOR_OFFSET; | ||||||
|  | using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; | ||||||
| using Tegra::Texture::TexturePair; | using Tegra::Texture::TexturePair; | ||||||
| using VideoCore::Surface::PixelFormat; | using VideoCore::Surface::PixelFormat; | ||||||
| using VideoCore::Surface::PixelFormatFromDepthFormat; | using VideoCore::Surface::PixelFormatFromDepthFormat; | ||||||
| @@ -431,7 +433,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||||||
|  |  | ||||||
|     update_descriptor_queue.Acquire(); |     update_descriptor_queue.Acquire(); | ||||||
|  |  | ||||||
|     RescalingPushConstant rescaling(num_textures); |     RescalingPushConstant rescaling; | ||||||
|     const VkSampler* samplers_it{samplers.data()}; |     const VkSampler* samplers_it{samplers.data()}; | ||||||
|     const VideoCommon::ImageViewInOut* views_it{views.data()}; |     const VideoCommon::ImageViewInOut* views_it{views.data()}; | ||||||
|     const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { |     const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { | ||||||
| @@ -477,15 +479,16 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) { | |||||||
|         if (bind_pipeline) { |         if (bind_pipeline) { | ||||||
|             cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); |             cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); | ||||||
|         } |         } | ||||||
|  |         cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, | ||||||
|  |                              RESCALING_LAYOUT_WORDS_OFFSET, sizeof(rescaling_data), | ||||||
|  |                              rescaling_data.data()); | ||||||
|         if (update_rescaling) { |         if (update_rescaling) { | ||||||
|             const f32 config_down_factor{Settings::values.resolution_info.down_factor}; |             const f32 config_down_factor{Settings::values.resolution_info.down_factor}; | ||||||
|             const f32 scale_down_factor{is_rescaling ? config_down_factor : 1.0f}; |             const f32 scale_down_factor{is_rescaling ? config_down_factor : 1.0f}; | ||||||
|             cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, |             cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, | ||||||
|                                  sizeof(scale_down_factor), &scale_down_factor); |                                  RESCALING_LAYOUT_DOWN_FACTOR_OFFSET, sizeof(scale_down_factor), | ||||||
|  |                                  &scale_down_factor); | ||||||
|         } |         } | ||||||
|         cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, |  | ||||||
|                              RESCALING_PUSH_CONSTANT_WORDS_OFFSET, sizeof(rescaling_data), |  | ||||||
|                              rescaling_data.data()); |  | ||||||
|         if (!descriptor_set_layout) { |         if (!descriptor_set_layout) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user