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:
@@ -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,
|
||||
|
||||
@@ -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_,
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user