From 5ec670b49f9f288e033ec8dc5243838327a44872 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 27 Mar 2023 13:39:23 +0200 Subject: [PATCH 1/9] Image Engine: Remove drawing artifacts (precision issues). --- .../draw/engines/image/image_batches.hh | 39 ++++++++++--------- .../draw/engines/image/image_drawing_mode.hh | 25 ++++++++++-- .../draw/engines/image/image_texture_info.hh | 24 +++--------- .../shaders/image_engine_color_vert.glsl | 3 +- .../shaders/image_engine_depth_vert.glsl | 3 +- .../image/shaders/infos/engine_image_info.hh | 4 +- 6 files changed, 51 insertions(+), 47 deletions(-) diff --git a/source/blender/draw/engines/image/image_batches.hh b/source/blender/draw/engines/image/image_batches.hh index 1d7e7a0b548..85ddc7f48ee 100644 --- a/source/blender/draw/engines/image/image_batches.hh +++ b/source/blender/draw/engines/image/image_batches.hh @@ -46,24 +46,8 @@ class BatchUpdater { GPU_batch_init_ex(info.batch, GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO); } - GPUVertBuf *create_vbo() - { - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, 4); - float pos[4][2]; - fill_tri_fan_from_rctf(pos, info.clipping_bounds); - float uv[4][2]; - fill_tri_fan_from_rctf(uv, info.clipping_uv_bounds); - - for (int i = 0; i < 4; i++) { - GPU_vertbuf_attr_set(vbo, pos_id, i, pos[i]); - GPU_vertbuf_attr_set(vbo, uv_id, i, uv[i]); - } - - return vbo; - } - - static void fill_tri_fan_from_rctf(float result[4][2], rctf &rect) + template + static void fill_tri_fan_from_rect(DataType result[4][2], RectType &rect) { result[0][0] = rect.xmin; result[0][1] = rect.ymin; @@ -75,10 +59,27 @@ class BatchUpdater { result[3][1] = rect.ymax; } + GPUVertBuf *create_vbo() + { + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, 4); + int pos[4][2]; + fill_tri_fan_from_rect(pos, info.clipping_bounds); + float uv[4][2]; + fill_tri_fan_from_rect(uv, info.clipping_uv_bounds); + + for (int i = 0; i < 4; i++) { + GPU_vertbuf_attr_set(vbo, pos_id, i, pos[i]); + GPU_vertbuf_attr_set(vbo, uv_id, i, uv[i]); + } + + return vbo; + } + void ensure_format() { if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT); GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); pos_id = GPU_vertformat_attr_id_get(&format, "pos"); diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index b77150fbb02..f3138417bfc 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -38,6 +38,8 @@ template class ScreenTileTextures { struct TextureInfoBounds { TextureInfo *info = nullptr; rctf uv_bounds; + /* Offset of this tile to be drawn on the screen (number of tiles from bottom left corner). */ + int2 tile_id; }; IMAGE_InstanceData *instance_data; @@ -78,7 +80,7 @@ template class ScreenTileTextures { rctf region_uv_bounds; BLI_rctf_init( ®ion_uv_bounds, region_uv_min.x, region_uv_max.x, region_uv_min.y, region_uv_max.y); - update_region_bounds_from_uv_bounds(region_uv_bounds, float2(region->winx, region->winy)); + update_region_bounds_from_uv_bounds(region_uv_bounds, int2(region->winx, region->winy)); } void ensure_gpu_textures_allocation() @@ -109,6 +111,7 @@ template class ScreenTileTextures { for (int x = 0; x < TexturesPerDimension; x++) { for (int y = 0; y < TexturesPerDimension; y++) { TextureInfoBounds texture_info_bounds; + texture_info_bounds.tile_id = int2(x, y); BLI_rctf_init(&texture_info_bounds.uv_bounds, uv_coords[x][y].x, uv_coords[x + 1][y + 1].x, @@ -129,6 +132,7 @@ template class ScreenTileTextures { if (info_bound.info == nullptr && BLI_rctf_compare(&info_bound.uv_bounds, &info.clipping_uv_bounds, 0.001)) { info_bound.info = &info; + info.tile_id = info_bound.tile_id; assigned = true; break; } @@ -145,20 +149,33 @@ template class ScreenTileTextures { for (TextureInfoBounds &info_bound : info_bounds) { if (info_bound.info == nullptr) { info_bound.info = unassigned_textures.pop_last(); + info_bound.info->tile_id = info_bound.tile_id; info_bound.info->need_full_update = true; info_bound.info->clipping_uv_bounds = info_bound.uv_bounds; } } } - void update_region_bounds_from_uv_bounds(const rctf ®ion_uv_bounds, const float2 region_size) + void update_region_bounds_from_uv_bounds(const rctf ®ion_uv_bounds, const int2 region_size) { rctf region_bounds; BLI_rctf_init(®ion_bounds, 0.0, region_size.x, 0.0, region_size.y); float4x4 uv_to_screen; BLI_rctf_transform_calc_m4_pivot_min(®ion_uv_bounds, ®ion_bounds, uv_to_screen.ptr()); + int2 tile_origin(0); + for (const TextureInfo &info : instance_data->texture_infos) { + if (info.tile_id == int2(0)) { + tile_origin = int2(math::transform_point( + uv_to_screen, + float3(info.clipping_uv_bounds.xmin, info.clipping_uv_bounds.ymin, 0.0))); + break; + } + } + for (TextureInfo &info : instance_data->texture_infos) { - info.update_region_bounds_from_uv_bounds(uv_to_screen); + int2 bottom_left = tile_origin + region_size * info.tile_id; + int2 top_right = bottom_left + region_size; + BLI_rcti_init(&info.clipping_bounds, bottom_left.x, top_right.x, bottom_left.y, top_right.y); } } }; @@ -498,7 +515,7 @@ template class ScreenSpaceDrawingMode : public AbstractD tile_buffer.y * (texture_info.clipping_uv_bounds.ymin - image_tile.get_tile_y_offset()), tile_buffer.y * (texture_info.clipping_uv_bounds.ymax - image_tile.get_tile_y_offset())); BLI_rctf_transform_calc_m4_pivot_min(&tile_area, &texture_area, uv_to_texel.ptr()); - invert_m4(uv_to_texel.ptr()); + uv_to_texel = math::invert(uv_to_texel); rctf crop_rect; rctf *crop_rect_ptr = nullptr; diff --git a/source/blender/draw/engines/image/image_texture_info.hh b/source/blender/draw/engines/image/image_texture_info.hh index ead037196d6..1e0eb2162fb 100644 --- a/source/blender/draw/engines/image/image_texture_info.hh +++ b/source/blender/draw/engines/image/image_texture_info.hh @@ -24,15 +24,19 @@ struct TextureInfo { bool need_full_update : 1; /** \brief area of the texture in screen space. */ - rctf clipping_bounds; + rcti clipping_bounds; /** \brief uv area of the texture in screen space. */ rctf clipping_uv_bounds; + /* Which tile of the screen is used with this texture. Used to safely calculate the correct + * offset of the textures. */ + int2 tile_id; + /** * \brief Batch to draw the associated text on the screen. * * Contains a VBO with `pos` and `uv`. - * `pos` (2xF32) is relative to the origin of the space. + * `pos` (2xI32) is relative to the origin of the space. * `uv` (2xF32) reflect the uv bounds. */ GPUBatch *batch = nullptr; @@ -68,22 +72,6 @@ struct TextureInfo { return int2(clipping_bounds.xmin, clipping_bounds.ymin); } - /** - * \brief Update the region bounds from the uv bounds by applying the given transform matrix. - */ - void update_region_bounds_from_uv_bounds(const float4x4 &uv_to_region) - { - float3 bottom_left_uv = float3(clipping_uv_bounds.xmin, clipping_uv_bounds.ymin, 0.0f); - float3 top_right_uv = float3(clipping_uv_bounds.xmax, clipping_uv_bounds.ymax, 0.0f); - float3 bottom_left_region = math::transform_point(uv_to_region, bottom_left_uv); - float3 top_right_region = math::transform_point(uv_to_region, top_right_uv); - BLI_rctf_init(&clipping_bounds, - bottom_left_region.x, - top_right_region.x, - bottom_left_region.y, - top_right_region.y); - } - void ensure_gpu_texture(int2 texture_size) { const bool is_allocated = texture != nullptr; diff --git a/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl index fb72a132613..d27a7fdd8df 100644 --- a/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl +++ b/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl @@ -5,7 +5,6 @@ void main() vec3 image_pos = vec3(pos, 0.0); uv_screen = image_pos.xy; - vec3 world_pos = point_object_to_world(image_pos); - vec4 position = point_world_to_ndc(world_pos); + vec4 position = point_world_to_ndc(image_pos); gl_Position = position; } diff --git a/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl index 3181a85ff55..ffd0653820f 100644 --- a/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl +++ b/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl @@ -5,7 +5,6 @@ void main() vec3 image_pos = vec3(pos, 0.0); uv_image = uv; - vec3 world_pos = point_object_to_world(image_pos); - vec4 position = point_world_to_ndc(world_pos); + vec4 position = point_world_to_ndc(image_pos); gl_Position = position; } diff --git a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh index 3e6673b79a2..6495ee03326 100644 --- a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh +++ b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh @@ -5,7 +5,7 @@ GPU_SHADER_INTERFACE_INFO(image_engine_color_iface, "").smooth(Type::VEC2, "uv_screen"); GPU_SHADER_CREATE_INFO(image_engine_color_shader) - .vertex_in(0, Type::VEC2, "pos") + .vertex_in(0, Type::IVEC2, "pos") .vertex_out(image_engine_color_iface) .fragment_out(0, Type::VEC4, "fragColor") .push_constant(Type::VEC4, "shuffle") @@ -23,7 +23,7 @@ GPU_SHADER_CREATE_INFO(image_engine_color_shader) GPU_SHADER_INTERFACE_INFO(image_engine_depth_iface, "").smooth(Type::VEC2, "uv_image"); GPU_SHADER_CREATE_INFO(image_engine_depth_shader) - .vertex_in(0, Type::VEC2, "pos") + .vertex_in(0, Type::IVEC2, "pos") .vertex_in(1, Type::VEC2, "uv") .vertex_out(image_engine_depth_iface) .push_constant(Type::VEC4, "min_max_uv") -- 2.30.2 From f6a1475f8b0292261f66d3e90f49d541e6cd4a59 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 27 Mar 2023 13:54:42 +0200 Subject: [PATCH 2/9] Increase the division of texture tiles to improve performance. --- .../draw/engines/image/image_drawing_mode.hh | 16 +++++++++++++--- .../blender/draw/engines/image/image_engine.cc | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index f3138417bfc..9f0213414dd 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -83,10 +83,19 @@ template class ScreenTileTextures { update_region_bounds_from_uv_bounds(region_uv_bounds, int2(region->winx, region->winy)); } - void ensure_gpu_textures_allocation() + /** + * Get the texture size of a single texture for the current settings. + */ + int2 gpu_texture_size() const { float2 viewport_size = DRW_viewport_size_get(); int2 texture_size(ceil(viewport_size.x / Divisions), ceil(viewport_size.y / Divisions)); + return texture_size; + } + + void ensure_gpu_textures_allocation() + { + int2 texture_size = gpu_texture_size(); for (TextureInfo &info : instance_data->texture_infos) { info.ensure_gpu_texture(texture_size); } @@ -172,9 +181,10 @@ template class ScreenTileTextures { } } + const int2 texture_size = gpu_texture_size(); for (TextureInfo &info : instance_data->texture_infos) { - int2 bottom_left = tile_origin + region_size * info.tile_id; - int2 top_right = bottom_left + region_size; + int2 bottom_left = tile_origin + texture_size * info.tile_id; + int2 top_right = bottom_left + texture_size; BLI_rcti_init(&info.clipping_bounds, bottom_left.x, top_right.x, bottom_left.y, top_right.y); } } diff --git a/source/blender/draw/engines/image/image_engine.cc b/source/blender/draw/engines/image/image_engine.cc index a836ee928cd..53e35e022ef 100644 --- a/source/blender/draw/engines/image/image_engine.cc +++ b/source/blender/draw/engines/image/image_engine.cc @@ -53,7 +53,7 @@ template< * * Useful during development to switch between drawing implementations. */ - typename DrawingMode = ScreenSpaceDrawingMode>> + typename DrawingMode = ScreenSpaceDrawingMode>> class ImageEngine { private: const DRWContextState *draw_ctx; -- 2.30.2 From cfdbf82cb7aa5786913e5818d8f5de3105cb3f44 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 28 Mar 2023 10:36:18 +0200 Subject: [PATCH 3/9] WIP: Use cached GPU texture as source. --- source/blender/draw/CMakeLists.txt | 2 + .../draw/engines/image/image_drawing_mode.hh | 62 ++++++++++++++++++- .../draw/engines/image/image_engine.cc | 3 +- .../draw/engines/image/image_private.hh | 1 + .../draw/engines/image/image_shader.cc | 10 +++ .../image_engine_color_depth_frag.glsl | 39 ++++++++++++ .../image_engine_color_depth_vert.glsl | 10 +++ .../image/shaders/infos/engine_image_info.hh | 22 +++++++ 8 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl create mode 100644 source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 20ed013a6f7..4fc8ad427ab 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -732,6 +732,8 @@ set(GLSL_SRC engines/image/shaders/image_engine_color_vert.glsl engines/image/shaders/image_engine_depth_frag.glsl engines/image/shaders/image_engine_depth_vert.glsl + engines/image/shaders/image_engine_color_depth_frag.glsl + engines/image/shaders/image_engine_color_depth_vert.glsl ) set(GLSL_C) diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index 9f0213414dd..9d479aa12c9 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -585,7 +585,6 @@ template class ScreenSpaceDrawingMode : public AbstractD if (!instance_data->flags.do_tile_drawing) { add_depth_shgroups(*instance_data, image, iuser); } - add_shgroups(instance_data); } void draw_finish(IMAGE_Data *vedata) const override @@ -612,6 +611,65 @@ template class ScreenSpaceDrawingMode : public AbstractD DRW_view_set_active(nullptr); GPU_framebuffer_bind(dfbl->default_fb); } -}; // namespace clipping +}; + +/** + * Drawing mode that uses the GPU textures stored alongside the image for drawing. + * + * This is better for images with a dimension smaller than 8K as it will lead to smoother + * interaction. Bigger images are required to use #ScreenSpaceDrawingMode. + */ +class ImageBasedDrawingMode : public AbstractDrawingMode { + DRWPass *create_image_pass() const + { + /* Write depth is needed for background overlay rendering. Near depth is used for + * transparency checker and Far depth is used for indicating the image size. */ + DRWState state = static_cast(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL); + return DRW_pass_create("Image", state); + } + + public: + void begin_sync(IMAGE_Data *vedata) const override + { + IMAGE_InstanceData *instance_data = vedata->instance_data; + DRWState state = static_cast(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL); + instance_data->passes.image_pass = DRW_pass_create("Image", state); + instance_data->passes.depth_pass = nullptr; + } + + void image_sync(IMAGE_Data *vedata, Image *image, ImageUser *iuser) const override + { + IMAGE_InstanceData *instance_data = vedata->instance_data; + + const bool is_tiled_texture = image->source == IMA_SRC_TILED; + GPUTexture *texture = nullptr; + if (is_tiled_texture) { + } + else { + texture = BKE_image_get_gpu_texture(image, iuser, nullptr); + } + + if (texture == nullptr) { + return; + } + // Add full screen rect. + GPUShader *shader = IMAGE_shader_color_depth_get(); + DRWShadingGroup *grp = DRW_shgroup_create(shader, instance_data->passes.image_pass); + + DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); + } + + void draw_viewport(IMAGE_Data *vedata) const override + { + IMAGE_InstanceData *instance_data = vedata->instance_data; + DRW_draw_pass(instance_data->passes.image_pass); + } + + void draw_finish(IMAGE_Data * /*vedata*/) const override + { + } +}; } // namespace blender::draw::image_engine diff --git a/source/blender/draw/engines/image/image_engine.cc b/source/blender/draw/engines/image/image_engine.cc index 53e35e022ef..a03a50b2d39 100644 --- a/source/blender/draw/engines/image/image_engine.cc +++ b/source/blender/draw/engines/image/image_engine.cc @@ -53,7 +53,8 @@ template< * * Useful during development to switch between drawing implementations. */ - typename DrawingMode = ScreenSpaceDrawingMode>> + typename DrawingMode = ImageBasedDrawingMode> + /*ScreenSpaceDrawingMode>*/ class ImageEngine { private: const DRWContextState *draw_ctx; diff --git a/source/blender/draw/engines/image/image_private.hh b/source/blender/draw/engines/image/image_private.hh index 4780eea5bf5..a63ff0d308b 100644 --- a/source/blender/draw/engines/image/image_private.hh +++ b/source/blender/draw/engines/image/image_private.hh @@ -51,6 +51,7 @@ class AbstractDrawingMode { GPUShader *IMAGE_shader_image_get(); GPUShader *IMAGE_shader_depth_get(); +GPUShader *IMAGE_shader_color_depth_get(); void IMAGE_shader_free(); } // namespace blender::draw::image_engine diff --git a/source/blender/draw/engines/image/image_shader.cc b/source/blender/draw/engines/image/image_shader.cc index b1d1f0c2882..de6ef58cf69 100644 --- a/source/blender/draw/engines/image/image_shader.cc +++ b/source/blender/draw/engines/image/image_shader.cc @@ -19,6 +19,7 @@ namespace blender::draw::image_engine { struct IMAGE_Shaders { GPUShader *image_sh; GPUShader *depth_sh; + GPUShader *color_depth_sh; }; static struct { @@ -43,6 +44,15 @@ GPUShader *IMAGE_shader_depth_get() return sh_data->depth_sh; } +GPUShader *IMAGE_shader_color_depth_get() +{ + IMAGE_Shaders *sh_data = &e_data.shaders; + if (sh_data->color_depth_sh == nullptr) { + sh_data->color_depth_sh = GPU_shader_create_from_info_name("image_engine_color_depth_shader"); + } + return sh_data->color_depth_sh; +} + void IMAGE_shader_free() { GPUShader **sh_data_as_array = (GPUShader **)&e_data.shaders; diff --git a/source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl b/source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl new file mode 100644 index 00000000000..0bc34c80558 --- /dev/null +++ b/source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl @@ -0,0 +1,39 @@ +#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl) + +/* Keep in sync with image_engine.c */ +#define IMAGE_DRAW_FLAG_SHOW_ALPHA (1 << 0) +#define IMAGE_DRAW_FLAG_APPLY_ALPHA (1 << 1) +#define IMAGE_DRAW_FLAG_SHUFFLING (1 << 2) +#define IMAGE_DRAW_FLAG_DEPTH (1 << 3) + +#define FAR_DISTANCE farNearDistances.x +#define NEAR_DISTANCE farNearDistances.y + +void main() +{ + ivec2 uvs_clamped = ivec2(uv_screen); + float depth = texelFetch(depth_texture, uvs_clamped, 0).r; + if (depth == 1.0) { + discard; + return; + } + + vec4 tex_color = texelFetch(imageTexture, uvs_clamped - offset, 0); + + if ((drawFlags & IMAGE_DRAW_FLAG_APPLY_ALPHA) != 0) { + if (!imgPremultiplied) { + tex_color.rgb *= tex_color.a; + } + } + if ((drawFlags & IMAGE_DRAW_FLAG_DEPTH) != 0) { + tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color); + } + + if ((drawFlags & IMAGE_DRAW_FLAG_SHUFFLING) != 0) { + tex_color = vec4(dot(tex_color, shuffle)); + } + if ((drawFlags & IMAGE_DRAW_FLAG_SHOW_ALPHA) == 0) { + tex_color.a = 1.0; + } + fragColor = tex_color; +} diff --git a/source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl new file mode 100644 index 00000000000..d27a7fdd8df --- /dev/null +++ b/source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl @@ -0,0 +1,10 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +void main() +{ + vec3 image_pos = vec3(pos, 0.0); + uv_screen = image_pos.xy; + + vec4 position = point_world_to_ndc(image_pos); + gl_Position = position; +} diff --git a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh index 6495ee03326..8b9a10ab88a 100644 --- a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh +++ b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh @@ -32,3 +32,25 @@ GPU_SHADER_CREATE_INFO(image_engine_depth_shader) .additional_info("draw_modelmat") .depth_write(DepthWrite::ANY) .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(image_engine_color_depth_base) + .vertex_in(0, Type::IVEC2, "pos") + .vertex_in(1, Type::VEC2, "uv") + .vertex_out(image_engine_color_iface) + .fragment_out(0, Type::VEC4, "fragColor") + .push_constant(Type::VEC4, "min_max_uv") + .push_constant(Type::VEC4, "shuffle") + .push_constant(Type::VEC2, "farNearDistances") + .push_constant(Type::IVEC2, "offset") + .push_constant(Type::INT, "drawFlags") + .push_constant(Type::BOOL, "imgPremultiplied") + .sampler(0, ImageType::FLOAT_2D, "imageTexture") + .vertex_source("image_engine_color_depth_vert.glsl") + .fragment_source("image_engine_color_depth_frag.glsl") + .additional_info("draw_modelmat"); + +GPU_SHADER_CREATE_INFO(image_engine_color_depth_shader) + .additional_info("image_engine_color_depth_base") + .sampler(0, ImageType::FLOAT_2D, "image_texture") + .do_static_compilation(true); +; -- 2.30.2 From d08f34fd82ceffe9dc6b84805efd8b972fc69dc7 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 3 Apr 2023 08:04:13 +0200 Subject: [PATCH 4/9] Remove new developments. --- source/blender/draw/CMakeLists.txt | 2 - .../draw/engines/image/image_drawing_mode.hh | 59 ------------------- .../draw/engines/image/image_engine.cc | 3 +- .../draw/engines/image/image_shader.cc | 10 ---- .../image_engine_color_depth_frag.glsl | 39 ------------ .../image_engine_color_depth_vert.glsl | 10 ---- .../shaders/image_engine_color_vert.glsl | 2 +- .../shaders/image_engine_depth_vert.glsl | 2 +- .../image/shaders/infos/engine_image_info.hh | 22 ------- 9 files changed, 3 insertions(+), 146 deletions(-) delete mode 100644 source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl delete mode 100644 source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index ef88bf1ca07..3309364c074 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -732,8 +732,6 @@ set(GLSL_SRC engines/image/shaders/image_engine_color_vert.glsl engines/image/shaders/image_engine_depth_frag.glsl engines/image/shaders/image_engine_depth_vert.glsl - engines/image/shaders/image_engine_color_depth_frag.glsl - engines/image/shaders/image_engine_color_depth_vert.glsl ) set(GLSL_C) diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index 8ff39ee8ddc..3b98c02adc7 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -611,63 +611,4 @@ template class ScreenSpaceDrawingMode : public AbstractD } }; -/** - * Drawing mode that uses the GPU textures stored alongside the image for drawing. - * - * This is better for images with a dimension smaller than 8K as it will lead to smoother - * interaction. Bigger images are required to use #ScreenSpaceDrawingMode. - */ -class ImageBasedDrawingMode : public AbstractDrawingMode { - DRWPass *create_image_pass() const - { - /* Write depth is needed for background overlay rendering. Near depth is used for - * transparency checker and Far depth is used for indicating the image size. */ - DRWState state = static_cast(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL); - return DRW_pass_create("Image", state); - } - - public: - void begin_sync(IMAGE_Data *vedata) const override - { - IMAGE_InstanceData *instance_data = vedata->instance_data; - DRWState state = static_cast(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL); - instance_data->passes.image_pass = DRW_pass_create("Image", state); - instance_data->passes.depth_pass = nullptr; - } - - void image_sync(IMAGE_Data *vedata, Image *image, ImageUser *iuser) const override - { - IMAGE_InstanceData *instance_data = vedata->instance_data; - - const bool is_tiled_texture = image->source == IMA_SRC_TILED; - GPUTexture *texture = nullptr; - if (is_tiled_texture) { - } - else { - texture = BKE_image_get_gpu_texture(image, iuser, nullptr); - } - - if (texture == nullptr) { - return; - } - // Add full screen rect. - GPUShader *shader = IMAGE_shader_color_depth_get(); - DRWShadingGroup *grp = DRW_shgroup_create(shader, instance_data->passes.image_pass); - - DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); - } - - void draw_viewport(IMAGE_Data *vedata) const override - { - IMAGE_InstanceData *instance_data = vedata->instance_data; - DRW_draw_pass(instance_data->passes.image_pass); - } - - void draw_finish(IMAGE_Data * /*vedata*/) const override - { - } -}; - } // namespace blender::draw::image_engine diff --git a/source/blender/draw/engines/image/image_engine.cc b/source/blender/draw/engines/image/image_engine.cc index a03a50b2d39..c93b66b4dbc 100644 --- a/source/blender/draw/engines/image/image_engine.cc +++ b/source/blender/draw/engines/image/image_engine.cc @@ -53,8 +53,7 @@ template< * * Useful during development to switch between drawing implementations. */ - typename DrawingMode = ImageBasedDrawingMode> - /*ScreenSpaceDrawingMode>*/ + typename DrawingMode = ScreenSpaceDrawingMode>> class ImageEngine { private: const DRWContextState *draw_ctx; diff --git a/source/blender/draw/engines/image/image_shader.cc b/source/blender/draw/engines/image/image_shader.cc index de6ef58cf69..b1d1f0c2882 100644 --- a/source/blender/draw/engines/image/image_shader.cc +++ b/source/blender/draw/engines/image/image_shader.cc @@ -19,7 +19,6 @@ namespace blender::draw::image_engine { struct IMAGE_Shaders { GPUShader *image_sh; GPUShader *depth_sh; - GPUShader *color_depth_sh; }; static struct { @@ -44,15 +43,6 @@ GPUShader *IMAGE_shader_depth_get() return sh_data->depth_sh; } -GPUShader *IMAGE_shader_color_depth_get() -{ - IMAGE_Shaders *sh_data = &e_data.shaders; - if (sh_data->color_depth_sh == nullptr) { - sh_data->color_depth_sh = GPU_shader_create_from_info_name("image_engine_color_depth_shader"); - } - return sh_data->color_depth_sh; -} - void IMAGE_shader_free() { GPUShader **sh_data_as_array = (GPUShader **)&e_data.shaders; diff --git a/source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl b/source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl deleted file mode 100644 index 0bc34c80558..00000000000 --- a/source/blender/draw/engines/image/shaders/image_engine_color_depth_frag.glsl +++ /dev/null @@ -1,39 +0,0 @@ -#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl) - -/* Keep in sync with image_engine.c */ -#define IMAGE_DRAW_FLAG_SHOW_ALPHA (1 << 0) -#define IMAGE_DRAW_FLAG_APPLY_ALPHA (1 << 1) -#define IMAGE_DRAW_FLAG_SHUFFLING (1 << 2) -#define IMAGE_DRAW_FLAG_DEPTH (1 << 3) - -#define FAR_DISTANCE farNearDistances.x -#define NEAR_DISTANCE farNearDistances.y - -void main() -{ - ivec2 uvs_clamped = ivec2(uv_screen); - float depth = texelFetch(depth_texture, uvs_clamped, 0).r; - if (depth == 1.0) { - discard; - return; - } - - vec4 tex_color = texelFetch(imageTexture, uvs_clamped - offset, 0); - - if ((drawFlags & IMAGE_DRAW_FLAG_APPLY_ALPHA) != 0) { - if (!imgPremultiplied) { - tex_color.rgb *= tex_color.a; - } - } - if ((drawFlags & IMAGE_DRAW_FLAG_DEPTH) != 0) { - tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color); - } - - if ((drawFlags & IMAGE_DRAW_FLAG_SHUFFLING) != 0) { - tex_color = vec4(dot(tex_color, shuffle)); - } - if ((drawFlags & IMAGE_DRAW_FLAG_SHOW_ALPHA) == 0) { - tex_color.a = 1.0; - } - fragColor = tex_color; -} diff --git a/source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl deleted file mode 100644 index d27a7fdd8df..00000000000 --- a/source/blender/draw/engines/image/shaders/image_engine_color_depth_vert.glsl +++ /dev/null @@ -1,10 +0,0 @@ -#pragma BLENDER_REQUIRE(common_view_lib.glsl) - -void main() -{ - vec3 image_pos = vec3(pos, 0.0); - uv_screen = image_pos.xy; - - vec4 position = point_world_to_ndc(image_pos); - gl_Position = position; -} diff --git a/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl index d27a7fdd8df..53b67032815 100644 --- a/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl +++ b/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl @@ -2,7 +2,7 @@ void main() { - vec3 image_pos = vec3(pos, 0.0); + vec3 image_pos = vec3(pos.x, pos.y, 0.0); uv_screen = image_pos.xy; vec4 position = point_world_to_ndc(image_pos); diff --git a/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl index ffd0653820f..c1516e09213 100644 --- a/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl +++ b/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl @@ -2,7 +2,7 @@ void main() { - vec3 image_pos = vec3(pos, 0.0); + vec3 image_pos = vec3(pos.x, pos.y, 0.0); uv_image = uv; vec4 position = point_world_to_ndc(image_pos); diff --git a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh index 8b9a10ab88a..6495ee03326 100644 --- a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh +++ b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh @@ -32,25 +32,3 @@ GPU_SHADER_CREATE_INFO(image_engine_depth_shader) .additional_info("draw_modelmat") .depth_write(DepthWrite::ANY) .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(image_engine_color_depth_base) - .vertex_in(0, Type::IVEC2, "pos") - .vertex_in(1, Type::VEC2, "uv") - .vertex_out(image_engine_color_iface) - .fragment_out(0, Type::VEC4, "fragColor") - .push_constant(Type::VEC4, "min_max_uv") - .push_constant(Type::VEC4, "shuffle") - .push_constant(Type::VEC2, "farNearDistances") - .push_constant(Type::IVEC2, "offset") - .push_constant(Type::INT, "drawFlags") - .push_constant(Type::BOOL, "imgPremultiplied") - .sampler(0, ImageType::FLOAT_2D, "imageTexture") - .vertex_source("image_engine_color_depth_vert.glsl") - .fragment_source("image_engine_color_depth_frag.glsl") - .additional_info("draw_modelmat"); - -GPU_SHADER_CREATE_INFO(image_engine_color_depth_shader) - .additional_info("image_engine_color_depth_base") - .sampler(0, ImageType::FLOAT_2D, "image_texture") - .do_static_compilation(true); -; -- 2.30.2 From c17715e45c22c5bd14f019e29d49bd985fec211d Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 3 Apr 2023 14:14:01 +0200 Subject: [PATCH 5/9] Fix drawing the image. --- source/blender/draw/engines/image/image_drawing_mode.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index 3b98c02adc7..de979463077 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -583,6 +583,7 @@ template class ScreenSpaceDrawingMode : public AbstractD if (!instance_data->flags.do_tile_drawing) { add_depth_shgroups(*instance_data, image, iuser); } + add_shgroups(instance_data); } void draw_finish(IMAGE_Data *vedata) const override -- 2.30.2 From 50fa3ae949cecac52210207e6070bbf8d7804238 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 4 Apr 2023 10:00:15 +0200 Subject: [PATCH 6/9] Increased the number of texture to 36. --- source/blender/draw/engines/image/image_engine.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/draw/engines/image/image_engine.cc b/source/blender/draw/engines/image/image_engine.cc index c93b66b4dbc..007a5ca4f14 100644 --- a/source/blender/draw/engines/image/image_engine.cc +++ b/source/blender/draw/engines/image/image_engine.cc @@ -53,7 +53,7 @@ template< * * Useful during development to switch between drawing implementations. */ - typename DrawingMode = ScreenSpaceDrawingMode>> + typename DrawingMode = ScreenSpaceDrawingMode>> class ImageEngine { private: const DRWContextState *draw_ctx; -- 2.30.2 From d1b45e619ffc3ff26b863303a884c6397dfcc833 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 11 Apr 2023 13:42:58 +0200 Subject: [PATCH 7/9] Revert changes to image engine to Blender 3.4. - Uses the 3.5 architecture so we can evolve on this as well. --- .../draw/engines/image/image_drawing_mode.hh | 79 +++++++++++++++++-- .../draw/engines/image/image_engine.cc | 2 +- 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index b875de29630..66c43fe5979 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -21,11 +21,78 @@ namespace blender::draw::image_engine { constexpr float EPSILON_UV_BOUNDS = 0.00001f; +class BaseTextureMethod { + protected: + IMAGE_InstanceData *instance_data; + + protected: + BaseTextureMethod(IMAGE_InstanceData *instance_data) : instance_data(instance_data) {} + + public: + /** + * \brief Ensure enough texture infos are allocated in `instance_data`. + */ + virtual void ensure_texture_infos() = 0; + + /** + * \brief Update the uv and region bounds of all texture_infos of instance_data. + */ + virtual void update_bounds(const ARegion *region) = 0; + + virtual void ensure_gpu_textures_allocation() = 0; +}; + +class OneTexture : public BaseTextureMethod { + public: + OneTexture(IMAGE_InstanceData *instance_data) : BaseTextureMethod(instance_data) {} + void ensure_texture_infos() override + { + instance_data->texture_infos.resize(1); + } + + void update_bounds(const ARegion *region) override + { + float4x4 mat = math::invert(float4x4(instance_data->ss_to_texture)); + float2 region_uv_min = math::transform_point(mat, float3(0.0f, 0.0f, 0.0f)).xy(); + float2 region_uv_max = math::transform_point(mat, float3(1.0f, 1.0f, 0.0f)).xy(); + + TextureInfo &texture_info = instance_data->texture_infos[0]; + texture_info.tile_id = int2(0); + texture_info.need_full_update = false; + rctf new_clipping_uv_bounds; + BLI_rctf_init(&new_clipping_uv_bounds, + region_uv_min.x, + region_uv_max.x, + region_uv_min.y, + region_uv_max.y); + + if (memcmp(&new_clipping_uv_bounds, &texture_info.clipping_uv_bounds, sizeof(rctf))) { + texture_info.clipping_uv_bounds = new_clipping_uv_bounds; + texture_info.need_full_update = true; + } + + rcti new_clipping_bounds; + BLI_rcti_init(&new_clipping_bounds, 0, region->winx, 0, region->winy); + if (memcmp(&new_clipping_bounds, &texture_info.clipping_bounds, sizeof(rcti))) { + texture_info.clipping_bounds = new_clipping_bounds; + texture_info.need_full_update = true; + } + } + + void ensure_gpu_textures_allocation() override + { + TextureInfo &texture_info = instance_data->texture_infos[0]; + int2 texture_size = int2(BLI_rcti_size_x(&texture_info.clipping_bounds), + BLI_rcti_size_y(&texture_info.clipping_bounds)); + texture_info.ensure_gpu_texture(texture_size); + } +}; + /** * \brief Screen space method using a multiple textures covering the region. * */ -template class ScreenTileTextures { +template class ScreenTileTextures : public BaseTextureMethod { public: static const size_t TexturesPerDimension = Divisions + 1; static const size_t TexturesRequired = TexturesPerDimension * TexturesPerDimension; @@ -42,15 +109,13 @@ template class ScreenTileTextures { int2 tile_id; }; - IMAGE_InstanceData *instance_data; - public: - ScreenTileTextures(IMAGE_InstanceData *instance_data) : instance_data(instance_data) {} + ScreenTileTextures(IMAGE_InstanceData *instance_data) : BaseTextureMethod(instance_data) {} /** * \brief Ensure enough texture infos are allocated in `instance_data`. */ - void ensure_texture_infos() + void ensure_texture_infos() override { instance_data->texture_infos.resize(TexturesRequired); } @@ -58,7 +123,7 @@ template class ScreenTileTextures { /** * \brief Update the uv and region bounds of all texture_infos of instance_data. */ - void update_bounds(const ARegion *region) + void update_bounds(const ARegion *region) override { /* determine uv_area of the region. */ Vector unassigned_textures; @@ -91,7 +156,7 @@ template class ScreenTileTextures { return texture_size; } - void ensure_gpu_textures_allocation() + void ensure_gpu_textures_allocation() override { int2 texture_size = gpu_texture_size(); for (TextureInfo &info : instance_data->texture_infos) { diff --git a/source/blender/draw/engines/image/image_engine.cc b/source/blender/draw/engines/image/image_engine.cc index 007a5ca4f14..1584a2f0a8f 100644 --- a/source/blender/draw/engines/image/image_engine.cc +++ b/source/blender/draw/engines/image/image_engine.cc @@ -53,7 +53,7 @@ template< * * Useful during development to switch between drawing implementations. */ - typename DrawingMode = ScreenSpaceDrawingMode>> + typename DrawingMode = ScreenSpaceDrawingMode> class ImageEngine { private: const DRWContextState *draw_ctx; -- 2.30.2 From 580c20809b662a55484dfced8e5c83624aa43606 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 11 Apr 2023 14:01:40 +0200 Subject: [PATCH 8/9] Remove unneeded changes. --- source/blender/draw/engines/image/image_private.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/draw/engines/image/image_private.hh b/source/blender/draw/engines/image/image_private.hh index a63ff0d308b..4780eea5bf5 100644 --- a/source/blender/draw/engines/image/image_private.hh +++ b/source/blender/draw/engines/image/image_private.hh @@ -51,7 +51,6 @@ class AbstractDrawingMode { GPUShader *IMAGE_shader_image_get(); GPUShader *IMAGE_shader_depth_get(); -GPUShader *IMAGE_shader_color_depth_get(); void IMAGE_shader_free(); } // namespace blender::draw::image_engine -- 2.30.2 From 9ce5e2f6b2f05650dd4545a85a89627bd2017ba1 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 11 Apr 2023 14:05:09 +0200 Subject: [PATCH 9/9] Added documentation to the class headers. --- source/blender/draw/engines/image/image_drawing_mode.hh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index 66c43fe5979..e1499cf2711 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -42,6 +42,10 @@ class BaseTextureMethod { virtual void ensure_gpu_textures_allocation() = 0; }; +/** + * Uses a single texture that covers the area. Every zoom/pan change requires a full + * update of the texture. + */ class OneTexture : public BaseTextureMethod { public: OneTexture(IMAGE_InstanceData *instance_data) : BaseTextureMethod(instance_data) {} @@ -91,6 +95,8 @@ class OneTexture : public BaseTextureMethod { /** * \brief Screen space method using a multiple textures covering the region. * + * This method improves panning speed, but has some drawing artifacts and + * therefore isn't selected. */ template class ScreenTileTextures : public BaseTextureMethod { public: -- 2.30.2