mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-14 06:10:21 +00:00
88dc49a5b6
Makes the verbose output (a lot) more verbose, but it makes the colorstates used in the shaders very visible. And it will be relevant once people start using different colorstates everywhere (like oklab for gradients/colors and so on).
281 lines
9.6 KiB
C
281 lines
9.6 KiB
C
#include "config.h"
|
|
|
|
#include "gskgpushaderopprivate.h"
|
|
|
|
#include "gskgpuframeprivate.h"
|
|
#include "gskgpuprintprivate.h"
|
|
#include "gskgldescriptorsprivate.h"
|
|
#include "gskgldeviceprivate.h"
|
|
#include "gskglframeprivate.h"
|
|
#include "gskglimageprivate.h"
|
|
#ifdef GDK_RENDERING_VULKAN
|
|
#include "gskvulkandescriptorsprivate.h"
|
|
#include "gskvulkandeviceprivate.h"
|
|
#endif
|
|
|
|
#include "gdkglcontextprivate.h"
|
|
|
|
/* maximum number of ops to merge into one call
|
|
* If this number is too high, the command may take too long
|
|
* causing the driver to kill us.
|
|
*/
|
|
#define MAX_MERGE_OPS (10 * 1000)
|
|
|
|
void
|
|
gsk_gpu_shader_op_finish (GskGpuOp *op)
|
|
{
|
|
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
|
|
|
|
g_clear_object (&self->desc);
|
|
}
|
|
|
|
void
|
|
gsk_gpu_shader_op_print (GskGpuOp *op,
|
|
GskGpuFrame *frame,
|
|
GString *string,
|
|
guint indent)
|
|
{
|
|
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
|
|
const GskGpuShaderOpClass *shader_class = (const GskGpuShaderOpClass *) op->op_class;
|
|
const char *shader_name;
|
|
guchar *instance;
|
|
gsize i;
|
|
|
|
if (g_str_has_prefix (shader_class->shader_name, "gskgpu"))
|
|
shader_name = shader_class->shader_name + 6;
|
|
else
|
|
shader_name = shader_class->shader_name;
|
|
|
|
instance = gsk_gpu_frame_get_vertex_data (frame, self->vertex_offset);
|
|
|
|
for (i = 0; i < self->n_ops; i++)
|
|
{
|
|
gsk_gpu_print_op (string, indent, shader_name);
|
|
gsk_gpu_print_shader_clip (string, self->clip);
|
|
gsk_gpu_print_color_states (string, self->color_states);
|
|
shader_class->print_instance (self,
|
|
instance + i * shader_class->vertex_size,
|
|
string);
|
|
gsk_gpu_print_newline (string);
|
|
}
|
|
}
|
|
|
|
#ifdef GDK_RENDERING_VULKAN
|
|
GskGpuOp *
|
|
gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
|
|
GskGpuFrame *frame,
|
|
GskVulkanCommandState *state,
|
|
gsize instance_scale)
|
|
{
|
|
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
|
|
GskGpuShaderOpClass *shader_op_class = (GskGpuShaderOpClass *) op->op_class;
|
|
GskVulkanDescriptors *desc;
|
|
GskGpuOp *next;
|
|
gsize i, n_ops, max_ops_per_draw;
|
|
|
|
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_MERGE) &&
|
|
gsk_vulkan_device_has_feature (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
|
|
GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING))
|
|
max_ops_per_draw = MAX_MERGE_OPS;
|
|
else
|
|
max_ops_per_draw = 1;
|
|
|
|
desc = GSK_VULKAN_DESCRIPTORS (self->desc);
|
|
if (desc && state->desc != desc)
|
|
{
|
|
gsk_vulkan_descriptors_bind (desc, state->desc, state->vk_command_buffer);
|
|
state->desc = desc;
|
|
}
|
|
|
|
n_ops = self->n_ops;
|
|
for (next = op->next; next; next = next->next)
|
|
{
|
|
GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next;
|
|
|
|
if (next->op_class != op->op_class ||
|
|
next_shader->desc != self->desc ||
|
|
next_shader->color_states != self->color_states ||
|
|
next_shader->variation != self->variation ||
|
|
next_shader->clip != self->clip ||
|
|
next_shader->vertex_offset != self->vertex_offset + n_ops * shader_op_class->vertex_size)
|
|
break;
|
|
|
|
n_ops += next_shader->n_ops;
|
|
}
|
|
|
|
vkCmdBindPipeline (state->vk_command_buffer,
|
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
gsk_vulkan_device_get_vk_pipeline (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
|
|
gsk_vulkan_descriptors_get_pipeline_layout (state->desc),
|
|
shader_op_class,
|
|
self->color_states,
|
|
self->variation,
|
|
self->clip,
|
|
state->blend,
|
|
state->vk_format,
|
|
state->vk_render_pass));
|
|
|
|
for (i = 0; i < n_ops; i += max_ops_per_draw)
|
|
{
|
|
vkCmdDraw (state->vk_command_buffer,
|
|
6 * instance_scale, MIN (max_ops_per_draw, n_ops - i),
|
|
0, self->vertex_offset / shader_op_class->vertex_size + i);
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
GskGpuOp *
|
|
gsk_gpu_shader_op_vk_command (GskGpuOp *op,
|
|
GskGpuFrame *frame,
|
|
GskVulkanCommandState *state)
|
|
{
|
|
return gsk_gpu_shader_op_vk_command_n (op, frame, state, 1);
|
|
}
|
|
#endif
|
|
|
|
GskGpuOp *
|
|
gsk_gpu_shader_op_gl_command_n (GskGpuOp *op,
|
|
GskGpuFrame *frame,
|
|
GskGLCommandState *state,
|
|
gsize instance_scale)
|
|
{
|
|
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
|
|
GskGpuShaderOpClass *shader_op_class = (GskGpuShaderOpClass *) op->op_class;
|
|
GskGLDescriptors *desc;
|
|
GskGpuOp *next;
|
|
gsize i, n_ops, n_external, max_ops_per_draw;
|
|
|
|
desc = GSK_GL_DESCRIPTORS (self->desc);
|
|
if (desc)
|
|
n_external = gsk_gl_descriptors_get_n_external (desc);
|
|
else
|
|
n_external = 0;
|
|
|
|
if (state->current_program.op_class != op->op_class ||
|
|
state->current_program.color_states != self->color_states ||
|
|
state->current_program.variation != self->variation ||
|
|
state->current_program.clip != self->clip ||
|
|
state->current_program.n_external != n_external)
|
|
{
|
|
state->current_program.op_class = op->op_class;
|
|
state->current_program.color_states = self->color_states;
|
|
state->current_program.variation = self->variation;
|
|
state->current_program.clip = self->clip;
|
|
state->current_program.n_external = n_external;
|
|
gsk_gl_frame_use_program (GSK_GL_FRAME (frame),
|
|
shader_op_class,
|
|
self->color_states,
|
|
self->variation,
|
|
self->clip,
|
|
n_external);
|
|
}
|
|
|
|
if (desc != state->desc && desc)
|
|
{
|
|
gsk_gl_descriptors_use (desc);
|
|
state->desc = desc;
|
|
}
|
|
|
|
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_MERGE))
|
|
max_ops_per_draw = MAX_MERGE_OPS;
|
|
else
|
|
max_ops_per_draw = 1;
|
|
|
|
n_ops = self->n_ops;
|
|
for (next = op->next; next; next = next->next)
|
|
{
|
|
GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next;
|
|
|
|
if (next->op_class != op->op_class ||
|
|
next_shader->desc != self->desc ||
|
|
next_shader->color_states != self->color_states ||
|
|
next_shader->variation != self->variation ||
|
|
next_shader->clip != self->clip ||
|
|
next_shader->vertex_offset != self->vertex_offset + n_ops * shader_op_class->vertex_size)
|
|
break;
|
|
|
|
n_ops += next_shader->n_ops;
|
|
}
|
|
|
|
for (i = 0; i < n_ops; i += max_ops_per_draw)
|
|
{
|
|
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
|
|
GDK_GL_FEATURE_BASE_INSTANCE))
|
|
{
|
|
glDrawArraysInstancedBaseInstance (GL_TRIANGLES,
|
|
0,
|
|
6 * instance_scale,
|
|
MIN (max_ops_per_draw, n_ops - i),
|
|
self->vertex_offset / shader_op_class->vertex_size + i);
|
|
}
|
|
else
|
|
{
|
|
shader_op_class->setup_vao (self->vertex_offset + i * shader_op_class->vertex_size);
|
|
|
|
glDrawArraysInstanced (GL_TRIANGLES,
|
|
0,
|
|
6 * instance_scale,
|
|
MIN (max_ops_per_draw, n_ops - i));
|
|
}
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
GskGpuOp *
|
|
gsk_gpu_shader_op_gl_command (GskGpuOp *op,
|
|
GskGpuFrame *frame,
|
|
GskGLCommandState *state)
|
|
{
|
|
return gsk_gpu_shader_op_gl_command_n (op, frame, state, 1);
|
|
}
|
|
|
|
void
|
|
gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
|
|
const GskGpuShaderOpClass *op_class,
|
|
GskGpuColorStates color_states,
|
|
guint32 variation,
|
|
GskGpuShaderClip clip,
|
|
GskGpuDescriptors *desc,
|
|
gpointer out_vertex_data)
|
|
{
|
|
GskGpuOp *last;
|
|
GskGpuShaderOp *last_shader;
|
|
gsize vertex_offset;
|
|
|
|
vertex_offset = gsk_gpu_frame_reserve_vertex_data (frame, op_class->vertex_size);
|
|
|
|
last = gsk_gpu_frame_get_last_op (frame);
|
|
/* careful: We're casting without checking, but the if() does the check */
|
|
last_shader = (GskGpuShaderOp *) last;
|
|
if (last &&
|
|
last->op_class == (const GskGpuOpClass *) op_class &&
|
|
last_shader->desc == desc &&
|
|
last_shader->color_states == color_states &&
|
|
last_shader->variation == variation &&
|
|
last_shader->clip == clip &&
|
|
last_shader->vertex_offset + last_shader->n_ops * op_class->vertex_size == vertex_offset)
|
|
{
|
|
last_shader->n_ops++;
|
|
}
|
|
else
|
|
{
|
|
GskGpuShaderOp *self;
|
|
self = (GskGpuShaderOp *) gsk_gpu_op_alloc (frame, &op_class->parent_class);
|
|
|
|
self->color_states = color_states;
|
|
self->variation = variation;
|
|
self->clip = clip;
|
|
self->vertex_offset = vertex_offset;
|
|
if (desc)
|
|
self->desc = g_object_ref (desc);
|
|
else
|
|
self->desc = NULL;
|
|
self->n_ops = 1;
|
|
}
|
|
|
|
*((gpointer *) out_vertex_data) = gsk_gpu_frame_get_vertex_data (frame, vertex_offset);
|
|
}
|
|
|