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>2020-09-05 18:29:51 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-09-05 18:49:14 +0300
commitc766d9b9dc5661693a58e01a3637f15197c2fe59 (patch)
tree6905f0fc085af0eff5cfdf74d87c4ebed412e741 /source/blender/gpu/intern/gpu_texture_private.hh
parentdb21c12abedd7606a3aaf50f70e506a24d9f0e7a (diff)
GPUTexture: GL Backend Isolation
This is a massive cleanup needed for vulkan support T68990. It provides: - More meaningful enums with conversion functions. - Less hacky supports of arrays and cubemaps (all considered layered). - More inline with the stateless design of vulkan and modern GL. - Methods Fallbacks are using framebuffer functions that are wrapped instead of implementing inside the texture module. What is not in there: - API change. - Samplers support (breaks a few effects). # Conflicts: # source/blender/gpu/GPU_texture.h
Diffstat (limited to 'source/blender/gpu/intern/gpu_texture_private.hh')
-rw-r--r--source/blender/gpu/intern/gpu_texture_private.hh393
1 files changed, 357 insertions, 36 deletions
diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh
index 5eeb3d9e0f0..7b5aed9562e 100644
--- a/source/blender/gpu/intern/gpu_texture_private.hh
+++ b/source/blender/gpu/intern/gpu_texture_private.hh
@@ -30,28 +30,32 @@
namespace blender {
namespace gpu {
-typedef enum eGPUTextureFlag {
- GPU_TEXFORMAT_DEPTH = (1 << 0),
- GPU_TEXFORMAT_STENCIL = (1 << 1),
- GPU_TEXFORMAT_INTEGER = (1 << 2),
- GPU_TEXFORMAT_FLOAT = (1 << 3),
-
- GPU_TEXTURE_1D = (1 << 10),
- GPU_TEXTURE_2D = (1 << 11),
- GPU_TEXTURE_3D = (1 << 12),
- GPU_TEXTURE_CUBE = (1 << 13),
- GPU_TEXTURE_ARRAY = (1 << 14),
- GPU_TEXTURE_BUFFER = (1 << 15),
+typedef enum eGPUTextureFormatFlag {
+ GPU_FORMAT_DEPTH = (1 << 0),
+ GPU_FORMAT_STENCIL = (1 << 1),
+ GPU_FORMAT_INTEGER = (1 << 2),
+ GPU_FORMAT_FLOAT = (1 << 3),
+ GPU_FORMAT_COMPRESSED = (1 << 4),
+
+ GPU_FORMAT_DEPTH_STENCIL = (GPU_FORMAT_DEPTH | GPU_FORMAT_STENCIL),
+} eGPUTextureFormatFlag;
+
+ENUM_OPERATORS(eGPUTextureFormatFlag)
+
+typedef enum eGPUTextureType {
+ GPU_TEXTURE_1D = (1 << 0),
+ GPU_TEXTURE_2D = (1 << 1),
+ GPU_TEXTURE_3D = (1 << 2),
+ GPU_TEXTURE_CUBE = (1 << 3),
+ GPU_TEXTURE_ARRAY = (1 << 4),
+ GPU_TEXTURE_BUFFER = (1 << 5),
GPU_TEXTURE_1D_ARRAY = (GPU_TEXTURE_1D | GPU_TEXTURE_ARRAY),
GPU_TEXTURE_2D_ARRAY = (GPU_TEXTURE_2D | GPU_TEXTURE_ARRAY),
GPU_TEXTURE_CUBE_ARRAY = (GPU_TEXTURE_CUBE | GPU_TEXTURE_ARRAY),
+} eGPUTextureType;
- GPU_TEXTURE_TARGET = (GPU_TEXTURE_1D | GPU_TEXTURE_2D | GPU_TEXTURE_3D | GPU_TEXTURE_CUBE |
- GPU_TEXTURE_ARRAY),
-} eGPUTextureFlag;
-
-ENUM_OPERATORS(eGPUTextureFlag)
+ENUM_OPERATORS(eGPUTextureType)
#ifdef DEBUG
# define DEBUG_NAME_LEN 64
@@ -60,23 +64,14 @@ ENUM_OPERATORS(eGPUTextureFlag)
#endif
/* Maximum number of FBOs a texture can be attached to. */
-#define GPU_TEX_MAX_FBO_ATTACHED 12
+#define GPU_TEX_MAX_FBO_ATTACHED 13
class Texture {
public:
- /** Width & Height & Depth. */
- int w = 0, h = 0, d = 0;
- /** Number of color/alpha channels. */
- int components = 0;
- /** Internal data format and it's characteristics. */
- eGPUTextureFormat format;
- eGPUTextureFlag flag;
/** Internal Sampler state. */
- eGPUSamplerState sampler_state;
- /** Number of mipmaps this texture has. */
- int mipmaps = 0;
+ eGPUSamplerState sampler_state = GPU_SAMPLER_DEFAULT;
/** Reference counter. */
- int refcount = 0;
+ int refcount = 1;
/** Width & Height (of source data), optional. */
int src_w = 0, src_h = 0;
/** Framebuffer references to update on deletion. */
@@ -84,6 +79,20 @@ class Texture {
FrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED];
protected:
+ /* ---- Texture format (immutable after init). ---- */
+ /** Width & Height & Depth. For cubemap arrays, d is number of facelayers. */
+ int w_, h_, d_;
+ /** Internal data format. */
+ eGPUTextureFormat format_;
+ /** Format caracteristics. */
+ eGPUTextureFormatFlag format_flag_;
+ /** Texture type. */
+ eGPUTextureType type_;
+
+ /** Number of mipmaps this texture has (Max miplvl). */
+ /* TODO(fclem) Should become immutable and the need for mipmaps should be specified upfront. */
+ int mipmaps_ = -1;
+
/** For debugging */
char name_[DEBUG_NAME_LEN];
@@ -91,22 +100,110 @@ class Texture {
Texture(const char *name);
virtual ~Texture();
- virtual void bind(int slot) = 0;
- virtual void update(void *data) = 0;
- virtual void update_sub(void *data, int offset[3], int size[3]) = 0;
+ /* 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_buffer(GPUVertBuf *vbo, eGPUTextureFormat format);
+
virtual void generate_mipmap(void) = 0;
virtual void copy_to(Texture *tex) = 0;
+ virtual void clear(eGPUDataFormat format, const void *data) = 0;
+ virtual void swizzle_set(const char swizzle_mask[4]) = 0;
+ virtual void mip_range_set(int min, int max) = 0;
+ virtual void *read(int mip, eGPUDataFormat format) = 0;
+
+ void attach_to(FrameBuffer *fb);
+ void update(eGPUDataFormat format, const void *data);
+ void update_mip(int mip, eGPUDataFormat format, const void *data);
- virtual void swizzle_set(char swizzle_mask[4]) = 0;
+ virtual void update_sub(
+ int mip, int offset[3], int extent[3], eGPUDataFormat format, const void *data) = 0;
/* TODO(fclem) Legacy. Should be removed at some point. */
- virtual uint gl_bindcode_get(void) = 0;
+ virtual uint gl_bindcode_get(void) const = 0;
- void attach_to(FrameBuffer *fb);
+ int width_get(void) const
+ {
+ return w_;
+ }
+ int height_get(void) const
+ {
+ return h_;
+ }
+ int depth_get(void) const
+ {
+ return d_;
+ }
+ void mip_size_get(int mip, int r_size[3]) const
+ {
+ /* TODO assert if lvl is below the limit of 1px in each dimension. */
+ int div = 1 << mip;
+ r_size[0] = max_ii(1, w_ / div);
+
+ if (type_ == GPU_TEXTURE_1D_ARRAY) {
+ r_size[1] = h_;
+ }
+ else if (h_ > 0) {
+ r_size[1] = max_ii(1, h_ / div);
+ }
+
+ if (type_ & (GPU_TEXTURE_ARRAY | GPU_TEXTURE_CUBE)) {
+ r_size[2] = d_;
+ }
+ else if (d_ > 0) {
+ r_size[2] = max_ii(1, d_ / div);
+ }
+ }
+
+ int mip_width_get(int mip) const
+ {
+ return max_ii(1, w_ / (1 << mip));
+ }
+ int mip_height_get(int mip) const
+ {
+ return (type_ == GPU_TEXTURE_1D_ARRAY) ? h_ : max_ii(1, h_ / (1 << mip));
+ }
+ int mip_depth_get(int mip) const
+ {
+ return (type_ & (GPU_TEXTURE_ARRAY | GPU_TEXTURE_CUBE)) ? d_ : max_ii(1, d_ / (1 << mip));
+ }
+
+ /* Return number of dimension taking the array type into account. */
+ int dimensions_count(void) const
+ {
+ const int array = (type_ & GPU_TEXTURE_ARRAY) ? 1 : 0;
+ switch (type_ & ~GPU_TEXTURE_ARRAY) {
+ case GPU_TEXTURE_BUFFER:
+ return 1;
+ case GPU_TEXTURE_1D:
+ return 1 + array;
+ case GPU_TEXTURE_2D:
+ return 2 + array;
+ case GPU_TEXTURE_CUBE:
+ case GPU_TEXTURE_3D:
+ default:
+ return 3;
+ }
+ }
+
+ eGPUTextureFormat format_get(void) const
+ {
+ return format_;
+ }
+ eGPUTextureFormatFlag format_flag_get(void) const
+ {
+ return format_flag_;
+ }
+ eGPUTextureType type_get(void) const
+ {
+ return type_;
+ }
GPUAttachmentType attachment_type(int slot) const
{
- switch (format) {
+ switch (format_) {
case GPU_DEPTH_COMPONENT32F:
case GPU_DEPTH_COMPONENT24:
case GPU_DEPTH_COMPONENT16:
@@ -120,9 +217,233 @@ class Texture {
return GPU_FB_COLOR_ATTACHMENT0 + slot;
}
}
+
+ protected:
+ virtual bool init_internal(void) = 0;
+ virtual bool init_internal(GPUVertBuf *vbo) = 0;
};
#undef DEBUG_NAME_LEN
+inline size_t to_bytesize(eGPUTextureFormat format)
+{
+ switch (format) {
+ case GPU_RGBA32F:
+ return 32;
+ case GPU_RG32F:
+ case GPU_RGBA16F:
+ case GPU_RGBA16:
+ return 16;
+ case GPU_RGB16F:
+ return 12;
+ case GPU_DEPTH32F_STENCIL8: /* 32-bit depth, 8 bits stencil, and 24 unused bits. */
+ return 8;
+ case GPU_RG16F:
+ case GPU_RG16I:
+ case GPU_RG16UI:
+ case GPU_RG16:
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_RGBA8UI:
+ case GPU_RGBA8:
+ case GPU_SRGB8_A8:
+ case GPU_R11F_G11F_B10F:
+ case GPU_R32F:
+ case GPU_R32UI:
+ case GPU_R32I:
+ return 4;
+ case GPU_DEPTH_COMPONENT24:
+ return 3;
+ case GPU_DEPTH_COMPONENT16:
+ case GPU_R16F:
+ case GPU_R16UI:
+ case GPU_R16I:
+ case GPU_RG8:
+ case GPU_R16:
+ return 2;
+ case GPU_R8:
+ case GPU_R8UI:
+ return 1;
+ case GPU_SRGB8_A8_DXT1:
+ case GPU_SRGB8_A8_DXT3:
+ case GPU_SRGB8_A8_DXT5:
+ case GPU_RGBA8_DXT1:
+ case GPU_RGBA8_DXT3:
+ case GPU_RGBA8_DXT5:
+ return 1; /* Incorrect but actual size is fractional. */
+ default:
+ BLI_assert(!"Texture format incorrect or unsupported\n");
+ return 0;
+ }
+}
+
+inline size_t to_block_size(eGPUTextureFormat data_type)
+{
+ switch (data_type) {
+ case GPU_SRGB8_A8_DXT1:
+ case GPU_RGBA8_DXT1:
+ return 8;
+ case GPU_SRGB8_A8_DXT3:
+ case GPU_SRGB8_A8_DXT5:
+ case GPU_RGBA8_DXT3:
+ case GPU_RGBA8_DXT5:
+ return 16;
+ default:
+ BLI_assert(!"Texture format is not a compressed format\n");
+ return 0;
+ }
+}
+
+inline eGPUTextureFormatFlag to_format_flag(eGPUTextureFormat format)
+{
+ switch (format) {
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ case GPU_DEPTH_COMPONENT32F:
+ return GPU_FORMAT_DEPTH;
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH32F_STENCIL8:
+ return GPU_FORMAT_DEPTH_STENCIL;
+ case GPU_R8UI:
+ case GPU_RG16I:
+ case GPU_R16I:
+ case GPU_RG16UI:
+ case GPU_R16UI:
+ case GPU_R32UI:
+ return GPU_FORMAT_INTEGER;
+ case GPU_SRGB8_A8_DXT1:
+ case GPU_SRGB8_A8_DXT3:
+ case GPU_SRGB8_A8_DXT5:
+ case GPU_RGBA8_DXT1:
+ case GPU_RGBA8_DXT3:
+ case GPU_RGBA8_DXT5:
+ return GPU_FORMAT_COMPRESSED;
+ default:
+ return GPU_FORMAT_FLOAT;
+ }
+}
+
+inline int to_component_len(eGPUTextureFormat format)
+{
+ switch (format) {
+ case GPU_RGBA8:
+ case GPU_RGBA8UI:
+ case GPU_RGBA16F:
+ case GPU_RGBA16:
+ case GPU_RGBA32F:
+ case GPU_SRGB8_A8:
+ return 4;
+ case GPU_RGB16F:
+ case GPU_R11F_G11F_B10F:
+ return 3;
+ case GPU_RG8:
+ case GPU_RG16:
+ case GPU_RG16F:
+ case GPU_RG16I:
+ case GPU_RG16UI:
+ case GPU_RG32F:
+ return 2;
+ default:
+ return 1;
+ }
+}
+
+inline size_t to_bytesize(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
+{
+ switch (data_format) {
+ case GPU_DATA_UNSIGNED_BYTE:
+ return 1 * to_component_len(tex_format);
+ case GPU_DATA_FLOAT:
+ case GPU_DATA_INT:
+ case GPU_DATA_UNSIGNED_INT:
+ return 4 * to_component_len(tex_format);
+ case GPU_DATA_UNSIGNED_INT_24_8:
+ case GPU_DATA_10_11_11_REV:
+ return 4;
+ default:
+ BLI_assert(!"Data format incorrect or unsupported\n");
+ return 0;
+ }
+}
+
+/* Definitely not complete, edit according to the gl specification. */
+inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
+{
+ switch (tex_format) {
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ case GPU_DEPTH_COMPONENT32F:
+ return data_format == GPU_DATA_FLOAT;
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH32F_STENCIL8:
+ return data_format == GPU_DATA_UNSIGNED_INT_24_8;
+ case GPU_R8UI:
+ case GPU_R16UI:
+ case GPU_RG16UI:
+ case GPU_R32UI:
+ return data_format == GPU_DATA_UNSIGNED_INT;
+ case GPU_RG16I:
+ case GPU_R16I:
+ return data_format == GPU_DATA_INT;
+ case GPU_R8:
+ case GPU_RG8:
+ case GPU_RGBA8:
+ case GPU_RGBA8UI:
+ case GPU_SRGB8_A8:
+ return ELEM(data_format, GPU_DATA_UNSIGNED_BYTE, GPU_DATA_FLOAT);
+ case GPU_R11F_G11F_B10F:
+ return ELEM(data_format, GPU_DATA_10_11_11_REV, GPU_DATA_FLOAT);
+ default:
+ return data_format == GPU_DATA_FLOAT;
+ }
+}
+
+/* Definitely not complete, edit according to the gl specification. */
+inline eGPUDataFormat to_data_format(eGPUTextureFormat tex_format)
+{
+ switch (tex_format) {
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ case GPU_DEPTH_COMPONENT32F:
+ return GPU_DATA_FLOAT;
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH32F_STENCIL8:
+ return GPU_DATA_UNSIGNED_INT_24_8;
+ case GPU_R8UI:
+ case GPU_R16UI:
+ case GPU_RG16UI:
+ case GPU_R32UI:
+ return GPU_DATA_UNSIGNED_INT;
+ case GPU_RG16I:
+ case GPU_R16I:
+ return GPU_DATA_INT;
+ case GPU_R8:
+ case GPU_RG8:
+ case GPU_RGBA8:
+ case GPU_RGBA8UI:
+ case GPU_SRGB8_A8:
+ return GPU_DATA_UNSIGNED_BYTE;
+ case GPU_R11F_G11F_B10F:
+ return GPU_DATA_10_11_11_REV;
+ default:
+ return GPU_DATA_FLOAT;
+ }
+}
+
+inline eGPUFrameBufferBits to_framebuffer_bits(eGPUTextureFormat tex_format)
+{
+ switch (tex_format) {
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ case GPU_DEPTH_COMPONENT32F:
+ return GPU_DEPTH_BIT;
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH32F_STENCIL8:
+ return GPU_DEPTH_BIT | GPU_STENCIL_BIT;
+ default:
+ return GPU_COLOR_BIT;
+ }
+}
+
} // namespace gpu
} // namespace blender