MacOS: Enable support for EDR rendering #105662

Merged
Brecht Van Lommel merged 26 commits from Jason-Fielder/blender:macos_EDR_support into main 2023-08-09 14:25:23 +02:00
6 changed files with 69 additions and 16 deletions
Showing only changes of commit 2a0fea33ad - Show all commits

View File

@ -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);

View File

@ -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.
brecht marked this conversation as resolved Outdated

Comment needs to be updated.

Comment needs to be updated.
* \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!

View File

@ -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,

View File

@ -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.");
brecht marked this conversation as resolved Outdated

Can we extend this tooltip with some more info?

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.
Can we extend this tooltip with some more info? ``` 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_ColorManagement_update");
RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
/* ** Color-space ** */
srna = RNA_def_struct(brna, "ColorManagedInputColorspaceSettings", NULL);

View File

@ -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);

View File

@ -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;
brecht marked this conversation as resolved Outdated

I see this code be repeated 3 times. better extract it in a static function.

I see this code be repeated 3 times. better extract it in a static function.
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)