Vulkan: HDR support for Wayland
This change enables HDR support for wayland as an experimental feature. It supports both non-linear extended sRGB and un-clamped sRGB. Windows isn't supported as the HDR settings are not accessible via an API and would require similar settings that games use to configure the monitor. Adding those sliders isn't what we would like to add. Vulkan (working group) is working on new extensions that might change the shortcomings. It isn't clear yet what the extension will do and what the impact is for applications that want to use it. When the extension is out we should review at the situation again. Pull Request: https://projects.blender.org/blender/blender/pulls/133159
This commit is contained in:
@@ -25,8 +25,7 @@
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -34,6 +33,7 @@
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -852,21 +852,19 @@ static bool selectSurfaceFormat(const VkPhysicalDevice physical_device,
|
||||
vector<VkSurfaceFormatKHR> formats(format_count);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, formats.data());
|
||||
|
||||
for (const VkSurfaceFormatKHR &format : formats) {
|
||||
if (format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR &&
|
||||
format.format == VK_FORMAT_R8G8B8A8_UNORM)
|
||||
{
|
||||
r_surfaceFormat = format;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
array<pair<VkColorSpaceKHR, VkFormat>, 4> selection_order = {
|
||||
make_pair(VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT, VK_FORMAT_R16G16B16A16_SFLOAT),
|
||||
make_pair(VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, VK_FORMAT_R16G16B16A16_SFLOAT),
|
||||
make_pair(VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, VK_FORMAT_R8G8B8A8_UNORM),
|
||||
make_pair(VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, VK_FORMAT_B8G8R8A8_UNORM),
|
||||
};
|
||||
|
||||
for (const VkSurfaceFormatKHR &format : formats) {
|
||||
if (format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR &&
|
||||
format.format == VK_FORMAT_B8G8R8A8_UNORM)
|
||||
{
|
||||
r_surfaceFormat = format;
|
||||
return true;
|
||||
for (pair<VkColorSpaceKHR, VkFormat> &pair : selection_order) {
|
||||
for (const VkSurfaceFormatKHR &format : formats) {
|
||||
if (format.colorSpace == pair.first && format.format == pair.second) {
|
||||
r_surfaceFormat = format;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1053,7 +1051,7 @@ GHOST_TSuccess GHOST_ContextVK::recreateSwapchain()
|
||||
create_info.imageExtent = m_render_extent;
|
||||
create_info.imageArrayLayers = 1;
|
||||
create_info.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
create_info.preTransform = capabilities.currentTransform;
|
||||
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
create_info.presentMode = present_mode;
|
||||
create_info.clipped = VK_TRUE;
|
||||
@@ -1207,6 +1205,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
|
||||
requireExtension(extensions_available, extensions_enabled, VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
requireExtension(extensions_available, extensions_enabled, native_surface_extension_name);
|
||||
required_device_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
optional_device_extensions.push_back(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
|
||||
|
||||
/* X11 doesn't use the correct swapchain offset, flipping can squash the first frames. */
|
||||
const bool use_swapchain_maintenance1 =
|
||||
|
||||
@@ -2878,6 +2878,13 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
|
||||
({"property": "write_legacy_blend_file_format"}, ("/blender/blender/issues/129309", "#129309")),
|
||||
),
|
||||
)
|
||||
import sys
|
||||
if sys.platform == "linux":
|
||||
self._draw_items(
|
||||
context, (
|
||||
({"property": "use_vulkan_hdr"}, ("/blender/blender/issues/140277", "#140277")),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# Keep this as tweaks can be useful to restore.
|
||||
|
||||
@@ -120,6 +120,9 @@ eGPUTextureFormat to_gpu_format(const VkFormat format)
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
return GPU_RGBA8;
|
||||
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
return GPU_RGBA16F;
|
||||
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
@@ -6,8 +6,12 @@
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "GPU_debug.hh"
|
||||
|
||||
#include "gpu_capabilities_private.hh"
|
||||
|
||||
#include "vk_backend.hh"
|
||||
#include "vk_context.hh"
|
||||
#include "vk_debug.hh"
|
||||
@@ -94,6 +98,11 @@ void VKContext::sync_backbuffer(bool cycle_resource_pool)
|
||||
|
||||
swap_chain_format_ = swap_chain_data.surface_format;
|
||||
vk_extent_ = swap_chain_data.extent;
|
||||
GCaps.hdr_viewport_support = U.experimental.use_vulkan_hdr &&
|
||||
(swap_chain_format_.format == VK_FORMAT_R16G16B16A16_SFLOAT) &&
|
||||
ELEM(swap_chain_format_.colorSpace,
|
||||
VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT,
|
||||
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,11 +375,17 @@ void VKContext::swap_buffers_post_callback()
|
||||
|
||||
void VKContext::swap_buffers_pre_handler(const GHOST_VulkanSwapChainData &swap_chain_data)
|
||||
{
|
||||
GPU_debug_group_begin("BackBuffer.Blit");
|
||||
|
||||
VKFrameBuffer &framebuffer = *unwrap(active_fb);
|
||||
VKTexture *color_attachment = unwrap(unwrap(framebuffer.color_tex(0)));
|
||||
|
||||
VKDevice &device = VKBackend::get().device;
|
||||
device.resources.add_image(swap_chain_data.image, 1, "SwapchainImage");
|
||||
|
||||
render_graph::VKRenderGraph &render_graph = this->render_graph();
|
||||
framebuffer.rendering_end(*this);
|
||||
GPU_debug_group_begin("BackBuffer.Blit");
|
||||
|
||||
render_graph::VKBlitImageNode::CreateInfo blit_image = {};
|
||||
blit_image.src_image = color_attachment->vk_image_handle();
|
||||
blit_image.dst_image = swap_chain_data.image;
|
||||
@@ -391,25 +406,17 @@ void VKContext::swap_buffers_pre_handler(const GHOST_VulkanSwapChainData &swap_c
|
||||
region.dstSubresource.baseArrayLayer = 0;
|
||||
region.dstSubresource.layerCount = 1;
|
||||
|
||||
/* Swap chain commands are CPU synchronized at this moment, allowing to temporary add the swap
|
||||
* chain image as device resources. When we move towards GPU swap chain synchronization we need
|
||||
* to keep track of the swap chain image between frames. */
|
||||
VKDevice &device = VKBackend::get().device;
|
||||
device.resources.add_image(swap_chain_data.image, 1, "SwapchainImage");
|
||||
|
||||
framebuffer.rendering_end(*this);
|
||||
flush_render_graph(RenderGraphFlushFlags::RENEW_RENDER_GRAPH);
|
||||
|
||||
render_graph::VKRenderGraph &render_graph = this->render_graph();
|
||||
render_graph.add_node(blit_image);
|
||||
GPU_debug_group_end();
|
||||
|
||||
render_graph::VKSynchronizationNode::CreateInfo synchronization = {};
|
||||
synchronization.vk_image = swap_chain_data.image;
|
||||
synchronization.vk_image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
synchronization.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
render_graph.add_node(synchronization);
|
||||
GPU_debug_group_end();
|
||||
|
||||
flush_render_graph(RenderGraphFlushFlags::SUBMIT | RenderGraphFlushFlags::RENEW_RENDER_GRAPH,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
swap_chain_data.acquire_semaphore,
|
||||
swap_chain_data.present_semaphore,
|
||||
swap_chain_data.submission_fence);
|
||||
|
||||
@@ -227,7 +227,8 @@ typedef struct UserDef_Experimental {
|
||||
char use_shader_node_previews;
|
||||
char use_bundle_and_closure_nodes;
|
||||
char use_socket_structure_type;
|
||||
char _pad[5];
|
||||
char use_vulkan_hdr;
|
||||
char _pad[4];
|
||||
} UserDef_Experimental;
|
||||
|
||||
#define USER_EXPERIMENTAL_TEST(userdef, member) \
|
||||
|
||||
@@ -7610,6 +7610,12 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
|
||||
"Recompute all ID usercounts before saving to a blendfile. Allows to "
|
||||
"work around invalid usercount handling in code that may lead to loss "
|
||||
"of data due to wrongly detected unused data-blocks");
|
||||
|
||||
prop = RNA_def_property(srna, "use_vulkan_hdr", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Vulkan HDR support Linux/Wayland",
|
||||
"Enables HDR on Linux/Wayland on HDR capable setups. Requires a restart");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
|
||||
Reference in New Issue
Block a user