mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-13 08:22:16 -04:00
render/vulkan: 3D LUT fallback for texture pass color transform
This commit is contained in:
parent
bf8b6a7127
commit
611e0649c5
4 changed files with 140 additions and 53 deletions
|
|
@ -168,6 +168,7 @@ enum wlr_vk_texture_transform {
|
||||||
WLR_VK_TEXTURE_TRANSFORM_ST2084_PQ = 2,
|
WLR_VK_TEXTURE_TRANSFORM_ST2084_PQ = 2,
|
||||||
WLR_VK_TEXTURE_TRANSFORM_GAMMA22 = 3,
|
WLR_VK_TEXTURE_TRANSFORM_GAMMA22 = 3,
|
||||||
WLR_VK_TEXTURE_TRANSFORM_BT1886 = 4,
|
WLR_VK_TEXTURE_TRANSFORM_BT1886 = 4,
|
||||||
|
WLR_VK_TEXTURE_TRANSFORM_LUT_3D = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wlr_vk_shader_source {
|
enum wlr_vk_shader_source {
|
||||||
|
|
@ -286,8 +287,8 @@ struct wlr_vk_command_buffer {
|
||||||
struct wl_list destroy_textures; // wlr_vk_texture.destroy_link
|
struct wl_list destroy_textures; // wlr_vk_texture.destroy_link
|
||||||
// Staging shared buffers to release after the command buffer completes
|
// Staging shared buffers to release after the command buffer completes
|
||||||
struct wl_list stage_buffers; // wlr_vk_shared_buffer.link
|
struct wl_list stage_buffers; // wlr_vk_shared_buffer.link
|
||||||
// Color transform to unref after the command buffer completes
|
// Color transforms to unref after the command buffer completes
|
||||||
struct wlr_color_transform *color_transform;
|
struct wl_array color_transforms; // struct wlr_color_transform*
|
||||||
|
|
||||||
// For DMA-BUF implicit sync interop, may be NULL
|
// For DMA-BUF implicit sync interop, may be NULL
|
||||||
VkSemaphore binary_semaphore;
|
VkSemaphore binary_semaphore;
|
||||||
|
|
@ -315,11 +316,12 @@ struct wlr_vk_renderer {
|
||||||
// for blend->output subpass
|
// for blend->output subpass
|
||||||
VkPipelineLayout output_pipe_layout;
|
VkPipelineLayout output_pipe_layout;
|
||||||
VkDescriptorSetLayout output_ds_srgb_layout;
|
VkDescriptorSetLayout output_ds_srgb_layout;
|
||||||
VkDescriptorSetLayout output_ds_lut3d_layout;
|
|
||||||
VkSampler output_sampler_lut3d;
|
VkDescriptorSetLayout ds_lut3d_layout;
|
||||||
|
VkSampler sampler_lut3d;
|
||||||
// descriptor set indicating dummy 1x1x1 image, for use in the lut3d slot
|
// descriptor set indicating dummy 1x1x1 image, for use in the lut3d slot
|
||||||
VkDescriptorSet output_ds_lut3d_dummy;
|
VkDescriptorSet ds_lut3d_dummy;
|
||||||
struct wlr_vk_descriptor_pool *output_ds_lut3d_dummy_pool;
|
struct wlr_vk_descriptor_pool *ds_lut3d_dummy_pool;
|
||||||
|
|
||||||
size_t last_output_pool_size;
|
size_t last_output_pool_size;
|
||||||
struct wl_list output_descriptor_pools; // wlr_vk_descriptor_pool.link
|
struct wl_list output_descriptor_pools; // wlr_vk_descriptor_pool.link
|
||||||
|
|
@ -374,6 +376,8 @@ struct wlr_vk_vert_pcr_data {
|
||||||
struct wlr_vk_frag_texture_pcr_data {
|
struct wlr_vk_frag_texture_pcr_data {
|
||||||
float matrix[4][4]; // only a 3x3 subset is used
|
float matrix[4][4]; // only a 3x3 subset is used
|
||||||
float alpha;
|
float alpha;
|
||||||
|
float lut_3d_offset;
|
||||||
|
float lut_3d_scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_vk_frag_output_pcr_data {
|
struct wlr_vk_frag_output_pcr_data {
|
||||||
|
|
@ -488,6 +492,8 @@ bool vulkan_wait_command_buffer(struct wlr_vk_command_buffer *cb,
|
||||||
struct wlr_vk_renderer *renderer);
|
struct wlr_vk_renderer *renderer);
|
||||||
VkSemaphore vulkan_command_buffer_wait_sync_file(struct wlr_vk_renderer *renderer,
|
VkSemaphore vulkan_command_buffer_wait_sync_file(struct wlr_vk_renderer *renderer,
|
||||||
struct wlr_vk_command_buffer *render_cb, size_t sem_index, int sync_file_fd);
|
struct wlr_vk_command_buffer *render_cb, size_t sem_index, int sync_file_fd);
|
||||||
|
bool vulkan_command_buffer_ref_color_transform(struct wlr_vk_command_buffer *cb,
|
||||||
|
struct wlr_color_transform *color_transform);
|
||||||
|
|
||||||
bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer,
|
bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer,
|
||||||
struct wlr_vk_render_pass *pass);
|
struct wlr_vk_render_pass *pass);
|
||||||
|
|
@ -583,7 +589,7 @@ struct wlr_vk_color_transform {
|
||||||
} lut_3d;
|
} lut_3d;
|
||||||
|
|
||||||
float color_matrix[9];
|
float color_matrix[9];
|
||||||
enum wlr_color_transfer_function inverse_eotf;
|
enum wlr_color_transfer_function eotf;
|
||||||
};
|
};
|
||||||
void vk_color_transform_destroy(struct wlr_addon *addon);
|
void vk_color_transform_destroy(struct wlr_addon *addon);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,12 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
need_lut = transform->lut_3d.dim > 0;
|
need_lut = transform->lut_3d.dim > 0;
|
||||||
dim = need_lut ? transform->lut_3d.dim : 1;
|
dim = need_lut ? transform->lut_3d.dim : 1;
|
||||||
memcpy(matrix, transform->color_matrix, sizeof(matrix));
|
memcpy(matrix, transform->color_matrix, sizeof(matrix));
|
||||||
tf = transform->inverse_eotf;
|
tf = transform->eotf;
|
||||||
|
}
|
||||||
|
if (need_lut) {
|
||||||
|
if (!vulkan_command_buffer_ref_color_transform(render_cb, pass->color_transform)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pass->color_transform == NULL || need_lut) {
|
if (pass->color_transform == NULL || need_lut) {
|
||||||
wlr_matrix_identity(matrix);
|
wlr_matrix_identity(matrix);
|
||||||
|
|
@ -304,7 +309,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
if (need_lut) {
|
if (need_lut) {
|
||||||
lut_ds = transform->lut_3d.ds;
|
lut_ds = transform->lut_3d.ds;
|
||||||
} else {
|
} else {
|
||||||
lut_ds = renderer->output_ds_lut3d_dummy;
|
lut_ds = renderer->ds_lut3d_dummy;
|
||||||
}
|
}
|
||||||
VkDescriptorSet ds[] = {
|
VkDescriptorSet ds[] = {
|
||||||
render_buffer->two_pass.blend_descriptor_set, // set 0
|
render_buffer->two_pass.blend_descriptor_set, // set 0
|
||||||
|
|
@ -772,6 +777,9 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
||||||
pixman_region32_fini(&clip);
|
pixman_region32_fini(&clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct wlr_vk_color_transform *vk_color_transform_create(
|
||||||
|
struct wlr_vk_renderer *renderer, struct wlr_color_transform *transform, bool output);
|
||||||
|
|
||||||
static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
||||||
const struct wlr_render_texture_options *options) {
|
const struct wlr_render_texture_options *options) {
|
||||||
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
||||||
|
|
@ -817,16 +825,42 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
||||||
};
|
};
|
||||||
encode_proj_matrix(matrix, vert_pcr_data.mat4);
|
encode_proj_matrix(matrix, vert_pcr_data.mat4);
|
||||||
|
|
||||||
enum wlr_color_transfer_function tf;
|
enum wlr_color_transfer_function tf = WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR;
|
||||||
float color_matrix[9];
|
float color_matrix[9];
|
||||||
if (!unwrap_texture_color_transform(options->color_transform, color_matrix, &tf))
|
bool need_lut = false;
|
||||||
{
|
size_t dim = 1;
|
||||||
tf = WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR;
|
struct wlr_vk_color_transform *transform = NULL;
|
||||||
|
if (options->color_transform != NULL) {
|
||||||
|
transform = get_color_transform(options->color_transform, renderer);
|
||||||
|
if (transform == NULL) {
|
||||||
|
transform = vk_color_transform_create(renderer, options->color_transform, false);
|
||||||
|
if (transform == NULL) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to create color transform");
|
||||||
|
pass->failed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
need_lut = transform->lut_3d.dim > 0;
|
||||||
|
dim = need_lut ? transform->lut_3d.dim : 1;
|
||||||
|
memcpy(color_matrix, transform->color_matrix, sizeof(color_matrix));
|
||||||
|
tf = transform->eotf;
|
||||||
|
}
|
||||||
|
if (need_lut) {
|
||||||
|
if (!vulkan_command_buffer_ref_color_transform(pass->command_buffer,
|
||||||
|
options->color_transform)) {
|
||||||
|
pass->failed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (options->color_transform == NULL || need_lut) {
|
||||||
wlr_matrix_identity(color_matrix);
|
wlr_matrix_identity(color_matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool srgb_image_view = false;
|
bool srgb_image_view = false;
|
||||||
enum wlr_vk_texture_transform tex_transform = 0;
|
enum wlr_vk_texture_transform tex_transform = 0;
|
||||||
|
if (need_lut) {
|
||||||
|
tex_transform = WLR_VK_TEXTURE_TRANSFORM_LUT_3D;
|
||||||
|
} else {
|
||||||
switch (tf) {
|
switch (tf) {
|
||||||
case WLR_COLOR_TRANSFER_FUNCTION_SRGB:
|
case WLR_COLOR_TRANSFER_FUNCTION_SRGB:
|
||||||
if (texture->using_mutable_srgb) {
|
if (texture->using_mutable_srgb) {
|
||||||
|
|
@ -849,6 +883,7 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
||||||
tex_transform = WLR_VK_TEXTURE_TRANSFORM_BT1886;
|
tex_transform = WLR_VK_TEXTURE_TRANSFORM_BT1886;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum wlr_color_encoding color_encoding = options->color_encoding;
|
enum wlr_color_encoding color_encoding = options->color_encoding;
|
||||||
bool is_ycbcr = vulkan_format_is_ycbcr(texture->format);
|
bool is_ycbcr = vulkan_format_is_ycbcr(texture->format);
|
||||||
|
|
@ -891,13 +926,26 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
||||||
|
|
||||||
struct wlr_vk_frag_texture_pcr_data frag_pcr_data = {
|
struct wlr_vk_frag_texture_pcr_data frag_pcr_data = {
|
||||||
.alpha = alpha,
|
.alpha = alpha,
|
||||||
|
.lut_3d_offset = 0.5f / dim,
|
||||||
|
.lut_3d_scale = (float)(dim - 1) / dim,
|
||||||
};
|
};
|
||||||
encode_color_matrix(color_matrix, frag_pcr_data.matrix);
|
encode_color_matrix(color_matrix, frag_pcr_data.matrix);
|
||||||
|
|
||||||
bind_pipeline(pass, pipe->vk);
|
bind_pipeline(pass, pipe->vk);
|
||||||
|
|
||||||
|
VkDescriptorSet lut_ds;
|
||||||
|
if (need_lut) {
|
||||||
|
lut_ds = transform->lut_3d.ds;
|
||||||
|
} else {
|
||||||
|
lut_ds = renderer->ds_lut3d_dummy;
|
||||||
|
}
|
||||||
|
VkDescriptorSet ds[] = {
|
||||||
|
view->ds, // set 0
|
||||||
|
lut_ds, // set 1
|
||||||
|
};
|
||||||
|
size_t ds_len = sizeof(ds) / sizeof(ds[0]);
|
||||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
pipe->layout->vk, 0, 1, &view->ds, 0, NULL);
|
pipe->layout->vk, 0, ds_len, ds, 0, NULL);
|
||||||
|
|
||||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||||
|
|
@ -1123,7 +1171,7 @@ static bool create_3d_lut_image(struct wlr_vk_renderer *renderer,
|
||||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_ACCESS_SHADER_READ_BIT);
|
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||||
|
|
||||||
*ds_pool = vulkan_alloc_texture_ds(renderer,
|
*ds_pool = vulkan_alloc_texture_ds(renderer,
|
||||||
renderer->output_ds_lut3d_layout, ds);
|
renderer->ds_lut3d_layout, ds);
|
||||||
if (!*ds_pool) {
|
if (!*ds_pool) {
|
||||||
wlr_log(WLR_ERROR, "Failed to allocate descriptor");
|
wlr_log(WLR_ERROR, "Failed to allocate descriptor");
|
||||||
goto fail_imageview;
|
goto fail_imageview;
|
||||||
|
|
@ -1154,15 +1202,22 @@ fail_image:
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_vk_color_transform *vk_color_transform_create(
|
static struct wlr_vk_color_transform *vk_color_transform_create(
|
||||||
struct wlr_vk_renderer *renderer, struct wlr_color_transform *transform) {
|
struct wlr_vk_renderer *renderer, struct wlr_color_transform *transform,
|
||||||
|
bool output) {
|
||||||
struct wlr_vk_color_transform *vk_transform =
|
struct wlr_vk_color_transform *vk_transform =
|
||||||
calloc(1, sizeof(*vk_transform));
|
calloc(1, sizeof(*vk_transform));
|
||||||
if (!vk_transform) {
|
if (!vk_transform) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool need_lut = !unwrap_output_color_transform(transform, vk_transform->color_matrix,
|
bool need_lut;
|
||||||
&vk_transform->inverse_eotf);
|
if (output) {
|
||||||
|
need_lut = !unwrap_output_color_transform(transform, vk_transform->color_matrix,
|
||||||
|
&vk_transform->eotf);
|
||||||
|
} else {
|
||||||
|
need_lut = !unwrap_texture_color_transform(transform, vk_transform->color_matrix,
|
||||||
|
&vk_transform->eotf);
|
||||||
|
}
|
||||||
|
|
||||||
if (need_lut) {
|
if (need_lut) {
|
||||||
vk_transform->lut_3d.dim = 33;
|
vk_transform->lut_3d.dim = 33;
|
||||||
|
|
@ -1226,7 +1281,7 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend
|
||||||
if (options != NULL && options->color_transform != NULL &&
|
if (options != NULL && options->color_transform != NULL &&
|
||||||
!get_color_transform(options->color_transform, renderer)) {
|
!get_color_transform(options->color_transform, renderer)) {
|
||||||
/* Try to create a new color transform */
|
/* Try to create a new color transform */
|
||||||
if (!vk_color_transform_create(renderer, options->color_transform)) {
|
if (!vk_color_transform_create(renderer, options->color_transform, true)) {
|
||||||
wlr_log(WLR_ERROR, "Failed to create color transform");
|
wlr_log(WLR_ERROR, "Failed to create color transform");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -551,10 +551,12 @@ static void release_command_buffer_resources(struct wlr_vk_command_buffer *cb,
|
||||||
wl_list_insert(&renderer->stage.buffers, &buf->link);
|
wl_list_insert(&renderer->stage.buffers, &buf->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb->color_transform) {
|
struct wlr_color_transform **transform;
|
||||||
wlr_color_transform_unref(cb->color_transform);
|
wl_array_for_each(transform, &cb->color_transforms) {
|
||||||
cb->color_transform = NULL;
|
wlr_color_transform_unref(*transform);
|
||||||
}
|
}
|
||||||
|
wl_array_release(&cb->color_transforms);
|
||||||
|
wl_array_init(&cb->color_transforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_vk_command_buffer *get_command_buffer(
|
static struct wlr_vk_command_buffer *get_command_buffer(
|
||||||
|
|
@ -666,6 +668,16 @@ void vulkan_reset_command_buffer(struct wlr_vk_command_buffer *cb) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vulkan_command_buffer_ref_color_transform(struct wlr_vk_command_buffer *cb,
|
||||||
|
struct wlr_color_transform *color_transform) {
|
||||||
|
struct wlr_color_transform **ref = wl_array_add(&cb->color_transforms, sizeof(*ref));
|
||||||
|
if (ref == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*ref = wlr_color_transform_ref(color_transform);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void finish_render_buffer_out(struct wlr_vk_render_buffer_out *out,
|
static void finish_render_buffer_out(struct wlr_vk_render_buffer_out *out,
|
||||||
VkDevice dev) {
|
VkDevice dev) {
|
||||||
vkDestroyFramebuffer(dev, out->framebuffer, NULL);
|
vkDestroyFramebuffer(dev, out->framebuffer, NULL);
|
||||||
|
|
@ -1259,9 +1271,9 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) {
|
||||||
vkDestroySemaphore(dev->dev, renderer->timeline_semaphore, NULL);
|
vkDestroySemaphore(dev->dev, renderer->timeline_semaphore, NULL);
|
||||||
vkDestroyPipelineLayout(dev->dev, renderer->output_pipe_layout, NULL);
|
vkDestroyPipelineLayout(dev->dev, renderer->output_pipe_layout, NULL);
|
||||||
vkDestroyDescriptorSetLayout(dev->dev, renderer->output_ds_srgb_layout, NULL);
|
vkDestroyDescriptorSetLayout(dev->dev, renderer->output_ds_srgb_layout, NULL);
|
||||||
vkDestroyDescriptorSetLayout(dev->dev, renderer->output_ds_lut3d_layout, NULL);
|
vkDestroyDescriptorSetLayout(dev->dev, renderer->ds_lut3d_layout, NULL);
|
||||||
vkDestroyCommandPool(dev->dev, renderer->command_pool, NULL);
|
vkDestroyCommandPool(dev->dev, renderer->command_pool, NULL);
|
||||||
vkDestroySampler(dev->dev, renderer->output_sampler_lut3d, NULL);
|
vkDestroySampler(dev->dev, renderer->sampler_lut3d, NULL);
|
||||||
|
|
||||||
if (renderer->read_pixels_cache.initialized) {
|
if (renderer->read_pixels_cache.initialized) {
|
||||||
vkFreeMemory(dev->dev, renderer->read_pixels_cache.dst_img_memory, NULL);
|
vkFreeMemory(dev->dev, renderer->read_pixels_cache.dst_img_memory, NULL);
|
||||||
|
|
@ -1680,10 +1692,15 @@ static bool init_tex_layouts(struct wlr_vk_renderer *renderer,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VkDescriptorSetLayout out_ds_layouts[] = {
|
||||||
|
*out_ds_layout,
|
||||||
|
renderer->ds_lut3d_layout,
|
||||||
|
};
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pl_info = {
|
VkPipelineLayoutCreateInfo pl_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
.setLayoutCount = 1,
|
.setLayoutCount = sizeof(out_ds_layouts) / sizeof(out_ds_layouts[0]),
|
||||||
.pSetLayouts = out_ds_layout,
|
.pSetLayouts = out_ds_layouts,
|
||||||
.pushConstantRangeCount = sizeof(pc_ranges) / sizeof(pc_ranges[0]),
|
.pushConstantRangeCount = sizeof(pc_ranges) / sizeof(pc_ranges[0]),
|
||||||
.pPushConstantRanges = pc_ranges,
|
.pPushConstantRanges = pc_ranges,
|
||||||
};
|
};
|
||||||
|
|
@ -1734,7 +1751,7 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer) {
|
||||||
};
|
};
|
||||||
|
|
||||||
res = vkCreateSampler(renderer->dev->dev, &sampler_create_info, NULL,
|
res = vkCreateSampler(renderer->dev->dev, &sampler_create_info, NULL,
|
||||||
&renderer->output_sampler_lut3d);
|
&renderer->sampler_lut3d);
|
||||||
if (res != VK_SUCCESS) {
|
if (res != VK_SUCCESS) {
|
||||||
wlr_vk_error("vkCreateSampler", res);
|
wlr_vk_error("vkCreateSampler", res);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1745,7 +1762,7 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer) {
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
.pImmutableSamplers = &renderer->output_sampler_lut3d,
|
.pImmutableSamplers = &renderer->sampler_lut3d,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo ds_lut3d_info = {
|
VkDescriptorSetLayoutCreateInfo ds_lut3d_info = {
|
||||||
|
|
@ -1755,7 +1772,7 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer) {
|
||||||
};
|
};
|
||||||
|
|
||||||
res = vkCreateDescriptorSetLayout(dev, &ds_lut3d_info, NULL,
|
res = vkCreateDescriptorSetLayout(dev, &ds_lut3d_info, NULL,
|
||||||
&renderer->output_ds_lut3d_layout);
|
&renderer->ds_lut3d_layout);
|
||||||
if (res != VK_SUCCESS) {
|
if (res != VK_SUCCESS) {
|
||||||
wlr_vk_error("vkCreateDescriptorSetLayout", res);
|
wlr_vk_error("vkCreateDescriptorSetLayout", res);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1777,7 +1794,7 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer) {
|
||||||
|
|
||||||
VkDescriptorSetLayout out_ds_layouts[] = {
|
VkDescriptorSetLayout out_ds_layouts[] = {
|
||||||
renderer->output_ds_srgb_layout,
|
renderer->output_ds_srgb_layout,
|
||||||
renderer->output_ds_lut3d_layout,
|
renderer->ds_lut3d_layout,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pl_info = {
|
VkPipelineLayoutCreateInfo pl_info = {
|
||||||
|
|
@ -2307,9 +2324,9 @@ static bool init_dummy_images(struct wlr_vk_renderer *renderer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->output_ds_lut3d_dummy_pool = vulkan_alloc_texture_ds(renderer,
|
renderer->ds_lut3d_dummy_pool = vulkan_alloc_texture_ds(renderer,
|
||||||
renderer->output_ds_lut3d_layout, &renderer->output_ds_lut3d_dummy);
|
renderer->ds_lut3d_layout, &renderer->ds_lut3d_dummy);
|
||||||
if (!renderer->output_ds_lut3d_dummy_pool) {
|
if (!renderer->ds_lut3d_dummy_pool) {
|
||||||
wlr_log(WLR_ERROR, "Failed to allocate descriptor");
|
wlr_log(WLR_ERROR, "Failed to allocate descriptor");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -2321,7 +2338,7 @@ static bool init_dummy_images(struct wlr_vk_renderer *renderer) {
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
.dstSet = renderer->output_ds_lut3d_dummy,
|
.dstSet = renderer->ds_lut3d_dummy,
|
||||||
.pImageInfo = &ds_img_info,
|
.pImageInfo = &ds_img_info,
|
||||||
};
|
};
|
||||||
vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL);
|
vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform sampler2D tex;
|
layout(set = 0, binding = 0) uniform sampler2D tex;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0) uniform sampler3D lut_3d;
|
||||||
|
|
||||||
layout(location = 0) in vec2 uv;
|
layout(location = 0) in vec2 uv;
|
||||||
layout(location = 0) out vec4 out_color;
|
layout(location = 0) out vec4 out_color;
|
||||||
|
|
||||||
|
|
@ -9,6 +11,8 @@ layout(location = 0) out vec4 out_color;
|
||||||
layout(push_constant, row_major) uniform UBO {
|
layout(push_constant, row_major) uniform UBO {
|
||||||
layout(offset = 80) mat4 matrix;
|
layout(offset = 80) mat4 matrix;
|
||||||
float alpha;
|
float alpha;
|
||||||
|
float lut_3d_offset;
|
||||||
|
float lut_3d_scale;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
layout (constant_id = 0) const int TEXTURE_TRANSFORM = 0;
|
layout (constant_id = 0) const int TEXTURE_TRANSFORM = 0;
|
||||||
|
|
@ -19,6 +23,7 @@ layout (constant_id = 0) const int TEXTURE_TRANSFORM = 0;
|
||||||
#define TEXTURE_TRANSFORM_ST2084_PQ 2
|
#define TEXTURE_TRANSFORM_ST2084_PQ 2
|
||||||
#define TEXTURE_TRANSFORM_GAMMA22 3
|
#define TEXTURE_TRANSFORM_GAMMA22 3
|
||||||
#define TEXTURE_TRANSFORM_BT1886 4
|
#define TEXTURE_TRANSFORM_BT1886 4
|
||||||
|
#define TEXTURE_TRANSFORM_LUT_3D 5
|
||||||
|
|
||||||
float srgb_channel_to_linear(float x) {
|
float srgb_channel_to_linear(float x) {
|
||||||
return mix(x / 12.92,
|
return mix(x / 12.92,
|
||||||
|
|
@ -79,6 +84,10 @@ void main() {
|
||||||
rgb = pow(rgb, vec3(2.2));
|
rgb = pow(rgb, vec3(2.2));
|
||||||
} else if (TEXTURE_TRANSFORM == TEXTURE_TRANSFORM_BT1886) {
|
} else if (TEXTURE_TRANSFORM == TEXTURE_TRANSFORM_BT1886) {
|
||||||
rgb = bt1886_color_to_linear(rgb);
|
rgb = bt1886_color_to_linear(rgb);
|
||||||
|
} else if (TEXTURE_TRANSFORM == TEXTURE_TRANSFORM_LUT_3D) {
|
||||||
|
// Apply 3D LUT
|
||||||
|
vec3 pos = data.lut_3d_offset + rgb * data.lut_3d_scale;
|
||||||
|
rgb = texture(lut_3d, pos).rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
rgb = mat3(data.matrix) * rgb;
|
rgb = mat3(data.matrix) * rgb;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue