11#include " wayfire/debug.hpp"
22#include " wayfire/opengl.hpp"
33#include " wayfire/region.hpp"
4+ #include " wayfire/vulkan.hpp"
45#include < memory>
56#include < wayfire/plugin.hpp>
67#include < wayfire/signal-definitions.hpp>
1011#include < wayfire/render-manager.hpp>
1112#include < wayfire/plugins/common/util.hpp>
1213
14+ #include " shaders/wobbly.vert.h"
15+ #include " shaders/wobbly.frag.h"
16+
1317extern " C"
1418{
1519#include " wobbly.h"
@@ -599,6 +603,7 @@ class wobbly_transformer_node_t : public wf::scene::transformer_base_node_t
599603 }
600604
601605 OpenGL::program_t *wobbly_program;
606+ std::array<std::shared_ptr<wf::vk::gpu_buffer_t >, 4 > vulkan_vertex_buffer;
602607
603608 private:
604609 wayfire_toplevel_view view;
@@ -884,24 +889,147 @@ class wobbly_render_instance_t :
884889 damage |= self->get_bounding_box ();
885890 }
886891
892+ class vulkan_state_t : public wf ::custom_data_t
893+ {
894+ public:
895+ std::shared_ptr<wf::vk::graphics_pipeline_t > pipeline;
896+ };
897+
898+ vulkan_state_t & ensure_vk (wf::vulkan_render_state_t & state)
899+ {
900+ if (auto data = state.get_data <vulkan_state_t >())
901+ {
902+ return *data;
903+ }
904+
905+ auto vs = state.get_context ()->load_shader_module (wobbly_vert_data, sizeof (wobbly_vert_data));
906+ auto fs = state.get_context ()->load_shader_module (wobbly_frag_data, sizeof (wobbly_frag_data));
907+
908+ wf::vk::pipeline_params_t params{};
909+ params.shaders = {
910+ {.stage = VK_SHADER_STAGE_VERTEX_BIT, .shader = vs},
911+ {.stage = VK_SHADER_STAGE_FRAGMENT_BIT, .shader = fs},
912+ };
913+
914+ params.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
915+ params.vertexInputDescription = {{
916+ .binding = 0 ,
917+ .stride = sizeof (float ) * 4 ,
918+ .inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
919+ }};
920+ params.vertexAttributeDescription = {
921+ {
922+ .location = 0 ,
923+ .binding = 0 ,
924+ .format = VK_FORMAT_R32G32_SFLOAT,
925+ .offset = 0 ,
926+ },
927+ {
928+ .location = 1 ,
929+ .binding = 0 ,
930+ .format = VK_FORMAT_R32G32_SFLOAT,
931+ .offset = sizeof (float ) * 2 ,
932+ },
933+ };
934+
935+ // One descriptor set for the uv texture.
936+ params.descriptorSetLayouts = {state.get_context ()->get_image_descriptor_set_layout ()};
937+ params.pushConstants = {
938+ VkPushConstantRange{
939+ .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
940+ .offset = 0 ,
941+ .size = sizeof (glm::mat4),
942+ },
943+ };
944+
945+ auto data = std::make_unique<vulkan_state_t >();
946+ data->pipeline = std::make_shared<wf::vk::graphics_pipeline_t >(state.get_context (), params);
947+ auto ptr = data.get ();
948+ state.store_data <vulkan_state_t >(std::move (data));
949+ return *ptr;
950+ }
951+
952+ std::shared_ptr<wf::vk::gpu_buffer_t > find_buffer (
953+ std::shared_ptr<wf::vk::context_t > ctx, VkDeviceSize total_size)
954+ {
955+ auto & buffers = self->vulkan_vertex_buffer ;
956+ for (size_t i = 0 ; i < buffers.size (); i++)
957+ {
958+ auto & buffer = buffers[i];
959+ // Try to reuse the vertex buffer if possible, to avoid reallocations.
960+ if (buffer && (buffer->get_size () >= total_size) && (buffer.use_count () == 1 ))
961+ {
962+ // LOGI("Reuse buffer index ", i);
963+ return buffers[i];
964+ }
965+ }
966+
967+ buffers[0 ] = ctx->create_buffer (total_size,
968+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
969+ return buffers[0 ];
970+ }
971+
887972 void render (const wf::scene::render_instruction_t & data) override
888973 {
889974 std::vector<float > vert, uv;
890975 auto subbox = self->get_children_bounding_box ();
891976 wobbly_graphics::prepare_geometry (self->model .get (), subbox, vert, uv);
977+ const int count_triangles = self->model ->x_cells * self->model ->y_cells * 2 ;
892978
893- auto tex = wf::gles_texture_t {get_texture (data.target .scale )};
894979 data.pass ->custom_gles_subpass (data.target , [&]
895980 {
981+ auto tex = wf::gles_texture_t {this ->get_texture (data.target .scale )};
982+ wf::gles::bind_render_buffer (data.target );
896983 for (auto box : data.damage )
897984 {
898985 wf::gles::render_target_logic_scissor (data.target , wlr_box_from_pixman_box (box));
899986 wobbly_graphics::render_triangles (self->wobbly_program , tex,
900987 wf::gles::render_target_orthographic_projection (data.target ),
901- vert.data (), uv.data (),
902- self->model ->x_cells * self->model ->y_cells * 2 );
988+ vert.data (), uv.data (), count_triangles);
903989 }
904990 });
991+
992+ data.pass ->custom_vulkan_subpass ([&] (wf::vulkan_render_state_t & state,
993+ wf::vk::command_buffer_t & cmd_buf)
994+ {
995+ auto & our_state = ensure_vk (state);
996+
997+ std::vector<float > unified_buffer;
998+ for (size_t i = 0 ; i < vert.size () / 2 ; i++)
999+ {
1000+ unified_buffer.push_back (vert[2 * i]);
1001+ unified_buffer.push_back (vert[2 * i + 1 ]);
1002+ unified_buffer.push_back (uv[2 * i]);
1003+ unified_buffer.push_back (uv[2 * i + 1 ]);
1004+ }
1005+ VkDeviceSize total_size = unified_buffer.size () * sizeof (float );
1006+
1007+ auto buffer = find_buffer (state.get_context (), total_size);
1008+ buffer->write (unified_buffer.data (), total_size);
1009+
1010+ auto tex = state.get_descriptor_pool ()->get_descriptor_set (cmd_buf,
1011+ get_texture (data.target .scale ));
1012+
1013+ cmd_buf.bind_pipeline (our_state.pipeline , data.target );
1014+ cmd_buf.set_full_viewport (data.target );
1015+
1016+ vkCmdBindDescriptorSets (cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, our_state.pipeline ->layout (),
1017+ 0 , 1 , &tex, 0 , nullptr );
1018+
1019+ auto transform = wf::vk::render_target_transform (data.target );
1020+ vkCmdPushConstants (cmd_buf, our_state.pipeline ->layout (), VK_SHADER_STAGE_VERTEX_BIT,
1021+ 0 , sizeof (glm::mat4), &transform);
1022+
1023+
1024+ cmd_buf.bind_buffer (buffer);
1025+ VkDeviceSize offset = 0 ;
1026+ vkCmdBindVertexBuffers (cmd_buf, 0 , 1 , &buffer->get_buffer (), &offset);
1027+
1028+ cmd_buf.for_each_scissor_rect (data.target , (data.damage & data.target .geometry ), [&]
1029+ {
1030+ vkCmdDraw (cmd_buf, count_triangles * 3 , 1 , 0 , 0 );
1031+ });
1032+ });
9051033 }
9061034};
9071035
@@ -923,14 +1051,6 @@ class wayfire_wobbly : public wf::plugin_interface_t
9231051 public:
9241052 void init () override
9251053 {
926- if (!wf::get_core ().is_gles2 ())
927- {
928- const char *render_type =
929- wf::get_core ().is_vulkan () ? " vulkan" : (wf::get_core ().is_pixman () ? " pixman" : " unknown" );
930- LOGE (" wobbly: requires GLES2 support, but current renderer is " , render_type);
931- return ;
932- }
933-
9341054 wf::get_core ().connect (&wobbly_changed);
9351055 wf::gles::run_in_context_if_gles ([&]
9361056 {
0 commit comments