From bb210dc1a125109807ff34ece8fc5105f31ebb85 Mon Sep 17 00:00:00 2001 From: BearOso Date: Fri, 10 Feb 2023 15:19:09 -0600 Subject: [PATCH] Gtk: Move simple vulkan output into separate class. --- gtk/CMakeLists.txt | 5 +- gtk/src/gtk_display_driver_vulkan.cpp | 240 +----------------------- gtk/src/gtk_display_driver_vulkan.h | 17 +- vulkan/vulkan_simple_output.cpp | 258 ++++++++++++++++++++++++++ vulkan/vulkan_simple_output.hpp | 36 ++++ 5 files changed, 308 insertions(+), 248 deletions(-) create mode 100644 vulkan/vulkan_simple_output.cpp create mode 100644 vulkan/vulkan_simple_output.hpp diff --git a/gtk/CMakeLists.txt b/gtk/CMakeLists.txt index 6cc9f1ba..29d38ee6 100644 --- a/gtk/CMakeLists.txt +++ b/gtk/CMakeLists.txt @@ -50,6 +50,7 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) pkg_check_modules(GTK REQUIRED gtkmm-3.0 gthread-2.0 libpng) pkg_check_modules(XRANDR REQUIRED xrandr) + find_library(X11 X11 REQUIRED) find_library(XEXT Xext REQUIRED) find_library(DL dl REQUIRED) @@ -116,7 +117,9 @@ if(USE_SLANG) ../vulkan/vulkan_pipeline_image.cpp ../vulkan/vulkan_pipeline_image.hpp ../vulkan/vulkan_shader_chain.cpp - ../vulkan/vulkan_shader_chain.hpp) + ../vulkan/vulkan_shader_chain.hpp + ../vulkan/vulkan_simple_output.hpp + ../vulkan/vulkan_simple_output.cpp) endif() diff --git a/gtk/src/gtk_display_driver_vulkan.cpp b/gtk/src/gtk_display_driver_vulkan.cpp index 1f8a021a..79811d70 100644 --- a/gtk/src/gtk_display_driver_vulkan.cpp +++ b/gtk/src/gtk_display_driver_vulkan.cpp @@ -8,159 +8,10 @@ #include "gtk_display.h" #include "gtk_display_driver_vulkan.h" #include "gtk_shader_parameters.h" -#include "../../vulkan/vulkan_context.hpp" -#include "../../vulkan/slang_shader.hpp" -#include "../../vulkan/slang_helpers.hpp" -#include "../../vulkan/vulkan_shader_chain.hpp" #include "snes9x.h" #include "gfx.h" #include "fmt/format.h" -static const char *vertex_shader = R"( -#version 450 - -layout(location = 0) out vec2 texcoord; - -vec2 positions[3] = vec2[](vec2(-1.0, -3.0), vec2(3.0, 1.0), vec2(-1.0, 1.0)); -vec2 texcoords[3] = vec2[](vec2(0.0, -1.0), vec2(2.0, 1.0), vec2(0.0, 1.0)); - -void main() -{ - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - texcoord = texcoords[gl_VertexIndex]; -} -)"; - -static const char *fragment_shader = R"( -#version 450 - -layout(location = 0) in vec2 texcoord; -layout(binding = 0) uniform sampler2D tsampler; - -layout(location = 0) out vec4 fragcolor; - -void main() -{ - fragcolor = texture(tsampler, texcoord); -} -)"; - -void S9xVulkanDisplayDriver::create_pipeline() -{ - auto vertex_spirv = SlangShader::generate_spirv(vertex_shader, "vertex"); - auto fragment_spirv = SlangShader::generate_spirv(fragment_shader, "fragment"); - - auto vertex_module = device.createShaderModuleUnique({ {}, vertex_spirv }); - auto fragment_module = device.createShaderModuleUnique({ {}, fragment_spirv }); - - vk::PipelineShaderStageCreateInfo vertex_ci; - vertex_ci.setStage(vk::ShaderStageFlagBits::eVertex) - .setModule(vertex_module.get()) - .setPName("main"); - - vk::PipelineShaderStageCreateInfo fragment_ci; - fragment_ci.setStage(vk::ShaderStageFlagBits::eFragment) - .setModule(fragment_module.get()) - .setPName("main"); - - std::vector stages = { vertex_ci, fragment_ci }; - - vk::PipelineVertexInputStateCreateInfo vertex_input_info{}; - - vk::PipelineInputAssemblyStateCreateInfo pipeline_input_assembly_info{}; - pipeline_input_assembly_info.setTopology(vk::PrimitiveTopology::eTriangleList) - .setPrimitiveRestartEnable(false); - - std::vector viewports(1); - viewports[0] - .setX(0.0f) - .setY(0.0f) - .setWidth(256) - .setHeight(256) - .setMinDepth(0.0f) - .setMaxDepth(1.0f); - std::vector scissors(1); - scissors[0].extent.width = 256; - scissors[0].extent.height = 256; - scissors[0].offset = vk::Offset2D(0, 0); - - vk::PipelineViewportStateCreateInfo pipeline_viewport_info; - pipeline_viewport_info.setViewports(viewports) - .setScissors(scissors); - - vk::PipelineRasterizationStateCreateInfo rasterizer_info; - rasterizer_info.setCullMode(vk::CullModeFlagBits::eBack) - .setFrontFace(vk::FrontFace::eClockwise) - .setLineWidth(1.0f) - .setDepthClampEnable(false) - .setRasterizerDiscardEnable(false) - .setPolygonMode(vk::PolygonMode::eFill) - .setDepthBiasEnable(false) - .setRasterizerDiscardEnable(false); - - vk::PipelineMultisampleStateCreateInfo multisample_info; - multisample_info.setSampleShadingEnable(false) - .setRasterizationSamples(vk::SampleCountFlagBits::e1); - - vk::PipelineDepthStencilStateCreateInfo depth_stencil_info; - depth_stencil_info.setDepthTestEnable(false); - - vk::PipelineColorBlendAttachmentState blend_attachment_info; - blend_attachment_info - .setColorWriteMask(vk::ColorComponentFlagBits::eB | - vk::ColorComponentFlagBits::eG | - vk::ColorComponentFlagBits::eR | - vk::ColorComponentFlagBits::eA) - .setBlendEnable(true) - .setColorBlendOp(vk::BlendOp::eAdd) - .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha) - .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha) - .setAlphaBlendOp(vk::BlendOp::eAdd) - .setSrcAlphaBlendFactor(vk::BlendFactor::eOne) - .setSrcAlphaBlendFactor(vk::BlendFactor::eZero); - - vk::PipelineColorBlendStateCreateInfo blend_state_info; - blend_state_info.setLogicOpEnable(false) - .setAttachments(blend_attachment_info); - - std::vector states = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; - vk::PipelineDynamicStateCreateInfo dynamic_state_info({}, states); - - vk::DescriptorSetLayoutBinding dslb{}; - dslb.setBinding(0) - .setStageFlags(vk::ShaderStageFlagBits::eFragment) - .setDescriptorCount(1) - .setDescriptorType(vk::DescriptorType::eCombinedImageSampler); - vk::DescriptorSetLayoutCreateInfo dslci{}; - dslci.setBindings(dslb); - descriptor_set_layout = device.createDescriptorSetLayoutUnique(dslci); - - vk::PipelineLayoutCreateInfo pipeline_layout_info; - pipeline_layout_info.setSetLayoutCount(0) - .setPushConstantRangeCount(0) - .setSetLayouts(descriptor_set_layout.get()); - - pipeline_layout = device.createPipelineLayoutUnique(pipeline_layout_info); - - vk::GraphicsPipelineCreateInfo pipeline_create_info; - pipeline_create_info.setStageCount(2) - .setStages(stages) - .setPVertexInputState(&vertex_input_info) - .setPInputAssemblyState(&pipeline_input_assembly_info) - .setPViewportState(&pipeline_viewport_info) - .setPRasterizationState(&rasterizer_info) - .setPMultisampleState(&multisample_info) - .setPDepthStencilState(&depth_stencil_info) - .setPColorBlendState(&blend_state_info) - .setPDynamicState(&dynamic_state_info) - .setLayout(pipeline_layout.get()) - .setRenderPass(swapchain->get_render_pass()) - .setSubpass(0); - - auto [result, pipeline] = device.createGraphicsPipelineUnique(nullptr, pipeline_create_info); - this->pipeline = std::move(pipeline); -} - S9xVulkanDisplayDriver::S9xVulkanDisplayDriver(Snes9xWindow *_window, Snes9xConfig *_config) { window = _window; @@ -227,7 +78,7 @@ int S9xVulkanDisplayDriver::init() context->init_Xlib(display, xid); } - swapchain = context->swapchain.get(); + device = context->device; if (!gui_config->shader_filename.empty() && gui_config->use_shaders) @@ -245,46 +96,7 @@ int S9xVulkanDisplayDriver::init() } } - create_pipeline(); - - descriptors.clear(); - for (size_t i = 0; i < swapchain->get_num_frames(); i++) - { - vk::DescriptorSetAllocateInfo dsai{}; - dsai - .setDescriptorPool(context->descriptor_pool.get()) - .setDescriptorSetCount(1) - .setSetLayouts(descriptor_set_layout.get()); - auto descriptor = device.allocateDescriptorSetsUnique(dsai); - descriptors.push_back(std::move(descriptor[0])); - } - - textures.clear(); - textures.resize(swapchain->get_num_frames()); - for (auto &t : textures) - { - t.init(context.get()); - t.create(256, 224, vk::Format::eR5G6B5UnormPack16, vk::SamplerAddressMode::eClampToEdge, Settings.BilinearFilter, false); - } - - vk::SamplerCreateInfo sci{}; - sci.setAddressModeU(vk::SamplerAddressMode::eClampToEdge) - .setAddressModeV(vk::SamplerAddressMode::eClampToEdge) - .setAddressModeW(vk::SamplerAddressMode::eClampToEdge) - .setMipmapMode(vk::SamplerMipmapMode::eLinear) - .setAnisotropyEnable(false) - .setMinFilter(vk::Filter::eLinear) - .setMagFilter(vk::Filter::eLinear) - .setUnnormalizedCoordinates(false) - .setMinLod(1.0f) - .setMaxLod(1.0f) - .setMipLodBias(0.0) - .setCompareEnable(false); - linear_sampler = device.createSampler(sci); - - sci.setMinFilter(vk::Filter::eNearest) - .setMagFilter(vk::Filter::eNearest); - nearest_sampler = device.createSampler(sci); + simple_output = std::make_unique(context.get(), vk::Format::eR5G6B5UnormPack16); return 0; } @@ -298,10 +110,6 @@ void S9xVulkanDisplayDriver::deinit() gtk_shader_parameters_dialog_close(); context->wait_idle(); - textures.clear(); - descriptors.clear(); - device.destroySampler(linear_sampler); - device.destroySampler(nearest_sampler); } void S9xVulkanDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels) @@ -310,7 +118,7 @@ void S9xVulkanDisplayDriver::update(uint16_t *buffer, int width, int height, int return; if (gui_config->reduce_input_lag) - device.waitIdle(); + context->wait_idle(); auto viewport = S9xApplyAspect(width, height, current_width, current_height); @@ -319,43 +127,11 @@ void S9xVulkanDisplayDriver::update(uint16_t *buffer, int width, int height, int shaderchain->do_frame((uint8_t *)buffer, width, height, stride_in_pixels << 1, vk::Format::eR5G6B5UnormPack16, viewport.x, viewport.y, viewport.w, viewport.h); return; } - - if (!swapchain->begin_frame()) - return; - - auto &tex = textures[swapchain->get_current_frame()]; - auto &cmd = swapchain->get_cmd(); - auto extents = swapchain->get_extents(); - auto &dstset = descriptors[swapchain->get_current_frame()].get(); - - tex.from_buffer(cmd, (uint8_t *)buffer, width, height, stride_in_pixels * 2); - - swapchain->begin_render_pass(); - - vk::DescriptorImageInfo dii{}; - dii.setImageView(tex.image_view) - .setSampler(Settings.BilinearFilter ? linear_sampler : nearest_sampler) - .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal); - vk::WriteDescriptorSet wds{}; - wds.setDescriptorCount(1) - .setDstBinding(0) - .setDstArrayElement(0) - .setDstSet(dstset) - .setDescriptorType(vk::DescriptorType::eCombinedImageSampler) - .setImageInfo(dii); - device.updateDescriptorSets(wds, {}); - - cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get()); - cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline_layout.get(), 0, dstset, {}); - - auto dest_rect = S9xApplyAspect(width, height, extents.width, extents.height); - - cmd.setViewport(0, vk::Viewport(dest_rect.x, dest_rect.y, dest_rect.w, dest_rect.h, 0.0f, 1.0f)); - cmd.setScissor(0, vk::Rect2D({}, extents)); - cmd.draw(3, 1, 0, 0); - - swapchain->end_render_pass(); - swapchain->end_frame(); + else if (simple_output) + { + simple_output->set_filter(Settings.BilinearFilter); + simple_output->do_frame((uint8_t *)buffer, width, height, stride_in_pixels << 1, viewport.x, viewport.y, viewport.w, viewport.h); + } } int S9xVulkanDisplayDriver::query_availability() diff --git a/gtk/src/gtk_display_driver_vulkan.h b/gtk/src/gtk_display_driver_vulkan.h index c3386105..75f6be75 100644 --- a/gtk/src/gtk_display_driver_vulkan.h +++ b/gtk/src/gtk_display_driver_vulkan.h @@ -8,9 +8,8 @@ #include "gtk_s9x.h" #include "gtk_display_driver.h" #include "../../vulkan/vulkan_context.hpp" -#include "../../vulkan/vulkan_texture.hpp" -#include "../../vulkan/slang_preset.hpp" #include "../../vulkan/vulkan_shader_chain.hpp" +#include "../../vulkan/vulkan_simple_output.hpp" #ifdef VK_USE_PLATFORM_WAYLAND_KHR #include "gtk_wayland_surface.h" @@ -33,14 +32,12 @@ class S9xVulkanDisplayDriver : public S9xDisplayDriver private: std::unique_ptr context; - Vulkan::Swapchain *swapchain; vk::Device device; GdkDisplay *gdk_display; GdkWindow *gdk_window; Display *display; Window xid; - Colormap colormap; int current_width; int current_height; @@ -48,16 +45,6 @@ class S9xVulkanDisplayDriver : public S9xDisplayDriver std::unique_ptr wayland_surface; #endif - void create_pipeline(); - vk::UniqueDescriptorSetLayout descriptor_set_layout; - vk::UniquePipelineLayout pipeline_layout; - vk::UniquePipeline pipeline; - vk::Sampler linear_sampler; - vk::Sampler nearest_sampler; - - void draw_buffer(uint8_t *buffer, int width, int height, int byte_stride); - bool filter = true; - std::vector textures; - std::vector descriptors; std::unique_ptr shaderchain; + std::unique_ptr simple_output; }; diff --git a/vulkan/vulkan_simple_output.cpp b/vulkan/vulkan_simple_output.cpp new file mode 100644 index 00000000..b3e2d257 --- /dev/null +++ b/vulkan/vulkan_simple_output.cpp @@ -0,0 +1,258 @@ +#include "vulkan_simple_output.hpp" +#include "slang_shader.hpp" + +namespace Vulkan +{ + +static const char *vertex_shader = R"( +#version 450 + +layout(location = 0) out vec2 texcoord; + +vec2 positions[3] = vec2[](vec2(-1.0, -3.0), vec2(3.0, 1.0), vec2(-1.0, 1.0)); +vec2 texcoords[3] = vec2[](vec2(0.0, -1.0), vec2(2.0, 1.0), vec2(0.0, 1.0)); + +void main() +{ + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + texcoord = texcoords[gl_VertexIndex]; +} +)"; + +static const char *fragment_shader = R"( +#version 450 + +layout(location = 0) in vec2 texcoord; +layout(binding = 0) uniform sampler2D tsampler; + +layout(location = 0) out vec4 fragcolor; + +void main() +{ + fragcolor = texture(tsampler, texcoord); +} +)"; + +SimpleOutput::SimpleOutput(Context *context, vk::Format format) +{ + this->context = context; + device = context->device; + swapchain = context->swapchain.get(); + this->format = format; + create_pipeline(); + create_objects(); +} + +SimpleOutput::~SimpleOutput() +{ + context->wait_idle(); + textures.clear(); + descriptors.clear(); + device.destroySampler(linear_sampler); + device.destroySampler(nearest_sampler); +} + +void SimpleOutput::create_objects() +{ + descriptors.clear(); + for (size_t i = 0; i < swapchain->get_num_frames(); i++) + { + vk::DescriptorSetAllocateInfo dsai{}; + dsai + .setDescriptorPool(context->descriptor_pool.get()) + .setDescriptorSetCount(1) + .setSetLayouts(descriptor_set_layout.get()); + auto descriptor = device.allocateDescriptorSetsUnique(dsai); + descriptors.push_back(std::move(descriptor[0])); + } + + textures.clear(); + textures.resize(swapchain->get_num_frames()); + for (auto &t : textures) + { + t.init(context); + t.create(256, 224, format, vk::SamplerAddressMode::eClampToEdge, filter, false); + } + + vk::SamplerCreateInfo sci{}; + sci.setAddressModeU(vk::SamplerAddressMode::eClampToEdge) + .setAddressModeV(vk::SamplerAddressMode::eClampToEdge) + .setAddressModeW(vk::SamplerAddressMode::eClampToEdge) + .setMipmapMode(vk::SamplerMipmapMode::eLinear) + .setAnisotropyEnable(false) + .setMinFilter(vk::Filter::eLinear) + .setMagFilter(vk::Filter::eLinear) + .setUnnormalizedCoordinates(false) + .setMinLod(1.0f) + .setMaxLod(1.0f) + .setMipLodBias(0.0) + .setCompareEnable(false); + linear_sampler = device.createSampler(sci); + + sci.setMinFilter(vk::Filter::eNearest) + .setMagFilter(vk::Filter::eNearest); + nearest_sampler = device.createSampler(sci); +} + +void SimpleOutput::create_pipeline() +{ + auto vertex_spirv = SlangShader::generate_spirv(vertex_shader, "vertex"); + auto fragment_spirv = SlangShader::generate_spirv(fragment_shader, "fragment"); + + auto vertex_module = device.createShaderModuleUnique({ {}, vertex_spirv }); + auto fragment_module = device.createShaderModuleUnique({ {}, fragment_spirv }); + + vk::PipelineShaderStageCreateInfo vertex_ci; + vertex_ci.setStage(vk::ShaderStageFlagBits::eVertex) + .setModule(vertex_module.get()) + .setPName("main"); + + vk::PipelineShaderStageCreateInfo fragment_ci; + fragment_ci.setStage(vk::ShaderStageFlagBits::eFragment) + .setModule(fragment_module.get()) + .setPName("main"); + + std::vector stages = { vertex_ci, fragment_ci }; + + vk::PipelineVertexInputStateCreateInfo vertex_input_info{}; + + vk::PipelineInputAssemblyStateCreateInfo pipeline_input_assembly_info{}; + pipeline_input_assembly_info.setTopology(vk::PrimitiveTopology::eTriangleList) + .setPrimitiveRestartEnable(false); + + std::vector viewports(1); + viewports[0] + .setX(0.0f) + .setY(0.0f) + .setWidth(256) + .setHeight(256) + .setMinDepth(0.0f) + .setMaxDepth(1.0f); + std::vector scissors(1); + scissors[0].extent.width = 256; + scissors[0].extent.height = 256; + scissors[0].offset = vk::Offset2D(0, 0); + + vk::PipelineViewportStateCreateInfo pipeline_viewport_info; + pipeline_viewport_info.setViewports(viewports) + .setScissors(scissors); + + vk::PipelineRasterizationStateCreateInfo rasterizer_info; + rasterizer_info.setCullMode(vk::CullModeFlagBits::eBack) + .setFrontFace(vk::FrontFace::eClockwise) + .setLineWidth(1.0f) + .setDepthClampEnable(false) + .setRasterizerDiscardEnable(false) + .setPolygonMode(vk::PolygonMode::eFill) + .setDepthBiasEnable(false) + .setRasterizerDiscardEnable(false); + + vk::PipelineMultisampleStateCreateInfo multisample_info; + multisample_info.setSampleShadingEnable(false) + .setRasterizationSamples(vk::SampleCountFlagBits::e1); + + vk::PipelineDepthStencilStateCreateInfo depth_stencil_info; + depth_stencil_info.setDepthTestEnable(false); + + vk::PipelineColorBlendAttachmentState blend_attachment_info; + blend_attachment_info + .setColorWriteMask(vk::ColorComponentFlagBits::eB | + vk::ColorComponentFlagBits::eG | + vk::ColorComponentFlagBits::eR | + vk::ColorComponentFlagBits::eA) + .setBlendEnable(true) + .setColorBlendOp(vk::BlendOp::eAdd) + .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha) + .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha) + .setAlphaBlendOp(vk::BlendOp::eAdd) + .setSrcAlphaBlendFactor(vk::BlendFactor::eOne) + .setSrcAlphaBlendFactor(vk::BlendFactor::eZero); + + vk::PipelineColorBlendStateCreateInfo blend_state_info; + blend_state_info.setLogicOpEnable(false) + .setAttachments(blend_attachment_info); + + std::vector states = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; + vk::PipelineDynamicStateCreateInfo dynamic_state_info({}, states); + + vk::DescriptorSetLayoutBinding dslb{}; + dslb.setBinding(0) + .setStageFlags(vk::ShaderStageFlagBits::eFragment) + .setDescriptorCount(1) + .setDescriptorType(vk::DescriptorType::eCombinedImageSampler); + vk::DescriptorSetLayoutCreateInfo dslci{}; + dslci.setBindings(dslb); + descriptor_set_layout = device.createDescriptorSetLayoutUnique(dslci); + + vk::PipelineLayoutCreateInfo pipeline_layout_info; + pipeline_layout_info.setSetLayoutCount(0) + .setPushConstantRangeCount(0) + .setSetLayouts(descriptor_set_layout.get()); + + pipeline_layout = device.createPipelineLayoutUnique(pipeline_layout_info); + + vk::GraphicsPipelineCreateInfo pipeline_create_info; + pipeline_create_info.setStageCount(2) + .setStages(stages) + .setPVertexInputState(&vertex_input_info) + .setPInputAssemblyState(&pipeline_input_assembly_info) + .setPViewportState(&pipeline_viewport_info) + .setPRasterizationState(&rasterizer_info) + .setPMultisampleState(&multisample_info) + .setPDepthStencilState(&depth_stencil_info) + .setPColorBlendState(&blend_state_info) + .setPDynamicState(&dynamic_state_info) + .setLayout(pipeline_layout.get()) + .setRenderPass(swapchain->get_render_pass()) + .setSubpass(0); + + auto [result, pipeline] = device.createGraphicsPipelineUnique(nullptr, pipeline_create_info); + this->pipeline = std::move(pipeline); +} + +void SimpleOutput::set_filter(bool on) +{ + filter = on; +} + +void SimpleOutput::do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height) +{ + if (!context) + return; + + if (!swapchain->begin_frame()) + return; + + auto &tex = textures[swapchain->get_current_frame()]; + auto &cmd = swapchain->get_cmd(); + auto extents = swapchain->get_extents(); + auto &dstset = descriptors[swapchain->get_current_frame()].get(); + + tex.from_buffer(cmd, (uint8_t *)buffer, width, height, byte_stride); + + swapchain->begin_render_pass(); + + vk::DescriptorImageInfo dii{}; + dii.setImageView(tex.image_view) + .setSampler(filter ? linear_sampler : nearest_sampler) + .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal); + vk::WriteDescriptorSet wds{}; + wds.setDescriptorCount(1) + .setDstBinding(0) + .setDstArrayElement(0) + .setDstSet(dstset) + .setDescriptorType(vk::DescriptorType::eCombinedImageSampler) + .setImageInfo(dii); + device.updateDescriptorSets(wds, {}); + + cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get()); + cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline_layout.get(), 0, dstset, {}); + cmd.setViewport(0, vk::Viewport(viewport_x, viewport_y, viewport_width, viewport_height, 0.0f, 1.0f)); + cmd.setScissor(0, vk::Rect2D({}, extents)); + cmd.draw(3, 1, 0, 0); + + swapchain->end_render_pass(); + swapchain->end_frame(); +} + +} // namespace Vulkan \ No newline at end of file diff --git a/vulkan/vulkan_simple_output.hpp b/vulkan/vulkan_simple_output.hpp new file mode 100644 index 00000000..77de954b --- /dev/null +++ b/vulkan/vulkan_simple_output.hpp @@ -0,0 +1,36 @@ +#pragma once +#include "vulkan_context.hpp" +#include "vulkan_texture.hpp" + +namespace Vulkan +{ + +class SimpleOutput +{ + public: + SimpleOutput(Vulkan::Context *context, vk::Format format); + ~SimpleOutput(); + void do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height); + void set_filter(bool on); + + private: + void create_pipeline(); + void create_objects(); + + Context *context; + vk::Device device; + Vulkan::Swapchain *swapchain; + + vk::UniqueDescriptorSetLayout descriptor_set_layout; + vk::UniquePipelineLayout pipeline_layout; + vk::UniquePipeline pipeline; + vk::Sampler linear_sampler; + vk::Sampler nearest_sampler; + vk::Format format; + std::vector textures; + std::vector descriptors; + + bool filter = true; +}; + +} // namespace Vulkan \ No newline at end of file