non-working example of how i want descriptor sets to be layed out.
All checks were successful
ci/woodpecker/push/woodpecker.json Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker.json Pipeline was successful
This commit is contained in:
parent
61738cd4b3
commit
7d694ca7a2
428
src/main.cpp
428
src/main.cpp
@ -132,10 +132,12 @@ private:
|
||||
return { .codeSize = embeded_shader_frag_glsl_spv.size, .pCode = reinterpret_cast<const std::uint32_t*>(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::raii::ImageView> vk_texture_view;
|
||||
std::optional<vk::raii::Sampler> vk_texture_sampler;
|
||||
|
||||
public:
|
||||
std::optional<vk::raii::DescriptorSet> vk_descriptor_sets_second;
|
||||
std::optional<vk::raii::DescriptorSet> vk_descriptor_sets_third;
|
||||
|
||||
public:
|
||||
template <class DataT>
|
||||
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::uint32_t>(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<vk::Offset3D, 2> image_offsets_src {
|
||||
vk::Offset3D { 0, 0, 0 },
|
||||
vk::Offset3D { static_cast<int32_t>(texture_size.width), static_cast<int32_t>(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<vk::Offset3D, 2> image_offsets_dest {
|
||||
vk::Offset3D { 0, 0, 0 },
|
||||
vk::Offset3D { static_cast<int32_t>(texture_size.width) > 1 ? static_cast<int32_t>(texture_size.width) / 2 : 1, static_cast<int32_t>(texture_size.height) > 1 ? static_cast<int32_t>(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<float>(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 <typename VertexT>
|
||||
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 <typename VertexT>
|
||||
class VulkanRenderPipeline {
|
||||
private:
|
||||
@ -252,9 +405,11 @@ private:
|
||||
: parent(_parent) { assert(_parent != nullptr); }
|
||||
|
||||
public:
|
||||
std::optional<vk::raii::DescriptorSetLayout> vk_descriptor_set_layout;
|
||||
std::optional<vk::raii::DescriptorPool> vk_descriptor_pool;
|
||||
std::vector<vk::raii::DescriptorSet> vk_descriptor_sets;
|
||||
std::optional<vk::raii::DescriptorSetLayout> 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<vk::DescriptorSetLayoutBinding> {
|
||||
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<vk::DescriptorSetLayoutBinding, 2> { descriptor_set_layout_binding_sampler, descriptor_set_layout_binding_ubo };
|
||||
} else
|
||||
return std::array<vk::DescriptorSetLayoutBinding, 1> { 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<std::uint32_t>(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<std::uint32_t>(this->parent->vk_max_frames_in_flight)
|
||||
.descriptorCount = static_cast<std::uint32_t>(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<std::uint32_t>(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<std::uint32_t>(this->parent->vk_max_frames_in_flight),
|
||||
.maxSets = maximum_texture_count + (!UsesProjection() ? 0 : ubo_count),
|
||||
.poolSizeCount = static_cast<std::uint32_t>(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<vk::DescriptorSetLayout> descriptor_set_layouts = std::vector<vk::DescriptorSetLayout>(this->parent->vk_max_frames_in_flight, *this->vk_descriptor_set_layout);
|
||||
}
|
||||
{ // update descriptor sets
|
||||
std::vector<vk::DescriptorSetLayout> 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<vk::DescriptorSetLayout>(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<std::uint32_t>(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<vk::WriteDescriptorSet> write_descriptor_sets;
|
||||
write_descriptor_sets.reserve(this->parent->vk_max_frames_in_flight);
|
||||
|
||||
std::vector<vk::DescriptorImageInfo> image_infos;
|
||||
image_infos.reserve(this->parent->vk_max_frames_in_flight);
|
||||
std::vector<vk::DescriptorBufferInfo> 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<vk::DescriptorBufferInfo> 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<VertexT>& vertices, const std::vector<IndexT>& 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<vk::DescriptorSet, 2> { *this->vk_descriptor_sets[frame_index], this->current_texture->GetDescriptorSet<VertexT>() };
|
||||
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::raii::ImageView> vk_depth_view;
|
||||
|
||||
private:
|
||||
std::uint32_t vk_texture_mip_levels;
|
||||
VulkanImage vk_texture_image;
|
||||
std::optional<vk::raii::ImageView> vk_texture_view;
|
||||
std::optional<vk::raii::Sampler> vk_texture_sampler;
|
||||
std::optional<Texture> 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<std::uint32_t>(embeded_debug_north_png_rgba.width), .height = static_cast<std::uint32_t>(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::uint32_t>(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<vk::Offset3D, 2> image_offsets_src {
|
||||
vk::Offset3D { 0, 0, 0 },
|
||||
vk::Offset3D { static_cast<int32_t>(texture_size.width), static_cast<int32_t>(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<vk::Offset3D, 2> image_offsets_dest {
|
||||
vk::Offset3D { 0, 0, 0 },
|
||||
vk::Offset3D { static_cast<int32_t>(texture_size.width) > 1 ? static_cast<int32_t>(texture_size.width) / 2 : 1, static_cast<int32_t>(texture_size.height) > 1 ? static_cast<int32_t>(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<float>(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<std::uint32_t>(embeded_debug_north_png_rgba.width), .height = static_cast<std::uint32_t>(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<std::uint8_t*>(5) = 5;
|
||||
throw std::logic_error(std::string("Received Vulkan-ValidationLayer Error: ") + callback_data->pMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
return vk::False;
|
||||
|
Loading…
x
Reference in New Issue
Block a user