Start Rendering a debug Test Image on our Plane.
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
18a990133f
commit
30ed1f679b
@ -191,12 +191,14 @@ public:
|
|||||||
if (type STREQUAL "image")
|
if (type STREQUAL "image")
|
||||||
cmake_path(GET file_path PARENT_PATH file_parent)
|
cmake_path(GET file_path PARENT_PATH file_parent)
|
||||||
cmake_path(GET file_path FILENAME file_name)
|
cmake_path(GET file_path FILENAME file_name)
|
||||||
exec_program("${ImageMagick_identify_EXECUTABLE}" "${file_parent}"
|
execute_process(COMMAND "${ImageMagick_identify_EXECUTABLE}" -format "%[fx:w]" "${file_name}"
|
||||||
ARGS -format "%[fx:w]" "${file_name}"
|
WORKING_DIRECTORY "${file_parent}"
|
||||||
OUTPUT_VARIABLE image_width)
|
OUTPUT_VARIABLE image_width
|
||||||
exec_program("${ImageMagick_identify_EXECUTABLE}" "${file_parent}"
|
COMMAND_ERROR_IS_FATAL ANY)
|
||||||
ARGS -format "%[fx:h]" "${file_name}"
|
execute_process(COMMAND "${ImageMagick_identify_EXECUTABLE}" -format "%[fx:h]" "${file_name}"
|
||||||
OUTPUT_VARIABLE image_height)
|
WORKING_DIRECTORY "${file_parent}"
|
||||||
|
OUTPUT_VARIABLE image_height
|
||||||
|
COMMAND_ERROR_IS_FATAL ANY)
|
||||||
file(APPEND "${EMBED_HEADER_DIR}/embed_resources.hpp" "inline EmbededImage embeded_${obj_cleaned_name}(${image_width}, ${image_height}, EmbededResource(&_binary_${obj_cleaned_name}_start, &_binary_${obj_cleaned_name}_end)); \n")
|
file(APPEND "${EMBED_HEADER_DIR}/embed_resources.hpp" "inline EmbededImage embeded_${obj_cleaned_name}(${image_width}, ${image_height}, EmbededResource(&_binary_${obj_cleaned_name}_start, &_binary_${obj_cleaned_name}_end)); \n")
|
||||||
|
|
||||||
elseif (type STREQUAL "embed")
|
elseif (type STREQUAL "embed")
|
||||||
@ -206,7 +208,7 @@ public:
|
|||||||
endforeach()
|
endforeach()
|
||||||
set(EMBED_OBJ_RET "${EMBED_OBJ_RET}" PARENT_SCOPE)
|
set(EMBED_OBJ_RET "${EMBED_OBJ_RET}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
EmbedResources(${SHADILER_OBJ_RET})
|
EmbedResources(${SHADILER_OBJ_RET} "${CMAKE_CURRENT_SOURCE_DIR}/res/debug_north.png")
|
||||||
|
|
||||||
target_sources(${PROJECT_NAME} PRIVATE ${EMBED_OBJ_RET})
|
target_sources(${PROJECT_NAME} PRIVATE ${EMBED_OBJ_RET})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC "${EMBED_HEADER_DIR}")
|
target_include_directories(${PROJECT_NAME} PUBLIC "${EMBED_HEADER_DIR}")
|
||||||
|
BIN
res/debug_north.png
Normal file
BIN
res/debug_north.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
@ -19,9 +19,12 @@
|
|||||||
|
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) out vec4 out_color;
|
|
||||||
layout(location = 0) in vec3 frag_color;
|
layout(location = 0) in vec3 frag_color;
|
||||||
|
layout(location = 1) in vec2 frag_texture_coordinate;
|
||||||
|
layout(binding = 1) uniform sampler2D texture_sampler;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 out_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
out_color = vec4(frag_color, 1.0);
|
out_color = texture(texture_sampler, frag_texture_coordinate);
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,13 @@ layout(binding = 0) uniform UniformBufferObject {
|
|||||||
|
|
||||||
layout(location = 0) in vec2 in_position;
|
layout(location = 0) in vec2 in_position;
|
||||||
layout(location = 2) in vec3 in_color;
|
layout(location = 2) in vec3 in_color;
|
||||||
|
layout(location = 4) in vec2 in_texture_coordinate;
|
||||||
|
|
||||||
layout(location = 0) out vec3 frag_color;
|
layout(location = 0) out vec3 frag_color;
|
||||||
|
layout(location = 1) out vec2 frag_texture_coordinate;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(in_position, 0.0, 1.0);
|
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(in_position, 0.0, 1.0);
|
||||||
//gl_Position = vec4(, 0.5, 1.0);
|
|
||||||
frag_color = in_color;
|
frag_color = in_color;
|
||||||
|
frag_texture_coordinate = in_texture_coordinate;
|
||||||
}
|
}
|
||||||
|
357
src/main.cpp
357
src/main.cpp
@ -68,7 +68,8 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugCallback(
|
|||||||
|
|
||||||
class VulkanExampleApplication {
|
class VulkanExampleApplication {
|
||||||
private:
|
private:
|
||||||
using VulkanBuffers = std::pair<std::unique_ptr<vk::raii::Buffer>, std::unique_ptr<vk::raii::DeviceMemory>>;
|
using VulkanBuffer = std::pair<std::unique_ptr<vk::raii::Buffer>, std::unique_ptr<vk::raii::DeviceMemory>>;
|
||||||
|
using VulkanImage = std::pair<std::unique_ptr<vk::raii::Image>, std::unique_ptr<vk::raii::DeviceMemory>>;
|
||||||
|
|
||||||
std::unique_ptr<SDL2pp::SDL> libsdl;
|
std::unique_ptr<SDL2pp::SDL> libsdl;
|
||||||
std::unique_ptr<SDL2pp::Window> window;
|
std::unique_ptr<SDL2pp::Window> window;
|
||||||
@ -119,12 +120,13 @@ private:
|
|||||||
} vk_physical_card_info;
|
} vk_physical_card_info;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VulkanBuffers vk_buffer_vertex; // in order to get a clean desctruction 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_vertex; // in order to get a clean desctruction sequence, instantiate the DeviceMemory for the vertex buffer first // https://github.com/KhronosGroup/Vulkan-Hpp/blob/6f72ceca515d59f40d64b64cf2734f6261e1f9f2/RAII_Samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp
|
||||||
VulkanBuffers vk_buffer_index; // used to make rendering models more efficent by sharing values
|
VulkanBuffer vk_buffer_index; // used to make rendering models more efficent by sharing values
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
glm::vec2 pos;
|
glm::vec2 pos;
|
||||||
glm::vec3 color;
|
glm::vec3 color;
|
||||||
|
glm::vec2 texture_coordinates;
|
||||||
|
|
||||||
static constexpr vk::VertexInputBindingDescription GetBindingDescription() {
|
static constexpr vk::VertexInputBindingDescription GetBindingDescription() {
|
||||||
constexpr vk::VertexInputBindingDescription binding_description {
|
constexpr vk::VertexInputBindingDescription binding_description {
|
||||||
@ -134,8 +136,8 @@ public:
|
|||||||
};
|
};
|
||||||
return binding_description;
|
return binding_description;
|
||||||
}
|
}
|
||||||
static constexpr std::array<vk::VertexInputAttributeDescription, 2> GetAttributeDescriptions() {
|
static constexpr std::array<vk::VertexInputAttributeDescription, 3> GetAttributeDescriptions() {
|
||||||
constexpr std::array<vk::VertexInputAttributeDescription, 2> attribute_descriptions {
|
constexpr std::array<vk::VertexInputAttributeDescription, 3> attribute_descriptions {
|
||||||
vk::VertexInputAttributeDescription { // https://docs.vulkan.org/tutorial/latest/04_Vertex_buffers/00_Vertex_input_description.html
|
vk::VertexInputAttributeDescription { // https://docs.vulkan.org/tutorial/latest/04_Vertex_buffers/00_Vertex_input_description.html
|
||||||
.location = 0,
|
.location = 0,
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
@ -145,16 +147,22 @@ public:
|
|||||||
.location = 2,
|
.location = 2,
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
.format = vk::Format::eR32G32B32Sfloat,
|
||||||
.offset = offsetof(Vertex, color) }
|
.offset = offsetof(Vertex, color) },
|
||||||
|
vk::VertexInputAttributeDescription {
|
||||||
|
.location = 4,
|
||||||
|
.binding = 0,
|
||||||
|
.format = vk::Format::eR32G32Sfloat,
|
||||||
|
.offset = offsetof(Vertex, texture_coordinates) }
|
||||||
|
|
||||||
};
|
};
|
||||||
return attribute_descriptions;
|
return attribute_descriptions;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static inline const std::vector<Vertex> quad_vertices = {
|
static inline const std::vector<Vertex> quad_vertices = {
|
||||||
{ { -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f } },
|
{ { -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f } },
|
||||||
{ { 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f } },
|
{ { 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f } },
|
||||||
{ { 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f } },
|
{ { 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } },
|
||||||
{ { -0.5f, 0.5f }, { 1.0f, 1.0f, 1.0f } }
|
{ { -0.5f, 0.5f }, { 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f } }
|
||||||
};
|
};
|
||||||
static inline const std::vector<std::uint16_t> quad_indexes = {
|
static inline const std::vector<std::uint16_t> quad_indexes = {
|
||||||
0, 1, 2, 2, 3, 0 // Wraps a quad-box's 2 triangles around itself. // https://docs.vulkan.org/tutorial/latest/04_Vertex_buffers/03_Index_buffer.html
|
0, 1, 2, 2, 3, 0 // Wraps a quad-box's 2 triangles around itself. // https://docs.vulkan.org/tutorial/latest/04_Vertex_buffers/03_Index_buffer.html
|
||||||
@ -167,9 +175,14 @@ public:
|
|||||||
alignas(16) glm::mat4 view;
|
alignas(16) glm::mat4 view;
|
||||||
alignas(16) glm::mat4 proj;
|
alignas(16) glm::mat4 proj;
|
||||||
};
|
};
|
||||||
std::vector<VulkanBuffers> vk_buffers_uniform;
|
std::vector<VulkanBuffer> vk_buffers_uniform;
|
||||||
std::vector<std::uint8_t*> vk_buffers_uniform_mapped;
|
std::vector<std::uint8_t*> vk_buffers_uniform_mapped;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VulkanImage vk_texture_image;
|
||||||
|
std::unique_ptr<vk::raii::ImageView> vk_texture_view;
|
||||||
|
std::unique_ptr<vk::raii::Sampler> vk_texture_sampler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VulkanExampleApplication() {
|
VulkanExampleApplication() {
|
||||||
try { // try me // all the code is in init :O boo hoo, ill shove all ur ram out of scope ASAP i can, dont seperate them, just scope them instead dumb dumb.
|
try { // try me // all the code is in init :O boo hoo, ill shove all ur ram out of scope ASAP i can, dont seperate them, just scope them instead dumb dumb.
|
||||||
@ -304,6 +317,9 @@ public:
|
|||||||
if (!VulkanCheckDeviceExtensionSupport(gfx_card))
|
if (!VulkanCheckDeviceExtensionSupport(gfx_card))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (!device_features.samplerAnisotropy)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret.surface_capabilities = gfx_card.getSurfaceCapabilitiesKHR(*found_screen_surface);
|
ret.surface_capabilities = gfx_card.getSurfaceCapabilitiesKHR(*found_screen_surface);
|
||||||
const auto surface_present_modes = gfx_card.getSurfacePresentModesKHR(*found_screen_surface);
|
const auto surface_present_modes = gfx_card.getSurfacePresentModesKHR(*found_screen_surface);
|
||||||
const auto surface_formats = gfx_card.getSurfaceFormatsKHR(*found_screen_surface);
|
const auto surface_formats = gfx_card.getSurfaceFormatsKHR(*found_screen_surface);
|
||||||
@ -352,7 +368,9 @@ public:
|
|||||||
return device_queues_we_need;
|
return device_queues_we_need;
|
||||||
}(this->vk_physical_card_info.graphics_family.value(), this->vk_physical_card_info.present_family.value());
|
}(this->vk_physical_card_info.graphics_family.value(), this->vk_physical_card_info.present_family.value());
|
||||||
|
|
||||||
constexpr vk::PhysicalDeviceFeatures device_features {};
|
constexpr vk::PhysicalDeviceFeatures device_features {
|
||||||
|
.samplerAnisotropy = vk::True
|
||||||
|
};
|
||||||
const vk::DeviceCreateInfo device_create_info {
|
const vk::DeviceCreateInfo device_create_info {
|
||||||
.queueCreateInfoCount = static_cast<uint32_t>(device_queue_create_infos.size()),
|
.queueCreateInfoCount = static_cast<uint32_t>(device_queue_create_infos.size()),
|
||||||
.pQueueCreateInfos = device_queue_create_infos.data(),
|
.pQueueCreateInfos = device_queue_create_infos.data(),
|
||||||
@ -552,16 +570,25 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Descriptor Layouts, appears required.
|
// Descriptor Layouts, appears required.
|
||||||
constexpr auto descriptor_set_layout_binding_ubo = vk::DescriptorSetLayoutBinding {
|
constexpr vk::DescriptorSetLayoutBinding descriptor_set_layout_binding_ubo {
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
||||||
.pImmutableSamplers = nullptr // Optional
|
.pImmutableSamplers = nullptr // Optional
|
||||||
};
|
};
|
||||||
const auto descriptor_set_layout_create_info = vk::DescriptorSetLayoutCreateInfo {
|
constexpr vk::DescriptorSetLayoutBinding descriptor_set_layout_binding_sampler {
|
||||||
.bindingCount = 1,
|
.binding = 1,
|
||||||
.pBindings = &descriptor_set_layout_binding_ubo
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
.pImmutableSamplers = nullptr // Optional
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::array<vk::DescriptorSetLayoutBinding, 2> descriptor_set_layout_bindings = { descriptor_set_layout_binding_ubo, descriptor_set_layout_binding_sampler };
|
||||||
|
const vk::DescriptorSetLayoutCreateInfo descriptor_set_layout_create_info {
|
||||||
|
.bindingCount = static_cast<uint32_t>(descriptor_set_layout_bindings.size()),
|
||||||
|
.pBindings = descriptor_set_layout_bindings.data()
|
||||||
};
|
};
|
||||||
this->vk_descriptor_set_layout_ubo = std::make_unique<vk::raii::DescriptorSetLayout>(*this->vk_gpu, descriptor_set_layout_create_info);
|
this->vk_descriptor_set_layout_ubo = std::make_unique<vk::raii::DescriptorSetLayout>(*this->vk_gpu, descriptor_set_layout_create_info);
|
||||||
|
|
||||||
@ -575,15 +602,20 @@ public:
|
|||||||
this->vk_pipeline_layout = std::make_unique<vk::raii::PipelineLayout>(*this->vk_gpu, pipeline_layout_create_info);
|
this->vk_pipeline_layout = std::make_unique<vk::raii::PipelineLayout>(*this->vk_gpu, pipeline_layout_create_info);
|
||||||
|
|
||||||
// descriptors
|
// descriptors
|
||||||
const vk::DescriptorPoolSize descriptor_pool_size {
|
const vk::DescriptorPoolSize descriptor_pool_size_ubo {
|
||||||
.type = vk::DescriptorType::eUniformBuffer,
|
.type = vk::DescriptorType::eUniformBuffer,
|
||||||
.descriptorCount = static_cast<uint32_t>(this->vk_max_frames_in_flight)
|
.descriptorCount = static_cast<uint32_t>(this->vk_max_frames_in_flight)
|
||||||
};
|
};
|
||||||
|
const vk::DescriptorPoolSize descriptor_pool_size_sampler {
|
||||||
|
.type = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.descriptorCount = static_cast<uint32_t>(this->vk_max_frames_in_flight)
|
||||||
|
};
|
||||||
|
const std::array<vk::DescriptorPoolSize, 2> descriptor_pool_sizes = { descriptor_pool_size_ubo, descriptor_pool_size_sampler };
|
||||||
const vk::DescriptorPoolCreateInfo descriptor_pool_create_info {
|
const vk::DescriptorPoolCreateInfo descriptor_pool_create_info {
|
||||||
.flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
|
.flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
|
||||||
.maxSets = static_cast<uint32_t>(this->vk_max_frames_in_flight),
|
.maxSets = static_cast<uint32_t>(this->vk_max_frames_in_flight),
|
||||||
.poolSizeCount = 1,
|
.poolSizeCount = static_cast<uint32_t>(descriptor_pool_sizes.size()),
|
||||||
.pPoolSizes = &descriptor_pool_size,
|
.pPoolSizes = descriptor_pool_sizes.data(),
|
||||||
};
|
};
|
||||||
assert(descriptor_pool_create_info.flags & vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet);
|
assert(descriptor_pool_create_info.flags & vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet);
|
||||||
this->vk_descriptor_pool = std::make_unique<vk::raii::DescriptorPool>(*this->vk_gpu, descriptor_pool_create_info);
|
this->vk_descriptor_pool = std::make_unique<vk::raii::DescriptorPool>(*this->vk_gpu, descriptor_pool_create_info);
|
||||||
@ -717,7 +749,7 @@ public:
|
|||||||
this->vk_fences_in_flight.emplace_back(*this->vk_gpu, vk::FenceCreateInfo { .flags = vk::FenceCreateFlagBits::eSignaled });
|
this->vk_fences_in_flight.emplace_back(*this->vk_gpu, vk::FenceCreateInfo { .flags = vk::FenceCreateFlagBits::eSignaled });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{ // uniform buffer object
|
||||||
assert(this->vk_buffers_uniform.empty());
|
assert(this->vk_buffers_uniform.empty());
|
||||||
assert(this->vk_buffers_uniform_mapped.empty());
|
assert(this->vk_buffers_uniform_mapped.empty());
|
||||||
this->vk_buffers_uniform.reserve(this->vk_max_frames_in_flight);
|
this->vk_buffers_uniform.reserve(this->vk_max_frames_in_flight);
|
||||||
@ -728,19 +760,71 @@ public:
|
|||||||
this->vk_buffers_uniform_mapped.emplace_back(static_cast<std::uint8_t*>(uniform_buffer.second->mapMemory(0, ubo_buffer_size)));
|
this->vk_buffers_uniform_mapped.emplace_back(static_cast<std::uint8_t*>(uniform_buffer.second->mapMemory(0, ubo_buffer_size)));
|
||||||
this->vk_buffers_uniform.emplace_back(std::move(uniform_buffer));
|
this->vk_buffers_uniform.emplace_back(std::move(uniform_buffer));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
{ // texture
|
||||||
|
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);
|
||||||
|
|
||||||
|
std::uint8_t* const texture_buffer_data = static_cast<std::uint8_t*>(texture_buffer_staging.second->mapMemory(0, texture_buffer_size));
|
||||||
|
memcpy(texture_buffer_data, embeded_debug_north_png_rgba.data.begin, texture_buffer_size);
|
||||||
|
texture_buffer_staging.second->unmapMemory();
|
||||||
|
|
||||||
|
this->vk_texture_image = CreateImage(texture_buffer_extent, vk::Format::eR8G8B8A8Srgb, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, vk::MemoryPropertyFlagBits::eDeviceLocal);
|
||||||
|
|
||||||
|
this->SingleTimeSubmitCommand([&](const auto& command_buffer) {
|
||||||
|
this->TransitionImageLayout(command_buffer, *this->vk_texture_image.first, vk::Format::eR8G8B8A8Srgb, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
|
||||||
|
this->CopyBuffer(command_buffer, *texture_buffer_staging.first, *this->vk_texture_image.first, texture_buffer_extent);
|
||||||
|
this->TransitionImageLayout(command_buffer, *this->vk_texture_image.first, vk::Format::eR8G8B8A8Srgb, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
|
});
|
||||||
|
const vk::ImageViewCreateInfo imageview_create_info {
|
||||||
|
.image = **this->vk_texture_image.first,
|
||||||
|
.viewType = vk::ImageViewType::e2D,
|
||||||
|
.format = vk::Format::eR8G8B8A8Srgb,
|
||||||
|
.components = {
|
||||||
|
.r = vk::ComponentSwizzle::eIdentity,
|
||||||
|
.g = vk::ComponentSwizzle::eIdentity,
|
||||||
|
.b = vk::ComponentSwizzle::eIdentity,
|
||||||
|
.a = vk::ComponentSwizzle::eIdentity },
|
||||||
|
.subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1 },
|
||||||
|
};
|
||||||
|
this->vk_texture_view = std::make_unique<vk::raii::ImageView>(*this->vk_gpu, imageview_create_info);
|
||||||
|
|
||||||
|
const vk::SamplerCreateInfo sampler_create_info {
|
||||||
|
.magFilter = vk::Filter::eLinear,
|
||||||
|
.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 = 0.0f,
|
||||||
|
.borderColor = vk::BorderColor::eIntOpaqueBlack,
|
||||||
|
.unnormalizedCoordinates = vk::False,
|
||||||
|
};
|
||||||
|
this->vk_texture_sampler = std::make_unique<vk::raii::Sampler>(*this->vk_gpu, sampler_create_info);
|
||||||
|
}
|
||||||
|
{ // update descriptors
|
||||||
|
std::vector<vk::WriteDescriptorSet> write_descriptor_sets;
|
||||||
|
write_descriptor_sets.reserve(this->vk_max_frames_in_flight);
|
||||||
|
|
||||||
std::vector<vk::DescriptorBufferInfo> buffer_infos;
|
std::vector<vk::DescriptorBufferInfo> buffer_infos;
|
||||||
std::vector<vk::WriteDescriptorSet> write_descriptor_sets;
|
|
||||||
buffer_infos.reserve(this->vk_max_frames_in_flight);
|
buffer_infos.reserve(this->vk_max_frames_in_flight);
|
||||||
write_descriptor_sets.reserve(this->vk_max_frames_in_flight);
|
|
||||||
for (std::size_t i = 0; i < this->vk_max_frames_in_flight; i++) {
|
for (std::size_t i = 0; i < this->vk_max_frames_in_flight; i++) {
|
||||||
const vk::DescriptorBufferInfo descriptor_buffer_info {
|
const vk::DescriptorBufferInfo descriptor_buffer_info_ubo {
|
||||||
.buffer = **this->vk_buffers_uniform.at(i).first,
|
.buffer = **this->vk_buffers_uniform.at(i).first,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.range = sizeof(UniformBufferObject),
|
.range = sizeof(UniformBufferObject),
|
||||||
};
|
};
|
||||||
const vk::DescriptorBufferInfo& descriptor_buffer_info_handle = buffer_infos.emplace_back(descriptor_buffer_info);
|
|
||||||
const vk::WriteDescriptorSet descriptor_write {
|
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],
|
.dstSet = *this->vk_descriptor_sets[i],
|
||||||
.dstBinding = 0,
|
.dstBinding = 0,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
@ -750,8 +834,29 @@ public:
|
|||||||
.pBufferInfo = &descriptor_buffer_info_handle,
|
.pBufferInfo = &descriptor_buffer_info_handle,
|
||||||
.pTexelBufferView = nullptr, // Optional
|
.pTexelBufferView = nullptr, // Optional
|
||||||
};
|
};
|
||||||
write_descriptor_sets.emplace_back(descriptor_write);
|
write_descriptor_sets.emplace_back(descriptor_write_ubo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<vk::DescriptorImageInfo> image_infos;
|
||||||
|
image_infos.reserve(this->vk_max_frames_in_flight);
|
||||||
|
for (std::size_t i = 0; i < this->vk_max_frames_in_flight; i++) {
|
||||||
|
const vk::DescriptorImageInfo descriptor_image_info_texture {
|
||||||
|
.sampler = **this->vk_texture_sampler,
|
||||||
|
.imageView = **this->vk_texture_view,
|
||||||
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
|
};
|
||||||
|
const vk::DescriptorImageInfo& descriptor_image_info_handle = image_infos.emplace_back(descriptor_image_info_texture);
|
||||||
|
const vk::WriteDescriptorSet descriptor_write_texture {
|
||||||
|
.dstSet = *this->vk_descriptor_sets[i],
|
||||||
|
.dstBinding = 1,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.pImageInfo = &descriptor_image_info_handle // Optional
|
||||||
|
};
|
||||||
|
write_descriptor_sets.emplace_back(descriptor_write_texture);
|
||||||
|
}
|
||||||
|
|
||||||
this->vk_gpu->updateDescriptorSets(write_descriptor_sets, nullptr);
|
this->vk_gpu->updateDescriptorSets(write_descriptor_sets, nullptr);
|
||||||
}
|
}
|
||||||
} catch (const vk::SystemError& error) {
|
} catch (const vk::SystemError& error) {
|
||||||
@ -769,8 +874,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VulkanBuffers
|
VulkanBuffer CreateBuffer(vk::DeviceSize wanted_size, vk::BufferUsageFlags wanted_usage, vk::MemoryPropertyFlags wanted_properties) const {
|
||||||
CreateBuffer(vk::DeviceSize wanted_size, vk::BufferUsageFlags wanted_usage, vk::MemoryPropertyFlags wanted_properties) const {
|
|
||||||
const vk::BufferCreateInfo buffer_create_info {
|
const vk::BufferCreateInfo buffer_create_info {
|
||||||
.size = wanted_size,
|
.size = wanted_size,
|
||||||
.usage = wanted_usage,
|
.usage = wanted_usage,
|
||||||
@ -779,7 +883,45 @@ protected:
|
|||||||
const auto allocated_buffer = std::make_unique<vk::raii::Buffer>(*this->vk_gpu, buffer_create_info);
|
const auto allocated_buffer = std::make_unique<vk::raii::Buffer>(*this->vk_gpu, buffer_create_info);
|
||||||
|
|
||||||
const auto memory_requirements = allocated_buffer->getMemoryRequirements();
|
const auto memory_requirements = allocated_buffer->getMemoryRequirements();
|
||||||
const auto FindMemoryType = [this](const std::uint32_t& type_filter, const vk::MemoryPropertyFlags& wanted_properties) -> std::uint32_t {
|
|
||||||
|
const vk::MemoryAllocateInfo vertex_allocate_info {
|
||||||
|
.allocationSize = memory_requirements.size,
|
||||||
|
.memoryTypeIndex = this->FindMemoryType(memory_requirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent)
|
||||||
|
};
|
||||||
|
const auto allocated_buffer_memory = std::make_unique<vk::raii::DeviceMemory>(*this->vk_gpu, vertex_allocate_info);
|
||||||
|
allocated_buffer->bindMemory(**allocated_buffer_memory, 0);
|
||||||
|
return { std::make_unique<vk::raii::Buffer>(std::move(*allocated_buffer)), std::make_unique<vk::raii::DeviceMemory>(std::move(*allocated_buffer_memory)) };
|
||||||
|
};
|
||||||
|
VulkanImage CreateImage(vk::Extent2D image_size, vk::Format wanted_format, vk::ImageTiling wanted_tiling, vk::ImageUsageFlags wanted_usage, vk::MemoryPropertyFlags wanted_properties) const {
|
||||||
|
const vk::ImageCreateInfo image_create_info {
|
||||||
|
.imageType = vk::ImageType::e2D,
|
||||||
|
.format = wanted_format,
|
||||||
|
.extent {
|
||||||
|
.width = image_size.width,
|
||||||
|
.height = image_size.height,
|
||||||
|
.depth = 1,
|
||||||
|
},
|
||||||
|
.mipLevels = 1,
|
||||||
|
.arrayLayers = 1,
|
||||||
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
|
.tiling = wanted_tiling, // https://docs.vulkan.org/tutorial/latest/06_Texture_mapping/00_Images.html#_texture_image
|
||||||
|
.usage = wanted_usage,
|
||||||
|
.sharingMode = vk::SharingMode::eExclusive,
|
||||||
|
.initialLayout = vk::ImageLayout::eUndefined,
|
||||||
|
//.flags = 0, // optional
|
||||||
|
};
|
||||||
|
const auto allocated_image_texture = std::make_unique<vk::raii::Image>(*this->vk_gpu, image_create_info);
|
||||||
|
|
||||||
|
const auto memory_requirements = allocated_image_texture->getMemoryRequirements();
|
||||||
|
const vk::MemoryAllocateInfo image_allocate_info {
|
||||||
|
.allocationSize = memory_requirements.size,
|
||||||
|
.memoryTypeIndex = this->FindMemoryType(memory_requirements.memoryTypeBits, wanted_properties)
|
||||||
|
};
|
||||||
|
const auto allocated_image_memory = std::make_unique<vk::raii::DeviceMemory>(*this->vk_gpu, image_allocate_info);
|
||||||
|
allocated_image_texture->bindMemory(**allocated_image_memory, 0);
|
||||||
|
return { std::make_unique<vk::raii::Image>(std::move(*allocated_image_texture)), std::make_unique<vk::raii::DeviceMemory>(std::move(*allocated_image_memory)) };
|
||||||
|
}
|
||||||
|
const std::uint32_t FindMemoryType(const std::uint32_t& type_filter, const vk::MemoryPropertyFlags& wanted_properties) const {
|
||||||
const auto memory_properties = this->vk_gfx_card->getMemoryProperties();
|
const auto memory_properties = this->vk_gfx_card->getMemoryProperties();
|
||||||
const std::uint32_t memory_type_count = memory_properties.memoryTypeCount;
|
const std::uint32_t memory_type_count = memory_properties.memoryTypeCount;
|
||||||
|
|
||||||
@ -794,30 +936,54 @@ protected:
|
|||||||
if (memory_type_to_test == memory_type_count)
|
if (memory_type_to_test == memory_type_count)
|
||||||
throw std::runtime_error("failed to find suitable memory type!");
|
throw std::runtime_error("failed to find suitable memory type!");
|
||||||
return memory_type_to_test;
|
return memory_type_to_test;
|
||||||
};
|
}
|
||||||
const vk::MemoryAllocateInfo vertex_allocate_info {
|
void CopyBuffer(const vk::CommandBuffer& command_buffer, const vk::Buffer& src_buffer, const vk::Buffer& dest_buffer, const vk::DeviceSize& size) const {
|
||||||
.allocationSize = memory_requirements.size,
|
|
||||||
.memoryTypeIndex = FindMemoryType(memory_requirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent)
|
|
||||||
};
|
|
||||||
const auto allocated_buffer_memory = std::make_unique<vk::raii::DeviceMemory>(*this->vk_gpu, vertex_allocate_info);
|
|
||||||
allocated_buffer->bindMemory(**allocated_buffer_memory, 0);
|
|
||||||
return { std::make_unique<vk::raii::Buffer>(std::move(*allocated_buffer)), std::make_unique<vk::raii::DeviceMemory>(std::move(*allocated_buffer_memory)) };
|
|
||||||
};
|
|
||||||
void CopyBuffer(const vk::Buffer& src_buffer, const vk::Buffer& dest_buffer, const vk::DeviceSize& size) const {
|
|
||||||
const vk::CommandBufferAllocateInfo command_buffer_allocate_info {
|
|
||||||
.commandPool = **this->vk_command_pool,
|
|
||||||
.level = vk::CommandBufferLevel::ePrimary,
|
|
||||||
.commandBufferCount = 1
|
|
||||||
};
|
|
||||||
const auto command_buffer = std::move(vk::raii::CommandBuffers(*this->vk_gpu, command_buffer_allocate_info).front());
|
|
||||||
command_buffer.begin(vk::CommandBufferBeginInfo { .flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit });
|
|
||||||
|
|
||||||
const vk::BufferCopy copy_region {
|
const vk::BufferCopy copy_region {
|
||||||
//.srcOffset = 0, // Optional
|
//.srcOffset = 0, // Optional
|
||||||
//.dstOffset = 0, // Optional
|
//.dstOffset = 0, // Optional
|
||||||
.size = size
|
.size = size
|
||||||
};
|
};
|
||||||
command_buffer.copyBuffer(src_buffer, dest_buffer, { copy_region });
|
command_buffer.copyBuffer(src_buffer, dest_buffer, { copy_region });
|
||||||
|
}
|
||||||
|
void CopyBuffer(const vk::Buffer& src_buffer, const vk::Buffer& dest_buffer, const vk::DeviceSize& size) const {
|
||||||
|
this->SingleTimeSubmitCommand([&](const auto& command_buffer) {
|
||||||
|
this->CopyBuffer(command_buffer, src_buffer, dest_buffer, size);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
void CopyBuffer(const vk::CommandBuffer& command_buffer, const vk::Buffer& src_buffer, const vk::Image& dest_buffer, const vk::Extent2D& size) const {
|
||||||
|
const vk::BufferImageCopy copy_region {
|
||||||
|
.bufferOffset = 0,
|
||||||
|
.bufferRowLength = 0,
|
||||||
|
.bufferImageHeight = 0,
|
||||||
|
.imageSubresource = {
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.mipLevel = 0,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
.imageOffset = { 0, 0, 0 },
|
||||||
|
.imageExtent = { size.width, size.height, 1 }
|
||||||
|
};
|
||||||
|
command_buffer.copyBufferToImage(src_buffer, dest_buffer, vk::ImageLayout::eTransferDstOptimal, copy_region);
|
||||||
|
}
|
||||||
|
void CopyBuffer(const vk::Buffer& src_buffer, const vk::Image& dest_buffer, const vk::Extent2D& size) const {
|
||||||
|
this->SingleTimeSubmitCommand([&](const auto& command_buffer) {
|
||||||
|
this->CopyBuffer(command_buffer, src_buffer, dest_buffer, size);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
template <typename Func>
|
||||||
|
void SingleTimeSubmitCommand(const Func& single_time_function) const {
|
||||||
|
const vk::CommandBufferAllocateInfo command_buffer_allocate_info {
|
||||||
|
.commandPool = **this->vk_command_pool,
|
||||||
|
.level = vk::CommandBufferLevel::ePrimary,
|
||||||
|
.commandBufferCount = 1
|
||||||
|
};
|
||||||
|
auto command_buffer = std::move(vk::raii::CommandBuffers(*this->vk_gpu, command_buffer_allocate_info).front());
|
||||||
|
|
||||||
|
command_buffer.begin(vk::CommandBufferBeginInfo { .flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit });
|
||||||
|
|
||||||
|
single_time_function(command_buffer);
|
||||||
|
|
||||||
command_buffer.end();
|
command_buffer.end();
|
||||||
|
|
||||||
const vk::SubmitInfo submit_queue {
|
const vk::SubmitInfo submit_queue {
|
||||||
@ -826,7 +992,104 @@ protected:
|
|||||||
};
|
};
|
||||||
this->vk_queue_graphics->submit(submit_queue);
|
this->vk_queue_graphics->submit(submit_queue);
|
||||||
this->vk_queue_graphics->waitIdle();
|
this->vk_queue_graphics->waitIdle();
|
||||||
|
}
|
||||||
|
void TransitionImageLayout(const vk::CommandBuffer& command_buffer, const vk::Image& image, vk::Format format, const vk::ImageLayout& old_layout, const vk::ImageLayout& new_layout) const {
|
||||||
|
// https://github.com/KhronosGroup/Vulkan-Hpp/blob/main/RAII_Samples/utils/utils.hpp#L101 // credits to the vulkanhpp project for having fantastic usage examples
|
||||||
|
// https://docs.vulkan.org/tutorial/latest/06_Texture_mapping/00_Images.html#_transition_barrier_masks
|
||||||
|
const vk::AccessFlags source_access_mask = [](const vk::ImageLayout& old_layout) -> vk::AccessFlags {
|
||||||
|
switch (old_layout) {
|
||||||
|
case vk::ImageLayout::eTransferDstOptimal:
|
||||||
|
return vk::AccessFlagBits::eTransferWrite;
|
||||||
|
case vk::ImageLayout::ePreinitialized:
|
||||||
|
return vk::AccessFlagBits::eHostWrite;
|
||||||
|
case vk::ImageLayout::eGeneral: // sourceAccessMask is empty
|
||||||
|
case vk::ImageLayout::eUndefined:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}(old_layout);
|
||||||
|
|
||||||
|
const vk::PipelineStageFlags source_stage = [](const vk::ImageLayout& old_layout) -> vk::PipelineStageFlags {
|
||||||
|
switch (old_layout) {
|
||||||
|
case vk::ImageLayout::eGeneral:
|
||||||
|
case vk::ImageLayout::ePreinitialized:
|
||||||
|
return vk::PipelineStageFlagBits::eHost;
|
||||||
|
case vk::ImageLayout::eTransferDstOptimal:
|
||||||
|
return vk::PipelineStageFlagBits::eTransfer;
|
||||||
|
case vk::ImageLayout::eUndefined:
|
||||||
|
return vk::PipelineStageFlagBits::eTopOfPipe;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}(old_layout);
|
||||||
|
|
||||||
|
const vk::AccessFlags destination_access_mask = [](const vk::ImageLayout& new_layout) -> vk::AccessFlags {
|
||||||
|
switch (new_layout) {
|
||||||
|
case vk::ImageLayout::eColorAttachmentOptimal:
|
||||||
|
return vk::AccessFlagBits::eColorAttachmentWrite;
|
||||||
|
case vk::ImageLayout::eDepthStencilAttachmentOptimal:
|
||||||
|
return vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||||
|
case vk::ImageLayout::eGeneral: // empty destinationAccessMask
|
||||||
|
case vk::ImageLayout::ePresentSrcKHR:
|
||||||
|
break;
|
||||||
|
case vk::ImageLayout::eShaderReadOnlyOptimal:
|
||||||
|
return vk::AccessFlagBits::eShaderRead;
|
||||||
|
case vk::ImageLayout::eTransferSrcOptimal:
|
||||||
|
return vk::AccessFlagBits::eTransferRead;
|
||||||
|
case vk::ImageLayout::eTransferDstOptimal:
|
||||||
|
return vk::AccessFlagBits::eTransferWrite;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}(new_layout);
|
||||||
|
|
||||||
|
const vk::PipelineStageFlags destination_stage = [](const vk::ImageLayout& new_layout) -> vk::PipelineStageFlags {
|
||||||
|
switch (new_layout) {
|
||||||
|
case vk::ImageLayout::eColorAttachmentOptimal:
|
||||||
|
return vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||||
|
case vk::ImageLayout::eDepthStencilAttachmentOptimal:
|
||||||
|
return vk::PipelineStageFlagBits::eEarlyFragmentTests;
|
||||||
|
case vk::ImageLayout::eGeneral:
|
||||||
|
return vk::PipelineStageFlagBits::eHost;
|
||||||
|
case vk::ImageLayout::ePresentSrcKHR:
|
||||||
|
return vk::PipelineStageFlagBits::eBottomOfPipe;
|
||||||
|
case vk::ImageLayout::eShaderReadOnlyOptimal:
|
||||||
|
return vk::PipelineStageFlagBits::eFragmentShader;
|
||||||
|
case vk::ImageLayout::eTransferDstOptimal:
|
||||||
|
case vk::ImageLayout::eTransferSrcOptimal:
|
||||||
|
return vk::PipelineStageFlagBits::eTransfer;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}(new_layout);
|
||||||
|
|
||||||
|
const vk::ImageMemoryBarrier image_memory_barrier {
|
||||||
|
.srcAccessMask = source_access_mask,
|
||||||
|
.dstAccessMask = destination_access_mask,
|
||||||
|
.oldLayout = old_layout,
|
||||||
|
.newLayout = new_layout,
|
||||||
|
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
|
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
|
.image = image,
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
command_buffer.pipelineBarrier(source_stage, destination_stage, {}, nullptr, nullptr, image_memory_barrier);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Run() {
|
void Run() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user