From 7d694ca7a2fc713bd973e9f4fe50963e21520faf Mon Sep 17 00:00:00 2001 From: Rebekah Rowe Date: Thu, 1 Aug 2024 08:19:24 -0400 Subject: [PATCH] non-working example of how i want descriptor sets to be layed out. --- src/main.cpp | 428 +++++++++++++++++++++++++++++---------------------- 1 file changed, 246 insertions(+), 182 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8597964..f45a4fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -132,10 +132,12 @@ private: return { .codeSize = embeded_shader_frag_glsl_spv.size, .pCode = reinterpret_cast(embeded_shader_frag_glsl_spv.begin) }; } + using Color = glm::vec4; + using TextureCoordinates = glm::vec2; struct Vertex2 { glm::vec2 pos; - glm::vec4 color; - glm::vec2 texture_coordinates; + Color color; + TextureCoordinates texture_coordinates; DrawMode draw_mode; static constexpr vk::ShaderModuleCreateInfo GetShaderInfoFragment() { @@ -185,8 +187,8 @@ private: struct Vertex3 { glm::vec3 pos; - glm::vec4 color; - glm::vec2 texture_coordinates; + Color color; + TextureCoordinates texture_coordinates; DrawMode draw_mode; static constexpr vk::ShaderModuleCreateInfo GetShaderInfoFragment() { @@ -237,6 +239,157 @@ private: }; }; + class Texture { + private: + const VulkanExampleApplication* parent; + + private: + std::uint32_t vk_texture_mip_levels; + VulkanImage vk_texture_image; + + public: + std::optional vk_texture_view; + std::optional vk_texture_sampler; + + public: + std::optional vk_descriptor_sets_second; + std::optional vk_descriptor_sets_third; + + public: + template + constexpr Texture(const VulkanExampleApplication* _parent, const DataT texture_buffer_data, const std::size_t texture_buffer_size, const vk::Extent2D texture_buffer_extent) + : parent(_parent) { + assert(parent != nullptr); + + { // Texture + const auto texture_format = vk::Format::eR8G8B8A8Srgb; + const auto texture_buffer_staging = this->parent->CreateBuffer(texture_buffer_size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); + + this->vk_texture_mip_levels = static_cast(std::floor(std::log2(std::max(texture_buffer_extent.width, texture_buffer_extent.height)))) + 1; + + this->parent->vk_allocator->copyMemoryToAllocation(embeded_debug_north_png_rgba.data.begin, *texture_buffer_staging->second, 0, texture_buffer_size); + + this->vk_texture_image = this->parent->CreateImage(texture_buffer_extent, texture_format, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, vk::MemoryPropertyFlagBits::eDeviceLocal, this->vk_texture_mip_levels, vk::SampleCountFlagBits::e1); + + this->parent->SingleTimeSubmitCommand([&](const auto& command_buffer) { + this->parent->TransitionImageLayout(command_buffer, *this->vk_texture_image->first, texture_format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, this->vk_texture_mip_levels); + this->parent->CopyBuffer(command_buffer, *texture_buffer_staging->first, *this->vk_texture_image->first, texture_buffer_extent); + const auto GenerateMipmaps = [this](const vk::CommandBuffer& command_buffer, const vk::Image& src_image, vk::Format src_format, vk::Extent2D texture_size, std::uint32_t mip_levels) { + assert(mip_levels); + + if (!(this->parent->vk_gfx_card->getFormatProperties(src_format).optimalTilingFeatures & vk::FormatFeatureFlagBits::eSampledImageFilterLinear)) + throw std::runtime_error("texture image format does not support linear blitting!"); + + vk::ImageMemoryBarrier image_memory_barrier { + .srcQueueFamilyIndex = vk::QueueFamilyIgnored, + .dstQueueFamilyIndex = vk::QueueFamilyIgnored, + .image = src_image, + .subresourceRange { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + for (std::uint32_t i = 1; i < mip_levels; i++) { + + image_memory_barrier.subresourceRange.baseMipLevel = i - 1; + image_memory_barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite, + image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead, + image_memory_barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal; + image_memory_barrier.newLayout = vk::ImageLayout::eTransferSrcOptimal, + command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, image_memory_barrier); + + const std::array image_offsets_src { + vk::Offset3D { 0, 0, 0 }, + vk::Offset3D { static_cast(texture_size.width), static_cast(texture_size.height), 1 } + }; + const vk::ImageSubresourceLayers image_subresource_layers_src { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .mipLevel = i - 1, + .baseArrayLayer = 0, + .layerCount = 1 + }; + const std::array image_offsets_dest { + vk::Offset3D { 0, 0, 0 }, + vk::Offset3D { static_cast(texture_size.width) > 1 ? static_cast(texture_size.width) / 2 : 1, static_cast(texture_size.height) > 1 ? static_cast(texture_size.height) / 2 : 1, 1 } + }; + const vk::ImageSubresourceLayers image_subresource_layers_dest { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .mipLevel = i, + .baseArrayLayer = 0, + .layerCount = 1 + }; + + const vk::ImageBlit image_blit { + .srcSubresource = image_subresource_layers_src, + .srcOffsets = image_offsets_src, + .dstSubresource = image_subresource_layers_dest, + .dstOffsets = image_offsets_dest + }; + command_buffer.blitImage(src_image, vk::ImageLayout::eTransferSrcOptimal, src_image, vk::ImageLayout::eTransferDstOptimal, image_blit, vk::Filter::eLinear); + + if (texture_size.width > 1) + texture_size.width /= 2; + if (texture_size.height > 1) + texture_size.height /= 2; + + image_memory_barrier.srcAccessMask = vk::AccessFlagBits::eTransferRead; + image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; + image_memory_barrier.oldLayout = vk::ImageLayout::eTransferSrcOptimal; + image_memory_barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; + command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, nullptr, nullptr, image_memory_barrier); + } + image_memory_barrier.subresourceRange.baseMipLevel = mip_levels - 1; + image_memory_barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; + image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; + image_memory_barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal; + image_memory_barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; + command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, nullptr, nullptr, image_memory_barrier); + }; + GenerateMipmaps(command_buffer, *this->vk_texture_image->first, texture_format, texture_buffer_extent, this->vk_texture_mip_levels); + }); + + this->vk_texture_view = this->parent->CreateImageView(*this->vk_texture_image->first, texture_format, vk::ImageAspectFlagBits::eColor, this->vk_texture_mip_levels); + } + + { // Sampler + const vk::SamplerCreateInfo sampler_create_info { + .magFilter = vk::Filter::eNearest, + .minFilter = vk::Filter::eLinear, + .mipmapMode = vk::SamplerMipmapMode::eLinear, + .addressModeU = vk::SamplerAddressMode::eRepeat, // https://docs.vulkan.org/tutorial/latest/06_Texture_mapping/01_Image_view_and_sampler.html#_samplers + .addressModeV = vk::SamplerAddressMode::eRepeat, + .addressModeW = vk::SamplerAddressMode::eRepeat, + .mipLodBias = 0.0f, + .anisotropyEnable = vk::True, + .maxAnisotropy = std::max(4.0f, this->parent->vk_gfx_card->getProperties().limits.maxSamplerAnisotropy), + .compareEnable = vk::False, + .compareOp = vk::CompareOp::eAlways, + .minLod = 0.0f, + .maxLod = vk::LodClampNone, + .borderColor = vk::BorderColor::eIntOpaqueBlack, + .unnormalizedCoordinates = vk::False, + }; + this->vk_texture_sampler.emplace(*this->parent->vk_gpu, sampler_create_info); + } + { + this->vk_descriptor_sets_second = this->parent->vk_pipeline_second.CreateImageDescriptorSet(*this->vk_texture_view, *this->vk_texture_sampler); + this->vk_descriptor_sets_third = this->parent->vk_pipeline_third.CreateImageDescriptorSet(*this->vk_texture_view, *this->vk_texture_sampler); + } + } + + template + const vk::DescriptorSet& GetDescriptorSet() const { + if constexpr (typeid(VertexT) == typeid(Vertex2)) + return **this->vk_descriptor_sets_second; + if constexpr (typeid(VertexT) == typeid(Vertex3)) + return **this->vk_descriptor_sets_third; + else + assert(false && "Texture: No descriptor set availiable for this type of vertex."); + } + }; + template class VulkanRenderPipeline { private: @@ -252,9 +405,11 @@ private: : parent(_parent) { assert(_parent != nullptr); } public: - std::optional vk_descriptor_set_layout; std::optional vk_descriptor_pool; std::vector vk_descriptor_sets; + std::optional vk_descriptor_set_layouts; + + const Texture* current_texture = nullptr; VulkanBuffer vk_buffer_vertex; // in order to get a clean destruction sequence, instantiate the DeviceMemory for the vertex buffer first // https://github.com/KhronosGroup/Vulkan-Hpp/blob/6f72ceca515d59f40d64b64cf2734f6261e1f9f2/RAII_Samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp VulkanBuffer vk_buffer_index; // used to make rendering models more efficent by sharing values @@ -281,8 +436,9 @@ private: this->vk_shader_vertex.emplace(gpu, VertexT::GetShaderInfoVertex()); this->vk_shader_frag.emplace(gpu, VertexT::GetShaderInfoFragment()); } - { - constexpr auto descriptor_set_layout_bindings = [&]() { + { // descriptor set layouts + + const auto descriptor_set_layout_bindings = []() -> std::vector { constexpr vk::DescriptorSetLayoutBinding descriptor_set_layout_binding_sampler { .binding = 0, .descriptorType = vk::DescriptorType::eCombinedImageSampler, @@ -290,6 +446,7 @@ private: .stageFlags = vk::ShaderStageFlagBits::eFragment, .pImmutableSamplers = nullptr // Optional }; + if constexpr (UsesProjection()) { constexpr vk::DescriptorSetLayoutBinding descriptor_set_layout_binding_ubo { .binding = 1, @@ -298,16 +455,15 @@ private: .stageFlags = vk::ShaderStageFlagBits::eVertex, .pImmutableSamplers = nullptr // Optional }; - return std::array { descriptor_set_layout_binding_sampler, descriptor_set_layout_binding_ubo }; - } else - return std::array { descriptor_set_layout_binding_sampler }; + return { descriptor_set_layout_binding_sampler, descriptor_set_layout_binding_ubo }; + } + return { descriptor_set_layout_binding_sampler }; }(); - const vk::DescriptorSetLayoutCreateInfo descriptor_set_layout_create_info { .bindingCount = static_cast(descriptor_set_layout_bindings.size()), .pBindings = descriptor_set_layout_bindings.data() }; - this->vk_descriptor_set_layout.emplace(gpu, descriptor_set_layout_create_info); + this->vk_descriptor_set_layouts.emplace(gpu, descriptor_set_layout_create_info); } { // Init graphics pipeline/renderpass const vk::PipelineShaderStageCreateInfo shader_stage_create_info_vertex { @@ -406,7 +562,7 @@ private: const vk::PipelineLayoutCreateInfo pipeline_layout_create_info { .setLayoutCount = 1, // Optional - .pSetLayouts = &**this->vk_descriptor_set_layout, // Optional + .pSetLayouts = &**this->vk_descriptor_set_layouts, // Optional //.pushConstantRangeCount = 0, // Optional //.pPushConstantRanges = nullptr // Optional }; @@ -431,7 +587,7 @@ private: }; this->vk_pipeline.emplace(gpu, nullptr, pipeline_create_info); } - if constexpr (UsesProjection()) { // uniform buffer object + if constexpr (UsesProjection()) { // create and map uniform buffer object assert(this->vk_buffers_uniform.empty()); assert(this->vk_buffers_uniform_mapped.empty()); this->vk_buffers_uniform.reserve(this->parent->vk_max_frames_in_flight); @@ -444,16 +600,16 @@ private: this->vk_buffers_uniform.emplace_back(std::move(uniform_buffer)); } } - } - void UpdateDescriptors(const vk::ImageView& texture_view) { - { // update descriptors + { // create descriptor pool + const std::size_t ubo_count = 256; const vk::DescriptorPoolSize descriptor_pool_size_ubo { .type = vk::DescriptorType::eUniformBuffer, - .descriptorCount = static_cast(this->parent->vk_max_frames_in_flight) + .descriptorCount = static_cast(this->parent->vk_max_frames_in_flight) * 2 }; + const std::size_t maximum_texture_count = 256; const vk::DescriptorPoolSize descriptor_pool_size_sampler { .type = vk::DescriptorType::eCombinedImageSampler, - .descriptorCount = static_cast(this->parent->vk_max_frames_in_flight) + .descriptorCount = maximum_texture_count }; const auto descriptor_pool_sizes = [&]() { if constexpr (UsesProjection()) @@ -463,73 +619,85 @@ private: }(); const vk::DescriptorPoolCreateInfo descriptor_pool_create_info { .flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, - .maxSets = static_cast(this->parent->vk_max_frames_in_flight), + .maxSets = maximum_texture_count + (!UsesProjection() ? 0 : ubo_count), .poolSizeCount = static_cast(descriptor_pool_sizes.size()), .pPoolSizes = descriptor_pool_sizes.data(), }; assert(descriptor_pool_create_info.flags & vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet); // requirement, to soothe validation layer complaints this->vk_descriptor_pool.emplace(*this->parent->vk_gpu, descriptor_pool_create_info); - - const std::vector descriptor_set_layouts = std::vector(this->parent->vk_max_frames_in_flight, *this->vk_descriptor_set_layout); + } + { // update descriptor sets + std::vector descriptor_set_layouts; + descriptor_set_layouts.reserve(this->parent->vk_max_frames_in_flight + 1); + descriptor_set_layouts.emplace_back(*this->vk_descriptor_set_layouts); + if constexpr (UsesProjection()) { + const auto addition_layouts = std::vector(this->parent->vk_max_frames_in_flight, *this->vk_descriptor_set_layouts); + descriptor_set_layouts.insert(descriptor_set_layouts.end(), addition_layouts.begin(), addition_layouts.end()); + } const vk::DescriptorSetAllocateInfo descriptor_set_allocate_info { .descriptorPool = **this->vk_descriptor_pool, .descriptorSetCount = static_cast(descriptor_set_layouts.size()), .pSetLayouts = descriptor_set_layouts.data() }; this->vk_descriptor_sets = vk::raii::DescriptorSets(*this->parent->vk_gpu, descriptor_set_allocate_info); - + } + if constexpr (UsesProjection()) { // update ubo descripor sets std::vector write_descriptor_sets; write_descriptor_sets.reserve(this->parent->vk_max_frames_in_flight); - std::vector image_infos; - image_infos.reserve(this->parent->vk_max_frames_in_flight); + std::vector buffer_infos; + buffer_infos.reserve(this->parent->vk_max_frames_in_flight); for (std::size_t i = 0; i < this->parent->vk_max_frames_in_flight; i++) { - const vk::DescriptorImageInfo descriptor_image_info_texture { - .sampler = **this->parent->vk_texture_sampler, - .imageView = texture_view, - .imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal, + const vk::DescriptorBufferInfo descriptor_buffer_info_ubo { + .buffer = *this->vk_buffers_uniform.at(i)->first, + .offset = 0, + .range = sizeof(UniformBufferObject_Projection), }; - const vk::DescriptorImageInfo& descriptor_image_info_handle = image_infos.emplace_back(descriptor_image_info_texture); - const vk::WriteDescriptorSet descriptor_write_texture { + const vk::DescriptorBufferInfo& descriptor_buffer_info_handle = buffer_infos.emplace_back(descriptor_buffer_info_ubo); + + const vk::WriteDescriptorSet descriptor_write_ubo { .dstSet = *this->vk_descriptor_sets[i], - .dstBinding = 0, + .dstBinding = 1, .dstArrayElement = 0, .descriptorCount = 1, - .descriptorType = vk::DescriptorType::eCombinedImageSampler, - .pImageInfo = &descriptor_image_info_handle // Optional + .descriptorType = vk::DescriptorType::eUniformBuffer, + .pImageInfo = nullptr, // Optional + .pBufferInfo = &descriptor_buffer_info_handle, + .pTexelBufferView = nullptr, // Optional }; - write_descriptor_sets.emplace_back(descriptor_write_texture); + write_descriptor_sets.emplace_back(descriptor_write_ubo); } - - std::vector buffer_infos; - if constexpr (UsesProjection()) { - buffer_infos.reserve(this->parent->vk_max_frames_in_flight); - for (std::size_t i = 0; i < this->parent->vk_max_frames_in_flight; i++) { - const vk::DescriptorBufferInfo descriptor_buffer_info_ubo { - .buffer = *this->vk_buffers_uniform.at(i)->first, - .offset = 0, - .range = sizeof(UniformBufferObject_Projection), - }; - const vk::DescriptorBufferInfo& descriptor_buffer_info_handle = buffer_infos.emplace_back(descriptor_buffer_info_ubo); - - const vk::WriteDescriptorSet descriptor_write_ubo { - .dstSet = *this->vk_descriptor_sets[i], - .dstBinding = 1, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = vk::DescriptorType::eUniformBuffer, - .pImageInfo = nullptr, // Optional - .pBufferInfo = &descriptor_buffer_info_handle, - .pTexelBufferView = nullptr, // Optional - }; - write_descriptor_sets.emplace_back(descriptor_write_ubo); - } - } - + std::cout << "UBO DESCRIPTORS" << std::endl; this->parent->vk_gpu->updateDescriptorSets(write_descriptor_sets, nullptr); } } + + vk::raii::DescriptorSet CreateImageDescriptorSet(const vk::raii::ImageView& texture_view, const vk::raii::Sampler& texture_sampler) const { + const vk::DescriptorSetAllocateInfo descriptor_set_allocate_info { + .descriptorPool = **this->vk_descriptor_pool, + .descriptorSetCount = 1, + .pSetLayouts = &**this->vk_descriptor_set_layouts + }; + vk::raii::DescriptorSet descriptor_set = std::move(vk::raii::DescriptorSets(*this->parent->vk_gpu, descriptor_set_allocate_info).front()); + + const vk::DescriptorImageInfo descriptor_image_info_texture { + .sampler = texture_sampler, + .imageView = texture_view, + .imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal, + }; + const vk::WriteDescriptorSet descriptor_write_texture { + .dstSet = *descriptor_set, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = vk::DescriptorType::eCombinedImageSampler, + .pImageInfo = &descriptor_image_info_texture + }; + std::cout << "SAMPLER_TEXTURES DESCRIPTORS" << std::endl; + this->parent->vk_gpu->updateDescriptorSets({ descriptor_write_texture }, nullptr); + return descriptor_set; + } void ReplaceModelInfo(const std::vector& vertices, const std::vector& indexes) { const auto vertex_buffer_size = sizeof(VertexT) * vertices.size(); const auto vertex_buffer_staging = this->parent->CreateBuffer(vertex_buffer_size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); @@ -566,11 +734,19 @@ private: ubo.proj[1][1] *= -1; // "GLM was originally designed for OpenGL, where the Y coordinate of the clip coordinates is inverted." - so it will flip the image to correct. } memcpy(this->vk_buffers_uniform_mapped[current_image], &ubo, sizeof(ubo)); + } else { + static_assert(false && "Uniform Buffer Object only available using 3d"); } } + void BindTexture(const Texture& t) { + this->current_texture = &t; + } void Bind(const vk::raii::CommandBuffer& command_buffer, const std::size_t frame_index) const { + assert(this->current_texture != nullptr); + command_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, **this->vk_pipeline); - command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *this->vk_pipeline_layout, 0, *this->vk_descriptor_sets[frame_index], nullptr); + const auto descriptor_sets = std::array { *this->vk_descriptor_sets[frame_index], this->current_texture->GetDescriptorSet() }; + command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *this->vk_pipeline_layout, 0, descriptor_sets, nullptr); command_buffer.bindVertexBuffers(0, { *this->vk_buffer_vertex->first }, { 0 }); command_buffer.bindIndexBuffer(*this->vk_buffer_index->first, 0, vk::IndexType::eUint16); } @@ -613,10 +789,7 @@ private: std::optional vk_depth_view; private: - std::uint32_t vk_texture_mip_levels; - VulkanImage vk_texture_image; - std::optional vk_texture_view; - std::optional vk_texture_sampler; + std::optional vk_texture; public: VulkanExampleApplication() @@ -1057,122 +1230,11 @@ public: } { // texture - const auto texture_format = vk::Format::eR8G8B8A8Srgb; - const auto texture_buffer_size = embeded_debug_north_png_rgba.data.size; - const vk::Extent2D texture_buffer_extent = { .width = static_cast(embeded_debug_north_png_rgba.width), .height = static_cast(embeded_debug_north_png_rgba.height) }; - const auto texture_buffer_staging = this->CreateBuffer(texture_buffer_size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); - - this->vk_texture_mip_levels = static_cast(std::floor(std::log2(std::max(texture_buffer_extent.width, texture_buffer_extent.height)))) + 1; - - this->vk_allocator->copyMemoryToAllocation(embeded_debug_north_png_rgba.data.begin, *texture_buffer_staging->second, 0, texture_buffer_size); - - this->vk_texture_image = CreateImage(texture_buffer_extent, texture_format, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, vk::MemoryPropertyFlagBits::eDeviceLocal, this->vk_texture_mip_levels, vk::SampleCountFlagBits::e1); - - this->SingleTimeSubmitCommand([&](const auto& command_buffer) { - this->TransitionImageLayout(command_buffer, *this->vk_texture_image->first, texture_format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, this->vk_texture_mip_levels); - this->CopyBuffer(command_buffer, *texture_buffer_staging->first, *this->vk_texture_image->first, texture_buffer_extent); - const auto GenerateMipmaps = [this](const vk::CommandBuffer& command_buffer, const vk::Image& src_image, vk::Format src_format, vk::Extent2D texture_size, std::uint32_t mip_levels) { - assert(mip_levels); - - if (!(this->vk_gfx_card->getFormatProperties(src_format).optimalTilingFeatures & vk::FormatFeatureFlagBits::eSampledImageFilterLinear)) - throw std::runtime_error("texture image format does not support linear blitting!"); - - vk::ImageMemoryBarrier image_memory_barrier { - .srcQueueFamilyIndex = vk::QueueFamilyIgnored, - .dstQueueFamilyIndex = vk::QueueFamilyIgnored, - .image = src_image, - .subresourceRange { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - for (std::uint32_t i = 1; i < mip_levels; i++) { - - image_memory_barrier.subresourceRange.baseMipLevel = i - 1; - image_memory_barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite, - image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead, - image_memory_barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal; - image_memory_barrier.newLayout = vk::ImageLayout::eTransferSrcOptimal, - command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, image_memory_barrier); - - const std::array image_offsets_src { - vk::Offset3D { 0, 0, 0 }, - vk::Offset3D { static_cast(texture_size.width), static_cast(texture_size.height), 1 } - }; - const vk::ImageSubresourceLayers image_subresource_layers_src { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .mipLevel = i - 1, - .baseArrayLayer = 0, - .layerCount = 1 - }; - const std::array image_offsets_dest { - vk::Offset3D { 0, 0, 0 }, - vk::Offset3D { static_cast(texture_size.width) > 1 ? static_cast(texture_size.width) / 2 : 1, static_cast(texture_size.height) > 1 ? static_cast(texture_size.height) / 2 : 1, 1 } - }; - const vk::ImageSubresourceLayers image_subresource_layers_dest { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .mipLevel = i, - .baseArrayLayer = 0, - .layerCount = 1 - }; - - const vk::ImageBlit image_blit { - .srcSubresource = image_subresource_layers_src, - .srcOffsets = image_offsets_src, - .dstSubresource = image_subresource_layers_dest, - .dstOffsets = image_offsets_dest - }; - command_buffer.blitImage(src_image, vk::ImageLayout::eTransferSrcOptimal, src_image, vk::ImageLayout::eTransferDstOptimal, image_blit, vk::Filter::eLinear); - - if (texture_size.width > 1) - texture_size.width /= 2; - if (texture_size.height > 1) - texture_size.height /= 2; - - image_memory_barrier.srcAccessMask = vk::AccessFlagBits::eTransferRead; - image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; - image_memory_barrier.oldLayout = vk::ImageLayout::eTransferSrcOptimal; - image_memory_barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; - command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, nullptr, nullptr, image_memory_barrier); - } - image_memory_barrier.subresourceRange.baseMipLevel = mip_levels - 1; - image_memory_barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; - image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; - image_memory_barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal; - image_memory_barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; - command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, nullptr, nullptr, image_memory_barrier); - }; - GenerateMipmaps(command_buffer, *this->vk_texture_image->first, texture_format, texture_buffer_extent, this->vk_texture_mip_levels); - }); - - this->vk_texture_view = this->CreateImageView(*this->vk_texture_image->first, texture_format, vk::ImageAspectFlagBits::eColor, this->vk_texture_mip_levels); - } - { // Sampler - const vk::SamplerCreateInfo sampler_create_info { - .magFilter = vk::Filter::eNearest, - .minFilter = vk::Filter::eLinear, - .mipmapMode = vk::SamplerMipmapMode::eLinear, - .addressModeU = vk::SamplerAddressMode::eRepeat, // https://docs.vulkan.org/tutorial/latest/06_Texture_mapping/01_Image_view_and_sampler.html#_samplers - .addressModeV = vk::SamplerAddressMode::eRepeat, - .addressModeW = vk::SamplerAddressMode::eRepeat, - .mipLodBias = 0.0f, - .anisotropyEnable = vk::True, - .maxAnisotropy = std::max(4.0f, this->vk_gfx_card->getProperties().limits.maxSamplerAnisotropy), - .compareEnable = vk::False, - .compareOp = vk::CompareOp::eAlways, - .minLod = 0.0f, - .maxLod = vk::LodClampNone, - .borderColor = vk::BorderColor::eIntOpaqueBlack, - .unnormalizedCoordinates = vk::False, - }; - this->vk_texture_sampler.emplace(*this->vk_gpu, sampler_create_info); - } - { - this->vk_pipeline_second.UpdateDescriptors(*this->vk_texture_view); - this->vk_pipeline_third.UpdateDescriptors(*this->vk_texture_view); + this->vk_texture.emplace(this, embeded_debug_north_png_rgba.data.begin, embeded_debug_north_png_rgba.data.size, vk::Extent2D { .width = static_cast(embeded_debug_north_png_rgba.width), .height = static_cast(embeded_debug_north_png_rgba.height) }); + this->vk_pipeline_second.BindTexture(*this->vk_texture); + this->vk_pipeline_third.BindTexture(*this->vk_texture); } + } catch (const vk::SystemError& error) { std::cout << "Received Vulkan-Specific Error during process init: " << error.what() << std::endl << "Going to rethrow!" << std::endl; @@ -1740,8 +1802,10 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanExampleApplication_VulkanDebugCallba if (message_severity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { if constexpr (fatal_errors) { const std::string_view msg = callback_data->pMessage; - if (!msg.starts_with("loader_scanned_icd_add: Could not get 'vkCreateInstance' via 'vk_icdGetInstanceProcAddr'")) + if (!msg.starts_with("loader_scanned_icd_add: Could not get 'vkCreateInstance' via 'vk_icdGetInstanceProcAddr'")) { + *reinterpret_cast(5) = 5; throw std::logic_error(std::string("Received Vulkan-ValidationLayer Error: ") + callback_data->pMessage); + } } } return vk::False;