GPUTexture: Add Texture Buffer support.
This is needed by opensubdiv and can be helpfull in a lot of other cases.
This commit is contained in:
parent
ddf308b04a
commit
402442997a
|
@ -39,6 +39,7 @@ extern "C" {
|
|||
struct Image;
|
||||
struct ImageUser;
|
||||
struct PreviewImage;
|
||||
struct Gwn_VertBuf;
|
||||
|
||||
struct GPUFrameBuffer;
|
||||
typedef struct GPUTexture GPUTexture;
|
||||
|
@ -62,38 +63,36 @@ typedef struct GPUTexture GPUTexture;
|
|||
* specification. */
|
||||
typedef enum GPUTextureFormat {
|
||||
/* Formats texture & renderbuffer */
|
||||
GPU_RGBA32F,
|
||||
GPU_RGBA16F,
|
||||
GPU_RGBA8,
|
||||
GPU_RG32F,
|
||||
GPU_RG16F,
|
||||
GPU_RG16I,
|
||||
GPU_RG16,
|
||||
GPU_R32F,
|
||||
GPU_R32UI,
|
||||
GPU_R16F,
|
||||
GPU_R16I,
|
||||
GPU_R16UI,
|
||||
GPU_RG8,
|
||||
GPU_R8,
|
||||
#if 0
|
||||
GPU_RGBA32I,
|
||||
GPU_RGBA32UI,
|
||||
GPU_RGBA16,
|
||||
GPU_RGBA16I,
|
||||
GPU_RGBA16UI,
|
||||
GPU_RGBA8I,
|
||||
GPU_RGBA8UI,
|
||||
GPU_RG32I,
|
||||
GPU_RG32UI,
|
||||
GPU_RG16UI,
|
||||
GPU_RG8I,
|
||||
GPU_RGBA8I,
|
||||
GPU_RGBA8,
|
||||
GPU_RGBA32UI,
|
||||
GPU_RGBA32I,
|
||||
GPU_RGBA32F,
|
||||
GPU_RGBA16UI,
|
||||
GPU_RGBA16I,
|
||||
GPU_RGBA16F,
|
||||
GPU_RGBA16,
|
||||
GPU_RG8UI,
|
||||
GPU_R32I,
|
||||
GPU_R16,
|
||||
GPU_R8I,
|
||||
GPU_RG8I,
|
||||
GPU_RG8,
|
||||
GPU_RG32UI,
|
||||
GPU_RG32I,
|
||||
GPU_RG32F,
|
||||
GPU_RG16UI,
|
||||
GPU_RG16I,
|
||||
GPU_RG16F,
|
||||
GPU_RG16,
|
||||
GPU_R8UI,
|
||||
#endif
|
||||
GPU_R8I,
|
||||
GPU_R8,
|
||||
GPU_R32UI,
|
||||
GPU_R32I,
|
||||
GPU_R32F,
|
||||
GPU_R16UI,
|
||||
GPU_R16I,
|
||||
GPU_R16F,
|
||||
GPU_R16, /* Max texture buffer format. */
|
||||
|
||||
/* Special formats texture & renderbuffer */
|
||||
#if 0
|
||||
|
@ -157,6 +156,7 @@ GPUTexture *GPU_texture_create_3D(
|
|||
int w, int h, int d, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_cube(
|
||||
int w, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_from_vertbuf(struct Gwn_VertBuf *vert);
|
||||
|
||||
GPUTexture *GPU_texture_from_blender(
|
||||
struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "BKE_global.h"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
#include "GPU_debug.h"
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_extensions.h"
|
||||
|
@ -608,6 +609,57 @@ static GPUTexture *GPU_texture_cube_create(
|
|||
return tex;
|
||||
}
|
||||
|
||||
/* Special buffer textures. data_type must be compatible with the buffer content. */
|
||||
static GPUTexture *GPU_texture_create_buffer(GPUTextureFormat data_type, const GLuint buffer)
|
||||
{
|
||||
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
|
||||
tex->number = -1;
|
||||
tex->refcount = 1;
|
||||
tex->format = data_type;
|
||||
tex->components = gpu_texture_get_component_count(data_type);
|
||||
tex->format_flag = 0;
|
||||
tex->target_base = tex->target = GL_TEXTURE_BUFFER;
|
||||
|
||||
GLenum format, internalformat, data_format;
|
||||
internalformat = gpu_texture_get_format(tex->components, data_type, &format, &data_format,
|
||||
&tex->format_flag, &tex->bytesize);
|
||||
|
||||
if (!(ELEM(data_type, GPU_R8, GPU_R16) ||
|
||||
ELEM(data_type, GPU_R16F, GPU_R32F) ||
|
||||
ELEM(data_type, GPU_R8I, GPU_R16I, GPU_R32I) ||
|
||||
ELEM(data_type, GPU_R8UI, GPU_R16UI, GPU_R32UI) ||
|
||||
ELEM(data_type, GPU_RG8, GPU_RG16) ||
|
||||
ELEM(data_type, GPU_RG16F, GPU_RG32F) ||
|
||||
ELEM(data_type, GPU_RG8I, GPU_RG16I, GPU_RG32I) ||
|
||||
ELEM(data_type, GPU_RG8UI, GPU_RG16UI, GPU_RG32UI) ||
|
||||
//ELEM(data_type, GPU_RGB32F, GPU_RGB32I, GPU_RGB32UI) || /* Not available until gl 4.0 */
|
||||
ELEM(data_type, GPU_RGBA8, GPU_RGBA16) ||
|
||||
ELEM(data_type, GPU_RGBA16F, GPU_RGBA32F) ||
|
||||
ELEM(data_type, GPU_RGBA8I, GPU_RGBA16I, GPU_RGBA32I) ||
|
||||
ELEM(data_type, GPU_RGBA8UI, GPU_RGBA16UI, GPU_RGBA32UI)))
|
||||
{
|
||||
fprintf(stderr, "GPUTexture: invalid format for texture buffer");
|
||||
GPU_texture_free(tex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Generate Texture object */
|
||||
glGenTextures(1, &tex->bindcode);
|
||||
|
||||
if (!tex->bindcode) {
|
||||
fprintf(stderr, "GPUTexture: texture create failed");
|
||||
GPU_texture_free(tex);
|
||||
BLI_assert(0 && "glGenTextures failled: Are you sure a valid OGL context is active on this thread?");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glBindTexture(tex->target, tex->bindcode);
|
||||
glTexBuffer(tex->target, internalformat, buffer);
|
||||
glBindTexture(tex->target, 0);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, double UNUSED(time), int mipmap)
|
||||
{
|
||||
int gputt;
|
||||
|
@ -768,6 +820,74 @@ GPUTexture *GPU_texture_create_cube(
|
|||
data_type, err_out);
|
||||
}
|
||||
|
||||
GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert)
|
||||
{
|
||||
Gwn_VertFormat *format = &vert->format;
|
||||
Gwn_VertAttr *attr = &format->attribs[0];
|
||||
|
||||
/* Detect incompatible cases (not supported by texture buffers) */
|
||||
BLI_assert(format->attrib_ct == 1 && vert->vbo_id != 0);
|
||||
BLI_assert(attr->comp_ct != 3); /* Not until OGL 4.0 */
|
||||
BLI_assert(attr->comp_type != GWN_COMP_I10);
|
||||
BLI_assert(attr->fetch_mode != GWN_FETCH_INT_TO_FLOAT);
|
||||
|
||||
unsigned int byte_per_comp = attr->sz / attr->comp_ct;
|
||||
bool is_uint = ELEM(attr->comp_type, GWN_COMP_U8, GWN_COMP_U16, GWN_COMP_U32);
|
||||
|
||||
/* Cannot fetch signed int or 32bit ints as normalized float. */
|
||||
if (attr->fetch_mode == GWN_FETCH_INT_TO_FLOAT_UNIT) {
|
||||
BLI_assert(is_uint || byte_per_comp <= 2);
|
||||
}
|
||||
|
||||
GPUTextureFormat data_type;
|
||||
switch (attr->fetch_mode) {
|
||||
case GWN_FETCH_FLOAT:
|
||||
switch (attr->comp_ct) {
|
||||
case 1: data_type = GPU_R32F; break;
|
||||
case 2: data_type = GPU_RG32F; break;
|
||||
// case 3: data_type = GPU_RGB32F; break; /* Not supported */
|
||||
default: data_type = GPU_RGBA32F; break;
|
||||
}
|
||||
break;
|
||||
case GWN_FETCH_INT:
|
||||
switch (attr->comp_ct) {
|
||||
case 1:
|
||||
switch (byte_per_comp) {
|
||||
case 1: data_type = (is_uint) ? GPU_R8UI : GPU_R8I; break;
|
||||
case 2: data_type = (is_uint) ? GPU_R16UI : GPU_R16I; break;
|
||||
default: data_type = (is_uint) ? GPU_R32UI : GPU_R32I; break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (byte_per_comp) {
|
||||
case 1: data_type = (is_uint) ? GPU_RG8UI : GPU_RG8I; break;
|
||||
case 2: data_type = (is_uint) ? GPU_RG16UI : GPU_RG16I; break;
|
||||
default: data_type = (is_uint) ? GPU_RG32UI : GPU_RG32I; break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (byte_per_comp) {
|
||||
case 1: data_type = (is_uint) ? GPU_RGBA8UI : GPU_RGBA8I; break;
|
||||
case 2: data_type = (is_uint) ? GPU_RGBA16UI : GPU_RGBA16I; break;
|
||||
default: data_type = (is_uint) ? GPU_RGBA32UI : GPU_RGBA32I; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GWN_FETCH_INT_TO_FLOAT_UNIT:
|
||||
switch (attr->comp_ct) {
|
||||
case 1: data_type = (byte_per_comp == 1) ? GPU_R8 : GPU_R16; break;
|
||||
case 2: data_type = (byte_per_comp == 1) ? GPU_RG8 : GPU_RG16; break;
|
||||
default: data_type = (byte_per_comp == 1) ? GPU_RGBA8 : GPU_RGBA16; break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
|
||||
return GPU_texture_create_buffer(data_type, vert->vbo_id);
|
||||
}
|
||||
|
||||
void GPU_texture_update(GPUTexture *tex, const float *pixels)
|
||||
{
|
||||
BLI_assert(tex->format > -1);
|
||||
|
|
Loading…
Reference in New Issue