50vk::ShaderModule create_shader(
52 const std::string& file_path,
53 const vk::Device& device)
55 std::ifstream file(file_path, std::ios::binary);
57 throw VulkanError{
"Failed to open file:"s + file_path};
59 file.seekg(0, std::ios_base::end);
60 auto size = file.tellg();
61 assert(size % 4 == 0);
63 std::vector<std::uint32_t> shader_code(size / 4);
64 file.read(
reinterpret_cast<char*
>(shader_code.data()),
static_cast<std::streamsize
>(size));
67 throw VulkanError{
"Error reading from file:"s + file_path};
70 vk::ShaderModuleCreateInfo shader_info;
72 .setCodeSize(shader_code.size() * 4)
73 .setPCode(shader_code.data());
74 return device.createShaderModule(shader_info);
77vk::SamplerYcbcrConversion createYCbCrConversion(vk::Device device, vk::Format format){
78 vk::SamplerYcbcrConversion yCbCr_conversion =
nullptr;
80 vk::SamplerYcbcrConversionCreateInfo conversion_info;
83 .setYcbcrModel(vk::SamplerYcbcrModelConversion::eYcbcr709)
84 .setYcbcrRange(vk::SamplerYcbcrRange::eItuNarrow)
86 .setChromaFilter(vk::Filter::eLinear)
87 .setXChromaOffset(vk::ChromaLocation::eMidpoint)
88 .setYChromaOffset(vk::ChromaLocation::eMidpoint)
89 .setForceExplicitReconstruction(
false);
90 yCbCr_conversion = device.createSamplerYcbcrConversion(conversion_info);
92 return yCbCr_conversion;
95vk::Sampler create_sampler(vk::Device device, vk::SamplerYcbcrConversion yCbCr_conversion, vk::Filter
filter) {
96 vk::SamplerYcbcrConversionInfo yCbCr_info{ yCbCr_conversion };
98 vk::SamplerCreateInfo sampler_info;
100 .setAddressModeU(vk::SamplerAddressMode::eClampToEdge)
101 .setAddressModeV(vk::SamplerAddressMode::eClampToEdge)
102 .setAddressModeW(vk::SamplerAddressMode::eClampToEdge)
105 .setAnisotropyEnable(
false)
106 .setUnnormalizedCoordinates(
false)
107 .setPNext(yCbCr_conversion ? &yCbCr_info :
nullptr);
108 return device.createSampler(sampler_info);
112 vk::DescriptorType
type;
113 vk::ShaderStageFlags stages;
114 vk::Sampler sampler =
nullptr;
117vk::DescriptorSetLayout create_descriptor_set_layout(vk::Device device, uint32_t first_binding, std::vector<Binding> bindings) {
118 std::vector<vk::DescriptorSetLayoutBinding> descriptor_set_layout_bindings(bindings.size());
119 for(
size_t i = 0; i < bindings.size(); i++){
120 descriptor_set_layout_bindings[i]
121 .setBinding(first_binding + i)
122 .setDescriptorCount(1)
123 .setDescriptorType(bindings[i].
type)
124 .setStageFlags(bindings[i].stages)
125 .setPImmutableSamplers(&bindings[i].sampler);
127 vk::DescriptorSetLayoutCreateInfo descriptor_set_layout_info{};
128 descriptor_set_layout_info
129 .setBindingCount(descriptor_set_layout_bindings.size())
130 .setPBindings(descriptor_set_layout_bindings.data());
132 return device.createDescriptorSetLayout(descriptor_set_layout_info);
135vk::PipelineLayout create_compute_pipeline_layout(vk::Device device,
const std::vector<vk::DescriptorSetLayout>& descriptor_set_layout){
136 vk::PushConstantRange push_constant_range{};
140 .setStageFlags(vk::ShaderStageFlagBits::eCompute);
142 vk::PipelineLayoutCreateInfo pipeline_layout_info;
144 .setSetLayoutCount(descriptor_set_layout.size())
145 .setPSetLayouts(descriptor_set_layout.data())
146 .setPushConstantRangeCount(1)
147 .setPPushConstantRanges(&push_constant_range);
149 return device.createPipelineLayout(pipeline_layout_info);
152vk::Pipeline create_compute_pipeline(vk::Device device, vk::PipelineLayout pipeline_layout, vk::ShaderModule shader){
153 vk::PipelineShaderStageCreateInfo shader_stage_info;
157 .setStage(vk::ShaderStageFlagBits::eCompute);
159 vk::ComputePipelineCreateInfo pipeline_info{};
161 .setStage(shader_stage_info)
162 .setLayout(pipeline_layout);
164 vk::Pipeline compute_pipeline;
165 auto result = device.createComputePipelines(
nullptr, 1, &pipeline_info,
nullptr, &compute_pipeline);
166 if(result != vk::Result::eSuccess){
169 return compute_pipeline;
185 {vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eCompute,
sampler}
188 {vk::DescriptorType::eStorageImage, vk::ShaderStageFlagBits::eCompute}
211 std::array<vk::DescriptorSet, 2> descriptor_sets)
213 cmd_buffer.pushConstants(
pipeline_layout, vk::ShaderStageFlagBits::eCompute,
214 0,
sizeof(image_size), &image_size);
216 cmd_buffer.bindPipeline(vk::PipelineBindPoint::eCompute,
pipeline);
217 cmd_buffer.bindDescriptorSets(vk::PipelineBindPoint::eCompute,
pipeline_layout, 0, descriptor_sets,
nullptr);
218 cmd_buffer.dispatch((image_size.
width + 16 - 1) / 16, (image_size.
height + 16 - 1) / 16, 1);
225vk::RenderPass create_render_pass(vk::Device device, vk::Format swapchain_image_format) {
226 vk::RenderPassCreateInfo render_pass_info;
228 vk::AttachmentDescription color_attachment;
230 .setFormat(swapchain_image_format)
231 .setSamples(vk::SampleCountFlagBits::e1)
232 .setLoadOp(vk::AttachmentLoadOp::eClear)
233 .setStoreOp(vk::AttachmentStoreOp::eStore)
234 .setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
235 .setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
236 .setInitialLayout(vk::ImageLayout::eUndefined)
237 .setFinalLayout(vk::ImageLayout::ePresentSrcKHR);
239 .setAttachmentCount(1)
240 .setPAttachments(&color_attachment);
242 vk::AttachmentReference attachment_reference;
245 .setLayout(vk::ImageLayout::eColorAttachmentOptimal);
246 vk::SubpassDescription subpass;
248 .setPipelineBindPoint(vk::PipelineBindPoint::eGraphics)
249 .setColorAttachmentCount(1)
250 .setPColorAttachments(&attachment_reference);
253 .setPSubpasses(&subpass);
255 vk::SubpassDependency subpass_dependency{};
257 .setSrcSubpass(VK_SUBPASS_EXTERNAL)
259 .setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
260 .setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
261 .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite);
263 .setDependencyCount(1)
264 .setPDependencies(&subpass_dependency);
266 return device.createRenderPass(render_pass_info);
269vk::PipelineLayout create_render_pipeline_layout(vk::Device device, vk::DescriptorSetLayout descriptor_set_layout){
270 vk::PipelineLayoutCreateInfo pipeline_layout_info{};
272 vk::PushConstantRange push_constants;
276 .setStageFlags(vk::ShaderStageFlagBits::eFragment);
278 .setPushConstantRangeCount(1)
279 .setPPushConstantRanges(&push_constants)
280 .setSetLayoutCount(1)
281 .setPSetLayouts(&descriptor_set_layout);
282 return device.createPipelineLayout(pipeline_layout_info);
286vk::Pipeline create_render_pipeline(vk::Device device, vk::PipelineLayout render_pipeline_layout, vk::RenderPass render_pass,
287 vk::ShaderModule vertex_shader, vk::ShaderModule fragment_shader)
289 vk::GraphicsPipelineCreateInfo pipeline_info{};
291 std::array<vk::PipelineShaderStageCreateInfo, 2> shader_stages_infos;
292 shader_stages_infos[0]
293 .setModule(vertex_shader)
295 .setStage(vk::ShaderStageFlagBits::eVertex);
296 shader_stages_infos[1]
297 .setModule(fragment_shader)
299 .setStage(vk::ShaderStageFlagBits::eFragment);
301 .setStageCount(
static_cast<uint32_t
>(shader_stages_infos.size()))
302 .setPStages(shader_stages_infos.data());
304 vk::PipelineVertexInputStateCreateInfo vertex_input_state_info{};
305 pipeline_info.setPVertexInputState(&vertex_input_state_info);
307 vk::PipelineInputAssemblyStateCreateInfo input_assembly_state_info{};
308 input_assembly_state_info.setTopology(vk::PrimitiveTopology::eTriangleList);
309 pipeline_info.setPInputAssemblyState(&input_assembly_state_info);
311 vk::PipelineViewportStateCreateInfo viewport_state_info;
314 .setViewportCount(1);
315 pipeline_info.setPViewportState(&viewport_state_info);
317 vk::PipelineRasterizationStateCreateInfo rasterization_info{};
319 .setPolygonMode(vk::PolygonMode::eFill)
321 pipeline_info.setPRasterizationState(&rasterization_info);
323 vk::PipelineMultisampleStateCreateInfo multisample_info;
325 .setSampleShadingEnable(
false)
326 .setRasterizationSamples(vk::SampleCountFlagBits::e1);
327 pipeline_info.setPMultisampleState(&multisample_info);
329 using ColorFlags = vk::ColorComponentFlagBits;
330 vk::PipelineColorBlendAttachmentState color_blend_attachment{};
331 color_blend_attachment
332 .setBlendEnable(
false)
333 .setColorWriteMask(ColorFlags::eR | ColorFlags::eG | ColorFlags::eB | ColorFlags::eA);
334 vk::PipelineColorBlendStateCreateInfo color_blend_info{};
336 .setAttachmentCount(1)
337 .setPAttachments(&color_blend_attachment);
338 pipeline_info.setPColorBlendState(&color_blend_info);
340 std::array dynamic_states{ vk::DynamicState::eViewport, vk::DynamicState::eScissor };
341 vk::PipelineDynamicStateCreateInfo dynamic_state_info{};
343 .setDynamicStateCount(
static_cast<uint32_t
>(dynamic_states.size()))
344 .setPDynamicStates(dynamic_states.data());
345 pipeline_info.setPDynamicState(&dynamic_state_info);
348 .setLayout(render_pipeline_layout)
349 .setRenderPass(render_pass);
351 vk::Pipeline render_pipeline;
352 auto result = device.createGraphicsPipelines(
nullptr, 1, &pipeline_info,
nullptr, &render_pipeline);
353 if(result != vk::Result::eSuccess){
356 return render_pipeline;
368 vertex_shader = create_shader(path_to_shaders +
"/render.vert.spv", device);
369 fragment_shader = create_shader(path_to_shaders +
"/render.frag.spv", device);
372 vk::ClearColorValue clear_color_value{};
373 clear_color_value.setFloat32({ 0.01f, 0.01f, 0.01f, 1.0f });
394 double wnd_aspect =
static_cast<double>(render_area_size.width) / render_area_size.height;
395 double img_aspect =
static_cast<double>(image_size.width) / image_size.height;
399 if (wnd_aspect > img_aspect) {
401 render_area.
width =
static_cast<uint32_t
>(std::round(render_area_size.height * img_aspect));
406 render_area.
height =
static_cast<uint32_t
>(std::round(render_area_size.width / img_aspect));
435 {vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment,
sampler}
442 vk::RenderPassBeginInfo render_pass_begin_info;
443 render_pass_begin_info
446 .setClearValueCount(1)
448 .setFramebuffer(framebuffer);
449 cmd_buffer.beginRenderPass(render_pass_begin_info, vk::SubpassContents::eInline);
451 cmd_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics,
pipeline);
453 cmd_buffer.setScissor(0,
scissor);
454 cmd_buffer.setViewport(0,
viewport);
456 cmd_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
458 cmd_buffer.draw(3, 1, 0, 0);
460 cmd_buffer.endRenderPass();
static af_result_code filter(void *state, struct audio_frame **frame)
vk::ShaderModule compute_shader
vk::PipelineLayout pipeline_layout
vk::DescriptorSetLayout destination_desc_set_layout
vk::DescriptorSetLayout source_desc_set_layout
void destroy(vk::Device device)
void create(vk::Device device, const std::string &shader_path, vk::Format format)
vk::SamplerYcbcrConversion yCbCr_conversion
void record_commands(vk::CommandBuffer cmd_buffer, ImageSize image_size, std::array< vk::DescriptorSet, 2 > descriptor_set)
vk::ClearValue clear_color
vk::ShaderModule vertex_shader
vk::SamplerYcbcrConversion yCbCr_conversion
void record_commands(vk::CommandBuffer cmd_buffer, vk::DescriptorSet image, vk::Framebuffer framebuffer)
void update_render_area(vk::Extent2D render_area_siza, vk::Extent2D image_size)
vk::ShaderModule fragment_shader
void create(VulkanContext &context, const std::string &path_to_shaders)
vk::Extent2D render_area_siza
vk::PipelineLayout pipeline_layout
vk::RenderPass render_pass
void reconfigure(vk::Device device, vk::Format sampler)
void destroy(vk::Device device)
vk::DescriptorSetLayout image_desc_set_layout
vk::Format get_swapchain_image_format()
constexpr bool is_yCbCr_format(vk::Format format)