Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-02-24 23:40:16 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-02-25 00:51:19 +0300
commite59f754c169d855110296a365d93c33e82333385 (patch)
treee42f9ad35ae0fbd4edf87e8d5d5f1eac2b46a3af /source/blender/gpu/opengl
parentc23ee6d7b4d6665aed4d0440153f0b1e80b77c8b (diff)
GPUTexture: Use immutable storage
This means textures need to have the number of mipmap levels specified upfront. It does not mean the data is immutable. There is fallback code for OpenGL < 4.2. Immutable storage will enables texture views in the future.
Diffstat (limited to 'source/blender/gpu/opengl')
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc3
-rw-r--r--source/blender/gpu/opengl/gl_context.hh1
-rw-r--r--source/blender/gpu/opengl/gl_texture.cc140
-rw-r--r--source/blender/gpu/opengl/gl_texture.hh2
4 files changed, 77 insertions, 69 deletions
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index 7a1674a5f01..302d8249914 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -240,6 +240,7 @@ static void detect_workarounds()
GLContext::texture_cube_map_array_support = false;
GLContext::texture_filter_anisotropic_support = false;
GLContext::texture_gather_support = false;
+ GLContext::texture_storage_support = false;
GLContext::vertex_attrib_binding_support = false;
return;
}
@@ -439,6 +440,7 @@ bool GLContext::shader_draw_parameters_support = false;
bool GLContext::texture_cube_map_array_support = false;
bool GLContext::texture_filter_anisotropic_support = false;
bool GLContext::texture_gather_support = false;
+bool GLContext::texture_storage_support = false;
bool GLContext::vertex_attrib_binding_support = false;
/** Workarounds. */
@@ -501,6 +503,7 @@ void GLBackend::capabilities_init()
GLContext::texture_cube_map_array_support = GLEW_ARB_texture_cube_map_array;
GLContext::texture_filter_anisotropic_support = GLEW_EXT_texture_filter_anisotropic;
GLContext::texture_gather_support = GLEW_ARB_texture_gather;
+ GLContext::texture_storage_support = GLEW_VERSION_4_3;
GLContext::vertex_attrib_binding_support = GLEW_ARB_vertex_attrib_binding;
detect_workarounds();
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
index fe2ad0a4747..369b667cbcc 100644
--- a/source/blender/gpu/opengl/gl_context.hh
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -64,6 +64,7 @@ class GLContext : public Context {
static bool texture_cube_map_array_support;
static bool texture_filter_anisotropic_support;
static bool texture_gather_support;
+ static bool texture_storage_support;
static bool vertex_attrib_binding_support;
/** Workarounds. */
diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc
index 22af2dd463f..37bf2f6b8b3 100644
--- a/source/blender/gpu/opengl/gl_texture.cc
+++ b/source/blender/gpu/opengl/gl_texture.cc
@@ -69,9 +69,79 @@ bool GLTexture::init_internal()
return false;
}
- this->ensure_mipmaps(0);
+ GLenum internal_format = to_gl_internal_format(format_);
+ const bool is_cubemap = bool(type_ == GPU_TEXTURE_CUBE);
+ const bool is_layered = bool(type_ & GPU_TEXTURE_ARRAY);
+ const bool is_compressed = bool(format_flag_ & GPU_TEXTURE_ARRAY);
+ const int dimensions = (is_cubemap) ? 2 : this->dimensions_count();
+ GLenum gl_format = to_gl_data_format(format_);
+ GLenum gl_type = to_gl(to_data_format(format_));
- /* Avoid issue with incomplete textures. */
+ auto mip_size = [&](int h, int w = 1, int d = 1) -> size_t {
+ return divide_ceil_u(w, 4) * divide_ceil_u(h, 4) * divide_ceil_u(d, 4) *
+ to_block_size(format_);
+ };
+ switch (dimensions) {
+ default:
+ case 1:
+ if (GLContext::texture_storage_support) {
+ glTexStorage1D(target_, mipmaps_, internal_format, w_);
+ }
+ else {
+ for (int i = 0, w = w_; i < mipmaps_; i++) {
+ if (is_compressed) {
+ glCompressedTexImage1D(target_, i, internal_format, w, 0, mip_size(w), nullptr);
+ }
+ else {
+ glTexImage1D(target_, i, internal_format, w, 0, gl_format, gl_type, nullptr);
+ }
+ w = max_ii(1, (w / 2));
+ }
+ }
+ break;
+ case 2:
+ if (GLContext::texture_storage_support) {
+ glTexStorage2D(target_, mipmaps_, internal_format, w_, h_);
+ }
+ else {
+ for (int i = 0, w = w_, h = h_; i < mipmaps_; i++) {
+ for (int f = 0; f < (is_cubemap ? 6 : 1); f++) {
+ GLenum target = (is_cubemap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + f : target_;
+ if (is_compressed) {
+ glCompressedTexImage2D(target, i, internal_format, w, h, 0, mip_size(w, h), nullptr);
+ }
+ else {
+ glTexImage2D(target, i, internal_format, w, h, 0, gl_format, gl_type, nullptr);
+ }
+ }
+ w = max_ii(1, (w / 2));
+ h = is_layered ? h_ : max_ii(1, (h / 2));
+ }
+ }
+ break;
+ case 3:
+ if (GLContext::texture_storage_support) {
+ glTexStorage3D(target_, mipmaps_, internal_format, w_, h_, d_);
+ }
+ else {
+ for (int i = 0, w = w_, h = h_, d = d_; i < mipmaps_; i++) {
+ if (is_compressed) {
+ glCompressedTexImage3D(
+ target_, i, internal_format, w, h, d, 0, mip_size(w, h, d), nullptr);
+ }
+ else {
+ glTexImage3D(target_, i, internal_format, w, h, d, 0, gl_format, gl_type, nullptr);
+ }
+ w = max_ii(1, (w / 2));
+ h = max_ii(1, (h / 2));
+ d = is_layered ? d_ : max_ii(1, (d / 2));
+ }
+ }
+ break;
+ }
+ this->mip_range_set(0, mipmaps_ - 1);
+
+ /* Avoid issue with formats not supporting filtering. Nearest by default. */
if (GLContext::direct_state_access_support) {
glTextureParameteri(tex_id_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
@@ -105,67 +175,6 @@ bool GLTexture::init_internal(GPUVertBuf *vbo)
return true;
}
-void GLTexture::ensure_mipmaps(int miplvl)
-{
- int effective_h = (type_ == GPU_TEXTURE_1D_ARRAY) ? 0 : h_;
- int effective_d = (type_ != GPU_TEXTURE_3D) ? 0 : d_;
- int max_dimension = max_iii(w_, effective_h, effective_d);
- int max_miplvl = floor(log2(max_dimension));
- miplvl = min_ii(miplvl, max_miplvl);
-
- while (mipmaps_ < miplvl) {
- int mip = ++mipmaps_;
- const int dimensions = this->dimensions_count();
-
- int w = mip_width_get(mip);
- int h = mip_height_get(mip);
- int d = mip_depth_get(mip);
- GLenum internal_format = to_gl_internal_format(format_);
- GLenum gl_format = to_gl_data_format(format_);
- GLenum gl_type = to_gl(to_data_format(format_));
-
- GLContext::state_manager_active_get()->texture_bind_temp(this);
-
- if (type_ == GPU_TEXTURE_CUBE) {
- for (int i = 0; i < d; i++) {
- GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
- glTexImage2D(target, mip, internal_format, w, h, 0, gl_format, gl_type, nullptr);
- }
- }
- else if (format_flag_ & GPU_FORMAT_COMPRESSED) {
- size_t size = ((w + 3) / 4) * ((h + 3) / 4) * to_block_size(format_);
- switch (dimensions) {
- default:
- case 1:
- glCompressedTexImage1D(target_, mip, internal_format, w, 0, size, nullptr);
- break;
- case 2:
- glCompressedTexImage2D(target_, mip, internal_format, w, h, 0, size, nullptr);
- break;
- case 3:
- glCompressedTexImage3D(target_, mip, internal_format, w, h, d, 0, size, nullptr);
- break;
- }
- }
- else {
- switch (dimensions) {
- default:
- case 1:
- glTexImage1D(target_, mip, internal_format, w, 0, gl_format, gl_type, nullptr);
- break;
- case 2:
- glTexImage2D(target_, mip, internal_format, w, h, 0, gl_format, gl_type, nullptr);
- break;
- case 3:
- glTexImage3D(target_, mip, internal_format, w, h, d, 0, gl_format, gl_type, nullptr);
- break;
- }
- }
- }
-
- this->mip_range_set(0, mipmaps_);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -216,9 +225,7 @@ void GLTexture::update_sub(
BLI_assert(validate_data_format(format_, type));
BLI_assert(data != nullptr);
- this->ensure_mipmaps(mip);
-
- if (mip > mipmaps_) {
+ if (mip >= mipmaps_) {
debug::raise_gl_error("Updating a miplvl on a texture too small to have this many levels.");
return;
}
@@ -283,7 +290,6 @@ void GLTexture::update_sub(
*/
void GLTexture::generate_mipmap()
{
- this->ensure_mipmaps(9999);
/* Some drivers have bugs when using #glGenerateMipmap with depth textures (see T56789).
* In this case we just create a complete texture with mipmaps manually without
* down-sampling. You must initialize the texture levels using other methods like
diff --git a/source/blender/gpu/opengl/gl_texture.hh b/source/blender/gpu/opengl/gl_texture.hh
index 07d3bb8c946..9e128da90e8 100644
--- a/source/blender/gpu/opengl/gl_texture.hh
+++ b/source/blender/gpu/opengl/gl_texture.hh
@@ -77,8 +77,6 @@ class GLTexture : public Texture {
private:
bool proxy_check(int mip);
- /** Will create enough mipmaps up to get to the given level. */
- void ensure_mipmaps(int mip);
void update_sub_direct_state_access(
int mip, int offset[3], int extent[3], GLenum gl_format, GLenum gl_type, const void *data);
GPUFrameBuffer *framebuffer_get();