diff options
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 26 | ||||
-rw-r--r-- | source/blender/gpu/GPU_batch.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 13 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_batch.cc | 10 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_node_graph.c | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader_create_info.hh | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader_dependency.cc | 6 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader_dependency_private.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.cc | 80 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture_private.hh | 15 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 4 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.cc | 3 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_context.hh | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_immediate.cc | 2 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_texture.cc | 150 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_texture.hh | 4 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_vertex_array.cc | 2 | ||||
-rw-r--r-- | source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh | 1 |
18 files changed, 235 insertions, 95 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index e883a12a5b2..3ad43ef05af 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -147,6 +147,7 @@ set(SRC intern/gpu_select_private.h intern/gpu_shader_create_info.hh intern/gpu_shader_create_info_private.hh + intern/gpu_shader_dependency_private.h intern/gpu_shader_interface.hh intern/gpu_shader_private.hh intern/gpu_state_private.hh @@ -384,7 +385,7 @@ file(GENERATE OUTPUT ${glsl_source_list_file} CONTENT "${GLSL_SOURCE_CONTENT}") list(APPEND SRC ${glsl_source_list_file}) list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}) -set(SHADER_CREATE_INFOS +set(SRC_SHADER_CREATE_INFOS ../draw/engines/workbench/shaders/infos/workbench_composite_info.hh ../draw/engines/workbench/shaders/infos/workbench_effect_antialiasing_info.hh ../draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh @@ -435,7 +436,7 @@ set(SHADER_CREATE_INFOS ) set(SHADER_CREATE_INFOS_CONTENT "") -foreach(DESCRIPTOR_FILE ${SHADER_CREATE_INFOS}) +foreach(DESCRIPTOR_FILE ${SRC_SHADER_CREATE_INFOS}) string(APPEND SHADER_CREATE_INFOS_CONTENT "#include \"${DESCRIPTOR_FILE}\"\n") endforeach() @@ -452,12 +453,21 @@ if(WITH_IMAGE_DDS) add_definitions(-DWITH_DDS) endif() +if(WITH_OPENCOLORIO) + add_definitions(-DWITH_OCIO) +endif() + blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") target_link_libraries(bf_gpu PUBLIC bf_draw_shaders bf_gpu_shaders ) +if(WITH_OPENCOLORIO) + target_link_libraries(bf_gpu PUBLIC bf_ocio_shaders) +endif() + + if(CXX_WARN_NO_SUGGEST_OVERRIDE) target_compile_options(bf_gpu PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wsuggest-override>) endif() @@ -477,18 +487,22 @@ if(WITH_GPU_SHADER_BUILDER) ) target_include_directories(shader_builder PRIVATE ${INC} ${CMAKE_CURRENT_BINARY_DIR}) - set(BAKED_CREATE_INFOS_FILE ${CMAKE_CURRENT_BINARY_DIR}/shader_baked.hh) + set(SRC_BAKED_CREATE_INFOS_FILE ${CMAKE_CURRENT_BINARY_DIR}/shader_baked.hh) add_custom_command( OUTPUT - ${BAKED_CREATE_INFOS_FILE} + ${SRC_BAKED_CREATE_INFOS_FILE} COMMAND - "$<TARGET_FILE:shader_builder>" ${BAKED_CREATE_INFOS_FILE} + "$<TARGET_FILE:shader_builder>" ${SRC_BAKED_CREATE_INFOS_FILE} DEPENDS shader_builder ) set(GPU_SHADER_INFO_SRC intern/gpu_shader_info_baked.cc - ${BAKED_CREATE_INFOS_FILE} + ${SRC_BAKED_CREATE_INFOS_FILE} + + # For project files to be aware of these headers. + ${SRC_SHADER_CREATE_INFOS} + shaders/infos/gpu_interface_info.hh ) blender_add_lib(bf_gpu_shader_infos "${GPU_SHADER_INFO_SRC}" "" "" "") diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 803a5825c94..7fad8dd23be 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -119,6 +119,7 @@ int GPU_batch_instbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo); * Returns the index of verts in the batch. */ int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo); +bool GPU_batch_vertbuf_has(GPUBatch *, GPUVertBuf *); #define GPU_batch_vertbuf_add(batch, verts) GPU_batch_vertbuf_add_ex(batch, verts, false) diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index d689fbe14b5..734d407d011 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -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, diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc index 44e95b1f5f5..32b117dac12 100644 --- a/source/blender/gpu/intern/gpu_batch.cc +++ b/source/blender/gpu/intern/gpu_batch.cc @@ -191,6 +191,16 @@ int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo) return -1; } +bool GPU_batch_vertbuf_has(GPUBatch *batch, GPUVertBuf *verts) +{ + for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) { + if (batch->verts[v] == verts) { + return true; + } + } + return false; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index da4e49f0257..57e415a8183 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -165,7 +165,7 @@ static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type) /** * Link stack uniform buffer. - * This is called for the input/output sockets that are note connected. + * This is called for the input/output sockets that are not connected. */ static GPUNodeLink *gpu_uniformbuffer_link(GPUMaterial *mat, bNode *node, diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh index bd0187e2dc5..bf74d44d9a7 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.hh +++ b/source/blender/gpu/intern/gpu_shader_create_info.hh @@ -255,7 +255,7 @@ struct StageInterfaceInfo { }; /** - * @brief Describe inputs & outputs, stage interfaces, resources and sources of a shader. + * \brief Describe inputs & outputs, stage interfaces, resources and sources of a shader. * If all data is correctly provided, this is all that is needed to create and compile * a GPUShader. * @@ -497,9 +497,9 @@ struct ShaderCreateInfo { /** * IMPORTANT: invocations count is only used if GL_ARB_gpu_shader5 is supported. On - * implementations that do not supports it, the max_vertices will be be multiplied by - * invocations. Your shader needs to account for this fact. Use `#ifdef GPU_ARB_gpu_shader5` - * and make a code path that does not rely on gl_InvocationID. + * implementations that do not supports it, the max_vertices will be multiplied by invocations. + * Your shader needs to account for this fact. Use `#ifdef GPU_ARB_gpu_shader5` and make a code + * path that does not rely on #gl_InvocationID. */ Self &geometry_layout(PrimitiveIn prim_in, PrimitiveOut prim_out, diff --git a/source/blender/gpu/intern/gpu_shader_dependency.cc b/source/blender/gpu/intern/gpu_shader_dependency.cc index 8a842ef4d7c..5b7df035acd 100644 --- a/source/blender/gpu/intern/gpu_shader_dependency.cc +++ b/source/blender/gpu/intern/gpu_shader_dependency.cc @@ -21,6 +21,9 @@ extern "C" { #define SHADER_SOURCE(datatoc, filename, filepath) extern char datatoc[]; #include "glsl_draw_source_list.h" #include "glsl_gpu_source_list.h" +#ifdef WITH_OCIO +# include "glsl_ocio_source_list.h" +#endif #undef SHADER_SOURCE } @@ -348,6 +351,9 @@ void gpu_shader_dependency_init() g_sources->add_new(filename, new GPUSource(filepath, filename, datatoc)); #include "glsl_draw_source_list.h" #include "glsl_gpu_source_list.h" +#ifdef WITH_OCIO +# include "glsl_ocio_source_list.h" +#endif #undef SHADER_SOURCE int errors = 0; diff --git a/source/blender/gpu/intern/gpu_shader_dependency_private.h b/source/blender/gpu/intern/gpu_shader_dependency_private.h index 29ee70962d1..7b9ecef5835 100644 --- a/source/blender/gpu/intern/gpu_shader_dependency_private.h +++ b/source/blender/gpu/intern/gpu_shader_dependency_private.h @@ -38,7 +38,7 @@ StringRefNull gpu_shader_dependency_get_source(const StringRefNull source_name); /** * \brief Find the name of the file from which the given string was generated. - * \return Return filename or empty string. + * \return filename or empty string. * \note source_string needs to be identical to the one given by gpu_shader_dependency_get_source() */ StringRefNull gpu_shader_dependency_get_filename_from_source_string( diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index da5f08f003e..9e6a6f75391 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -52,11 +52,13 @@ Texture::~Texture() #endif } -bool Texture::init_1D(int w, int layers, eGPUTextureFormat format) +bool Texture::init_1D(int w, int layers, int mips, eGPUTextureFormat format) { w_ = w; h_ = layers; d_ = 0; + int mips_max = 1 + floorf(log2f(w)); + mipmaps_ = min_ii(mips, mips_max); format_ = format; format_flag_ = to_format_flag(format); type_ = (layers > 0) ? GPU_TEXTURE_1D_ARRAY : GPU_TEXTURE_1D; @@ -66,11 +68,13 @@ bool Texture::init_1D(int w, int layers, eGPUTextureFormat format) return this->init_internal(); } -bool Texture::init_2D(int w, int h, int layers, eGPUTextureFormat format) +bool Texture::init_2D(int w, int h, int layers, int mips, eGPUTextureFormat format) { w_ = w; h_ = h; d_ = layers; + int mips_max = 1 + floorf(log2f(max_ii(w, h))); + mipmaps_ = min_ii(mips, mips_max); format_ = format; format_flag_ = to_format_flag(format); type_ = (layers > 0) ? GPU_TEXTURE_2D_ARRAY : GPU_TEXTURE_2D; @@ -80,11 +84,13 @@ bool Texture::init_2D(int w, int h, int layers, eGPUTextureFormat format) return this->init_internal(); } -bool Texture::init_3D(int w, int h, int d, eGPUTextureFormat format) +bool Texture::init_3D(int w, int h, int d, int mips, eGPUTextureFormat format) { w_ = w; h_ = h; d_ = d; + int mips_max = 1 + floorf(log2f(max_iii(w, h, d))); + mipmaps_ = min_ii(mips, mips_max); format_ = format; format_flag_ = to_format_flag(format); type_ = GPU_TEXTURE_3D; @@ -94,11 +100,13 @@ bool Texture::init_3D(int w, int h, int d, eGPUTextureFormat format) return this->init_internal(); } -bool Texture::init_cubemap(int w, int layers, eGPUTextureFormat format) +bool Texture::init_cubemap(int w, int layers, int mips, eGPUTextureFormat format) { w_ = w; h_ = w; d_ = max_ii(1, layers) * 6; + int mips_max = 1 + floorf(log2f(w)); + mipmaps_ = min_ii(mips, mips_max); format_ = format; format_flag_ = to_format_flag(format); type_ = (layers > 0) ? GPU_TEXTURE_CUBE_ARRAY : GPU_TEXTURE_CUBE; @@ -123,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); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -187,28 +231,29 @@ static inline GPUTexture *gpu_texture_create(const char *name, const int h, const int d, const eGPUTextureType type, - int UNUSED(mips), + int mips, eGPUTextureFormat tex_format, eGPUDataFormat data_format, const void *pixels) { + BLI_assert(mips > 0); Texture *tex = GPUBackend::get()->texture_alloc(name); bool success = false; switch (type) { case GPU_TEXTURE_1D: case GPU_TEXTURE_1D_ARRAY: - success = tex->init_1D(w, h, tex_format); + success = tex->init_1D(w, h, mips, tex_format); break; case GPU_TEXTURE_2D: case GPU_TEXTURE_2D_ARRAY: - success = tex->init_2D(w, h, d, tex_format); + success = tex->init_2D(w, h, d, mips, tex_format); break; case GPU_TEXTURE_3D: - success = tex->init_3D(w, h, d, tex_format); + success = tex->init_3D(w, h, d, mips, tex_format); break; case GPU_TEXTURE_CUBE: case GPU_TEXTURE_CUBE_ARRAY: - success = tex->init_cubemap(w, d, tex_format); + success = tex->init_cubemap(w, d, mips, tex_format); break; default: break; @@ -286,7 +331,7 @@ GPUTexture *GPU_texture_create_compressed_2d( const char *name, int w, int h, int miplen, eGPUTextureFormat tex_format, const void *data) { Texture *tex = GPUBackend::get()->texture_alloc(name); - bool success = tex->init_2D(w, h, 0, tex_format); + bool success = tex->init_2D(w, h, 0, miplen, tex_format); if (!success) { delete tex; @@ -334,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_, diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index 2c57c467bcf..ec11fab421c 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -101,11 +101,17 @@ class Texture { virtual ~Texture(); /* Return true on success. */ - bool init_1D(int w, int layers, eGPUTextureFormat format); - bool init_2D(int w, int h, int layers, eGPUTextureFormat format); - bool init_3D(int w, int h, int d, eGPUTextureFormat format); - bool init_cubemap(int w, int layers, eGPUTextureFormat format); + bool init_1D(int w, int layers, int mips, eGPUTextureFormat format); + bool init_2D(int w, int h, int layers, int mips, eGPUTextureFormat format); + 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. */ diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index fd4a87bc544..b5a572bccbe 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -277,8 +277,6 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo GPU_matrix_identity_set(); GPU_matrix_identity_projection_set(); immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE); - immUniform1i("overlayTexture", 0); - immUniform1i("imageTexture", 1); int settings = stereo_format->display_mode; if (settings == S3D_DISPLAY_ANAGLYPH) { switch (stereo_format->anaglyph_type) { @@ -432,8 +430,6 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); GPU_batch_uniform_1i(batch, "overlay", do_overlay_merge); GPU_batch_uniform_1i(batch, "display_transform", display_colorspace); - GPU_batch_uniform_1i(batch, "image_texture", 0); - GPU_batch_uniform_1i(batch, "overlays_texture", 1); } GPU_texture_bind(color, 0); 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_immediate.cc b/source/blender/gpu/opengl/gl_immediate.cc index cfedfe348f1..c32a6afd8cf 100644 --- a/source/blender/gpu/opengl/gl_immediate.cc +++ b/source/blender/gpu/opengl/gl_immediate.cc @@ -139,7 +139,7 @@ void GLImmediate::end() GLContext::get()->state_manager->apply_state(); /* We convert the offset in vertex offset from the buffer's start. - * This works because we added some padding to align the first vertex vertex. */ + * This works because we added some padding to align the first vertex. */ uint v_first = buffer_offset() / vertex_format.stride; GLVertArray::update_bindings( vao_id_, v_first, &vertex_format, reinterpret_cast<Shader *>(shader)->interface); diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc index 22af2dd463f..0a5c7f8e79e 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_)); + + 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 incomplete textures. */ + /* 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,65 +175,26 @@ bool GLTexture::init_internal(GPUVertBuf *vbo) return true; } -void GLTexture::ensure_mipmaps(int miplvl) +bool GLTexture::init_internal(const GPUTexture *src, int mip_offset, int layer_offset) { - 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_)); + BLI_assert(GLContext::texture_storage_support); - GLContext::state_manager_active_get()->texture_bind_temp(this); + const GLTexture *gl_src = static_cast<const GLTexture *>(unwrap(src)); + GLenum internal_format = to_gl_internal_format(format_); + target_ = to_gl_target(type_); - 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; - } - } - } + glTextureView(tex_id_, + target_, + gl_src->tex_id_, + internal_format, + mip_offset, + mipmaps_, + layer_offset, + this->layer_count()); - this->mip_range_set(0, mipmaps_); + debug::object_label(GL_TEXTURE, tex_id_, name_); + + return true; } /** \} */ @@ -216,9 +247,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 +312,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..d4d024f5e3e 100644 --- a/source/blender/gpu/opengl/gl_texture.hh +++ b/source/blender/gpu/opengl/gl_texture.hh @@ -74,11 +74,11 @@ 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); - /** 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(); diff --git a/source/blender/gpu/opengl/gl_vertex_array.cc b/source/blender/gpu/opengl/gl_vertex_array.cc index 88b69eb5b62..04f60f10d41 100644 --- a/source/blender/gpu/opengl/gl_vertex_array.cc +++ b/source/blender/gpu/opengl/gl_vertex_array.cc @@ -54,7 +54,7 @@ static uint16_t vbo_bind(const ShaderInterface *interface, const char *name = GPU_vertformat_attr_name_get(format, a, n_idx); const ShaderInput *input = interface->attr_get(name); - if (input == nullptr) { + if (input == nullptr || input->location == -1) { continue; } diff --git a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh index d3b70cb67f9..2798846b310 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh @@ -16,6 +16,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_2D_image_overlays_merge) .push_constant(Type::MAT4, "ModelViewProjectionMatrix") .push_constant(Type::BOOL, "display_transform") .push_constant(Type::BOOL, "overlay") + /* Sampler slots should match OCIO's. */ .sampler(0, ImageType::FLOAT_2D, "image_texture") .sampler(1, ImageType::FLOAT_2D, "overlays_texture") .vertex_source("gpu_shader_2D_image_vert.glsl") |