Skip to content

Commit b577ef4

Browse files
committed
tmp wobbly
1 parent bc8697c commit b577ef4

File tree

18 files changed

+487
-123
lines changed

18 files changed

+487
-123
lines changed

plugins/wobbly/wobbly.cpp

Lines changed: 131 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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>
@@ -10,6 +11,9 @@
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+
1317
extern "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
{

shaders/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
shaders = [
33
'core-basic.vert',
44
'core-basic.frag',
5+
'wobbly.vert',
6+
'wobbly.frag',
57
]
68

79
glslang = find_program('glslang', 'glslangValidator', native: true, required: true)

shaders/wobbly.frag

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#version 450
2+
3+
layout(location = 0) out vec4 out_color;
4+
5+
layout(set = 0, binding = 0) uniform sampler2D tex;
6+
layout(set = 0, binding = 1, column_major) uniform UVT {
7+
mat3 uv_transform;
8+
} uvt;
9+
10+
layout(location = 0) in vec2 uv;
11+
12+
float srgb_channel_to_linear(float x) {
13+
return mix(x / 12.92,
14+
pow((x + 0.055) / 1.055, 2.4),
15+
x > 0.04045);
16+
}
17+
18+
19+
void main() {
20+
vec4 r = texture(tex, (uvt.uv_transform * vec3(uv, 1.0)).xy);
21+
r = vec4(srgb_channel_to_linear(r.r),
22+
srgb_channel_to_linear(r.g),
23+
srgb_channel_to_linear(r.b),
24+
r.a);
25+
//r = pow(r, vec4(2.2));
26+
out_color = r;
27+
}

shaders/wobbly.vert

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#version 450
2+
3+
layout(push_constant, column_major) uniform UBO {
4+
mat4 mvp;
5+
} data;
6+
7+
layout(location = 0) out vec2 uv;
8+
9+
layout(location = 0) in vec2 pos;
10+
layout(location = 1) in vec2 uv_in;
11+
12+
void main() {
13+
gl_Position = data.mvp * vec4(pos, 0.0, 1.0);
14+
uv = uv_in;
15+
}

src/api/wayfire/nonstd/wlroots-full.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ extern "C"
4848
#undef static
4949
#include <wlr/types/wlr_buffer.h>
5050
#include <wlr/types/wlr_viewporter.h>
51+
#include <wlr/types/wlr_color_management_v1.h>
52+
#include <wlr/types/wlr_color_representation_v1.h>
5153

5254
#include <wlr/types/wlr_damage_ring.h>
5355
#include <wlr/types/wlr_presentation_time.h>

src/api/wayfire/render.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ namespace vk
2424
class command_buffer_t;
2525
}
2626

27+
/**
28+
* A struct which describes the color space of a given texture.
29+
*/
30+
struct color_transform_t
31+
{
32+
wlr_color_transfer_function transfer_function = WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR;
33+
wlr_color_named_primaries primaries = WLR_COLOR_NAMED_PRIMARIES_SRGB;
34+
wlr_color_encoding color_encoding = WLR_COLOR_ENCODING_NONE;
35+
wlr_color_range color_range = WLR_COLOR_RANGE_NONE;
36+
37+
bool operator ==(const color_transform_t& other) const;
38+
bool operator !=(const color_transform_t& other) const;
39+
};
40+
2741
/**
2842
* A wrapper around wlr_texture which ensures that the texture is kept alive as long as the wrapper object
2943
* is alive.
@@ -51,6 +65,10 @@ class texture_t : public wf::signal::provider_t
5165
std::optional<wlr_scale_filter_mode> get_filter_mode() const;
5266
void set_filter_mode(const std::optional<wlr_scale_filter_mode>& mode);
5367

68+
// Getters and setters for color_transform
69+
std::optional<color_transform_t> get_color_transform() const;
70+
void set_color_transform(const std::optional<color_transform_t>& ct);
71+
5472
/**
5573
* Manage an existing wlr_texture created from a wlr_buffer.
5674
* We keep the texture alive by keeping the associated buffer alive.
@@ -96,6 +114,7 @@ class texture_t : public wf::signal::provider_t
96114
std::optional<wlr_fbox> source_box = {};
97115
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
98116
std::optional<wlr_scale_filter_mode> filter_mode = {};
117+
std::optional<color_transform_t> color_transform = {};
99118
};
100119

101120
/**

src/api/wayfire/unstable/wlr-surface-node.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct surface_state_t
2222
wf::dimensions_t size = {0, 0};
2323
std::optional<wlr_fbox> src_viewport;
2424
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
25+
std::optional<wf::color_transform_t> color_transform;
2526

2627
// Sequence number of the last commit read from a wlr_surface state
2728
std::optional<uint32_t> seq{};
@@ -66,7 +67,7 @@ class wlr_surface_node_t : public node_t, public zero_copy_texturable_node_t
6667
void gen_render_instances(std::vector<render_instance_uptr>& instances, damage_callback damage,
6768
wf::output_t *output) override;
6869
wf::geometry_t get_bounding_box() override;
69-
std::optional<std::shared_ptr<wf::texture_t>> to_texture() const override;
70+
std::shared_ptr<wf::texture_t> to_texture() const override;
7071

7172
wlr_surface *get_surface() const;
7273
void apply_state(surface_state_t&& state);

src/api/wayfire/view-transform.hpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ class zero_copy_texturable_node_t
2222
* Get a texture from the node without copying.
2323
* Note that this operation might fail for non-trivial transformers.
2424
*/
25-
virtual std::optional<std::shared_ptr<wf::texture_t>> to_texture() const
25+
virtual std::shared_ptr<wf::texture_t> to_texture() const
2626
{
27-
return {};
27+
return nullptr;
2828
}
2929
};
3030

@@ -88,18 +88,22 @@ template<class NodeType>
8888
class transformer_render_instance_t : public render_instance_t
8989
{
9090
protected:
91-
std::optional<std::shared_ptr<wf::texture_t>> zero_copy_texture()
91+
std::shared_ptr<wf::texture_t> zero_copy_texture()
9292
{
9393
if (self->get_children().size() == 1)
9494
{
9595
auto child = self->get_children().front().get();
9696
if (auto zcopy = dynamic_cast<zero_copy_texturable_node_t*>(child))
9797
{
98-
return zcopy->to_texture();
98+
auto tex = zcopy->to_texture();
99+
if (tex && !tex->get_color_transform())
100+
{
101+
return tex;
102+
}
99103
}
100104
}
101105

102-
return {};
106+
return nullptr;
103107
}
104108

105109
// A pointer to the transformer node this render instance belongs to.
@@ -128,7 +132,7 @@ class transformer_render_instance_t : public render_instance_t
128132
if (auto tex = zero_copy_texture())
129133
{
130134
self->release_buffers();
131-
return *tex;
135+
return tex;
132136
}
133137

134138
return self->get_updated_contents(self->get_children_bounding_box(), scale, children);

0 commit comments

Comments
 (0)