summaryrefslogtreecommitdiff
path: root/gsk/vulkan/gskvulkanpushconstants.c
blob: 0bf5ca71b04b98edbecd90a81b101f02dce4e134 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "config.h"

#include "gskvulkanpushconstantsprivate.h"

#include "gskroundedrectprivate.h"
#include "gsktransform.h"

typedef struct _GskVulkanPushConstantsWire GskVulkanPushConstantsWire;

struct _GskVulkanPushConstantsWire
{
  struct {
    float mvp[16];
    float clip[12];
  } common;
};

/* This is the value we know every conformant GPU must provide.
 * See value for maxPushConstantsSize in table 55 of
 * https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#limits-minmax
 */
G_STATIC_ASSERT (sizeof (GskVulkanPushConstantsWire) <= 128);

void
gsk_vulkan_push_constants_init (GskVulkanPushConstants  *constants,
                                const graphene_matrix_t *mvp,
                                const graphene_rect_t   *viewport)
{
  graphene_matrix_init_from_matrix (&constants->mvp, mvp);
  gsk_vulkan_clip_init_empty (&constants->clip, viewport);
}

void
gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants       *self,
                                     const GskVulkanPushConstants *src)
{
  *self = *src;
}

gboolean
gsk_vulkan_push_constants_transform (GskVulkanPushConstants       *self,
                                     const GskVulkanPushConstants *src,
                                     GskTransform                 *transform,
                                     const graphene_rect_t        *viewport)

{
  graphene_matrix_t matrix;

  if (!gsk_vulkan_clip_transform (&self->clip, &src->clip, transform, viewport))
    return FALSE;

  gsk_transform_to_matrix (transform, &matrix);
  graphene_matrix_multiply (&matrix, &src->mvp, &self->mvp);

  return TRUE;
}

gboolean
gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants       *self,
                                          const GskVulkanPushConstants *src,
                                          const graphene_rect_t        *rect)
{
  if (!gsk_vulkan_clip_intersect_rect (&self->clip, &src->clip, rect))
    return FALSE;

  graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
  return TRUE;
}

gboolean
gsk_vulkan_push_constants_intersect_rounded (GskVulkanPushConstants       *self,
                                             const GskVulkanPushConstants *src,
                                             const GskRoundedRect         *rect)
{
  if (!gsk_vulkan_clip_intersect_rounded_rect (&self->clip, &src->clip, rect))
    return FALSE;

  graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
  return TRUE;
}

static void
gsk_vulkan_push_constants_wire_init (GskVulkanPushConstantsWire   *wire,
                                     const GskVulkanPushConstants *self)
{
  graphene_matrix_to_float (&self->mvp, wire->common.mvp);
  gsk_rounded_rect_to_float (&self->clip.rect, graphene_point_zero (), wire->common.clip);
}

void
gsk_vulkan_push_constants_push (const GskVulkanPushConstants *self,
                                VkCommandBuffer               command_buffer,
                                VkPipelineLayout              pipeline_layout)
{
  GskVulkanPushConstantsWire wire;

  gsk_vulkan_push_constants_wire_init (&wire, self);

  vkCmdPushConstants (command_buffer,
                      pipeline_layout,
                      VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
                      G_STRUCT_OFFSET (GskVulkanPushConstantsWire, common),
                      sizeof (wire.common),
                      &wire.common);
}

uint32_t
gsk_vulkan_push_constants_get_range_count (void)
{
  return 1;
}

const VkPushConstantRange *
gsk_vulkan_push_constants_get_ranges (void)
{
  static const VkPushConstantRange ranges[1] = {
      {
          .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
          .offset = G_STRUCT_OFFSET (GskVulkanPushConstantsWire, common),
          .size = sizeof (((GskVulkanPushConstantsWire *) 0)->common)
      }
  };

  return ranges;
}