GPUTexture: Add support for texture view

This is an OpenGL 4.3 feature that enables creating a texture using a range
of the same data as another texture.
This commit is contained in:
2022-02-24 22:45:00 +01:00
parent e59f754c16
commit 7d7dd66ba7
5 changed files with 95 additions and 0 deletions

View File

@@ -226,6 +226,19 @@ GPUTexture *GPU_texture_create_compressed_2d(
* Create an error texture that will bind an invalid texture (pink) at draw time.
*/
GPUTexture *GPU_texture_create_error(int dimension, bool array);
/**
* Create an alias of the source texture data.
* If \a src is freed, the texture view will continue to be valid.
* If \a mip_start or \a mip_len is bigger than available mips they will be clamped.
* TODO(@fclem): Target conversion is not implemented yet.
*/
GPUTexture *GPU_texture_create_view(const char *name,
const GPUTexture *src,
eGPUTextureFormat format,
int mip_start,
int mip_len,
int layer_start,
int layer_len);
void GPU_texture_update_mipmap(GPUTexture *tex,
int miplvl,

View File

@@ -131,6 +131,42 @@ bool Texture::init_buffer(GPUVertBuf *vbo, eGPUTextureFormat format)
return this->init_internal(vbo);
}
bool Texture::init_view(const GPUTexture *src_,
eGPUTextureFormat format,
int mip_start,
int mip_len,
int layer_start,
int layer_len)
{
const Texture *src = unwrap(src_);
w_ = src->w_;
h_ = src->h_;
d_ = src->d_;
switch (type_) {
case GPU_TEXTURE_1D_ARRAY:
h_ = layer_len;
break;
case GPU_TEXTURE_CUBE_ARRAY:
BLI_assert(layer_len % 6 == 0);
ATTR_FALLTHROUGH;
case GPU_TEXTURE_2D_ARRAY:
d_ = layer_len;
break;
default:
BLI_assert(layer_len == 1 && layer_start == 0);
break;
}
mip_start = min_ii(mip_start, src->mipmaps_ - 1);
mip_len = min_ii(mip_len, (src->mipmaps_ - mip_start));
mipmaps_ = mip_len;
format_ = format;
format_flag_ = to_format_flag(format);
/* For now always copy the target. Target aliasing could be exposed later. */
type_ = src->type_;
sampler_state = src->sampler_state;
return this->init_internal(src_, mip_start, layer_start);
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -343,6 +379,21 @@ GPUTexture *GPU_texture_create_error(int dimension, bool is_array)
return gpu_texture_create("invalid_tex", w, h, d, type, 1, GPU_RGBA8, GPU_DATA_FLOAT, pixel);
}
GPUTexture *GPU_texture_create_view(const char *name,
const GPUTexture *src,
eGPUTextureFormat format,
int mip_start,
int mip_len,
int layer_start,
int layer_len)
{
BLI_assert(mip_len > 0);
BLI_assert(layer_len > 0);
Texture *view = GPUBackend::get()->texture_alloc(name);
view->init_view(src, format, mip_start, mip_len, layer_start, layer_len);
return wrap(view);
}
/* ------ Update ------ */
void GPU_texture_update_mipmap(GPUTexture *tex_,

View File

@@ -106,6 +106,12 @@ class Texture {
bool init_3D(int w, int h, int d, int mips, eGPUTextureFormat format);
bool init_cubemap(int w, int layers, int mips, eGPUTextureFormat format);
bool init_buffer(GPUVertBuf *vbo, eGPUTextureFormat format);
bool init_view(const GPUTexture *src,
eGPUTextureFormat format,
int mip_start,
int mip_len,
int layer_start,
int layer_len);
virtual void generate_mipmap() = 0;
virtual void copy_to(Texture *tex) = 0;
@@ -234,6 +240,7 @@ class Texture {
protected:
virtual bool init_internal() = 0;
virtual bool init_internal(GPUVertBuf *vbo) = 0;
virtual bool init_internal(const GPUTexture *src, int mip_offset, int layer_offset) = 0;
};
/* Syntactic sugar. */

View File

@@ -175,6 +175,28 @@ bool GLTexture::init_internal(GPUVertBuf *vbo)
return true;
}
bool GLTexture::init_internal(const GPUTexture *src, int mip_offset, int layer_offset)
{
BLI_assert(GLContext::texture_storage_support);
const GLTexture *gl_src = static_cast<const GLTexture *>(unwrap(src));
GLenum internal_format = to_gl_internal_format(format_);
target_ = to_gl_target(type_);
glTextureView(tex_id_,
target_,
gl_src->tex_id_,
internal_format,
mip_offset,
mipmaps_,
layer_offset,
this->layer_count());
debug::object_label(GL_TEXTURE, tex_id_, name_);
return true;
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -74,6 +74,8 @@ class GLTexture : public Texture {
bool init_internal() override;
/** Return true on success. */
bool init_internal(GPUVertBuf *vbo) override;
/** Return true on success. */
bool init_internal(const GPUTexture *src, int mip_offset, int layer_offset) override;
private:
bool proxy_check(int mip);