[Bf-blender-cvs] [387dbd65ac1] temp-gpu-image-engine: Merge branch 'master' into temp-gpu-image-engine

Jeroen Bakker noreply at git.blender.org
Fri Dec 3 16:07:31 CET 2021


Commit: 387dbd65ac12b98a23c013993a0bc37c0c8cd6a6
Author: Jeroen Bakker
Date:   Fri Dec 3 14:00:34 2021 +0100
Branches: temp-gpu-image-engine
https://developer.blender.org/rB387dbd65ac12b98a23c013993a0bc37c0c8cd6a6

Merge branch 'master' into temp-gpu-image-engine

===================================================================



===================================================================

diff --cc source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
index 26f5bb895e7,00000000000..3f1daf066ca
mode 100644,000000..100644
--- a/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
+++ b/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
@@@ -1,546 -1,0 +1,546 @@@
 +/*
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + * Copyright 2021, Blender Foundation.
 + */
 +
 +/** \file
 + * \ingroup draw_engine
 + */
 +
 +#pragma once
 +
 +#include "image_private.hh"
 +
 +#include "BKE_image_partial_update.hh"
 +
 +namespace blender::draw::image_engine {
 +
 +constexpr float EPSILON_UV_BOUNDS = 0.00001f;
 +
 +/**
 + * \brief Accessor to texture slots.
 + *
 + * Texture slots info is stored in IMAGE_PrivateData. The GPUTextures are stored in
 + * IMAGE_TextureList. This class simplifies accessing texture slots by providing
 + */
 +struct PrivateDataAccessor {
 +  IMAGE_PrivateData *pd;
 +  IMAGE_TextureList *txl;
 +  PrivateDataAccessor(IMAGE_PrivateData *pd, IMAGE_TextureList *txl) : pd(pd), txl(txl)
 +  {
 +  }
 +
 +  /** \brief Clear dirty flag from all texture slots. */
 +  void clear_dirty_flag()
 +  {
 +    for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
 +      pd->screen_space.texture_infos[i].dirty = false;
 +    }
 +  }
 +
 +  /** \brief Update the texture slot uv and screen space bounds. */
 +  void update_screen_space_bounds(const ARegion *region)
 +  {
 +    /* Create a single texture that covers the visible screen space. */
 +    BLI_rctf_init(
 +        &pd->screen_space.texture_infos[0].clipping_bounds, 0, region->winx, 0, region->winy);
 +    pd->screen_space.texture_infos[0].visible = true;
 +
 +    /* Mark the other textures as invalid. */
 +    for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
 +      BLI_rctf_init_minmax(&pd->screen_space.texture_infos[i].clipping_bounds);
 +      pd->screen_space.texture_infos[i].visible = false;
 +    }
 +  }
 +
 +  void update_uv_bounds()
 +  {
 +    /* Calculate the uv coordinates of the screen space visible corners. */
 +    float inverse_mat[4][4];
 +    DRW_view_viewmat_get(NULL, inverse_mat, true);
 +
 +    rctf new_uv_bounds;
 +    float uv_min[3];
 +    static const float screen_space_co1[3] = {0.0, 0.0, 0.0};
 +    mul_v3_m4v3(uv_min, inverse_mat, screen_space_co1);
 +
 +    static const float screen_space_co2[3] = {1.0, 1.0, 0.0};
 +    float uv_max[3];
 +    mul_v3_m4v3(uv_max, inverse_mat, screen_space_co2);
 +    BLI_rctf_init(&new_uv_bounds, uv_min[0], uv_max[0], uv_min[1], uv_max[1]);
 +
 +    if (!BLI_rctf_compare(
 +            &pd->screen_space.texture_infos[0].uv_bounds, &new_uv_bounds, EPSILON_UV_BOUNDS)) {
 +      pd->screen_space.texture_infos[0].uv_bounds = new_uv_bounds;
 +      pd->screen_space.texture_infos[0].dirty = true;
 +      update_uv_to_texture_matrix(&pd->screen_space.texture_infos[0]);
 +    }
 +
 +    /* Mark the other textures as invalid. */
 +    for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
 +      BLI_rctf_init_minmax(&pd->screen_space.texture_infos[i].clipping_bounds);
 +    }
 +  }
 +
 +  void update_uv_to_texture_matrix(IMAGE_ScreenSpaceTextureInfo *info)
 +  {
 +    // TODO: I remember that there was a function for this somewhere.
 +    unit_m4(info->uv_to_texture);
 +    float scale_x = 1.0 / BLI_rctf_size_x(&info->uv_bounds);
 +    float scale_y = 1.0 / BLI_rctf_size_y(&info->uv_bounds);
 +    float translate_x = scale_x * -info->uv_bounds.xmin;
 +    float translate_y = scale_y * -info->uv_bounds.ymin;
 +
 +    info->uv_to_texture[0][0] = scale_x;
 +    info->uv_to_texture[1][1] = scale_y;
 +    info->uv_to_texture[3][0] = translate_x;
 +    info->uv_to_texture[3][1] = translate_y;
 +  }
 +};
 +
 +struct ImageTileAccessor {
 +  ImageTile *image_tile;
 +  ImageTileAccessor(ImageTile *image_tile) : image_tile(image_tile)
 +  {
 +  }
 +
 +  int get_tile_number() const
 +  {
 +    return image_tile->tile_number;
 +  }
 +
 +  int get_tile_x_offset() const
 +  {
 +    int tile_number = get_tile_number();
 +    return (tile_number - 1001) % 10;
 +  }
 +
 +  int get_tile_y_offset() const
 +  {
 +    int tile_number = get_tile_number();
 +    return (tile_number - 1001) / 10;
 +  }
 +};
 +
 +using namespace blender::bke::image::partial_update;
 +
 +class ScreenSpaceDrawingMode : public AbstractDrawingMode {
 + private:
 +  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<DRWState>(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
 +                                           DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL);
 +    return DRW_pass_create("Image", state);
 +  }
 +
 +  void add_shgroups(IMAGE_PassList *psl,
 +                    IMAGE_TextureList *txl,
 +                    IMAGE_PrivateData *pd,
 +                    const ShaderParameters &sh_params) const
 +  {
 +    GPUBatch *geom = DRW_cache_quad_get();
 +    GPUShader *shader = IMAGE_shader_image_get(false);
 +
 +    DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass);
 +    DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", sh_params.far_near);
 +    DRW_shgroup_uniform_vec4_copy(shgrp, "color", ShaderParameters::color);
 +    DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", sh_params.shuffle);
 +    DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", sh_params.flags);
 +    DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", sh_params.use_premul_alpha);
 +    float image_mat[4][4];
 +    unit_m4(image_mat);
 +    for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
 +      if (!pd->screen_space.texture_infos[i].visible) {
 +        continue;
 +      }
 +
 +      image_mat[0][0] = pd->screen_space.texture_infos[i].clipping_bounds.xmax;
 +      image_mat[1][1] = pd->screen_space.texture_infos[i].clipping_bounds.ymax;
 +
 +      DRWShadingGroup *shgrp_sub = DRW_shgroup_create_sub(shgrp);
 +      DRW_shgroup_uniform_texture_ex(
 +          shgrp_sub, "imageTexture", txl->screen_space.textures[i], GPU_SAMPLER_DEFAULT);
 +      DRW_shgroup_call_obmat(shgrp_sub, geom, image_mat);
 +    }
 +  }
 +
 +  /**
 +   * \brief check if the partial update user in the private data can still be used.
 +   *
 +   * When switching to a different image the partial update user should be recreated.
 +   */
 +  bool partial_update_is_valid(const IMAGE_PrivateData *pd, const Image *image) const
 +  {
 +    if (pd->screen_space.partial_update_image != image) {
 +      return false;
 +    }
 +
 +    return pd->screen_space.partial_update_user != nullptr;
 +  }
 +
 +  void partial_update_allocate(IMAGE_PrivateData *pd, const Image *image) const
 +  {
 +    BLI_assert(pd->screen_space.partial_update_user == nullptr);
 +    pd->screen_space.partial_update_user = BKE_image_partial_update_create(image);
 +    pd->screen_space.partial_update_image = image;
 +  }
 +
 +  void partial_update_free(IMAGE_PrivateData *pd) const
 +  {
 +    if (pd->screen_space.partial_update_user != nullptr) {
 +      BKE_image_partial_update_free(pd->screen_space.partial_update_user);
 +      pd->screen_space.partial_update_user = nullptr;
 +    }
 +  }
 +
 +  void update_texture_slot_allocation(IMAGE_TextureList *txl, IMAGE_PrivateData *pd) const
 +  {
 +    for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
 +      const bool is_allocated = txl->screen_space.textures[i] != nullptr;
 +      const bool is_visible = pd->screen_space.texture_infos[i].visible;
 +      const bool should_be_freed = !is_visible && is_allocated;
 +      const bool should_be_created = is_visible && !is_allocated;
 +
 +      if (should_be_freed) {
 +        GPU_texture_free(txl->screen_space.textures[i]);
 +        txl->screen_space.textures[i] = nullptr;
 +      }
 +
 +      if (should_be_created) {
 +        DRW_texture_ensure_fullscreen_2d(
 +            &txl->screen_space.textures[i], GPU_RGBA16F, static_cast<DRWTextureFlag>(0));
 +      }
 +      pd->screen_space.texture_infos[i].dirty |= should_be_created;
 +    }
 +  }
 +
 +  void mark_all_texture_slots_dirty(IMAGE_PrivateData *pd) const
 +  {
 +    for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
 +      pd->screen_space.texture_infos[i].dirty = true;
 +    }
 +  }
 +
 +  /**
 +   * \brief Update GPUTextures for drawing the image.
 +   *
 +   * GPUTextures that are marked dirty are rebuild. GPUTextures that aren't marked dirty are
 +   * updated with changed region of the image.
 +   */
 +  void update_textures(IMAGE_TextureList *txl,
 +                       IMAGE_PrivateData *pd,
 +                       Image *image,
 +                       ImageUser *image_user) const
 +  {
 +    PartialUpdateChecker<ImageTileData> checker(
 +        image, image_user, pd->screen_space.partial_update_user);
 +    PartialUpdateChecker<ImageTileData>::CollectResult changes = checker.collect_changes();
 +
 +    switch (changes.get_result_code()) {
 +      case ePartialUpdateCollectResult::FullUpdateNeeded:
 +        mark_all_texture_slots_dirty(pd);
 +        break;
 +      case ePartialUpdateCollectResult::NoChangesDetected:
 +        break;
 +      case ePartialUpdateCollectResult::PartialChangesDetected:
 +        do_partial_update(changes, txl, pd, image);
 +        break;
 +    }
 +    do_full_update_for_dirty_textures(txl, pd, image_user);
 +  }
 +
 +  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list