[Bf-blender-cvs] [402442997a3] blender2.8: GPUTexture: Add Texture Buffer support.

Clément Foucault noreply at git.blender.org
Sun May 13 22:36:40 CEST 2018


Commit: 402442997a39067d6f84538770665f1baf206f79
Author: Clément Foucault
Date:   Sun May 13 22:12:32 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB402442997a39067d6f84538770665f1baf206f79

GPUTexture: Add Texture Buffer support.

This is needed by opensubdiv and can be helpfull in a lot of other cases.

===================================================================

M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/intern/gpu_texture.c

===================================================================

diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index a64b0a0a862..cc66b5dbf9b 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -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_RGBA8UI,
+	GPU_RGBA8I,
+	GPU_RGBA8,
+	GPU_RGBA32UI,
+	GPU_RGBA32I,
 	GPU_RGBA32F,
+	GPU_RGBA16UI,
+	GPU_RGBA16I,
 	GPU_RGBA16F,
-	GPU_RGBA8,
+	GPU_RGBA16,
+	GPU_RG8UI,
+	GPU_RG8I,
+	GPU_RG8,
+	GPU_RG32UI,
+	GPU_RG32I,
 	GPU_RG32F,
-	GPU_RG16F,
+	GPU_RG16UI,
 	GPU_RG16I,
+	GPU_RG16F,
 	GPU_RG16,
-	GPU_R32F,
-	GPU_R32UI,
-	GPU_R16F,
-	GPU_R16I,
-	GPU_R16UI,
-	GPU_RG8,
+	GPU_R8UI,
+	GPU_R8I,
 	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_RG8UI,
+	GPU_R32UI,
 	GPU_R32I,
-	GPU_R16,
-	GPU_R8I,
-	GPU_R8UI,
-#endif
+	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);
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 19e26dcce8c..3961278ad1a 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -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);



More information about the Bf-blender-cvs mailing list