diff options
Diffstat (limited to 'render/vulkan/renderer.c')
-rw-r--r-- | render/vulkan/renderer.c | 67 |
1 files changed, 64 insertions, 3 deletions
diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 2adb1822..82d81c00 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -87,7 +87,8 @@ static void mat3_to_mat4(const float mat3[9], float mat4[4][4]) { } struct wlr_vk_descriptor_pool *vulkan_alloc_texture_ds( - struct wlr_vk_renderer *renderer, VkDescriptorSet *ds) { + struct wlr_vk_renderer *renderer, VkDescriptorSetLayout ds_layout, + VkDescriptorSet *ds) { VkResult res; bool found = false; @@ -139,7 +140,7 @@ struct wlr_vk_descriptor_pool *vulkan_alloc_texture_ds( VkDescriptorSetAllocateInfo ds_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .descriptorSetCount = 1, - .pSetLayouts = &renderer->ds_layout, + .pSetLayouts = &ds_layout, .descriptorPool = pool->pool, }; res = vkAllocateDescriptorSets(renderer->dev->dev, &ds_info, ds); @@ -168,6 +169,7 @@ static void destroy_render_format_setup(struct wlr_vk_renderer *renderer, vkDestroyRenderPass(dev, setup->render_pass, NULL); vkDestroyPipeline(dev, setup->tex_identity_pipe, NULL); vkDestroyPipeline(dev, setup->tex_srgb_pipe, NULL); + vkDestroyPipeline(dev, setup->tex_nv12_pipe, NULL); vkDestroyPipeline(dev, setup->quad_pipe, NULL); } @@ -1182,11 +1184,14 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render VkPipeline pipe; // SRGB formats already have the transfer function applied - if (texture->format->is_srgb) { + if (texture->format->drm == DRM_FORMAT_NV12) { + pipe = renderer->current_render_buffer->render_setup->tex_nv12_pipe; + } else if (texture->format->is_srgb) { pipe = renderer->current_render_buffer->render_setup->tex_identity_pipe; } else { pipe = renderer->current_render_buffer->render_setup->tex_srgb_pipe; } + assert(pipe != VK_NULL_HANDLE); if (pipe != renderer->bound_pipe) { vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); renderer->bound_pipe = pipe; @@ -1403,6 +1408,7 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) { vkDestroyPipelineLayout(dev->dev, renderer->pipe_layout, NULL); vkDestroyDescriptorSetLayout(dev->dev, renderer->ds_layout, NULL); vkDestroySampler(dev->dev, renderer->sampler, NULL); + vkDestroySamplerYcbcrConversion(dev->dev, renderer->nv12_conversion, NULL); vkDestroyCommandPool(dev->dev, renderer->command_pool, NULL); if (renderer->read_pixels_cache.initialized) { @@ -1671,6 +1677,47 @@ static const struct wlr_renderer_impl renderer_impl = { .texture_from_buffer = vulkan_texture_from_buffer, }; +static bool init_nv12_sampler(struct wlr_vk_renderer *renderer, VkSampler *sampler) { + VkResult res; + + VkSamplerYcbcrConversionCreateInfo conversion_create_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, + .format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + .ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601, + .ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, + .xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT, + .yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT, + .chromaFilter = VK_FILTER_LINEAR, + }; + res = vkCreateSamplerYcbcrConversion(renderer->dev->dev, &conversion_create_info, NULL, &renderer->nv12_conversion); + if (res != VK_SUCCESS) { + wlr_vk_error("vkCreateSamplerYcbcrConversion", res); + return false; + } + + VkSamplerYcbcrConversionInfo conversion_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, + .conversion = renderer->nv12_conversion, + }; + VkSamplerCreateInfo sampler_create_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .pNext = &conversion_info, + .magFilter = VK_FILTER_LINEAR, + .minFilter = VK_FILTER_LINEAR, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, + }; + res = vkCreateSampler(renderer->dev->dev, &sampler_create_info, NULL, sampler); + if (res != VK_SUCCESS) { + wlr_vk_error("vkCreateSampler", res); + return false; + } + + return true; +} + // Initializes the VkDescriptorSetLayout and VkPipelineLayout needed // for the texture rendering pipeline using the given VkSampler. static bool init_tex_layouts(struct wlr_vk_renderer *renderer, @@ -1889,10 +1936,18 @@ static bool init_static_render_data(struct wlr_vk_renderer *renderer) { return false; } + if (renderer->dev->sampler_ycbcr_conversion && !init_nv12_sampler(renderer, &renderer->nv12_sampler)) { + return false; + } + if (!init_tex_layouts(renderer, renderer->sampler, &renderer->ds_layout, &renderer->pipe_layout)) { return false; } + if (renderer->dev->sampler_ycbcr_conversion && !init_tex_layouts(renderer, renderer->nv12_sampler, + &renderer->nv12_ds_layout, &renderer->nv12_pipe_layout)) { + return false; + } // load vert module and tex frag module since they are needed to // initialize the tex pipeline @@ -2033,6 +2088,12 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup( goto error; } + if (renderer->dev->sampler_ycbcr_conversion && !init_tex_pipeline(renderer, + setup->render_pass, renderer->nv12_pipe_layout, + WLR_VK_TEXTURE_TRANSFORM_SRGB, &setup->tex_nv12_pipe)) { + goto error; + } + VkPipelineShaderStageCreateInfo quad_stages[2] = { { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |