From 2e8755b2611b922c3aace9f79105f19de4ae8fed Mon Sep 17 00:00:00 2001 From: Jason Fielder Date: Fri, 10 Mar 2023 11:27:32 +0000 Subject: [PATCH 01/16] WIP: Enable support for EDR on Mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Basic enablement of EDR support for EDR capable displays on Mac. Added a new, “Extended sRGB” display option which enables the additional color/intensity range for viewport and Cycles renders. --- intern/ghost/intern/GHOST_ContextCGL.mm | 14 +++++++++++++- intern/ghost/intern/GHOST_WindowCocoa.mm | 11 +++++++++++ .../gpu_shader_display_transform_frag.glsl | 5 ++++- intern/opencolorio/ocio_capi.cc | 6 ++++-- intern/opencolorio/ocio_capi.h | 3 ++- intern/opencolorio/ocio_impl.h | 6 ++++-- intern/opencolorio/ocio_impl_glsl.cc | 12 +++++++++--- intern/opencolorio/ocio_shader_shared.hh | 2 +- release/datafiles/colormanagement/config.ocio | 4 +++- source/blender/editors/screen/screen_draw.c | 2 +- source/blender/editors/space_view3d/view3d_draw.cc | 2 +- source/blender/imbuf/intern/colormanagement.c | 4 +++- source/blender/windowmanager/intern/wm_draw.c | 6 +++--- 13 files changed, 59 insertions(+), 18 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 4defd68b90f..8ed04320e78 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -88,6 +88,18 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual, [m_metalLayer removeAllAnimations]; [m_metalLayer setDevice:metalDevice]; m_metalLayer.allowsNextDrawableTimeout = NO; + + // Enable EDR support. This is done by: + // 1. Using a floating point render target, so that values ouside 0..1 can be used + // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 + // 3. Setting the extended sRGB color space so tha the OS knows how to interpret the values + m_metalLayer.wantsExtendedDynamicRangeContent = YES; + m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; + const CFStringRef name = kCGColorSpaceExtendedSRGB; + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name); + m_metalLayer.colorspace = colorspace; + CGColorSpaceRelease(colorspace); + metalInit(); } else { @@ -518,7 +530,7 @@ GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles() * * Use Metal layer to avoid Viewport lagging on macOS, see #60043. */ -static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatBGRA8Unorm; +static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatRGBA16Float; static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT = kCVPixelFormatType_32BGRA; void GHOST_ContextCGL::metalInit() diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index dd25ce56cf8..e693b48ef2b 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -343,6 +343,17 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, [m_metalLayer setPresentsWithTransaction:NO]; [m_metalLayer removeAllAnimations]; [m_metalLayer setDevice:metalDevice]; + + // Enable EDR support. This is done by: + // 1. Using a floating point render target, so that values ouside 0..1 can be used + // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 + // 3. Setting the extended sRGB color space so tha the OS knows how to interpret the values + m_metalLayer.wantsExtendedDynamicRangeContent = YES; + m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; + const CFStringRef name = kCGColorSpaceExtendedSRGB; + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name); + m_metalLayer.colorspace = colorspace; + CGColorSpaceRelease(colorspace); m_metalView = [[CocoaMetalView alloc] initWithFrame:rect]; [m_metalView setWantsLayer:YES]; diff --git a/intern/opencolorio/gpu_shader_display_transform_frag.glsl b/intern/opencolorio/gpu_shader_display_transform_frag.glsl index 92cf9b013fd..130a2306b52 100644 --- a/intern/opencolorio/gpu_shader_display_transform_frag.glsl +++ b/intern/opencolorio/gpu_shader_display_transform_frag.glsl @@ -169,7 +169,10 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay) * merge UI using alpha blending in the correct color space. */ if (parameters.use_overlay) { col.rgb = pow(col.rgb, vec3(parameters.exponent * 2.2)); - col = clamp(col, 0.0, 1.0); + if (!parameters.use_extended) { + /* if we're not using an extended colour space, clamp the color 0..1 */ + col = clamp(col, 0.0, 1.0); + } col *= 1.0 - col_overlay.a; col += col_overlay; /* Assumed unassociated alpha. */ col.rgb = pow(col.rgb, vec3(1.0 / 2.2)); diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index b31f3794361..ae8817530cb 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -289,7 +289,8 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, const float exponent, const float dither, const bool use_predivide, - const bool use_overlay) + const bool use_overlay, + const bool use_extended) { return impl->gpuDisplayShaderBind(config, input, @@ -301,7 +302,8 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, exponent, dither, use_predivide, - use_overlay); + use_overlay, + use_extended); } void OCIO_gpuDisplayShaderUnbind() diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 97e6ff02779..4a580af9f94 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -196,7 +196,8 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, const float exponent, const float dither, const bool use_predivide, - const bool use_overlay); + const bool use_overlay, + const bool use_extended); void OCIO_gpuDisplayShaderUnbind(void); void OCIO_gpuCacheFree(void); diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index 2c00eff6d6c..9564ed84057 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -114,7 +114,8 @@ class IOCIOImpl { const float /*exponent*/, const float /*dither*/, const bool /*use_predivide*/, - const bool /*use_overlay*/) + const bool /*use_overlay*/, + const bool /*use_extended*/) { return false; } @@ -317,7 +318,8 @@ class OCIOImpl : public IOCIOImpl { const float exponent, const float dither, const bool use_predivide, - const bool use_overlay); + const bool use_overlay, + const bool use_extended); void gpuDisplayShaderUnbind(void); void gpuCacheFree(void); diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index ad5b1d79835..ccdd12bcead 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -512,7 +512,8 @@ static void updateGPUDisplayParameters(OCIO_GPUShader &shader, float exponent, float dither, bool use_predivide, - bool use_overlay) + bool use_overlay, + bool use_extended) { bool do_update = false; if (shader.parameters_buffer == nullptr) { @@ -540,6 +541,10 @@ static void updateGPUDisplayParameters(OCIO_GPUShader &shader, data.use_overlay = use_overlay; do_update = true; } + if (bool(data.use_extended) != use_extended) { + data.use_extended = use_extended; + do_update = true; + } if (do_update) { GPU_uniformbuf_update(shader.parameters_buffer, &data); } @@ -678,7 +683,8 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, const float exponent, const float dither, const bool use_predivide, - const bool use_overlay) + const bool use_overlay, + const bool use_extended) { /* Get GPU shader from cache or create new one. */ OCIO_GPUDisplayShader &display_shader = getGPUDisplayShader( @@ -713,7 +719,7 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, GPU_uniformbuf_bind(textures.uniforms_buffer, UNIFORMBUF_SLOT_LUTS); } - updateGPUDisplayParameters(shader, scale, exponent, dither, use_predivide, use_overlay); + updateGPUDisplayParameters(shader, scale, exponent, dither, use_predivide, use_overlay, use_extended); GPU_uniformbuf_bind(shader.parameters_buffer, UNIFORMBUF_SLOT_DISPLAY); /* TODO(fclem): remove remains of IMM. */ diff --git a/intern/opencolorio/ocio_shader_shared.hh b/intern/opencolorio/ocio_shader_shared.hh index c7045217196..91b85da0fab 100644 --- a/intern/opencolorio/ocio_shader_shared.hh +++ b/intern/opencolorio/ocio_shader_shared.hh @@ -35,7 +35,7 @@ struct OCIO_GPUParameters { float exponent; bool1 use_predivide; bool1 use_overlay; + bool1 use_extended; int _pad0; int _pad1; - int _pad2; }; diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 91d722a311f..d525ec92c00 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -56,6 +56,8 @@ displays: - ! {name: Filmic Log, colorspace: Filmic Log} - ! {name: Raw, colorspace: Raw} - ! {name: False Color, colorspace: False Color} + Extended sRGB: + - ! {name: Standard, colorspace: sRGB} XYZ: - ! {name: Standard, colorspace: XYZ} - ! {name: DCI, colorspace: dci_xyz} @@ -63,7 +65,7 @@ displays: None: - ! {name: Standard, colorspace: Raw} -active_displays: [sRGB, XYZ, None] +active_displays: [sRGB, Extended sRGB, XYZ, None] active_views: [Standard, Filmic, Filmic Log, Raw, False Color] colorspaces: diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 384aeccfc4c..fc047d9780e 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -425,7 +425,7 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y) void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uint *r_rect) { char err_out[256] = "unknown"; - GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, true, GPU_RGBA8, err_out); + GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, true, GPU_RGBA16F, err_out); GPU_offscreen_bind(offscreen, true); GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index 665e1a35f5a..185c5e54586 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -1887,7 +1887,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, if (own_ofs) { /* bind */ - ofs = GPU_offscreen_create(sizex, sizey, true, GPU_RGBA8, err_out); + ofs = GPU_offscreen_create(sizex, sizey, true, GPU_RGBA16F, err_out); if (ofs == nullptr) { DRW_opengl_context_disable(); return nullptr; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 344dccfe919..9906c029b54 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -4097,6 +4097,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( const float gamma = applied_view_settings->gamma; const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure); const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma); + const bool use_extended = STRPREFIX(display_settings->display_device, "Extended"); OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); @@ -4111,7 +4112,8 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( exponent, dither, predivide, - do_overlay_merge); + do_overlay_merge, + use_extended); OCIO_configRelease(config); diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 15707553e9d..656b4aefcea 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -685,7 +685,7 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_ * depth or multisample buffers. 3D view creates own buffers with * the data it needs. */ GPUOffScreen *offscreen = GPU_offscreen_create( - region->winx, region->winy, false, GPU_RGBA8, NULL); + region->winx, region->winy, false, GPU_RGBA16F, NULL); if (!offscreen) { WM_report(RPT_ERROR, "Region could not be drawn!"); return; @@ -1148,7 +1148,7 @@ static void wm_draw_window(bContext *C, wmWindow *win) * stereo methods, but it's less efficient than drawing directly. */ const int width = WM_window_pixels_x(win); const int height = WM_window_pixels_y(win); - GPUOffScreen *offscreen = GPU_offscreen_create(width, height, false, GPU_RGBA8, NULL); + GPUOffScreen *offscreen = GPU_offscreen_create(width, height, false, GPU_RGBA16F, NULL); if (offscreen) { GPUTexture *texture = GPU_offscreen_color_texture(offscreen); @@ -1223,7 +1223,7 @@ uint *WM_window_pixels_read_offscreen(bContext *C, wmWindow *win, int r_size[2]) r_size[0] = WM_window_pixels_x(win); r_size[1] = WM_window_pixels_y(win); - GPUOffScreen *offscreen = GPU_offscreen_create(r_size[0], r_size[1], false, GPU_RGBA8, NULL); + GPUOffScreen *offscreen = GPU_offscreen_create(r_size[0], r_size[1], false, GPU_RGBA16F, NULL); if (UNLIKELY(!offscreen)) { return NULL; } -- 2.30.2 From c0e6309ddd044a8a96d34845e2c3696817b3b5fa Mon Sep 17 00:00:00 2001 From: Jason Fielder Date: Sat, 11 Mar 2023 14:15:49 +0000 Subject: [PATCH 02/16] ensure compatibility with OpenGL --- intern/ghost/intern/GHOST_ContextCGL.mm | 35 ++++++++++++++---------- intern/ghost/intern/GHOST_WindowCocoa.mm | 22 ++++++++------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 8ed04320e78..64787c45197 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -89,16 +89,18 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual, [m_metalLayer setDevice:metalDevice]; m_metalLayer.allowsNextDrawableTimeout = NO; - // Enable EDR support. This is done by: - // 1. Using a floating point render target, so that values ouside 0..1 can be used - // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 - // 3. Setting the extended sRGB color space so tha the OS knows how to interpret the values - m_metalLayer.wantsExtendedDynamicRangeContent = YES; - m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; - const CFStringRef name = kCGColorSpaceExtendedSRGB; - CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name); - m_metalLayer.colorspace = colorspace; - CGColorSpaceRelease(colorspace); + if (m_useMetalForRendering) { + // Enable EDR support. This is done by: + // 1. Using a floating point render target, so that values ouside 0..1 can be used + // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 + // 3. Setting the extended sRGB color space so that the OS knows how to interpret the values + m_metalLayer.wantsExtendedDynamicRangeContent = YES; + m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; + const CFStringRef name = kCGColorSpaceExtendedSRGB; + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name); + m_metalLayer.colorspace = colorspace; + CGColorSpaceRelease(colorspace); + } metalInit(); } @@ -530,8 +532,9 @@ GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles() * * Use Metal layer to avoid Viewport lagging on macOS, see #60043. */ -static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatRGBA16Float; -static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT = kCVPixelFormatType_32BGRA; +static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT_EDR = MTLPixelFormatRGBA16Float; +static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT_SDR = MTLPixelFormatBGRA8Unorm; +static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT_SDR = kCVPixelFormatType_32BGRA; void GHOST_ContextCGL::metalInit() { @@ -598,7 +601,9 @@ void GHOST_ContextCGL::metalInit() /* Ensure library is released. */ [library autorelease]; - [desc.colorAttachments objectAtIndexedSubscript:0].pixelFormat = METAL_FRAMEBUFFERPIXEL_FORMAT; + MTLPixelFormat attachmentFormat = m_useMetalForRendering ? + METAL_FRAMEBUFFERPIXEL_FORMAT_EDR : METAL_FRAMEBUFFERPIXEL_FORMAT_SDR; + [desc.colorAttachments objectAtIndexedSubscript:0].pixelFormat = attachmentFormat; m_metalRenderPipeline = (MTLRenderPipelineState *)[device newRenderPipelineStateWithDescriptor:desc @@ -698,7 +703,7 @@ void GHOST_ContextCGL::metalUpdateFramebuffer() CVReturn cvret = CVPixelBufferCreate(kCFAllocatorDefault, width, height, - METAL_CORE_VIDEO_PIXEL_FORMAT, + METAL_CORE_VIDEO_PIXEL_FORMAT_SDR, (__bridge CFDictionaryRef)cvPixelBufferProps, &cvPixelBuffer); if (cvret != kCVReturnSuccess) { @@ -740,7 +745,7 @@ void GHOST_ContextCGL::metalUpdateFramebuffer() cvMetalTexCache, cvPixelBuffer, nil, - METAL_FRAMEBUFFERPIXEL_FORMAT, + METAL_FRAMEBUFFERPIXEL_FORMAT_SDR, width, height, 0, diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index e693b48ef2b..499e5a026a0 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -344,16 +344,18 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, [m_metalLayer removeAllAnimations]; [m_metalLayer setDevice:metalDevice]; - // Enable EDR support. This is done by: - // 1. Using a floating point render target, so that values ouside 0..1 can be used - // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 - // 3. Setting the extended sRGB color space so tha the OS knows how to interpret the values - m_metalLayer.wantsExtendedDynamicRangeContent = YES; - m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; - const CFStringRef name = kCGColorSpaceExtendedSRGB; - CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name); - m_metalLayer.colorspace = colorspace; - CGColorSpaceRelease(colorspace); + if (type == GHOST_kDrawingContextTypeMetal) { + // Enable EDR support. This is done by: + // 1. Using a floating point render target, so that values ouside 0..1 can be used + // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 + // 3. Setting the extended sRGB color space so that the OS knows how to interpret the values + m_metalLayer.wantsExtendedDynamicRangeContent = YES; + m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; + const CFStringRef name = kCGColorSpaceExtendedSRGB; + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name); + m_metalLayer.colorspace = colorspace; + CGColorSpaceRelease(colorspace); + } m_metalView = [[CocoaMetalView alloc] initWithFrame:rect]; [m_metalView setWantsLayer:YES]; -- 2.30.2 From 9cfe3fd876b885551f165e813ed4fa7c9e7dc95f Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Fri, 9 Jun 2023 18:27:28 +0100 Subject: [PATCH 03/16] Cleanup comments. --- intern/ghost/intern/GHOST_ContextCGL.mm | 13 +++++++------ intern/ghost/intern/GHOST_WindowCocoa.mm | 11 ++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 6424b23971a..f89c2691fee 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -92,10 +92,11 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual, m_metalLayer.allowsNextDrawableTimeout = NO; if (m_useMetalForRendering) { - // Enable EDR support. This is done by: - // 1. Using a floating point render target, so that values ouside 0..1 can be used - // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 - // 3. Setting the extended sRGB color space so that the OS knows how to interpret the values + /* Enable EDR support. This is done by: + * 1. Using a floating point render target, so that values ouside 0..1 can be used + * 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 + * 3. Setting the extended sRGB color space so that the OS knows how to interpret the + * values. */ m_metalLayer.wantsExtendedDynamicRangeContent = YES; m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; const CFStringRef name = kCGColorSpaceExtendedSRGB; @@ -607,8 +608,8 @@ void GHOST_ContextCGL::metalInit() /* Ensure library is released. */ [library autorelease]; - MTLPixelFormat attachmentFormat = m_useMetalForRendering ? - METAL_FRAMEBUFFERPIXEL_FORMAT_EDR : METAL_FRAMEBUFFERPIXEL_FORMAT_SDR; + MTLPixelFormat attachmentFormat = m_useMetalForRendering ? METAL_FRAMEBUFFERPIXEL_FORMAT_EDR : + METAL_FRAMEBUFFERPIXEL_FORMAT_SDR; [desc.colorAttachments objectAtIndexedSubscript:0].pixelFormat = attachmentFormat; m_metalRenderPipeline = (MTLRenderPipelineState *)[device diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 669d53fc234..664e601fc2f 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -343,12 +343,13 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, [m_metalLayer setPresentsWithTransaction:NO]; [m_metalLayer removeAllAnimations]; [m_metalLayer setDevice:metalDevice]; - + if (type == GHOST_kDrawingContextTypeMetal) { - // Enable EDR support. This is done by: - // 1. Using a floating point render target, so that values ouside 0..1 can be used - // 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 - // 3. Setting the extended sRGB color space so that the OS knows how to interpret the values + /* Enable EDR support. This is done by: + * 1. Using a floating point render target, so that values ouside 0..1 can be used + * 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1 + * 3. Setting the extended sRGB color space so that the OS knows how to interpret the + * values. */ m_metalLayer.wantsExtendedDynamicRangeContent = YES; m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float; const CFStringRef name = kCGColorSpaceExtendedSRGB; -- 2.30.2 From 823d88a55d391e5c95816f23e1b394da6551bff0 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Fri, 9 Jun 2023 18:30:13 +0100 Subject: [PATCH 04/16] Change HDR/EDR option to be exposed via user preferences, rather than colour space selection. --- intern/opencolorio/ocio_impl_glsl.cc | 3 ++- release/datafiles/colormanagement/config.ocio | 4 +--- scripts/startup/bl_ui/space_userpref.py | 3 +++ source/blender/imbuf/intern/colormanagement.cc | 3 ++- source/blender/makesdna/DNA_userdef_types.h | 1 + source/blender/makesrna/intern/rna_userdef.c | 8 ++++++++ 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index ee5bdae2b01..5190a2cbeae 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -723,7 +723,8 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, GPU_uniformbuf_bind(textures.uniforms_buffer, UNIFORMBUF_SLOT_LUTS); } - updateGPUDisplayParameters(shader, scale, exponent, dither, use_predivide, use_overlay, use_extended); + updateGPUDisplayParameters( + shader, scale, exponent, dither, use_predivide, use_overlay, use_extended); GPU_uniformbuf_bind(shader.parameters_buffer, UNIFORMBUF_SLOT_DISPLAY); /* TODO(fclem): remove remains of IMM. */ diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index d525ec92c00..91d722a311f 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -56,8 +56,6 @@ displays: - ! {name: Filmic Log, colorspace: Filmic Log} - ! {name: Raw, colorspace: Raw} - ! {name: False Color, colorspace: False Color} - Extended sRGB: - - ! {name: Standard, colorspace: sRGB} XYZ: - ! {name: Standard, colorspace: XYZ} - ! {name: DCI, colorspace: dci_xyz} @@ -65,7 +63,7 @@ displays: None: - ! {name: Standard, colorspace: Raw} -active_displays: [sRGB, Extended sRGB, XYZ, None] +active_displays: [sRGB, XYZ, None] active_views: [Standard, Filmic, Filmic Log, Raw, False Color] colorspaces: diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index 00e82f83685..f8d985f7aeb 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -759,6 +759,9 @@ class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel): col.prop(system, "use_overlay_smooth_wire", text="Overlay") col.prop(system, "use_edit_mode_smooth_wire", text="Edit Mode") + col = layout.column(heading="Viewport Colorspace") + col.prop(system, "use_hdr", text="High Dynamic Range") + class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel): bl_label = "Textures" diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index 04237bbf08e..8350118f24e 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -4050,7 +4050,8 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( const float gamma = applied_view_settings->gamma; const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure); const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma); - const bool use_extended = STRPREFIX(display_settings->display_device, "Extended"); + const bool use_extended = U.gpu_flag & USER_GPU_FLAG_HDR_ENABLED; + ; OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 68b88e2a47e..c1e3cf3c375 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -1182,6 +1182,7 @@ typedef enum eUserpref_GPU_Flag { USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE = (1 << 1), USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE = (1 << 2), USER_GPU_FLAG_SUBDIVISION_EVALUATION = (1 << 3), + USER_GPU_FLAG_HDR_ENABLED = (1 << 4) } eUserpref_GPU_Flag; /** #UserDef.tablet_api */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index ea0e960b047..c800d29a208 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5676,6 +5676,14 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "use_hdr", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "gpu_flag", USER_GPU_FLAG_HDR_ENABLED); + RNA_def_property_ui_text(prop, + "Viewport High Dynamic Range", + "Enable high dynamic range with extended colorspace in viewport, " + "uncapping display brightness for rendered content."); + RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); + prop = RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "light_param", ""); RNA_def_property_struct_type(prop, "UserSolidLight"); -- 2.30.2 From 214c20dce0b477ab4017d35024d5f46e2649af21 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Fri, 9 Jun 2023 18:40:50 +0100 Subject: [PATCH 05/16] Remove range clamping form fallback display shader and modify calculation for better functionality with transparent overlays. --- .../gpu_shader_display_transform_frag.glsl | 9 ++++++++- source/blender/gpu/intern/gpu_viewport.c | 2 ++ .../shaders/gpu_shader_image_overlays_merge_frag.glsl | 11 ++++++++++- .../infos/gpu_shader_2D_image_overlays_merge_info.hh | 1 + 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/intern/opencolorio/gpu_shader_display_transform_frag.glsl b/intern/opencolorio/gpu_shader_display_transform_frag.glsl index 130a2306b52..a85fc41ef10 100644 --- a/intern/opencolorio/gpu_shader_display_transform_frag.glsl +++ b/intern/opencolorio/gpu_shader_display_transform_frag.glsl @@ -169,9 +169,16 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay) * merge UI using alpha blending in the correct color space. */ if (parameters.use_overlay) { col.rgb = pow(col.rgb, vec3(parameters.exponent * 2.2)); + vec4 clamped_col = clamp(col, 0.0, 1.0); + if (!parameters.use_extended) { /* if we're not using an extended colour space, clamp the color 0..1 */ - col = clamp(col, 0.0, 1.0); + col = clamped_col; + } + else { + /* When using extended colorspace, interpolate towards clamped color to improve display of + * alpha-blended overlays. */ + col = mix(col, clamped_col, col_overlay.a); } col *= 1.0 - col_overlay.a; col += col_overlay; /* Assumed unassociated alpha. */ diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 4cbe3850448..ffddd36c442 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -451,9 +451,11 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, GPU_batch_program_set_imm_shader(batch); } else { + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); GPU_batch_uniform_1i(batch, "overlay", do_overlay_merge); GPU_batch_uniform_1i(batch, "display_transform", display_colorspace); + GPU_batch_uniform_1i(batch, "use_extended", U.gpu_flag & USER_GPU_FLAG_HDR_ENABLED); } GPU_texture_bind(color, 0); diff --git a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl index d77f073b7de..75f600ba648 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -36,7 +36,16 @@ void main() vec4 overlay_col = texture(overlays_texture, texCoord_interp.xy); if (overlay) { - fragColor = clamp(fragColor, 0.0, 1.0); + vec4 clamped_col = clamp(fragColor, 0.0, 1.0); + if (!use_extended) { + /* Only clamp color if we are not using an extended display colorspace. */ + fragColor = clamped_col; + } + else { + /* When using extended colorspace, interpolate towards clamped color to avoid over-brightened + * overlays. */ + fragColor = mix(fragColor, clamped_col, overlay_col.a); + } fragColor *= 1.0 - overlay_col.a; fragColor += overlay_col; } diff --git a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh index ea32d9d5f5d..0452c053d81 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh @@ -17,6 +17,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_2D_image_overlays_merge) .push_constant(Type::MAT4, "ModelViewProjectionMatrix") .push_constant(Type::BOOL, "display_transform") .push_constant(Type::BOOL, "overlay") + .push_constant(Type::BOOL, "use_extended") /* Sampler slots should match OCIO's. */ .sampler(0, ImageType::FLOAT_2D, "image_texture") .sampler(1, ImageType::FLOAT_2D, "overlays_texture") -- 2.30.2 From 5e33e15eac373025d6d220f9795f44b0512342b3 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 12 Jun 2023 10:51:29 +0100 Subject: [PATCH 06/16] EDR support for material previews --- .../blender/editors/render/render_preview.cc | 66 +++++++++++++------ source/blender/imbuf/IMB_colormanagement.h | 9 +++ .../blender/imbuf/intern/colormanagement.cc | 25 +++++++ source/blender/render/RE_pipeline.h | 4 ++ source/blender/render/intern/pipeline.cc | 11 ++++ source/blender/render/intern/render_result.cc | 26 ++++++++ source/blender/render/intern/render_result.h | 8 +++ 7 files changed, 130 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 33ddad9e857..2fb385b93bb 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -675,28 +675,56 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty); if (rres.rectx && rres.recty) { - uchar *rect_byte = static_cast( - MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect")); - float fx = rect->xmin + offx; - float fy = rect->ymin; - /* material preview only needs monoscopy (view 0) */ - RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0); + /* High dynamic range preview. */ + if (U.gpu_flag & USER_GPU_FLAG_HDR_ENABLED) { + float *rect_float = static_cast(MEM_mallocN( + rres.rectx * rres.recty * sizeof(float) * 4, "ed_preview_draw_rect_float")); + float fx = rect->xmin + offx; + float fy = rect->ymin; - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); - immDrawPixelsTexTiled(&state, - fx, - fy, - rres.rectx, - rres.recty, - GPU_RGBA8, - false, - rect_byte, - 1.0f, - 1.0f, - nullptr); + /* material preview only needs monoscopy (view 0) */ + RE_AcquiredResultGetFloat(re, &rres, rect_float, 0); - MEM_freeN(rect_byte); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); + immDrawPixelsTexTiled(&state, + fx, + fy, + rres.rectx, + rres.recty, + GPU_RGBA16F, + false, + rect_float, + 1.0f, + 1.0f, + nullptr); + + MEM_freeN(rect_float); + } + else { + uchar *rect_byte = static_cast( + MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect")); + float fx = rect->xmin + offx; + float fy = rect->ymin; + + /* material preview only needs monoscopy (view 0) */ + RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0); + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); + immDrawPixelsTexTiled(&state, + fx, + fy, + rres.rectx, + rres.recty, + GPU_RGBA8, + false, + rect_byte, + 1.0f, + 1.0f, + nullptr); + + MEM_freeN(rect_byte); + } ok = true; } diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 31dccdc9b72..ebf92d5d9e0 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -297,6 +297,15 @@ void IMB_display_buffer_transform_apply(unsigned char *display_buffer, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, bool predivide); +void IMB_display_buffer_transform_apply_float( + float *float_display_buffer, + float *linear_buffer, + int width, + int height, + int channels, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + bool predivide); void IMB_display_buffer_release(void *cache_handle); diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index 8350118f24e..b22ddbb4129 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -2784,6 +2784,31 @@ void IMB_display_buffer_transform_apply(uchar *display_buffer, MEM_freeN(buffer); } +void IMB_display_buffer_transform_apply_float(float *float_display_buffer, + float *linear_buffer, + int width, + int height, + int channels, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + bool predivide) +{ + float *buffer; + ColormanageProcessor *cm_processor = IMB_colormanagement_display_processor_new(view_settings, + display_settings); + + buffer = static_cast(MEM_mallocN(size_t(channels) * width * height * sizeof(float), + "display transform temp buffer")); + memcpy(buffer, linear_buffer, size_t(channels) * width * height * sizeof(float)); + + IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); + + IMB_colormanagement_processor_free(cm_processor); + + memcpy(float_display_buffer, buffer, size_t(channels) * width * height * sizeof(float)); + MEM_freeN(buffer); +} + void IMB_display_buffer_release(void *cache_handle) { if (cache_handle) { diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h index 81b44d4d856..97791b89378 100644 --- a/source/blender/render/RE_pipeline.h +++ b/source/blender/render/RE_pipeline.h @@ -261,6 +261,10 @@ void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect, int view_id); +void RE_AcquiredResultGetFloat(struct Render *re, + struct RenderResult *result, + float *rect, + const int view_id); void RE_render_result_full_channel_name(char *fullname, const char *layname, diff --git a/source/blender/render/intern/pipeline.cc b/source/blender/render/intern/pipeline.cc index 385bf83a2eb..bd5dfa8644a 100644 --- a/source/blender/render/intern/pipeline.cc +++ b/source/blender/render/intern/pipeline.cc @@ -516,6 +516,17 @@ void RE_AcquiredResultGet32(Render *re, RenderResult *result, uint *rect, const view_id); } +void RE_AcquiredResultGetFloat(Render *re, RenderResult *result, float *rect, const int view_id) +{ + render_result_rect_get_pixels_float(result, + rect, + re->rectx, + re->recty, + &re->scene->view_settings, + &re->scene->display_settings, + view_id); +} + RenderStats *RE_GetStats(Render *re) { return &re->i; diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index 42dfe8a9256..64fafbb7e11 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -1046,6 +1046,32 @@ void render_result_rect_get_pixels(RenderResult *rr, } } +void render_result_rect_get_pixels_float(RenderResult *rr, + float *rect, + int rectx, + int recty, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + const int view_id) +{ + RenderView *rv = RE_RenderViewGetById(rr, view_id); + + if (rv && rv->combined_buffer.data) { + IMB_display_buffer_transform_apply_float(rect, + rv->combined_buffer.data, + rr->rectx, + rr->recty, + 4, + view_settings, + display_settings, + true); + } + else { + /* else fill with black */ + memset(rect, 0, sizeof(int) * rectx * recty); + } +} + /*************************** multiview functions *****************************/ bool RE_HasCombinedLayer(const RenderResult *result) diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h index 8b2af1158cc..9b3ccb55a02 100644 --- a/source/blender/render/intern/render_result.h +++ b/source/blender/render/intern/render_result.h @@ -121,6 +121,14 @@ void render_result_rect_get_pixels(struct RenderResult *rr, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, int view_id); +void render_result_rect_get_pixels_float( + struct RenderResult *rr, + float *rect, + int rectx, + int recty, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + int view_id); /** * Create a new views #ListBase in rr without duplicating the memory pointers. -- 2.30.2 From dbb21dee2fcf5cde353df8d340ea975503a8676c Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 12 Jun 2023 12:12:40 +0100 Subject: [PATCH 07/16] Move HDR setting into scene color management settings --- scripts/startup/bl_ui/properties_render.py | 1 + scripts/startup/bl_ui/space_userpref.py | 3 --- .../editors/interface/interface_templates.cc | 3 +++ .../blender/editors/render/render_preview.cc | 5 +++-- source/blender/gpu/intern/gpu_viewport.c | 3 ++- .../blender/imbuf/intern/colormanagement.cc | 3 +-- source/blender/makesdna/DNA_color_types.h | 1 + source/blender/makesdna/DNA_userdef_types.h | 1 - source/blender/makesrna/intern/rna_color.c | 21 +++++++++++++++++++ source/blender/makesrna/intern/rna_userdef.c | 8 ------- 10 files changed, 32 insertions(+), 17 deletions(-) diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index bf3c322f377..eaa90ea8154 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -75,6 +75,7 @@ class RENDER_PT_color_management(RenderButtonsPanel, Panel): col = flow.column() col.prop(view, "exposure") col.prop(view, "gamma") + col.prop(view, "use_hdr_view") col.separator() diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index f8d985f7aeb..00e82f83685 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -759,9 +759,6 @@ class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel): col.prop(system, "use_overlay_smooth_wire", text="Overlay") col.prop(system, "use_edit_mode_smooth_wire", text="Edit Mode") - col = layout.column(heading="Viewport Colorspace") - col.prop(system, "use_hdr", text="High Dynamic Range") - class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel): bl_label = "Textures" diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index 967b8c85bf1..4089ac9d4d1 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -6680,6 +6680,9 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, uiItemR(col, &view_transform_ptr, "exposure", 0, nullptr, ICON_NONE); uiItemR(col, &view_transform_ptr, "gamma", 0, nullptr, ICON_NONE); + col = uiLayoutColumn(layout, false); + uiItemR(col, &view_transform_ptr, "use_hdr_view", 0, nullptr, ICON_NONE); + col = uiLayoutColumn(layout, false); uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, nullptr, ICON_NONE); if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 2fb385b93bb..7a3e23d48b0 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -676,8 +676,9 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect if (rres.rectx && rres.recty) { - /* High dynamic range preview. */ - if (U.gpu_flag & USER_GPU_FLAG_HDR_ENABLED) { + /*Use floating point texture for material preview if High Dynamic Range enabled. */ + Scene *scene = RE_GetScene(re); + if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { float *rect_float = static_cast(MEM_mallocN( rres.rectx * rres.recty * sizeof(float) * 4, "ed_preview_draw_rect_float")); float fx = rect->xmin + offx; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index ffddd36c442..43d0d131225 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -455,7 +455,8 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); GPU_batch_uniform_1i(batch, "overlay", do_overlay_merge); GPU_batch_uniform_1i(batch, "display_transform", display_colorspace); - GPU_batch_uniform_1i(batch, "use_extended", U.gpu_flag & USER_GPU_FLAG_HDR_ENABLED); + GPU_batch_uniform_1i( + batch, "use_extended", viewport->view_settings.flag & COLORMANAGE_VIEW_USE_HDR); } GPU_texture_bind(color, 0); diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index b22ddbb4129..e313a11084f 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -4075,8 +4075,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( const float gamma = applied_view_settings->gamma; const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure); const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma); - const bool use_extended = U.gpu_flag & USER_GPU_FLAG_HDR_ENABLED; - ; + const bool use_extended = (applied_view_settings->flag & COLORMANAGE_VIEW_USE_HDR) != 0; OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 89ce1d8392c..f05ddf303b6 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -207,6 +207,7 @@ typedef struct ColorManagedColorspaceSettings { /** #ColorManagedViewSettings.flag */ enum { COLORMANAGE_VIEW_USE_CURVES = (1 << 0), + COLORMANAGE_VIEW_USE_HDR = (1 << 1), }; #ifdef __cplusplus diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index c1e3cf3c375..68b88e2a47e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -1182,7 +1182,6 @@ typedef enum eUserpref_GPU_Flag { USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE = (1 << 1), USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE = (1 << 2), USER_GPU_FLAG_SUBDIVISION_EVALUATION = (1 << 3), - USER_GPU_FLAG_HDR_ENABLED = (1 << 4) } eUserpref_GPU_Flag; /** #UserDef.tablet_api */ diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 347d674e26d..29c40a48f02 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -508,6 +508,18 @@ static void rna_ColorManagedViewSettings_look_set(PointerRNA *ptr, int value) } } +static void rna_ColorManagedViewSettings_use_hdr_set(PointerRNA *ptr, bool value) +{ + ColorManagedViewSettings *view_settings = (ColorManagedViewSettings *)ptr->data; + + if (value) { + view_settings->flag |= COLORMANAGE_VIEW_USE_HDR; + } + else { + view_settings->flag &= ~COLORMANAGE_VIEW_USE_HDR; + } +} + static const EnumPropertyItem *rna_ColorManagedViewSettings_look_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -1275,6 +1287,15 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Curves", "Use RGB curved for pre-display transformation"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); + prop = RNA_def_property(srna, "use_hdr_view", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLORMANAGE_VIEW_USE_HDR); + RNA_def_property_boolean_funcs(prop, NULL, "rna_ColorManagedViewSettings_use_hdr_set"); + RNA_def_property_ui_text(prop, + "High Dynamic Range", + "Enable high dynamic range with extended colorspace in viewport, " + "uncapping display brightness for rendered content."); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); + /* ** Color-space ** */ srna = RNA_def_struct(brna, "ColorManagedInputColorspaceSettings", NULL); RNA_def_struct_path_func(srna, "rna_ColorManagedInputColorspaceSettings_path"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index c800d29a208..ea0e960b047 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5676,14 +5676,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop = RNA_def_property(srna, "use_hdr", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "gpu_flag", USER_GPU_FLAG_HDR_ENABLED); - RNA_def_property_ui_text(prop, - "Viewport High Dynamic Range", - "Enable high dynamic range with extended colorspace in viewport, " - "uncapping display brightness for rendered content."); - RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); - prop = RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "light_param", ""); RNA_def_property_struct_type(prop, "UserSolidLight"); -- 2.30.2 From 2a0fea33ad385101c3fd58559bdffcfd09779e34 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 12 Jun 2023 13:45:42 +0100 Subject: [PATCH 08/16] WIP determine HDR availability dynamically and allocate panels depending on format --- .../editors/space_view3d/view3d_draw.cc | 15 ++++- source/blender/gpu/GPU_framebuffer.h | 6 ++ source/blender/gpu/intern/gpu_framebuffer.cc | 5 ++ source/blender/makesrna/intern/rna_color.c | 2 +- source/blender/windowmanager/WM_api.h | 2 +- source/blender/windowmanager/intern/wm_draw.c | 55 +++++++++++++++---- 6 files changed, 69 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index 69bd9491166..59446d7c5c4 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -1887,7 +1887,16 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, bool is_ortho = false; float winmat[4][4]; - if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) { + /* Determine desired offscreen format depending on HDR availability. */ + bool use_hdr = false; + if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { + use_hdr = true; + } + eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + + if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey) || + (GPU_offscreen_format(ofs) != desired_format))) + { /* sizes differ, can't reuse */ ofs = nullptr; } @@ -1906,7 +1915,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, ofs = GPU_offscreen_create(sizex, sizey, true, - GPU_RGBA16F, + desired_format, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ, err_out); if (ofs == nullptr) { @@ -2377,7 +2386,7 @@ void ED_view3d_depth_override(Depsgraph *depsgraph, rv3d->rflag |= RV3D_ZOFFSET_DISABLED; /* Needed in cases the 3D Viewport isn't already setup. */ - WM_draw_region_viewport_ensure(region, SPACE_VIEW3D); + WM_draw_region_viewport_ensure(scene, region, SPACE_VIEW3D); WM_draw_region_viewport_bind(region); GPUViewport *viewport = WM_draw_region_get_viewport(region); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index 42c823144ee..383970333f5 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -653,6 +653,12 @@ int GPU_offscreen_height(const GPUOffScreen *offscreen); */ struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *offscreen); +/** + * Return the color texture of a #GPUOffScreen. Does not give ownership. + * \note only to be used by viewport code! + */ +eGPUTextureFormat GPU_offscreen_format(const GPUOffScreen *offscreen); + /** * Return the internals of a #GPUOffScreen. Does not give ownership. * \note only to be used by viewport code! diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 4d4fa3afa86..c31fdeb8c78 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -785,6 +785,11 @@ GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs) return ofs->color; } +eGPUTextureFormat GPU_offscreen_format(const GPUOffScreen *offscreen) +{ + return GPU_texture_format(offscreen->color); +} + void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs, GPUFrameBuffer **r_fb, GPUTexture **r_color, diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 29c40a48f02..59b98280d66 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -1294,7 +1294,7 @@ static void rna_def_colormanage(BlenderRNA *brna) "High Dynamic Range", "Enable high dynamic range with extended colorspace in viewport, " "uncapping display brightness for rendered content."); - RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); /* ** Color-space ** */ srna = RNA_def_struct(brna, "ColorManagedInputColorspaceSettings", NULL); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index bfd826450c4..1774c3a9b67 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -1686,7 +1686,7 @@ void *WM_draw_cb_activate(struct wmWindow *win, void WM_draw_cb_exit(struct wmWindow *win, void *handle); void WM_redraw_windows(struct bContext *C); -void WM_draw_region_viewport_ensure(struct ARegion *region, short space_type); +void WM_draw_region_viewport_ensure(struct Scene *scene, struct ARegion *region, short space_type); void WM_draw_region_viewport_bind(struct ARegion *region); void WM_draw_region_viewport_unbind(struct ARegion *region); diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 34da22a3744..67d0b66ecb9 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -654,8 +654,19 @@ static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) GPU_texture_mipmap_mode(texture, false, false); } -static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_viewport) +static void wm_draw_region_buffer_create(Scene *scene, + ARegion *region, + bool stereo, + bool use_viewport) { + + /* Determine desired offscreen format. */ + bool use_hdr = false; + if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { + use_hdr = true; + } + eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + if (region->draw_buffer) { if (region->draw_buffer->stereo != stereo) { /* Free draw buffer on stereo changes. */ @@ -665,7 +676,8 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_ /* Free offscreen buffer on size changes. Viewport auto resizes. */ GPUOffScreen *offscreen = region->draw_buffer->offscreen; if (offscreen && (GPU_offscreen_width(offscreen) != region->winx || - GPU_offscreen_height(offscreen) != region->winy)) + GPU_offscreen_height(offscreen) != region->winy || + GPU_offscreen_format(offscreen) != desired_format)) { wm_draw_region_buffer_free(region); } @@ -684,7 +696,7 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_ * depth or multi-sample buffers. 3D view creates own buffers with * the data it needs. */ GPUOffScreen *offscreen = GPU_offscreen_create( - region->winx, region->winy, false, GPU_RGBA16F, GPU_TEXTURE_USAGE_SHADER_READ, NULL); + region->winx, region->winy, false, desired_format, GPU_TEXTURE_USAGE_SHADER_READ, NULL); if (!offscreen) { WM_report(RPT_ERROR, "Region could not be drawn!"); return; @@ -935,7 +947,8 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) GPU_debug_group_begin(use_viewport ? "Viewport" : "ARegion"); if (stereo && wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID)) { - wm_draw_region_buffer_create(region, true, use_viewport); + Scene *scene = WM_window_get_active_scene(win); + wm_draw_region_buffer_create(scene, region, true, use_viewport); for (int view = 0; view < 2; view++) { eStereoViews sview; @@ -958,7 +971,8 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) } else { wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID); - wm_draw_region_buffer_create(region, false, use_viewport); + Scene *scene = WM_window_get_active_scene(win); + wm_draw_region_buffer_create(scene, region, false, use_viewport); wm_draw_region_bind(region, 0); ED_region_do_draw(C, region); wm_draw_region_unbind(region); @@ -991,7 +1005,8 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) region->type->layout(C, region); } - wm_draw_region_buffer_create(region, false, false); + Scene *scene = WM_window_get_active_scene(win); + wm_draw_region_buffer_create(scene, region, false, false); wm_draw_region_bind(region, 0); GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); ED_region_do_draw(C, region); @@ -1146,13 +1161,21 @@ static void wm_draw_window(bContext *C, wmWindow *win) wm_draw_window_onscreen(C, win, -1); } else { + /* Determine desired offscreen format. */ + bool use_hdr = false; + Scene *scene = WM_window_get_active_scene(win); + if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { + use_hdr = true; + } + eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + /* For side-by-side and top-bottom, we need to render each view to an * an off-screen texture and then draw it. This used to happen for all * stereo methods, but it's less efficient than drawing directly. */ const int width = WM_window_pixels_x(win); const int height = WM_window_pixels_y(win); GPUOffScreen *offscreen = GPU_offscreen_create( - width, height, false, GPU_RGBA16F, GPU_TEXTURE_USAGE_SHADER_READ, NULL); + width, height, false, desired_format, GPU_TEXTURE_USAGE_SHADER_READ, NULL); if (offscreen) { GPUTexture *texture = GPU_offscreen_color_texture(offscreen); @@ -1301,8 +1324,16 @@ uint8_t *WM_window_pixels_read_from_offscreen(bContext *C, wmWindow *win, int r_ r_size[0] = WM_window_pixels_x(win); r_size[1] = WM_window_pixels_y(win); + /* Determine desired offscreen format depending on HDR availability. */ + bool use_hdr = false; + Scene *scene = WM_window_get_active_scene(win); + if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { + use_hdr = true; + } + eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + GPUOffScreen *offscreen = GPU_offscreen_create( - r_size[0], r_size[1], false, GPU_RGBA16F, GPU_TEXTURE_USAGE_SHADER_READ, NULL); + r_size[0], r_size[1], false, desired_format, GPU_TEXTURE_USAGE_SHADER_READ, NULL); if (UNLIKELY(!offscreen)) { return NULL; } @@ -1543,7 +1574,9 @@ void wm_draw_region_test(bContext *C, ScrArea *area, ARegion *region) { /* Function for redraw timer benchmark. */ bool use_viewport = WM_region_use_viewport(area, region); - wm_draw_region_buffer_create(region, false, use_viewport); + wmWindow *win = CTX_wm_window(C); + Scene *scene = WM_window_get_active_scene(win); + wm_draw_region_buffer_create(scene, region, false, use_viewport); wm_draw_region_bind(region, 0); ED_region_do_draw(C, region); wm_draw_region_unbind(region); @@ -1575,10 +1608,10 @@ void WM_redraw_windows(bContext *C) * * \{ */ -void WM_draw_region_viewport_ensure(ARegion *region, short space_type) +void WM_draw_region_viewport_ensure(struct Scene *scene, ARegion *region, short space_type) { bool use_viewport = wm_region_use_viewport_by_type(space_type, region->regiontype); - wm_draw_region_buffer_create(region, false, use_viewport); + wm_draw_region_buffer_create(scene, region, false, use_viewport); } void WM_draw_region_viewport_bind(ARegion *region) -- 2.30.2 From 66326f431f065bb2835aa191770c83cd0de78c06 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 12 Jun 2023 14:32:44 +0100 Subject: [PATCH 09/16] Fix secondary HDR alpha blending issue caused by negative colour values --- intern/opencolorio/gpu_shader_display_transform_frag.glsl | 3 ++- .../gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/opencolorio/gpu_shader_display_transform_frag.glsl b/intern/opencolorio/gpu_shader_display_transform_frag.glsl index a85fc41ef10..405e5c60dfb 100644 --- a/intern/opencolorio/gpu_shader_display_transform_frag.glsl +++ b/intern/opencolorio/gpu_shader_display_transform_frag.glsl @@ -169,7 +169,8 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay) * merge UI using alpha blending in the correct color space. */ if (parameters.use_overlay) { col.rgb = pow(col.rgb, vec3(parameters.exponent * 2.2)); - vec4 clamped_col = clamp(col, 0.0, 1.0); + col = max(col, 0.0); + vec4 clamped_col = min(col, 1.0); if (!parameters.use_extended) { /* if we're not using an extended colour space, clamp the color 0..1 */ diff --git a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl index 75f600ba648..07f761f59b7 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -36,7 +36,8 @@ void main() vec4 overlay_col = texture(overlays_texture, texCoord_interp.xy); if (overlay) { - vec4 clamped_col = clamp(fragColor, 0.0, 1.0); + fragColor = max(fragColor, 0.0); + vec4 clamped_col = min(fragColor, 1.0); if (!use_extended) { /* Only clamp color if we are not using an extended display colorspace. */ fragColor = clamped_col; -- 2.30.2 From 14cd9d6bd9cb1165d7b015f220042706d2430936 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 12 Jun 2023 15:37:15 +0100 Subject: [PATCH 10/16] Add GPU capabilities for HDR and guard python UI change behind capability. Also remove HDR option from render output colormanagement as this is a viewport display property. HDR content was already being rendered to the saved output files. --- scripts/startup/bl_ui/properties_render.py | 6 +++++- .../editors/interface/interface_templates.cc | 3 --- source/blender/editors/render/render_preview.cc | 4 +++- .../blender/editors/space_view3d/view3d_draw.cc | 3 ++- source/blender/gpu/GPU_capabilities.h | 1 + source/blender/gpu/intern/gpu_capabilities.cc | 5 +++++ .../gpu/intern/gpu_capabilities_private.hh | 1 + source/blender/gpu/intern/gpu_viewport.c | 5 +++-- source/blender/gpu/metal/mtl_backend.mm | 1 + source/blender/gpu/opengl/gl_backend.cc | 2 ++ source/blender/imbuf/intern/colormanagement.cc | 5 ++++- source/blender/makesrna/intern/rna_color.c | 2 +- source/blender/python/gpu/gpu_py_capabilities.c | 17 +++++++++++++++++ source/blender/windowmanager/intern/wm_draw.c | 7 ++++--- 14 files changed, 49 insertions(+), 13 deletions(-) diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index eaa90ea8154..78c56ed5c8d 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -55,6 +55,8 @@ class RENDER_PT_color_management(RenderButtonsPanel, Panel): 'BLENDER_WORKBENCH_NEXT'} def draw(self, context): + import gpu + layout = self.layout layout.use_property_split = True layout.use_property_decorate = False # No animation. @@ -75,7 +77,9 @@ class RENDER_PT_color_management(RenderButtonsPanel, Panel): col = flow.column() col.prop(view, "exposure") col.prop(view, "gamma") - col.prop(view, "use_hdr_view") + + if gpu.capabilities.hdr_support_get(): + col.prop(view, "use_hdr_view") col.separator() diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index 4089ac9d4d1..967b8c85bf1 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -6680,9 +6680,6 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, uiItemR(col, &view_transform_ptr, "exposure", 0, nullptr, ICON_NONE); uiItemR(col, &view_transform_ptr, "gamma", 0, nullptr, ICON_NONE); - col = uiLayoutColumn(layout, false); - uiItemR(col, &view_transform_ptr, "use_hdr_view", 0, nullptr, ICON_NONE); - col = uiLayoutColumn(layout, false); uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, nullptr, ICON_NONE); if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 7a3e23d48b0..b601fb67eca 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -74,6 +74,7 @@ #include "BIF_glutil.h" +#include "GPU_capabilities.h" #include "GPU_shader.h" #include "RE_engine.h" @@ -678,7 +679,8 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect /*Use floating point texture for material preview if High Dynamic Range enabled. */ Scene *scene = RE_GetScene(re); - if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { + if (GPU_HDR_support() && scene && + ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { float *rect_float = static_cast(MEM_mallocN( rres.rectx * rres.recty * sizeof(float) * 4, "ed_preview_draw_rect_float")); float fx = rect->xmin + offx; diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index 59446d7c5c4..3c9422f801a 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -62,6 +62,7 @@ #include "GPU_batch.h" #include "GPU_batch_presets.h" +#include "GPU_capabilities.h" #include "GPU_framebuffer.h" #include "GPU_immediate.h" #include "GPU_immediate_util.h" @@ -1890,7 +1891,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, /* Determine desired offscreen format depending on HDR availability. */ bool use_hdr = false; if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = true; + use_hdr = GPU_HDR_support(); } eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; diff --git a/source/blender/gpu/GPU_capabilities.h b/source/blender/gpu/GPU_capabilities.h index 7ba6f6c0536..dd70935a8d0 100644 --- a/source/blender/gpu/GPU_capabilities.h +++ b/source/blender/gpu/GPU_capabilities.h @@ -52,6 +52,7 @@ bool GPU_compute_shader_support(void); bool GPU_shader_storage_buffer_objects_support(void); bool GPU_shader_image_load_store_support(void); bool GPU_shader_draw_parameters_support(void); +bool GPU_HDR_support(void); bool GPU_mem_stats_supported(void); void GPU_mem_stats_get(int *totalmem, int *freemem); diff --git a/source/blender/gpu/intern/gpu_capabilities.cc b/source/blender/gpu/intern/gpu_capabilities.cc index 6fe3ee21449..6d6af1ec1f8 100644 --- a/source/blender/gpu/intern/gpu_capabilities.cc +++ b/source/blender/gpu/intern/gpu_capabilities.cc @@ -182,6 +182,11 @@ bool GPU_shader_draw_parameters_support() return GCaps.shader_draw_parameters_support; } +bool GPU_HDR_support() +{ + return GCaps.hdr_viewport_support; +} + int GPU_max_shader_storage_buffer_bindings() { return GCaps.max_shader_storage_buffer_bindings; diff --git a/source/blender/gpu/intern/gpu_capabilities_private.hh b/source/blender/gpu/intern/gpu_capabilities_private.hh index 8134c39871d..4598ad2198d 100644 --- a/source/blender/gpu/intern/gpu_capabilities_private.hh +++ b/source/blender/gpu/intern/gpu_capabilities_private.hh @@ -48,6 +48,7 @@ struct GPUCapabilities { bool shader_image_load_store_support = false; bool shader_draw_parameters_support = false; bool transform_feedback_support = false; + bool hdr_viewport_support = false; /* OpenGL related workarounds. */ bool mip_render_workaround = false; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 43d0d131225..2eafa1f3798 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -428,6 +428,8 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, GPUTexture *color_overlay = viewport->color_overlay_tx[view]; bool use_ocio = false; + bool use_hdr = GPU_HDR_support() && + ((viewport->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0); if (viewport->do_color_management && display_colorspace) { /* During the binding process the last used VertexFormat is tested and can assert as it is not @@ -455,8 +457,7 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); GPU_batch_uniform_1i(batch, "overlay", do_overlay_merge); GPU_batch_uniform_1i(batch, "display_transform", display_colorspace); - GPU_batch_uniform_1i( - batch, "use_extended", viewport->view_settings.flag & COLORMANAGE_VIEW_USE_HDR); + GPU_batch_uniform_1i(batch, "use_extended", use_hdr); } GPU_texture_bind(color, 0); diff --git a/source/blender/gpu/metal/mtl_backend.mm b/source/blender/gpu/metal/mtl_backend.mm index a50dfe2c8ce..9d389ab927c 100644 --- a/source/blender/gpu/metal/mtl_backend.mm +++ b/source/blender/gpu/metal/mtl_backend.mm @@ -405,6 +405,7 @@ void MTLBackend::capabilities_init(MTLContext *ctx) GCaps.compute_shader_support = true; GCaps.shader_storage_buffer_objects_support = true; GCaps.shader_draw_parameters_support = true; + GCaps.hdr_viewport_support = true; GCaps.geometry_shader_support = false; diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 9caf6d487a1..40d537222e4 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -234,6 +234,7 @@ static void detect_workarounds() GCaps.shader_image_load_store_support = false; GCaps.shader_draw_parameters_support = false; GCaps.shader_storage_buffer_objects_support = false; + GCaps.hdr_viewport_support = false; GLContext::base_instance_support = false; GLContext::clear_texture_support = false; GLContext::copy_image_support = false; @@ -538,6 +539,7 @@ void GLBackend::capabilities_init() epoxy_gl_version() >= 43; GCaps.geometry_shader_support = true; GCaps.max_samplers = GCaps.max_textures; + GCaps.hdr_viewport_support = false; if (GCaps.compute_shader_support) { glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &GCaps.max_work_group_count[0]); diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index e313a11084f..f81cd067226 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -42,6 +42,8 @@ #include "BKE_image_format.h" #include "BKE_main.h" +#include "GPU_capabilities.h" + #include "RNA_define.h" #include "SEQ_iterator.h" @@ -4075,7 +4077,8 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( const float gamma = applied_view_settings->gamma; const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure); const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma); - const bool use_extended = (applied_view_settings->flag & COLORMANAGE_VIEW_USE_HDR) != 0; + const bool use_extended = GPU_HDR_support() && + (applied_view_settings->flag & COLORMANAGE_VIEW_USE_HDR) != 0; OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 59b98280d66..45bb421ee1d 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -1293,7 +1293,7 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_property_ui_text(prop, "High Dynamic Range", "Enable high dynamic range with extended colorspace in viewport, " - "uncapping display brightness for rendered content."); + "uncapping display brightness for rendered content"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); /* ** Color-space ** */ diff --git a/source/blender/python/gpu/gpu_py_capabilities.c b/source/blender/python/gpu/gpu_py_capabilities.c index fbc1db86533..7319f4d68e3 100644 --- a/source/blender/python/gpu/gpu_py_capabilities.c +++ b/source/blender/python/gpu/gpu_py_capabilities.c @@ -228,6 +228,19 @@ static PyObject *pygpu_shader_image_load_store_support_get(PyObject *UNUSED(self { return PyBool_FromLong(GPU_shader_image_load_store_support()); } + +PyDoc_STRVAR(pygpu_hdr_support_get_doc, + ".. function:: hdr_support_get()\n" + "\n" + " Return whether GPU backend supports High Dynamic range for viewport.\n" + "\n" + " :return: HDR support available.\n" + " :rtype: bool\n"); +static PyObject *pygpu_hdr_support_get(PyObject *UNUSED(self)) +{ + return PyBool_FromLong(GPU_HDR_support()); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -297,6 +310,10 @@ static PyMethodDef pygpu_capabilities__tp_methods[] = { (PyCFunction)pygpu_shader_image_load_store_support_get, METH_NOARGS, pygpu_shader_image_load_store_support_get_doc}, + {"hdr_support_get", + (PyCFunction)pygpu_hdr_support_get, + METH_NOARGS, + pygpu_hdr_support_get_doc}, {NULL, NULL, 0, NULL}, }; diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 67d0b66ecb9..4b0a4d79776 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -38,6 +38,7 @@ #include "ED_view3d.h" #include "GPU_batch_presets.h" +#include "GPU_capabilities.h" #include "GPU_context.h" #include "GPU_debug.h" #include "GPU_framebuffer.h" @@ -663,7 +664,7 @@ static void wm_draw_region_buffer_create(Scene *scene, /* Determine desired offscreen format. */ bool use_hdr = false; if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = true; + use_hdr = GPU_HDR_support(); } eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; @@ -1165,7 +1166,7 @@ static void wm_draw_window(bContext *C, wmWindow *win) bool use_hdr = false; Scene *scene = WM_window_get_active_scene(win); if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = true; + use_hdr = GPU_HDR_support(); } eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; @@ -1328,7 +1329,7 @@ uint8_t *WM_window_pixels_read_from_offscreen(bContext *C, wmWindow *win, int r_ bool use_hdr = false; Scene *scene = WM_window_get_active_scene(win); if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = true; + use_hdr = GPU_HDR_support(); } eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; -- 2.30.2 From b06504c1535b36bfdb87483778426555bc38fedb Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Thu, 3 Aug 2023 11:46:09 +0100 Subject: [PATCH 11/16] Apply Jeroen's PR feedback. --- .../gpu_shader_display_transform_frag.glsl | 6 ++-- .../editors/space_view3d/view3d_draw.cc | 2 +- source/blender/gpu/GPU_capabilities.h | 2 +- source/blender/gpu/GPU_framebuffer.h | 3 +- source/blender/gpu/intern/gpu_capabilities.cc | 2 +- source/blender/gpu/intern/gpu_viewport.cc | 2 +- .../gpu_shader_image_overlays_merge_frag.glsl | 12 +++---- .../blender/imbuf/intern/colormanagement.cc | 2 +- source/blender/makesrna/intern/rna_color.cc | 13 ------- .../blender/python/gpu/gpu_py_capabilities.cc | 2 +- .../blender/windowmanager/intern/wm_draw.cc | 34 ++++++++----------- 11 files changed, 29 insertions(+), 51 deletions(-) diff --git a/intern/opencolorio/gpu_shader_display_transform_frag.glsl b/intern/opencolorio/gpu_shader_display_transform_frag.glsl index 405e5c60dfb..3403bd624ea 100644 --- a/intern/opencolorio/gpu_shader_display_transform_frag.glsl +++ b/intern/opencolorio/gpu_shader_display_transform_frag.glsl @@ -169,17 +169,15 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay) * merge UI using alpha blending in the correct color space. */ if (parameters.use_overlay) { col.rgb = pow(col.rgb, vec3(parameters.exponent * 2.2)); - col = max(col, 0.0); - vec4 clamped_col = min(col, 1.0); if (!parameters.use_extended) { /* if we're not using an extended colour space, clamp the color 0..1 */ - col = clamped_col; + col = clamp(col, 0.0, 1.0); } else { /* When using extended colorspace, interpolate towards clamped color to improve display of * alpha-blended overlays. */ - col = mix(col, clamped_col, col_overlay.a); + col = mix(max(col, 0.0), clamp(col, 0.0, 1.0), col_overlay.a); } col *= 1.0 - col_overlay.a; col += col_overlay; /* Assumed unassociated alpha. */ diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index 63644940695..b60500ac4cb 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -1906,7 +1906,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, /* Determine desired offscreen format depending on HDR availability. */ bool use_hdr = false; if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = GPU_HDR_support(); + use_hdr = GPU_hdr_support(); } eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; diff --git a/source/blender/gpu/GPU_capabilities.h b/source/blender/gpu/GPU_capabilities.h index dd70935a8d0..ef2123f9754 100644 --- a/source/blender/gpu/GPU_capabilities.h +++ b/source/blender/gpu/GPU_capabilities.h @@ -52,7 +52,7 @@ bool GPU_compute_shader_support(void); bool GPU_shader_storage_buffer_objects_support(void); bool GPU_shader_image_load_store_support(void); bool GPU_shader_draw_parameters_support(void); -bool GPU_HDR_support(void); +bool GPU_hdr_support(void); bool GPU_mem_stats_supported(void); void GPU_mem_stats_get(int *totalmem, int *freemem); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index 371b1c2ab75..dd233e79691 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -654,8 +654,7 @@ int GPU_offscreen_height(const GPUOffScreen *offscreen); struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *offscreen); /** - * Return the color texture of a #GPUOffScreen. Does not give ownership. - * \note only to be used by viewport code! + * Return the texture format of a #GPUOffScreen. */ eGPUTextureFormat GPU_offscreen_format(const GPUOffScreen *offscreen); diff --git a/source/blender/gpu/intern/gpu_capabilities.cc b/source/blender/gpu/intern/gpu_capabilities.cc index 819adce0f95..0b4ac4a7678 100644 --- a/source/blender/gpu/intern/gpu_capabilities.cc +++ b/source/blender/gpu/intern/gpu_capabilities.cc @@ -182,7 +182,7 @@ bool GPU_shader_draw_parameters_support() return GCaps.shader_draw_parameters_support; } -bool GPU_HDR_support() +bool GPU_hdr_support() { return GCaps.hdr_viewport_support; } diff --git a/source/blender/gpu/intern/gpu_viewport.cc b/source/blender/gpu/intern/gpu_viewport.cc index 91ac7191f18..3978f8db844 100644 --- a/source/blender/gpu/intern/gpu_viewport.cc +++ b/source/blender/gpu/intern/gpu_viewport.cc @@ -441,7 +441,7 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, GPUTexture *color_overlay = viewport->color_overlay_tx[view]; bool use_ocio = false; - bool use_hdr = GPU_HDR_support() && + bool use_hdr = GPU_hdr_support() && ((viewport->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0); if (viewport->do_color_management && display_colorspace) { diff --git a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl index 07f761f59b7..c307c682cee 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -36,16 +36,14 @@ void main() vec4 overlay_col = texture(overlays_texture, texCoord_interp.xy); if (overlay) { - fragColor = max(fragColor, 0.0); - vec4 clamped_col = min(fragColor, 1.0); if (!use_extended) { - /* Only clamp color if we are not using an extended display colorspace. */ - fragColor = clamped_col; + /* if we're not using an extended colour space, clamp the color 0..1 */ + fragColor = clamp(fragColor, 0.0, 1.0); } else { - /* When using extended colorspace, interpolate towards clamped color to avoid over-brightened - * overlays. */ - fragColor = mix(fragColor, clamped_col, overlay_col.a); + /* When using extended colorspace, interpolate towards clamped color to improve display of + * alpha-blended overlays. */ + fragColor = mix(max(fragColor, 0.0), clamp(fragColor, 0.0, 1.0), overlay_col.a); } fragColor *= 1.0 - overlay_col.a; fragColor += overlay_col; diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index 45c4d8a4e21..a8fe3178e0f 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -4107,7 +4107,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( const float gamma = applied_view_settings->gamma; const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure); const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma); - const bool use_extended = GPU_HDR_support() && + const bool use_extended = GPU_hdr_support() && (applied_view_settings->flag & COLORMANAGE_VIEW_USE_HDR) != 0; OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); diff --git a/source/blender/makesrna/intern/rna_color.cc b/source/blender/makesrna/intern/rna_color.cc index fd4ef0d0c9d..7bbb96a0b34 100644 --- a/source/blender/makesrna/intern/rna_color.cc +++ b/source/blender/makesrna/intern/rna_color.cc @@ -506,18 +506,6 @@ static void rna_ColorManagedViewSettings_look_set(PointerRNA *ptr, int value) } } -static void rna_ColorManagedViewSettings_use_hdr_set(PointerRNA *ptr, bool value) -{ - ColorManagedViewSettings *view_settings = (ColorManagedViewSettings *)ptr->data; - - if (value) { - view_settings->flag |= COLORMANAGE_VIEW_USE_HDR; - } - else { - view_settings->flag &= ~COLORMANAGE_VIEW_USE_HDR; - } -} - static const EnumPropertyItem *rna_ColorManagedViewSettings_look_itemf(bContext * /*C*/, PointerRNA *ptr, PropertyRNA * /*prop*/, @@ -1287,7 +1275,6 @@ static void rna_def_colormanage(BlenderRNA *brna) prop = RNA_def_property(srna, "use_hdr_view", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", COLORMANAGE_VIEW_USE_HDR); - RNA_def_property_boolean_funcs(prop, NULL, "rna_ColorManagedViewSettings_use_hdr_set"); RNA_def_property_ui_text(prop, "High Dynamic Range", "Enable high dynamic range with extended colorspace in viewport, " diff --git a/source/blender/python/gpu/gpu_py_capabilities.cc b/source/blender/python/gpu/gpu_py_capabilities.cc index 95ea16b7813..4c2a5d3d80a 100644 --- a/source/blender/python/gpu/gpu_py_capabilities.cc +++ b/source/blender/python/gpu/gpu_py_capabilities.cc @@ -238,7 +238,7 @@ PyDoc_STRVAR(pygpu_hdr_support_get_doc, " :rtype: bool\n"); static PyObject *pygpu_hdr_support_get(PyObject * /*self*/) { - return PyBool_FromLong(GPU_HDR_support()); + return PyBool_FromLong(GPU_hdr_support()); } /** \} */ diff --git a/source/blender/windowmanager/intern/wm_draw.cc b/source/blender/windowmanager/intern/wm_draw.cc index 48380125bfb..26098f49ff4 100644 --- a/source/blender/windowmanager/intern/wm_draw.cc +++ b/source/blender/windowmanager/intern/wm_draw.cc @@ -663,18 +663,24 @@ static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) GPU_texture_mipmap_mode(texture, false, false); } +static eGPUTextureFormat get_hdr_framebuffer_format(const Scene *scene) +{ + bool use_hdr = false; + if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { + use_hdr = GPU_hdr_support(); + } + eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + return desired_format; +} + static void wm_draw_region_buffer_create(Scene *scene, ARegion *region, bool stereo, bool use_viewport) { - /* Determine desired offscreen format. */ - bool use_hdr = false; - if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = GPU_HDR_support(); - } - eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + /* Determine desired offscreen format depending on HDR availability. */ + eGPUTextureFormat desired_format = get_hdr_framebuffer_format(scene); if (region->draw_buffer) { if (region->draw_buffer->stereo != stereo) { @@ -1177,13 +1183,8 @@ static void wm_draw_window(bContext *C, wmWindow *win) wm_draw_window_onscreen(C, win, -1); } else { - /* Determine desired offscreen format. */ - bool use_hdr = false; - Scene *scene = WM_window_get_active_scene(win); - if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = GPU_HDR_support(); - } - eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + /* Determine desired offscreen format depending on HDR availability. */ + eGPUTextureFormat desired_format = get_hdr_framebuffer_format(WM_window_get_active_scene(win)); /* For side-by-side and top-bottom, we need to render each view to an * an off-screen texture and then draw it. This used to happen for all @@ -1343,12 +1344,7 @@ uint8_t *WM_window_pixels_read_from_offscreen(bContext *C, wmWindow *win, int r_ r_size[1] = WM_window_pixels_y(win); /* Determine desired offscreen format depending on HDR availability. */ - bool use_hdr = false; - Scene *scene = WM_window_get_active_scene(win); - if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) { - use_hdr = GPU_HDR_support(); - } - eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8; + eGPUTextureFormat desired_format = get_hdr_framebuffer_format(WM_window_get_active_scene(win)); GPUOffScreen *offscreen = GPU_offscreen_create( r_size[0], r_size[1], false, desired_format, GPU_TEXTURE_USAGE_SHADER_READ, nullptr); -- 2.30.2 From 725ed87ebb460df3013cceb1e78c59278fa5fff9 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Thu, 3 Aug 2023 11:59:58 +0100 Subject: [PATCH 12/16] Grey out HDR option for non-compatible display transforms and improve feature description following Brechts feedback. --- scripts/startup/bl_ui/properties_render.py | 5 ++++- source/blender/makesrna/intern/rna_color.cc | 9 +++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index 8b10fbab662..16bbf38e49b 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -81,8 +81,11 @@ class RENDER_PT_color_management(RenderButtonsPanel, Panel): col.prop(view, "exposure") col.prop(view, "gamma") + # Only display HDR toggle for non-Filmic display transforms. if gpu.capabilities.hdr_support_get(): - col.prop(view, "use_hdr_view") + sub = col.row() + sub.active = (view.view_transform != "Filmic" and view.view_transform != "Filmic Log") + sub.prop(view, "use_hdr_view") col.separator() diff --git a/source/blender/makesrna/intern/rna_color.cc b/source/blender/makesrna/intern/rna_color.cc index 7bbb96a0b34..48194e7f1e0 100644 --- a/source/blender/makesrna/intern/rna_color.cc +++ b/source/blender/makesrna/intern/rna_color.cc @@ -1275,10 +1275,11 @@ static void rna_def_colormanage(BlenderRNA *brna) prop = RNA_def_property(srna, "use_hdr_view", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", COLORMANAGE_VIEW_USE_HDR); - RNA_def_property_ui_text(prop, - "High Dynamic Range", - "Enable high dynamic range with extended colorspace in viewport, " - "uncapping display brightness for rendered content"); + RNA_def_property_ui_text( + prop, + "High Dynamic Range", + "Enable high dynamic range display in rendered viewport, uncapping display brightness. This " + "requires a monitor with HDR support and a view transform designed for HDR."); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); /* ** Color-space ** */ -- 2.30.2 From 1f982508b41c53ac86b198f6500606edc28dad4b Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Thu, 3 Aug 2023 12:15:32 +0100 Subject: [PATCH 13/16] Apply further PR feedback on naming conventions. Remove unneeded changes. --- .../gpu_shader_display_transform_frag.glsl | 4 ++-- intern/opencolorio/ocio_capi.cc | 4 ++-- intern/opencolorio/ocio_capi.h | 2 +- intern/opencolorio/ocio_impl.h | 4 ++-- intern/opencolorio/ocio_impl_glsl.cc | 11 +++++------ intern/opencolorio/ocio_shader_shared.hh | 2 +- source/blender/editors/screen/screen_draw.cc | 2 +- source/blender/gpu/intern/gpu_viewport.cc | 3 +-- .../shaders/gpu_shader_image_overlays_merge_frag.glsl | 4 ++-- .../infos/gpu_shader_2D_image_overlays_merge_info.hh | 2 +- source/blender/imbuf/intern/colormanagement.cc | 6 +++--- 11 files changed, 21 insertions(+), 23 deletions(-) diff --git a/intern/opencolorio/gpu_shader_display_transform_frag.glsl b/intern/opencolorio/gpu_shader_display_transform_frag.glsl index 3403bd624ea..1d9a3f69dde 100644 --- a/intern/opencolorio/gpu_shader_display_transform_frag.glsl +++ b/intern/opencolorio/gpu_shader_display_transform_frag.glsl @@ -170,8 +170,8 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay) if (parameters.use_overlay) { col.rgb = pow(col.rgb, vec3(parameters.exponent * 2.2)); - if (!parameters.use_extended) { - /* if we're not using an extended colour space, clamp the color 0..1 */ + if (!parameters.use_hdr) { + /* If we're not using an extended colour space, clamp the color 0..1. */ col = clamp(col, 0.0, 1.0); } else { diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index 992b81183c1..33ea7be7dd1 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -291,7 +291,7 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, const float dither, const bool use_predivide, const bool use_overlay, - const bool use_extended) + const bool use_hdr) { return impl->gpuDisplayShaderBind(config, input, @@ -304,7 +304,7 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, dither, use_predivide, use_overlay, - use_extended); + use_hdr); } void OCIO_gpuDisplayShaderUnbind() diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 6baac200d79..6097189cb7c 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -198,7 +198,7 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, const float dither, const bool use_predivide, const bool use_overlay, - const bool use_extended); + const bool use_hdr); void OCIO_gpuDisplayShaderUnbind(void); void OCIO_gpuCacheFree(void); diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index 7d0f2b96082..4f334c0344d 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -114,7 +114,7 @@ class IOCIOImpl { const float /*dither*/, const bool /*use_predivide*/, const bool /*use_overlay*/, - const bool /*use_extended*/) + const bool /*use_hdr*/) { return false; } @@ -312,7 +312,7 @@ class OCIOImpl : public IOCIOImpl { const float dither, const bool use_predivide, const bool use_overlay, - const bool use_extended); + const bool use_hdr); void gpuDisplayShaderUnbind(void); void gpuCacheFree(void); diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index 5cddaedbc77..2f0f9d72eb6 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -516,7 +516,7 @@ static void updateGPUDisplayParameters(OCIO_GPUShader &shader, float dither, bool use_predivide, bool use_overlay, - bool use_extended) + bool use_hdr) { bool do_update = false; if (shader.parameters_buffer == nullptr) { @@ -544,8 +544,8 @@ static void updateGPUDisplayParameters(OCIO_GPUShader &shader, data.use_overlay = use_overlay; do_update = true; } - if (bool(data.use_extended) != use_extended) { - data.use_extended = use_extended; + if (bool(data.use_hdr) != use_hdr) { + data.use_hdr = use_hdr; do_update = true; } if (do_update) { @@ -690,7 +690,7 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, const float dither, const bool use_predivide, const bool use_overlay, - const bool use_extended) + const bool use_hdr) { /* Get GPU shader from cache or create new one. */ OCIO_GPUDisplayShader &display_shader = getGPUDisplayShader( @@ -725,8 +725,7 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, GPU_uniformbuf_bind(textures.uniforms_buffer, UNIFORMBUF_SLOT_LUTS); } - updateGPUDisplayParameters( - shader, scale, exponent, dither, use_predivide, use_overlay, use_extended); + updateGPUDisplayParameters(shader, scale, exponent, dither, use_predivide, use_overlay, use_hdr); GPU_uniformbuf_bind(shader.parameters_buffer, UNIFORMBUF_SLOT_DISPLAY); /* TODO(fclem): remove remains of IMM. */ diff --git a/intern/opencolorio/ocio_shader_shared.hh b/intern/opencolorio/ocio_shader_shared.hh index 933e5c58593..a91a959a477 100644 --- a/intern/opencolorio/ocio_shader_shared.hh +++ b/intern/opencolorio/ocio_shader_shared.hh @@ -36,7 +36,7 @@ struct OCIO_GPUParameters { float exponent; bool1 use_predivide; bool1 use_overlay; - bool1 use_extended; + bool1 use_hdr; int _pad0; int _pad1; }; diff --git a/source/blender/editors/screen/screen_draw.cc b/source/blender/editors/screen/screen_draw.cc index f27593e6dd2..2ce42994f9d 100644 --- a/source/blender/editors/screen/screen_draw.cc +++ b/source/blender/editors/screen/screen_draw.cc @@ -429,7 +429,7 @@ void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uin GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, true, - GPU_RGBA16F, + GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ, err_out); diff --git a/source/blender/gpu/intern/gpu_viewport.cc b/source/blender/gpu/intern/gpu_viewport.cc index 3978f8db844..587c09e9cb8 100644 --- a/source/blender/gpu/intern/gpu_viewport.cc +++ b/source/blender/gpu/intern/gpu_viewport.cc @@ -466,11 +466,10 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, GPU_batch_program_set_imm_shader(batch); } else { - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); GPU_batch_uniform_1i(batch, "overlay", do_overlay_merge); GPU_batch_uniform_1i(batch, "display_transform", display_colorspace); - GPU_batch_uniform_1i(batch, "use_extended", use_hdr); + GPU_batch_uniform_1i(batch, "use_hdr", use_hdr); } GPU_texture_bind(color, 0); diff --git a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl index c307c682cee..5ed519c0e93 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -36,8 +36,8 @@ void main() vec4 overlay_col = texture(overlays_texture, texCoord_interp.xy); if (overlay) { - if (!use_extended) { - /* if we're not using an extended colour space, clamp the color 0..1 */ + if (!use_hdr) { + /* If we're not using an extended colour space, clamp the color 0..1. */ fragColor = clamp(fragColor, 0.0, 1.0); } else { diff --git a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh index 0452c053d81..30e205ed14c 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh @@ -17,7 +17,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_2D_image_overlays_merge) .push_constant(Type::MAT4, "ModelViewProjectionMatrix") .push_constant(Type::BOOL, "display_transform") .push_constant(Type::BOOL, "overlay") - .push_constant(Type::BOOL, "use_extended") + .push_constant(Type::BOOL, "use_hdr") /* Sampler slots should match OCIO's. */ .sampler(0, ImageType::FLOAT_2D, "image_texture") .sampler(1, ImageType::FLOAT_2D, "overlays_texture") diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index a8fe3178e0f..802f98849c2 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -4107,8 +4107,8 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( const float gamma = applied_view_settings->gamma; const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure); const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma); - const bool use_extended = GPU_hdr_support() && - (applied_view_settings->flag & COLORMANAGE_VIEW_USE_HDR) != 0; + const bool use_hdr = GPU_hdr_support() && + (applied_view_settings->flag & COLORMANAGE_VIEW_USE_HDR) != 0; OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); @@ -4124,7 +4124,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( dither, predivide, do_overlay_merge, - use_extended); + use_hdr); OCIO_configRelease(config); -- 2.30.2 From 001bbcebcdd62dea10811b52ed403b00058b50e2 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 7 Aug 2023 16:29:12 +0100 Subject: [PATCH 14/16] Minor bits of cleanup. --- source/blender/editors/render/render_preview.cc | 1 - source/blender/makesrna/intern/rna_color.cc | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 8bc7507de05..e099d3b4da6 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -74,7 +74,6 @@ #include "BIF_glutil.h" -#include "GPU_capabilities.h" #include "GPU_shader.h" #include "RE_engine.h" diff --git a/source/blender/makesrna/intern/rna_color.cc b/source/blender/makesrna/intern/rna_color.cc index 48194e7f1e0..2eaa3878b9b 100644 --- a/source/blender/makesrna/intern/rna_color.cc +++ b/source/blender/makesrna/intern/rna_color.cc @@ -1279,7 +1279,7 @@ static void rna_def_colormanage(BlenderRNA *brna) prop, "High Dynamic Range", "Enable high dynamic range display in rendered viewport, uncapping display brightness. This " - "requires a monitor with HDR support and a view transform designed for HDR."); + "requires a monitor with HDR support and a view transform designed for HDR"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); /* ** Color-space ** */ -- 2.30.2 From e6720a8cc10c581d7ad19ac4c3e3040575b19682 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Tue, 8 Aug 2023 11:34:59 +0100 Subject: [PATCH 15/16] Fix compilation error after --- source/blender/windowmanager/WM_api.hh | 2 +- source/blender/windowmanager/intern/wm_draw.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/windowmanager/WM_api.hh b/source/blender/windowmanager/WM_api.hh index 1c53cc59417..d3dda5cda6f 100644 --- a/source/blender/windowmanager/WM_api.hh +++ b/source/blender/windowmanager/WM_api.hh @@ -1597,7 +1597,7 @@ void *WM_draw_cb_activate(wmWindow *win, void (*draw)(const wmWindow *, void *), void WM_draw_cb_exit(wmWindow *win, void *handle); void WM_redraw_windows(bContext *C); -void WM_draw_region_viewport_ensure(ARegion *region, short space_type); +void WM_draw_region_viewport_ensure(Scene *scene, ARegion *region, short space_type); void WM_draw_region_viewport_bind(ARegion *region); void WM_draw_region_viewport_unbind(ARegion *region); diff --git a/source/blender/windowmanager/intern/wm_draw.cc b/source/blender/windowmanager/intern/wm_draw.cc index 6da5bd19579..120e79d8d84 100644 --- a/source/blender/windowmanager/intern/wm_draw.cc +++ b/source/blender/windowmanager/intern/wm_draw.cc @@ -1623,7 +1623,7 @@ void WM_redraw_windows(bContext *C) * * \{ */ -void WM_draw_region_viewport_ensure(struct Scene *scene, ARegion *region, short space_type) +void WM_draw_region_viewport_ensure(Scene *scene, ARegion *region, short space_type) { bool use_viewport = wm_region_use_viewport_by_type(space_type, region->regiontype); wm_draw_region_buffer_create(scene, region, false, use_viewport); -- 2.30.2 From 413100672885175cb3f34efacf1ea00ed239bea7 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Tue, 8 Aug 2023 16:45:43 +0100 Subject: [PATCH 16/16] Move HDR option to display sub-panel and update description for HDR toggle. --- scripts/startup/bl_ui/properties_render.py | 38 +++++++++++++++++---- source/blender/makesrna/intern/rna_color.cc | 3 +- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index 34ba9b9fc58..51d25c744d5 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -58,7 +58,6 @@ class RENDER_PT_color_management(RenderButtonsPanel, Panel): 'BLENDER_WORKBENCH_NEXT'} def draw(self, context): - import gpu layout = self.layout layout.use_property_split = True @@ -81,17 +80,41 @@ class RENDER_PT_color_management(RenderButtonsPanel, Panel): col.prop(view, "exposure") col.prop(view, "gamma") - # Only display HDR toggle for non-Filmic display transforms. - if gpu.capabilities.hdr_support_get(): - sub = col.row() - sub.active = (view.view_transform != "Filmic" and view.view_transform != "Filmic Log") - sub.prop(view, "use_hdr_view") - col.separator() col.prop(scene.sequencer_colorspace_settings, "name", text="Sequencer") +class RENDER_PT_color_management_display_settings(RenderButtonsPanel, Panel): + bl_label = "Display" + bl_parent_id = "RENDER_PT_color_management" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = { + 'BLENDER_RENDER', + 'BLENDER_EEVEE', + 'BLENDER_EEVEE_NEXT', + 'BLENDER_WORKBENCH', + 'BLENDER_WORKBENCH_NEXT'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + scene = context.scene + view = scene.view_settings + + # Only enable display sub-section if HDR support is available. + import gpu + layout.enabled = gpu.capabilities.hdr_support_get() + + # Only display HDR toggle for non-Filmic display transforms. + col = layout.column(align=True) + sub = col.row() + sub.active = (view.view_transform != "Filmic" and view.view_transform != "Filmic Log") + sub.prop(view, "use_hdr_view") + + class RENDER_PT_color_management_curves(RenderButtonsPanel, Panel): bl_label = "Use Curves" bl_parent_id = "RENDER_PT_color_management" @@ -1231,6 +1254,7 @@ classes = ( RENDER_PT_opengl_film, RENDER_PT_hydra_debug, RENDER_PT_color_management, + RENDER_PT_color_management_display_settings, RENDER_PT_color_management_curves, RENDER_PT_simplify, RENDER_PT_simplify_viewport, diff --git a/source/blender/makesrna/intern/rna_color.cc b/source/blender/makesrna/intern/rna_color.cc index ec88394222c..6ac71adba60 100644 --- a/source/blender/makesrna/intern/rna_color.cc +++ b/source/blender/makesrna/intern/rna_color.cc @@ -1279,7 +1279,8 @@ static void rna_def_colormanage(BlenderRNA *brna) prop, "High Dynamic Range", "Enable high dynamic range display in rendered viewport, uncapping display brightness. This " - "requires a monitor with HDR support and a view transform designed for HDR"); + "requires a monitor with HDR support and a view transform designed for HDR. " + "'Filmic' does not generate HDR colors"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); /* ** Color-space ** */ -- 2.30.2