diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_texture_private.hh')
-rw-r--r-- | source/blender/gpu/intern/gpu_texture_private.hh | 393 |
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 |