mirror of https://github.com/snes9xgit/snes9x.git
Gtk: Move simple vulkan output into separate class.
This commit is contained in:
parent
410696ce4e
commit
bb210dc1a1
|
@ -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()
|
||||
|
||||
|
|
|
@ -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<vk::PipelineShaderStageCreateInfo> 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<vk::Viewport> viewports(1);
|
||||
viewports[0]
|
||||
.setX(0.0f)
|
||||
.setY(0.0f)
|
||||
.setWidth(256)
|
||||
.setHeight(256)
|
||||
.setMinDepth(0.0f)
|
||||
.setMaxDepth(1.0f);
|
||||
std::vector<vk::Rect2D> 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<vk::DynamicState> 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<Vulkan::SimpleOutput>(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()
|
||||
|
|
|
@ -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<Vulkan::Context> 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<WaylandSurface> 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<Vulkan::Texture> textures;
|
||||
std::vector<vk::UniqueDescriptorSet> descriptors;
|
||||
std::unique_ptr<Vulkan::ShaderChain> shaderchain;
|
||||
std::unique_ptr<Vulkan::SimpleOutput> simple_output;
|
||||
};
|
||||
|
|
|
@ -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<vk::PipelineShaderStageCreateInfo> 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<vk::Viewport> viewports(1);
|
||||
viewports[0]
|
||||
.setX(0.0f)
|
||||
.setY(0.0f)
|
||||
.setWidth(256)
|
||||
.setHeight(256)
|
||||
.setMinDepth(0.0f)
|
||||
.setMaxDepth(1.0f);
|
||||
std::vector<vk::Rect2D> 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<vk::DynamicState> 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
|
|
@ -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<Vulkan::Texture> textures;
|
||||
std::vector<vk::UniqueDescriptorSet> descriptors;
|
||||
|
||||
bool filter = true;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
Loading…
Reference in New Issue