2011-02-23 10:52:22 +00:00
|
|
|
/*
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
* 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
|
2011-11-29 10:54:47 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
*
|
|
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
*
|
2020-07-29 18:13:19 +02:00
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
* All rights reserved.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
2020-07-29 18:13:19 +02:00
|
|
|
* \ingroup bke
|
2011-02-27 20:25:53 +00:00
|
|
|
*/
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
#include "MEM_guardedalloc.h"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2020-12-18 09:15:55 +01:00
|
|
|
#include "BLI_bitmap.h"
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
#include "BLI_boxpack_2d.h"
|
2013-06-15 14:01:16 +00:00
|
|
|
#include "BLI_linklist.h"
|
2020-07-29 18:13:19 +02:00
|
|
|
#include "BLI_listbase.h"
|
2013-06-15 14:01:16 +00:00
|
|
|
#include "BLI_threads.h"
|
Changes to Color Management
After testing and feedback, I've decided to slightly modify the way color
management works internally. While the previous method worked well for
rendering, was a smaller transition and had some advantages over this
new method, it was a bit more ambiguous, and was making things difficult
for other areas such as compositing.
This implementation now considers all color data (with only a couple of
exceptions such as brush colors) to be stored in linear RGB color space,
rather than sRGB as previously. This brings it in line with Nuke, which also
operates this way, quite successfully. Color swatches, pickers, color ramp
display are now gamma corrected to display gamma so you can see what
you're doing, but the numbers themselves are considered linear. This
makes understanding blending modes more clear (a 0.5 value on overlay
will not change the result now) as well as making color swatches act more
predictably in the compositor, however bringing over color values from
applications like photoshop or gimp, that operate in a gamma space,
will give identical results.
This commit will convert over existing files saved by earlier 2.5 versions to
work generally the same, though there may be some slight differences with
things like textures. Now that we're set on changing other areas of shading,
this won't be too disruptive overall.
I've made a diagram explaining the pipeline here:
http://mke3.net/blender/devel/2.5/25_linear_workflow_pipeline.png
and some docs here:
http://www.blender.org/development/release-logs/blender-250/color-management/
2009-12-02 07:56:34 +00:00
|
|
|
|
2019-12-17 11:11:15 +11:00
|
|
|
#include "DNA_image_types.h"
|
|
|
|
|
#include "DNA_userdef_types.h"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2019-04-23 13:56:30 +02:00
|
|
|
#include "IMB_colormanagement.h"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
|
|
|
|
|
#include "BKE_global.h"
|
|
|
|
|
#include "BKE_image.h"
|
|
|
|
|
#include "BKE_main.h"
|
|
|
|
|
|
2020-09-07 19:35:56 +02:00
|
|
|
#include "GPU_capabilities.h"
|
2020-07-29 18:13:19 +02:00
|
|
|
#include "GPU_state.h"
|
2015-12-06 21:20:19 +01:00
|
|
|
#include "GPU_texture.h"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2014-05-22 11:58:07 +10:00
|
|
|
#include "PIL_time.h"
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
/* Prototypes. */
|
2020-07-01 14:55:43 +02:00
|
|
|
static void gpu_free_unused_buffers(void);
|
2020-07-29 18:13:19 +02:00
|
|
|
static void image_free_gpu(Image *ima, const bool immediate);
|
2020-12-18 09:15:55 +01:00
|
|
|
static void image_update_gputexture_ex(
|
|
|
|
|
Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h);
|
|
|
|
|
|
|
|
|
|
/* Internal structs. */
|
|
|
|
|
#define IMA_PARTIAL_REFRESH_TILE_SIZE 256
|
|
|
|
|
typedef struct ImagePartialRefresh {
|
|
|
|
|
struct ImagePartialRefresh *next, *prev;
|
|
|
|
|
int tile_x;
|
|
|
|
|
int tile_y;
|
|
|
|
|
} ImagePartialRefresh;
|
2020-07-29 04:55:21 +02:00
|
|
|
|
2020-09-22 13:52:38 +02:00
|
|
|
/* Is the alpha of the `GPUTexture` for a given image/ibuf premultiplied. */
|
|
|
|
|
bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
|
|
|
|
|
{
|
2020-11-17 15:23:47 +01:00
|
|
|
if (image) {
|
|
|
|
|
/* Render result and compositor output are always premultiplied */
|
|
|
|
|
if (ELEM(image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
/* Generated images use pre multiplied float buffer, but straight alpha for byte buffers. */
|
|
|
|
|
if (image->type == IMA_TYPE_UV_TEST && ibuf) {
|
|
|
|
|
return ibuf->rect_float != NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-16 13:54:02 +01:00
|
|
|
if (ibuf) {
|
2020-11-17 15:23:47 +01:00
|
|
|
if (ibuf->rect_float) {
|
|
|
|
|
return image ? (image->alpha_mode != IMA_ALPHA_STRAIGHT) : false;
|
|
|
|
|
}
|
2020-11-17 12:58:26 -05:00
|
|
|
|
|
|
|
|
return image ? (image->alpha_mode == IMA_ALPHA_PREMUL) : true;
|
2020-11-17 15:23:47 +01:00
|
|
|
}
|
|
|
|
|
return false;
|
2020-09-22 13:52:38 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
2020-07-29 18:13:19 +02:00
|
|
|
/** \name UDIM gpu texture
|
2020-07-29 04:55:21 +02:00
|
|
|
* \{ */
|
2021-02-08 15:42:59 +01:00
|
|
|
static bool is_over_resolution_limit(int w, int h, bool limit_gl_texture_size)
|
2013-03-15 16:16:11 +00:00
|
|
|
{
|
2021-02-08 15:42:59 +01:00
|
|
|
return (w > GPU_texture_size_with_limit(w, limit_gl_texture_size) ||
|
|
|
|
|
h > GPU_texture_size_with_limit(h, limit_gl_texture_size));
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-08 15:42:59 +01:00
|
|
|
static int smaller_power_of_2_limit(int num, bool limit_gl_texture_size)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2021-02-08 15:42:59 +01:00
|
|
|
return power_of_2_min_i(GPU_texture_size_with_limit(num, limit_gl_texture_size));
|
World textures displaying for viewport in BI.
This patch supports "Image or Movie" and "Environment map" types of world texture for the viewport.
It supports:
- "View", "AngMap" and "Equirectangular" types of mapping.
- Different types of texture blending (according to BI world render).
- Same color blending as when it lacked textures (but render via glsl).
{F207734}
{F207735}
Example: {F275180}
Original author: @valentin_b4w
Regards,
Alexander (Blend4Web Team).
Reviewers: sergey, valentin_b4w, brecht, merwin
Reviewed By: merwin
Subscribers: campbellbarton, merwin, blueprintrandom, youle, a.romanov, yurikovelenov, AlexKowel, Evgeny_Rodygin
Projects: #rendering, #opengl_gfx, #bf_blender:_next
Differential Revision: https://developer.blender.org/D1414
2016-01-27 12:06:57 +03:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye)
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
{
|
2020-07-26 20:20:03 +02:00
|
|
|
GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye];
|
2020-03-12 17:21:58 +01:00
|
|
|
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
if (tilearray == NULL) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float array_w = GPU_texture_width(tilearray);
|
|
|
|
|
float array_h = GPU_texture_height(tilearray);
|
|
|
|
|
|
2020-07-25 18:36:48 +02:00
|
|
|
ImageTile *last_tile = (ImageTile *)ima->tiles.last;
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
/* Tiles are sorted by number. */
|
|
|
|
|
int max_tile = last_tile->tile_number - 1001;
|
|
|
|
|
|
|
|
|
|
/* create image */
|
|
|
|
|
int width = max_tile + 1;
|
2020-07-25 18:36:48 +02:00
|
|
|
float *data = (float *)MEM_callocN(width * 8 * sizeof(float), __func__);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
|
data[4 * i] = -1.0f;
|
|
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
|
|
|
|
|
int i = tile->tile_number - 1001;
|
|
|
|
|
data[4 * i] = tile->runtime.tilearray_layer;
|
|
|
|
|
|
|
|
|
|
float *tile_info = &data[4 * width + 4 * i];
|
|
|
|
|
tile_info[0] = tile->runtime.tilearray_offset[0] / array_w;
|
|
|
|
|
tile_info[1] = tile->runtime.tilearray_offset[1] / array_h;
|
|
|
|
|
tile_info[2] = tile->runtime.tilearray_size[0] / array_w;
|
|
|
|
|
tile_info[3] = tile->runtime.tilearray_size[1] / array_h;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 17:33:56 +02:00
|
|
|
GPUTexture *tex = GPU_texture_create_1d_array(ima->id.name + 2, width, 2, 1, GPU_RGBA32F, data);
|
2020-07-29 04:55:21 +02:00
|
|
|
GPU_texture_mipmap_mode(tex, false, false);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
MEM_freeN(data);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
return tex;
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct PackTile {
|
|
|
|
|
FixedSizeBoxPack boxpack;
|
|
|
|
|
ImageTile *tile;
|
|
|
|
|
float pack_score;
|
|
|
|
|
} PackTile;
|
|
|
|
|
|
|
|
|
|
static int compare_packtile(const void *a, const void *b)
|
|
|
|
|
{
|
2020-07-25 18:36:48 +02:00
|
|
|
const PackTile *tile_a = (const PackTile *)a;
|
|
|
|
|
const PackTile *tile_b = (const PackTile *)b;
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
|
|
|
|
return tile_a->pack_score < tile_b->pack_score;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
{
|
2021-02-08 15:42:59 +01:00
|
|
|
const bool limit_gl_texture_size = (ima->gpuflag & IMA_GPU_MAX_RESOLUTION) == 0;
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
int arraywidth = 0, arrayheight = 0;
|
|
|
|
|
ListBase boxes = {NULL};
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
|
|
|
|
|
ImageUser iuser;
|
|
|
|
|
BKE_imageuser_default(&iuser);
|
|
|
|
|
iuser.tile = tile->tile_number;
|
|
|
|
|
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
|
|
|
|
|
|
|
|
|
|
if (ibuf) {
|
2020-07-25 18:36:48 +02:00
|
|
|
PackTile *packtile = (PackTile *)MEM_callocN(sizeof(PackTile), __func__);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
packtile->tile = tile;
|
|
|
|
|
packtile->boxpack.w = ibuf->x;
|
|
|
|
|
packtile->boxpack.h = ibuf->y;
|
|
|
|
|
|
2021-02-08 15:42:59 +01:00
|
|
|
if (is_over_resolution_limit(
|
|
|
|
|
packtile->boxpack.w, packtile->boxpack.h, limit_gl_texture_size)) {
|
|
|
|
|
packtile->boxpack.w = smaller_power_of_2_limit(packtile->boxpack.w, limit_gl_texture_size);
|
|
|
|
|
packtile->boxpack.h = smaller_power_of_2_limit(packtile->boxpack.h, limit_gl_texture_size);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
arraywidth = max_ii(arraywidth, packtile->boxpack.w);
|
|
|
|
|
arrayheight = max_ii(arrayheight, packtile->boxpack.h);
|
|
|
|
|
|
|
|
|
|
/* We sort the tiles by decreasing size, with an additional penalty term
|
|
|
|
|
* for high aspect ratios. This improves packing efficiency. */
|
|
|
|
|
float w = packtile->boxpack.w, h = packtile->boxpack.h;
|
|
|
|
|
packtile->pack_score = max_ff(w, h) / min_ff(w, h) * w * h;
|
|
|
|
|
|
|
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
|
|
|
|
BLI_addtail(&boxes, packtile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert(arraywidth > 0 && arrayheight > 0);
|
|
|
|
|
|
|
|
|
|
BLI_listbase_sort(&boxes, compare_packtile);
|
|
|
|
|
int arraylayers = 0;
|
|
|
|
|
/* Keep adding layers until all tiles are packed. */
|
|
|
|
|
while (boxes.first != NULL) {
|
|
|
|
|
ListBase packed = {NULL};
|
|
|
|
|
BLI_box_pack_2d_fixedarea(&boxes, arraywidth, arrayheight, &packed);
|
|
|
|
|
BLI_assert(packed.first != NULL);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (PackTile *, packtile, &packed) {
|
|
|
|
|
ImageTile *tile = packtile->tile;
|
|
|
|
|
int *tileoffset = tile->runtime.tilearray_offset;
|
|
|
|
|
int *tilesize = tile->runtime.tilearray_size;
|
|
|
|
|
|
|
|
|
|
tileoffset[0] = packtile->boxpack.x;
|
|
|
|
|
tileoffset[1] = packtile->boxpack.y;
|
|
|
|
|
tilesize[0] = packtile->boxpack.w;
|
|
|
|
|
tilesize[1] = packtile->boxpack.h;
|
|
|
|
|
tile->runtime.tilearray_layer = arraylayers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_freelistN(&packed);
|
|
|
|
|
arraylayers++;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-29 17:10:35 +02:00
|
|
|
const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH);
|
2020-07-30 16:40:20 +02:00
|
|
|
/* Create Texture without content. */
|
|
|
|
|
GPUTexture *tex = IMB_touch_gpu_texture(
|
2020-09-05 17:33:56 +02:00
|
|
|
ima->id.name + 2, main_ibuf, arraywidth, arrayheight, arraylayers, use_high_bitdepth);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
/* Upload each tile one by one. */
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
|
|
|
|
|
int tilelayer = tile->runtime.tilearray_layer;
|
|
|
|
|
int *tileoffset = tile->runtime.tilearray_offset;
|
|
|
|
|
int *tilesize = tile->runtime.tilearray_size;
|
|
|
|
|
|
|
|
|
|
if (tilesize[0] == 0 || tilesize[1] == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImageUser iuser;
|
|
|
|
|
BKE_imageuser_default(&iuser);
|
|
|
|
|
iuser.tile = tile->tile_number;
|
|
|
|
|
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
|
|
|
|
|
|
2020-02-03 08:58:01 +01:00
|
|
|
if (ibuf) {
|
2020-09-22 13:52:38 +02:00
|
|
|
const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, ibuf);
|
2020-07-30 16:40:20 +02:00
|
|
|
IMB_update_gpu_texture_sub(tex,
|
|
|
|
|
ibuf,
|
|
|
|
|
UNPACK2(tileoffset),
|
|
|
|
|
tilelayer,
|
|
|
|
|
UNPACK2(tilesize),
|
|
|
|
|
use_high_bitdepth,
|
|
|
|
|
store_premultiplied);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
if (GPU_mipmap_enabled()) {
|
2020-07-29 04:55:21 +02:00
|
|
|
GPU_texture_generate_mipmap(tex);
|
2020-07-29 17:10:35 +02:00
|
|
|
GPU_texture_mipmap_mode(tex, true, true);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
if (ima) {
|
|
|
|
|
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-29 17:10:35 +02:00
|
|
|
else {
|
|
|
|
|
GPU_texture_mipmap_mode(tex, false, true);
|
|
|
|
|
}
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
return tex;
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Regular gpu texture
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
static GPUTexture **get_image_gpu_texture_ptr(Image *ima,
|
|
|
|
|
eGPUTextureTarget textarget,
|
|
|
|
|
const int multiview_eye)
|
2019-04-23 13:56:30 +02:00
|
|
|
{
|
2020-07-29 18:13:19 +02:00
|
|
|
const bool in_range = (textarget >= 0) && (textarget < TEXTARGET_COUNT);
|
|
|
|
|
BLI_assert(in_range);
|
2021-01-25 11:17:03 +01:00
|
|
|
BLI_assert(multiview_eye == 0 || multiview_eye == 1);
|
2019-04-23 13:56:30 +02:00
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
if (in_range) {
|
|
|
|
|
return &(ima->gputexture[textarget][multiview_eye]);
|
2019-04-23 13:56:30 +02:00
|
|
|
}
|
2020-07-29 18:13:19 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2019-04-23 13:56:30 +02:00
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
static GPUTexture *image_gpu_texture_error_create(eGPUTextureTarget textarget)
|
|
|
|
|
{
|
2020-09-05 02:55:22 +02:00
|
|
|
fprintf(stderr, "GPUTexture: Blender Texture Not Loaded!\n");
|
2020-07-29 18:13:19 +02:00
|
|
|
switch (textarget) {
|
|
|
|
|
case TEXTARGET_2D_ARRAY:
|
|
|
|
|
return GPU_texture_create_error(2, true);
|
|
|
|
|
case TEXTARGET_TILE_MAPPING:
|
|
|
|
|
return GPU_texture_create_error(1, true);
|
|
|
|
|
case TEXTARGET_2D:
|
|
|
|
|
default:
|
|
|
|
|
return GPU_texture_create_error(2, false);
|
2020-07-29 04:55:21 +02:00
|
|
|
}
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
static GPUTexture *image_get_gpu_texture(Image *ima,
|
|
|
|
|
ImageUser *iuser,
|
|
|
|
|
ImBuf *ibuf,
|
|
|
|
|
eGPUTextureTarget textarget)
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
{
|
2020-07-29 04:55:21 +02:00
|
|
|
if (ima == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
/* Free any unused GPU textures, since we know we are in a thread with OpenGL
|
|
|
|
|
* context and might as well ensure we have as much space free as possible. */
|
|
|
|
|
gpu_free_unused_buffers();
|
2019-04-23 13:56:30 +02:00
|
|
|
|
2020-09-14 10:45:20 +02:00
|
|
|
/* Free GPU textures when requesting a different render pass/layer.
|
|
|
|
|
* When `iuser` isn't set (texture painting single image mode) we assume that
|
|
|
|
|
* the current `pass` and `layer` should be 0. */
|
|
|
|
|
short requested_pass = iuser ? iuser->pass : 0;
|
|
|
|
|
short requested_layer = iuser ? iuser->layer : 0;
|
2021-01-25 11:17:03 +01:00
|
|
|
short requested_view = iuser ? iuser->multi_index : 0;
|
2021-02-08 15:42:59 +01:00
|
|
|
const bool limit_resolution = U.glreslimit != 0 &&
|
|
|
|
|
((iuser && (iuser->flag & IMA_SHOW_MAX_RESOLUTION) == 0) ||
|
|
|
|
|
(iuser == NULL));
|
|
|
|
|
short requested_gpu_flags = limit_resolution ? 0 : IMA_GPU_MAX_RESOLUTION;
|
|
|
|
|
#define GPU_FLAGS_TO_CHECK (IMA_GPU_MAX_RESOLUTION)
|
2021-01-25 11:17:03 +01:00
|
|
|
/* There is room for 2 multiview textures. When a higher number is requested we should always
|
|
|
|
|
* target the first view slot. This is fine as multi view images aren't used together. */
|
|
|
|
|
if (requested_view < 2) {
|
|
|
|
|
requested_view = 0;
|
|
|
|
|
}
|
|
|
|
|
if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer ||
|
2021-02-08 15:42:59 +01:00
|
|
|
ima->gpu_view != requested_view ||
|
|
|
|
|
((ima->gpuflag & GPU_FLAGS_TO_CHECK) != requested_gpu_flags)) {
|
2020-09-14 10:45:20 +02:00
|
|
|
ima->gpu_pass = requested_pass;
|
|
|
|
|
ima->gpu_layer = requested_layer;
|
2021-01-25 11:17:03 +01:00
|
|
|
ima->gpu_view = requested_view;
|
2021-02-08 15:42:59 +01:00
|
|
|
ima->gpuflag &= ~GPU_FLAGS_TO_CHECK;
|
|
|
|
|
ima->gpuflag |= requested_gpu_flags | IMA_GPU_REFRESH;
|
2020-09-11 07:59:48 +02:00
|
|
|
}
|
2021-02-08 15:42:59 +01:00
|
|
|
#undef GPU_FLAGS_TO_CHECK
|
2020-09-11 07:59:48 +02:00
|
|
|
|
2020-12-18 09:15:55 +01:00
|
|
|
/* Check if image has been updated and tagged to be updated (full or partial). */
|
|
|
|
|
ImageTile *tile = BKE_image_get_tile(ima, 0);
|
|
|
|
|
if (((ima->gpuflag & IMA_GPU_REFRESH) != 0) ||
|
|
|
|
|
((ibuf == NULL || tile == NULL || !tile->ok) &&
|
|
|
|
|
((ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) != 0))) {
|
2020-07-29 18:13:19 +02:00
|
|
|
image_free_gpu(ima, true);
|
2020-12-18 09:15:55 +01:00
|
|
|
BLI_freelistN(&ima->gpu_refresh_areas);
|
|
|
|
|
ima->gpuflag &= ~(IMA_GPU_REFRESH | IMA_GPU_PARTIAL_REFRESH);
|
|
|
|
|
}
|
|
|
|
|
else if (ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) {
|
|
|
|
|
BLI_assert(ibuf);
|
|
|
|
|
BLI_assert(tile && tile->ok);
|
|
|
|
|
ImagePartialRefresh *refresh_area;
|
|
|
|
|
while ((refresh_area = BLI_pophead(&ima->gpu_refresh_areas))) {
|
|
|
|
|
const int tile_offset_x = refresh_area->tile_x * IMA_PARTIAL_REFRESH_TILE_SIZE;
|
|
|
|
|
const int tile_offset_y = refresh_area->tile_y * IMA_PARTIAL_REFRESH_TILE_SIZE;
|
|
|
|
|
const int tile_width = MIN2(IMA_PARTIAL_REFRESH_TILE_SIZE, ibuf->x - tile_offset_x);
|
|
|
|
|
const int tile_height = MIN2(IMA_PARTIAL_REFRESH_TILE_SIZE, ibuf->y - tile_offset_y);
|
|
|
|
|
image_update_gputexture_ex(
|
|
|
|
|
ima, tile, ibuf, tile_offset_x, tile_offset_y, tile_width, tile_height);
|
|
|
|
|
MEM_freeN(refresh_area);
|
|
|
|
|
}
|
|
|
|
|
ima->gpuflag &= ~IMA_GPU_PARTIAL_REFRESH;
|
2019-04-23 13:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
/* Tag as in active use for garbage collector. */
|
|
|
|
|
BKE_image_tag_time(ima);
|
|
|
|
|
|
|
|
|
|
/* Test if we already have a texture. */
|
2021-01-25 11:17:03 +01:00
|
|
|
int current_view = iuser ? iuser->multi_index : 0;
|
|
|
|
|
if (current_view >= 2) {
|
|
|
|
|
current_view = 0;
|
|
|
|
|
}
|
2020-09-11 07:59:48 +02:00
|
|
|
GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, current_view);
|
2020-07-29 04:55:21 +02:00
|
|
|
if (*tex) {
|
|
|
|
|
return *tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if we have a valid image. If not, we return a dummy
|
2020-07-30 08:31:25 +10:00
|
|
|
* texture with zero bind-code so we don't keep trying. */
|
2020-07-29 04:55:21 +02:00
|
|
|
if (tile == NULL || tile->ok == 0) {
|
2020-07-29 18:13:19 +02:00
|
|
|
*tex = image_gpu_texture_error_create(textarget);
|
2020-07-29 04:55:21 +02:00
|
|
|
return *tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check if we have a valid image buffer */
|
|
|
|
|
ImBuf *ibuf_intern = ibuf;
|
|
|
|
|
if (ibuf_intern == NULL) {
|
|
|
|
|
ibuf_intern = BKE_image_acquire_ibuf(ima, iuser, NULL);
|
|
|
|
|
if (ibuf_intern == NULL) {
|
2020-07-29 18:13:19 +02:00
|
|
|
*tex = image_gpu_texture_error_create(textarget);
|
2020-07-29 04:55:21 +02:00
|
|
|
return *tex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (textarget == TEXTARGET_2D_ARRAY) {
|
|
|
|
|
*tex = gpu_texture_create_tile_array(ima, ibuf_intern);
|
|
|
|
|
}
|
|
|
|
|
else if (textarget == TEXTARGET_TILE_MAPPING) {
|
|
|
|
|
*tex = gpu_texture_create_tile_mapping(ima, iuser ? iuser->multiview_eye : 0);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-07-29 17:10:35 +02:00
|
|
|
const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH);
|
2020-09-22 13:52:38 +02:00
|
|
|
const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima,
|
|
|
|
|
ibuf_intern);
|
2021-02-08 15:42:59 +01:00
|
|
|
const bool limit_gl_texture_size = (ima->gpuflag & IMA_GPU_MAX_RESOLUTION) == 0;
|
2020-07-29 17:10:35 +02:00
|
|
|
|
2021-02-08 15:42:59 +01:00
|
|
|
*tex = IMB_create_gpu_texture(ima->id.name + 2,
|
|
|
|
|
ibuf_intern,
|
|
|
|
|
use_high_bitdepth,
|
|
|
|
|
store_premultiplied,
|
|
|
|
|
limit_gl_texture_size);
|
2020-07-29 17:10:35 +02:00
|
|
|
|
2021-04-29 18:28:25 +02:00
|
|
|
if (*tex) {
|
|
|
|
|
GPU_texture_wrap_mode(*tex, true, false);
|
|
|
|
|
|
|
|
|
|
if (GPU_mipmap_enabled()) {
|
|
|
|
|
GPU_texture_generate_mipmap(*tex);
|
|
|
|
|
if (ima) {
|
|
|
|
|
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
|
|
|
|
|
}
|
|
|
|
|
GPU_texture_mipmap_mode(*tex, true, true);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GPU_texture_mipmap_mode(*tex, false, true);
|
2020-07-29 17:10:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if `ibuf` was given, we don't own the `ibuf_intern` */
|
|
|
|
|
if (ibuf == NULL) {
|
|
|
|
|
BKE_image_release_ibuf(ima, ibuf_intern, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 18:28:25 +02:00
|
|
|
if (*tex) {
|
|
|
|
|
GPU_texture_orig_size_set(*tex, ibuf_intern->x, ibuf_intern->y);
|
|
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
|
|
|
|
|
return *tex;
|
2016-05-05 11:25:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
GPUTexture *BKE_image_get_gpu_texture(Image *image, ImageUser *iuser, ImBuf *ibuf)
|
2020-07-29 04:55:21 +02:00
|
|
|
{
|
2020-07-29 18:13:19 +02:00
|
|
|
return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_2D);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUTexture *BKE_image_get_gpu_tiles(Image *image, ImageUser *iuser, ImBuf *ibuf)
|
|
|
|
|
{
|
|
|
|
|
return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_2D_ARRAY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUTexture *BKE_image_get_gpu_tilemap(Image *image, ImageUser *iuser, ImBuf *ibuf)
|
|
|
|
|
{
|
|
|
|
|
return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_TILE_MAPPING);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Delayed GPU texture free
|
|
|
|
|
*
|
|
|
|
|
* Image datablocks can be deleted by any thread, but there may not be any active OpenGL context.
|
|
|
|
|
* In that case we push them into a queue and free the buffers later.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static LinkNode *gpu_texture_free_queue = NULL;
|
|
|
|
|
static ThreadMutex gpu_texture_queue_mutex = BLI_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
|
|
static void gpu_free_unused_buffers(void)
|
|
|
|
|
{
|
|
|
|
|
if (gpu_texture_free_queue == NULL) {
|
|
|
|
|
return;
|
2020-07-29 04:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
BLI_mutex_lock(&gpu_texture_queue_mutex);
|
|
|
|
|
|
2020-08-05 02:00:31 +02:00
|
|
|
while (gpu_texture_free_queue != NULL) {
|
|
|
|
|
GPUTexture *tex = BLI_linklist_pop(&gpu_texture_free_queue);
|
|
|
|
|
GPU_texture_free(tex);
|
2020-07-29 04:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
BLI_mutex_unlock(&gpu_texture_queue_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_image_free_unused_gpu_textures()
|
|
|
|
|
{
|
|
|
|
|
if (BLI_thread_is_main()) {
|
|
|
|
|
gpu_free_unused_buffers();
|
2020-07-29 04:55:21 +02:00
|
|
|
}
|
2020-07-29 18:13:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
2020-07-29 04:55:21 +02:00
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Deletion
|
|
|
|
|
* \{ */
|
2020-07-29 17:10:35 +02:00
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
static void image_free_gpu(Image *ima, const bool immediate)
|
|
|
|
|
{
|
|
|
|
|
for (int eye = 0; eye < 2; eye++) {
|
|
|
|
|
for (int i = 0; i < TEXTARGET_COUNT; i++) {
|
|
|
|
|
if (ima->gputexture[i][eye] != NULL) {
|
|
|
|
|
if (immediate) {
|
|
|
|
|
GPU_texture_free(ima->gputexture[i][eye]);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_mutex_lock(&gpu_texture_queue_mutex);
|
|
|
|
|
BLI_linklist_prepend(&gpu_texture_free_queue, ima->gputexture[i][eye]);
|
|
|
|
|
BLI_mutex_unlock(&gpu_texture_queue_mutex);
|
|
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
ima->gputexture[i][eye] = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_image_free_gputextures(Image *ima)
|
|
|
|
|
{
|
|
|
|
|
image_free_gpu(ima, BLI_thread_is_main());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_image_free_all_gputextures(Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
if (bmain) {
|
|
|
|
|
LISTBASE_FOREACH (Image *, ima, &bmain->images) {
|
|
|
|
|
BKE_image_free_gputextures(ima);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
/* same as above but only free animated images */
|
|
|
|
|
void BKE_image_free_anim_gputextures(Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
if (bmain) {
|
|
|
|
|
LISTBASE_FOREACH (Image *, ima, &bmain->images) {
|
|
|
|
|
if (BKE_image_is_animated(ima)) {
|
|
|
|
|
BKE_image_free_gputextures(ima);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_image_free_old_gputextures(Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
static int lasttime = 0;
|
|
|
|
|
int ctime = (int)PIL_check_seconds_timer();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Run garbage collector once for every collecting period of time
|
|
|
|
|
* if textimeout is 0, that's the option to NOT run the collector
|
|
|
|
|
*/
|
|
|
|
|
if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* of course not! */
|
|
|
|
|
if (G.is_rendering) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lasttime = ctime;
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (Image *, ima, &bmain->images) {
|
|
|
|
|
if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) {
|
|
|
|
|
/* If it's in GL memory, deallocate and set time tag to current time
|
|
|
|
|
* This gives textures a "second chance" to be used before dying. */
|
|
|
|
|
if (BKE_image_has_opengl_texture(ima)) {
|
|
|
|
|
BKE_image_free_gputextures(ima);
|
|
|
|
|
ima->lastused = ctime;
|
|
|
|
|
}
|
|
|
|
|
/* Otherwise, just kill the buffers */
|
|
|
|
|
else {
|
|
|
|
|
BKE_image_free_buffers(ima);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Paint Update
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static ImBuf *update_do_scale(uchar *rect,
|
|
|
|
|
float *rect_float,
|
|
|
|
|
int *x,
|
|
|
|
|
int *y,
|
|
|
|
|
int *w,
|
|
|
|
|
int *h,
|
|
|
|
|
int limit_w,
|
|
|
|
|
int limit_h,
|
|
|
|
|
int full_w,
|
|
|
|
|
int full_h)
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
{
|
|
|
|
|
/* Partial update with scaling. */
|
2020-07-29 04:55:21 +02:00
|
|
|
float xratio = limit_w / (float)full_w;
|
|
|
|
|
float yratio = limit_h / (float)full_h;
|
|
|
|
|
|
|
|
|
|
int part_w = *w, part_h = *h;
|
|
|
|
|
|
|
|
|
|
/* Find sub coordinates in scaled image. Take ceiling because we will be
|
|
|
|
|
* losing 1 pixel due to rounding errors in x,y. */
|
|
|
|
|
*x *= xratio;
|
|
|
|
|
*y *= yratio;
|
|
|
|
|
*w = (int)ceil(xratio * (*w));
|
|
|
|
|
*h = (int)ceil(yratio * (*h));
|
|
|
|
|
|
|
|
|
|
/* ...but take back if we are over the limit! */
|
|
|
|
|
if (*x + *w > limit_w) {
|
|
|
|
|
(*w)--;
|
|
|
|
|
}
|
|
|
|
|
if (*y + *h > limit_h) {
|
|
|
|
|
(*h)--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Scale pixels. */
|
|
|
|
|
ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, part_w, part_h, 4);
|
|
|
|
|
IMB_scaleImBuf(ibuf, *w, *h);
|
|
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
|
}
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
static void gpu_texture_update_scaled(GPUTexture *tex,
|
|
|
|
|
uchar *rect,
|
|
|
|
|
float *rect_float,
|
|
|
|
|
int full_w,
|
|
|
|
|
int full_h,
|
|
|
|
|
int x,
|
|
|
|
|
int y,
|
|
|
|
|
int layer,
|
|
|
|
|
const int *tile_offset,
|
|
|
|
|
const int *tile_size,
|
|
|
|
|
int w,
|
|
|
|
|
int h)
|
|
|
|
|
{
|
|
|
|
|
ImBuf *ibuf;
|
|
|
|
|
if (layer > -1) {
|
|
|
|
|
ibuf = update_do_scale(
|
|
|
|
|
rect, rect_float, &x, &y, &w, &h, tile_size[0], tile_size[1], full_w, full_h);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
/* Shift to account for tile packing. */
|
|
|
|
|
x += tile_offset[0];
|
|
|
|
|
y += tile_offset[1];
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2020-07-29 04:55:21 +02:00
|
|
|
/* Partial update with scaling. */
|
2020-12-18 09:15:55 +01:00
|
|
|
int limit_w = GPU_texture_width(tex);
|
|
|
|
|
int limit_h = GPU_texture_height(tex);
|
2020-07-29 04:55:21 +02:00
|
|
|
|
|
|
|
|
ibuf = update_do_scale(rect, rect_float, &x, &y, &w, &h, limit_w, limit_h, full_w, full_h);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
void *data = (ibuf->rect_float) ? (void *)(ibuf->rect_float) : (void *)(ibuf->rect);
|
2021-02-17 12:38:21 -03:00
|
|
|
eGPUDataFormat data_format = (ibuf->rect_float) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE;
|
2020-07-29 04:55:21 +02:00
|
|
|
|
|
|
|
|
GPU_texture_update_sub(tex, data_format, data, x, y, layer, w, h, 1);
|
|
|
|
|
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
static void gpu_texture_update_unscaled(GPUTexture *tex,
|
|
|
|
|
uchar *rect,
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
float *rect_float,
|
|
|
|
|
int x,
|
|
|
|
|
int y,
|
|
|
|
|
int layer,
|
2020-07-29 04:55:21 +02:00
|
|
|
const int tile_offset[2],
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
int w,
|
|
|
|
|
int h,
|
2020-07-29 04:55:21 +02:00
|
|
|
int tex_stride,
|
|
|
|
|
int tex_offset)
|
2016-05-05 11:25:31 +02:00
|
|
|
{
|
2020-07-29 04:55:21 +02:00
|
|
|
if (layer > -1) {
|
|
|
|
|
/* Shift to account for tile packing. */
|
|
|
|
|
x += tile_offset[0];
|
|
|
|
|
y += tile_offset[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *data = (rect_float) ? (void *)(rect_float + tex_offset) : (void *)(rect + tex_offset);
|
2021-02-17 12:38:21 -03:00
|
|
|
eGPUDataFormat data_format = (rect_float) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE;
|
2020-07-29 04:55:21 +02:00
|
|
|
|
2019-04-23 13:56:30 +02:00
|
|
|
/* Partial update without scaling. Stride and offset are used to copy only a
|
|
|
|
|
* subset of a possible larger buffer than what we are updating. */
|
2020-07-17 18:51:26 +02:00
|
|
|
GPU_unpack_row_length_set(tex_stride);
|
2019-04-23 13:56:30 +02:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
GPU_texture_update_sub(tex, data_format, data, x, y, layer, w, h, 1);
|
2020-07-17 18:51:26 +02:00
|
|
|
/* Restore default. */
|
|
|
|
|
GPU_unpack_row_length_set(0);
|
2016-05-05 11:25:31 +02:00
|
|
|
}
|
|
|
|
|
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
static void gpu_texture_update_from_ibuf(
|
|
|
|
|
GPUTexture *tex, Image *ima, ImBuf *ibuf, ImageTile *tile, int x, int y, int w, int h)
|
2016-05-05 11:25:31 +02:00
|
|
|
{
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
bool scaled;
|
|
|
|
|
if (tile != NULL) {
|
|
|
|
|
int *tilesize = tile->runtime.tilearray_size;
|
|
|
|
|
scaled = (ibuf->x != tilesize[0]) || (ibuf->y != tilesize[1]);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-12-18 09:15:55 +01:00
|
|
|
scaled = (GPU_texture_width(tex) != ibuf->x) || (GPU_texture_height(tex) != ibuf->y);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
2019-04-23 13:56:30 +02:00
|
|
|
|
|
|
|
|
if (scaled) {
|
|
|
|
|
/* Extra padding to account for bleed from neighboring pixels. */
|
|
|
|
|
const int padding = 4;
|
|
|
|
|
const int xmax = min_ii(x + w + padding, ibuf->x);
|
|
|
|
|
const int ymax = min_ii(y + h + padding, ibuf->y);
|
|
|
|
|
x = max_ii(x - padding, 0);
|
|
|
|
|
y = max_ii(y - padding, 0);
|
|
|
|
|
w = xmax - x;
|
|
|
|
|
h = ymax - y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get texture data pointers. */
|
|
|
|
|
float *rect_float = ibuf->rect_float;
|
|
|
|
|
uchar *rect = (uchar *)ibuf->rect;
|
2020-07-29 04:55:21 +02:00
|
|
|
int tex_stride = ibuf->x;
|
|
|
|
|
int tex_offset = ibuf->channels * (y * ibuf->x + x);
|
2019-04-23 13:56:30 +02:00
|
|
|
|
2020-09-22 13:52:38 +02:00
|
|
|
const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, ibuf);
|
2019-04-23 13:56:30 +02:00
|
|
|
if (rect_float == NULL) {
|
|
|
|
|
/* Byte pixels. */
|
|
|
|
|
if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
|
|
|
|
|
const bool compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(
|
|
|
|
|
ibuf->rect_colorspace);
|
|
|
|
|
|
2020-08-08 13:29:21 +10:00
|
|
|
rect = (uchar *)MEM_mallocN(sizeof(uchar[4]) * w * h, __func__);
|
2019-04-23 13:56:30 +02:00
|
|
|
if (rect == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tex_stride = w;
|
|
|
|
|
tex_offset = 0;
|
|
|
|
|
|
|
|
|
|
/* Convert to scene linear with sRGB compression, and premultiplied for
|
|
|
|
|
* correct texture interpolation. */
|
2019-06-07 17:49:58 +02:00
|
|
|
IMB_colormanagement_imbuf_to_byte_texture(
|
|
|
|
|
rect, x, y, w, h, ibuf, compress_as_srgb, store_premultiplied);
|
2019-04-23 13:56:30 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-06-07 17:49:58 +02:00
|
|
|
else {
|
2019-04-23 13:56:30 +02:00
|
|
|
/* Float pixels. */
|
2019-06-07 17:49:58 +02:00
|
|
|
if (ibuf->channels != 4 || scaled || !store_premultiplied) {
|
2020-08-08 13:29:21 +10:00
|
|
|
rect_float = (float *)MEM_mallocN(sizeof(float[4]) * w * h, __func__);
|
2019-06-07 17:49:58 +02:00
|
|
|
if (rect_float == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-23 13:56:30 +02:00
|
|
|
|
2019-06-07 17:49:58 +02:00
|
|
|
tex_stride = w;
|
|
|
|
|
tex_offset = 0;
|
|
|
|
|
|
|
|
|
|
IMB_colormanagement_imbuf_to_float_texture(
|
|
|
|
|
rect_float, x, y, w, h, ibuf, store_premultiplied);
|
|
|
|
|
}
|
2019-04-23 13:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scaled) {
|
|
|
|
|
/* Slower update where we first have to scale the input pixels. */
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
if (tile != NULL) {
|
|
|
|
|
int *tileoffset = tile->runtime.tilearray_offset;
|
|
|
|
|
int *tilesize = tile->runtime.tilearray_size;
|
|
|
|
|
int tilelayer = tile->runtime.tilearray_layer;
|
2020-07-29 04:55:21 +02:00
|
|
|
gpu_texture_update_scaled(
|
|
|
|
|
tex, rect, rect_float, ibuf->x, ibuf->y, x, y, tilelayer, tileoffset, tilesize, w, h);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2020-07-29 04:55:21 +02:00
|
|
|
gpu_texture_update_scaled(
|
|
|
|
|
tex, rect, rect_float, ibuf->x, ibuf->y, x, y, -1, NULL, NULL, w, h);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
2016-05-05 11:25:31 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2019-04-23 13:56:30 +02:00
|
|
|
/* Fast update at same resolution. */
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
if (tile != NULL) {
|
|
|
|
|
int *tileoffset = tile->runtime.tilearray_offset;
|
|
|
|
|
int tilelayer = tile->runtime.tilearray_layer;
|
2020-07-29 04:55:21 +02:00
|
|
|
gpu_texture_update_unscaled(
|
|
|
|
|
tex, rect, rect_float, x, y, tilelayer, tileoffset, w, h, tex_stride, tex_offset);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2020-07-29 04:55:21 +02:00
|
|
|
gpu_texture_update_unscaled(
|
|
|
|
|
tex, rect, rect_float, x, y, -1, NULL, w, h, tex_stride, tex_offset);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
2019-04-23 13:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Free buffers if needed. */
|
|
|
|
|
if (rect && rect != (uchar *)ibuf->rect) {
|
|
|
|
|
MEM_freeN(rect);
|
|
|
|
|
}
|
|
|
|
|
if (rect_float && rect_float != ibuf->rect_float) {
|
|
|
|
|
MEM_freeN(rect_float);
|
2016-05-05 11:25:31 +02:00
|
|
|
}
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
if (GPU_mipmap_enabled()) {
|
2020-07-29 04:55:21 +02:00
|
|
|
GPU_texture_generate_mipmap(tex);
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPU_texture_unbind(tex);
|
2016-05-05 11:25:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-18 09:15:55 +01:00
|
|
|
static void image_update_gputexture_ex(
|
|
|
|
|
Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h)
|
|
|
|
|
{
|
|
|
|
|
GPUTexture *tex = ima->gputexture[TEXTARGET_2D][0];
|
|
|
|
|
/* Check if we need to update the main gputexture. */
|
|
|
|
|
if (tex != NULL && tile == ima->tiles.first) {
|
|
|
|
|
gpu_texture_update_from_ibuf(tex, ima, ibuf, NULL, x, y, w, h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if we need to update the array gputexture. */
|
|
|
|
|
tex = ima->gputexture[TEXTARGET_2D_ARRAY][0];
|
|
|
|
|
if (tex != NULL) {
|
|
|
|
|
gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-29 18:13:19 +02:00
|
|
|
/* Partial update of texture for texture painting. This is often much
|
|
|
|
|
* quicker than fully updating the texture for high resolution images. */
|
|
|
|
|
void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
|
2019-04-02 16:05:22 +02:00
|
|
|
{
|
2020-07-29 04:55:21 +02:00
|
|
|
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
|
|
|
|
|
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-29 04:55:21 +02:00
|
|
|
if ((ibuf == NULL) || (w == 0) || (h == 0)) {
|
|
|
|
|
/* Full reload of texture. */
|
2020-07-29 18:13:19 +02:00
|
|
|
BKE_image_free_gputextures(ima);
|
2012-06-30 04:34:34 +00:00
|
|
|
}
|
2020-12-18 09:15:55 +01:00
|
|
|
image_update_gputexture_ex(ima, tile, ibuf, x, y, w, h);
|
|
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-18 09:15:55 +01:00
|
|
|
/* Mark areas on the GPUTexture that needs to be updated. The areas are marked in chunks.
|
|
|
|
|
* The next time the GPUTexture is used these tiles will be refreshes. This saves time
|
|
|
|
|
* when writing to the same place multiple times This happens for during foreground
|
|
|
|
|
* rendering. */
|
|
|
|
|
void BKE_image_update_gputexture_delayed(
|
|
|
|
|
struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h)
|
|
|
|
|
{
|
|
|
|
|
/* Check for full refresh. */
|
|
|
|
|
if (ibuf && x == 0 && y == 0 && w == ibuf->x && h == ibuf->y) {
|
|
|
|
|
ima->gpuflag |= IMA_GPU_REFRESH;
|
|
|
|
|
}
|
|
|
|
|
/* Check if we can promote partial refresh to a full refresh. */
|
|
|
|
|
if ((ima->gpuflag & (IMA_GPU_REFRESH | IMA_GPU_PARTIAL_REFRESH)) ==
|
|
|
|
|
(IMA_GPU_REFRESH | IMA_GPU_PARTIAL_REFRESH)) {
|
|
|
|
|
ima->gpuflag &= ~IMA_GPU_PARTIAL_REFRESH;
|
|
|
|
|
BLI_freelistN(&ima->gpu_refresh_areas);
|
|
|
|
|
}
|
|
|
|
|
/* Image is already marked for complete refresh. */
|
|
|
|
|
if (ima->gpuflag & IMA_GPU_REFRESH) {
|
|
|
|
|
return;
|
2012-10-25 12:54:16 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-18 09:15:55 +01:00
|
|
|
/* Schedule the tiles that covers the requested area. */
|
|
|
|
|
const int start_tile_x = x / IMA_PARTIAL_REFRESH_TILE_SIZE;
|
|
|
|
|
const int start_tile_y = y / IMA_PARTIAL_REFRESH_TILE_SIZE;
|
|
|
|
|
const int end_tile_x = (x + w) / IMA_PARTIAL_REFRESH_TILE_SIZE;
|
|
|
|
|
const int end_tile_y = (y + h) / IMA_PARTIAL_REFRESH_TILE_SIZE;
|
|
|
|
|
const int num_tiles_x = (end_tile_x + 1) - (start_tile_x);
|
|
|
|
|
const int num_tiles_y = (end_tile_y + 1) - (start_tile_y);
|
|
|
|
|
const int num_tiles = num_tiles_x * num_tiles_y;
|
|
|
|
|
const bool allocate_on_heap = BLI_BITMAP_SIZE(num_tiles) > 16;
|
|
|
|
|
BLI_bitmap *requested_tiles = NULL;
|
|
|
|
|
if (allocate_on_heap) {
|
|
|
|
|
requested_tiles = BLI_BITMAP_NEW(num_tiles, __func__);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
requested_tiles = BLI_BITMAP_NEW_ALLOCA(num_tiles);
|
2012-06-30 04:34:34 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-18 09:15:55 +01:00
|
|
|
/* Mark the tiles that have already been requested. They don't need to be requested again. */
|
|
|
|
|
int num_tiles_not_scheduled = num_tiles;
|
|
|
|
|
LISTBASE_FOREACH (ImagePartialRefresh *, area, &ima->gpu_refresh_areas) {
|
|
|
|
|
if (area->tile_x < start_tile_x || area->tile_x > end_tile_x || area->tile_y < start_tile_y ||
|
|
|
|
|
area->tile_y > end_tile_y) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int requested_tile_index = (area->tile_x - start_tile_x) +
|
|
|
|
|
(area->tile_y - start_tile_y) * num_tiles_x;
|
|
|
|
|
BLI_BITMAP_ENABLE(requested_tiles, requested_tile_index);
|
|
|
|
|
num_tiles_not_scheduled--;
|
|
|
|
|
if (num_tiles_not_scheduled == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Schedule the tiles that aren't requested yet. */
|
|
|
|
|
if (num_tiles_not_scheduled) {
|
|
|
|
|
int tile_index = 0;
|
|
|
|
|
for (int tile_y = start_tile_y; tile_y <= end_tile_y; tile_y++) {
|
|
|
|
|
for (int tile_x = start_tile_x; tile_x <= end_tile_x; tile_x++) {
|
|
|
|
|
if (!BLI_BITMAP_TEST_BOOL(requested_tiles, tile_index)) {
|
|
|
|
|
ImagePartialRefresh *area = MEM_mallocN(sizeof(ImagePartialRefresh), __func__);
|
|
|
|
|
area->tile_x = tile_x;
|
|
|
|
|
area->tile_y = tile_y;
|
|
|
|
|
BLI_addtail(&ima->gpu_refresh_areas, area);
|
|
|
|
|
}
|
|
|
|
|
tile_index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ima->gpuflag |= IMA_GPU_PARTIAL_REFRESH;
|
|
|
|
|
}
|
|
|
|
|
if (allocate_on_heap) {
|
|
|
|
|
MEM_freeN(requested_tiles);
|
|
|
|
|
}
|
2012-06-30 04:34:34 +00:00
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
|
|
|
|
/* these two functions are called on entering and exiting texture paint mode,
|
2012-03-09 18:28:30 +00:00
|
|
|
* temporary disabling/enabling mipmapping on all images for quick texture
|
|
|
|
|
* updates with glTexSubImage2D. images that didn't change don't have to be
|
|
|
|
|
* re-uploaded to OpenGL */
|
2020-07-29 18:13:19 +02:00
|
|
|
void BKE_image_paint_set_mipmap(Main *bmain, bool mipmap)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2020-07-29 04:55:21 +02:00
|
|
|
LISTBASE_FOREACH (Image *, ima, &bmain->images) {
|
|
|
|
|
if (BKE_image_has_opengl_texture(ima)) {
|
|
|
|
|
if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) {
|
2020-03-12 17:21:58 +01:00
|
|
|
for (int eye = 0; eye < 2; eye++) {
|
|
|
|
|
for (int a = 0; a < TEXTARGET_COUNT; a++) {
|
2020-07-26 20:20:03 +02:00
|
|
|
if (ELEM(a, TEXTARGET_2D, TEXTARGET_2D_ARRAY)) {
|
2020-03-12 17:21:58 +01:00
|
|
|
GPUTexture *tex = ima->gputexture[a][eye];
|
|
|
|
|
if (tex != NULL) {
|
2020-07-29 04:55:21 +02:00
|
|
|
GPU_texture_mipmap_mode(tex, mipmap, true);
|
2020-03-12 17:21:58 +01:00
|
|
|
}
|
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
2020-01-14 00:33:21 +01:00
|
|
|
}
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 16:06:08 +01:00
|
|
|
}
|
World textures displaying for viewport in BI.
This patch supports "Image or Movie" and "Environment map" types of world texture for the viewport.
It supports:
- "View", "AngMap" and "Equirectangular" types of mapping.
- Different types of texture blending (according to BI world render).
- Same color blending as when it lacked textures (but render via glsl).
{F207734}
{F207735}
Example: {F275180}
Original author: @valentin_b4w
Regards,
Alexander (Blend4Web Team).
Reviewers: sergey, valentin_b4w, brecht, merwin
Reviewed By: merwin
Subscribers: campbellbarton, merwin, blueprintrandom, youle, a.romanov, yurikovelenov, AlexKowel, Evgeny_Rodygin
Projects: #rendering, #opengl_gfx, #bf_blender:_next
Differential Revision: https://developer.blender.org/D1414
2016-01-27 12:06:57 +03:00
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2019-04-22 09:32:37 +10:00
|
|
|
else {
|
2020-07-29 18:13:19 +02:00
|
|
|
BKE_image_free_gputextures(ima);
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
else {
|
|
|
|
|
ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2014-05-22 11:58:07 +10:00
|
|
|
}
|
2020-07-29 04:55:21 +02:00
|
|
|
|
2020-07-30 08:31:25 +10:00
|
|
|
/** \} */
|