GPU: Fix crash and missing texture due to recent C++ port

Fix T79306 DRW: small issues with yesterday commits modifying TEXTARGET
Fix T79303 Image texture node crashes EEVEE when connected to a shader output
This commit is contained in:
Clément Foucault 2020-07-27 13:37:14 +02:00
parent bfeb94eccc
commit 0b04f0e4e6
Notes: blender-bot 2023-02-14 06:37:09 +01:00
Referenced by issue #79303, Image texture node crashes EEVEE when connected to a shader output
Referenced by issue #79306, DRW: small issues with yesterday commits modifying TEXTARGET
6 changed files with 90 additions and 74 deletions

View File

@ -1295,7 +1295,7 @@ static void drw_shgroup_material_texture(DRWShadingGroup *grp,
GPUMaterialTexture *tex,
const char *name,
eGPUSamplerState state,
int textarget)
eGPUTextureTarget textarget)
{
GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
@ -1316,13 +1316,13 @@ void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial
/* Image */
if (tex->tiled_mapping_name[0]) {
drw_shgroup_material_texture(
grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D_ARRAY);
grp, tex, tex->sampler_name, tex->sampler_state, TEXTARGET_2D_ARRAY);
drw_shgroup_material_texture(
grp, tex, tex->tiled_mapping_name, tex->sampler_state, GL_TEXTURE_1D_ARRAY);
grp, tex, tex->tiled_mapping_name, tex->sampler_state, TEXTARGET_TILE_MAPPING);
}
else {
drw_shgroup_material_texture(
grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D);
grp, tex, tex->sampler_name, tex->sampler_state, TEXTARGET_2D);
}
}
else if (tex->colorband) {

View File

@ -58,21 +58,7 @@ float GPU_get_anisotropic(void);
void GPU_paint_update_image(
struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h);
void GPU_create_gl_tex(unsigned int *bind,
unsigned int *rect,
float *frect,
int rectw,
int recth,
int textarget,
bool mipmap,
bool half_float,
bool use_srgb,
struct Image *ima);
void GPU_create_gl_tex_compressed(unsigned int *bind,
int textarget,
struct Image *ima,
struct ImBuf *ibuf);
bool GPU_upload_dxt_texture(struct ImBuf *ibuf, bool use_srgb);
bool GPU_upload_dxt_texture(struct ImBuf *ibuf, bool use_srgb, uint *bindcode);
void GPU_free_image(struct Image *ima);
void GPU_free_images(struct Main *bmain);
void GPU_free_images_anim(struct Main *bmain);

View File

@ -41,6 +41,15 @@ struct PreviewImage;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
/* Used to get the correct gpu texture from an Image datablock. */
typedef enum eGPUTextureTarget {
TEXTARGET_2D = 0,
TEXTARGET_CUBE_MAP,
TEXTARGET_2D_ARRAY,
TEXTARGET_TILE_MAPPING,
TEXTARGET_COUNT,
} eGPUTextureTarget;
/* GPU Samplers state
* - Specify the sampler state to bind a texture with.
* - Internally used by textures.
@ -222,16 +231,16 @@ GPUTexture *GPU_texture_create_cube_array(
GPUTexture *GPU_texture_create_from_vertbuf(struct GPUVertBuf *vert);
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat data_type, const uint buffer);
GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode);
GPUTexture *GPU_texture_from_bindcode(eGPUTextureTarget target, int bindcode);
GPUTexture *GPU_texture_from_blender(struct Image *ima,
struct ImageUser *iuser,
struct ImBuf *ibuf,
int textarget);
eGPUTextureTarget target);
/* movie clip drawing */
GPUTexture *GPU_texture_from_movieclip(struct MovieClip *clip,
struct MovieClipUser *cuser,
int textarget);
eGPUTextureTarget target);
void GPU_free_texture_movieclip(struct MovieClip *clip);
void GPU_texture_add_mipmap(GPUTexture *tex,

View File

@ -1186,18 +1186,24 @@ GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint
return tex;
}
static GLenum convert_target_to_gl(int target)
static GLenum convert_target_to_gl(eGPUTextureTarget target)
{
static const GLenum table[] = {
[TEXTARGET_2D] = GL_TEXTURE_2D,
[TEXTARGET_CUBE_MAP] = GL_TEXTURE_CUBE_MAP,
[TEXTARGET_2D_ARRAY] = GL_TEXTURE_2D_ARRAY,
[TEXTARGET_TILE_MAPPING] = GL_TEXTURE_1D_ARRAY,
};
return table[target];
switch (target) {
case TEXTARGET_2D:
return GL_TEXTURE_2D;
case TEXTARGET_CUBE_MAP:
return GL_TEXTURE_CUBE_MAP;
case TEXTARGET_2D_ARRAY:
return GL_TEXTURE_2D_ARRAY;
case TEXTARGET_TILE_MAPPING:
return GL_TEXTURE_1D_ARRAY;
default:
BLI_assert(0);
return GL_TEXTURE_2D;
}
}
GPUTexture *GPU_texture_from_bindcode(int target, int bindcode)
GPUTexture *GPU_texture_from_bindcode(eGPUTextureTarget target, int bindcode)
{
GLenum textarget = convert_target_to_gl(target);

View File

@ -63,6 +63,20 @@
static void gpu_free_image(Image *ima, const bool immediate);
static void gpu_free_unused_buffers(void);
static void gpu_create_gl_tex_compressed(unsigned int *bind,
eGPUTextureTarget textarget,
Image *ima,
ImBuf *ibuf);
static void gpu_create_gl_tex(uint *bind,
uint *rect,
float *frect,
int rectw,
int recth,
eGPUTextureTarget textarget,
bool mipmap,
bool half_float,
bool use_srgb,
Image *ima);
//* Checking powers of two for images since OpenGL ES requires it */
#ifdef WITH_DDS
@ -456,7 +470,7 @@ static uint gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
return bindcode;
}
static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, eGPUTextureTarget textarget)
{
uint bindcode = 0;
const bool mipmap = GPU_get_mipmap();
@ -465,7 +479,7 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
#ifdef WITH_DDS
if (ibuf->ftype == IMB_FTYPE_DDS) {
/* DDS is loaded directly in compressed form. */
GPU_create_gl_tex_compressed(&bindcode, textarget, ima, ibuf);
gpu_create_gl_tex_compressed(&bindcode, textarget, ima, ibuf);
return bindcode;
}
#endif
@ -518,7 +532,7 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
}
/* Create OpenGL texture. */
GPU_create_gl_tex(&bindcode,
gpu_create_gl_tex(&bindcode,
(uint *)rect,
rect_float,
ibuf->x,
@ -542,7 +556,7 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
static GPUTexture **gpu_get_movieclip_gputexture(MovieClip *clip,
MovieClipUser *cuser,
GLenum textarget)
eGPUTextureTarget textarget)
{
LISTBASE_FOREACH (MovieClip_RuntimeGPUTexture *, tex, &clip->runtime.gputextures) {
if (memcmp(&tex->user, cuser, sizeof(MovieClipUser)) == 0) {
@ -558,12 +572,7 @@ static GPUTexture **gpu_get_movieclip_gputexture(MovieClip *clip,
BLI_addtail(&clip->runtime.gputextures, tex);
}
if (textarget == GL_TEXTURE_2D) {
return &tex->gputexture[TEXTARGET_2D];
}
else if (textarget == GL_TEXTURE_CUBE_MAP) {
return &tex->gputexture[TEXTARGET_CUBE_MAP];
}
return &tex->gputexture[textarget];
}
}
return NULL;
@ -841,7 +850,10 @@ static void gpu_texture_update_from_ibuf(
*
* `iuser` and `ibuf` are mutual exclusive parameters. The caller can pass the `ibuf` when already
* available. It is also required when requesting the GPUTexture for a render result. */
GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf, int textarget)
GPUTexture *GPU_texture_from_blender(Image *ima,
ImageUser *iuser,
ImBuf *ibuf,
eGPUTextureTarget textarget)
{
#ifndef GPU_STANDALONE
if (ima == NULL) {
@ -915,7 +927,9 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf,
return NULL;
}
GPUTexture *GPU_texture_from_movieclip(MovieClip *clip, MovieClipUser *cuser, int textarget)
GPUTexture *GPU_texture_from_movieclip(MovieClip *clip,
MovieClipUser *cuser,
eGPUTextureTarget textarget)
{
#ifndef GPU_STANDALONE
if (clip == NULL) {
@ -1039,17 +1053,19 @@ static void gpu_del_cube_map(void **cube_map)
}
/* Image *ima can be NULL */
void GPU_create_gl_tex(uint *bind,
uint *rect,
float *frect,
int rectw,
int recth,
int textarget,
bool mipmap,
bool half_float,
bool use_srgb,
Image *ima)
static void gpu_create_gl_tex(uint *bind,
uint *rect,
float *frect,
int rectw,
int recth,
eGPUTextureTarget target,
bool mipmap,
bool half_float,
bool use_srgb,
Image *ima)
{
GLenum textarget = (target == TEXTARGET_2D) ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP;
ImBuf *ibuf = NULL;
if (textarget == GL_TEXTURE_2D && is_over_resolution_limit(textarget, rectw, recth)) {
@ -1140,13 +1156,14 @@ void GPU_create_gl_tex(uint *bind,
}
/**
* GPU_upload_dxt_texture() assumes that the texture is already bound and ready to go.
* This is so the viewport and the BGE can share some code.
* Returns false if the provided ImBuf doesn't have a supported DXT compression format
*/
bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb, uint *bindcode)
{
#ifdef WITH_DDS
glGenTextures(1, (GLuint *)bindcode);
glBindTexture(GL_TEXTURE_2D, *bindcode);
GLint format = 0;
int blocksize, height, width, i, size, offset = 0;
@ -1170,6 +1187,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
if (format == 0) {
fprintf(stderr, "Unable to find a suitable DXT compression, falling back to uncompressed\n");
glDeleteTextures(1, (GLuint *)bindcode);
return false;
}
@ -1177,6 +1195,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
fprintf(
stderr,
"Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
glDeleteTextures(1, (GLuint *)bindcode);
return false;
}
@ -1210,6 +1229,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
/* set number of mipmap levels we have, needed in case they don't go down to 1x1 */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1);
glBindTexture(GL_TEXTURE_2D, 0);
return true;
#else
UNUSED_VARS(ibuf, use_srgb);
@ -1217,7 +1237,10 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
#endif
}
void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima, ImBuf *ibuf)
static void gpu_create_gl_tex_compressed(unsigned int *bind,
eGPUTextureTarget textarget,
Image *ima,
ImBuf *ibuf)
{
/* For DDS we only support data, scene linear and sRGB. Converting to
* different colorspace would break the compression. */
@ -1229,19 +1252,19 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima,
#ifndef WITH_DDS
(void)ibuf;
/* Fall back to uncompressed if DDS isn't enabled */
GPU_create_gl_tex(
gpu_create_gl_tex(
bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, half_float, use_srgb, ima);
#else
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf, use_srgb) == 0) {
glDeleteTextures(1, (GLuint *)bind);
GPU_create_gl_tex(
bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, half_float, use_srgb, ima);
if (textarget == TEXTARGET_2D) {
if (GPU_upload_dxt_texture(ibuf, use_srgb, bind)) {
/* All went fine! */
return;
}
}
glBindTexture(textarget, 0);
/* Fallback. */
gpu_create_gl_tex(
bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, half_float, use_srgb, ima);
#endif
}

View File

@ -117,14 +117,6 @@ typedef struct ImageTile {
#define IMA_NEED_FRAME_RECALC (1 << 3)
#define IMA_SHOW_STEREO (1 << 4)
enum {
TEXTARGET_2D = 0,
TEXTARGET_CUBE_MAP,
TEXTARGET_2D_ARRAY,
TEXTARGET_TILE_MAPPING,
TEXTARGET_COUNT,
};
typedef struct Image {
ID id;