[Bf-blender-cvs] [d9cc3f5] experimental-build: Support for multi-sample off-screen buffers

Campbell Barton noreply at git.blender.org
Tue Oct 13 14:13:46 CEST 2015


Commit: d9cc3f50682302ca12e3a4fa0390c857f2013c25
Author: Campbell Barton
Date:   Tue Oct 13 22:36:02 2015 +1100
Branches: experimental-build
https://developer.blender.org/rBd9cc3f50682302ca12e3a4fa0390c857f2013c25

Support for multi-sample off-screen buffers

Currently only used for OpenGL render,
replaces slower accumulation buffer which simply did multiple renders.

Reviewers: psy-fi, brecht, sergey

Differential Revision: https://developer.blender.org/D1556

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

M	source/blender/editors/render/render_opengl.c
M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/gpu/GPU_extensions.h
M	source/blender/gpu/intern/gpu_extensions.c

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

diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 954fcde..c8ced55 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -375,54 +375,11 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
 
 		rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
 
-		if ((scene->r.mode & R_OSA) == 0) {
-			ED_view3d_draw_offscreen(
-			        scene, v3d, ar, sizex, sizey, NULL, winmat,
-			        draw_bgpic, draw_sky, is_persp,
-			        oglrender->ofs, oglrender->fx, &fx_settings, viewname);
-			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
-		}
-		else {
-			/* simple accumulation, less hassle then FSAA FBO's */
-			static float jit_ofs[32][2];
-			float winmat_jitter[4][4];
-			int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1");
-			int i, j;
-
-			BLI_jitter_init(jit_ofs, scene->r.osa);
-
-			/* first sample buffer, also initializes 'rv3d->persmat' */
-			ED_view3d_draw_offscreen(
-			        scene, v3d, ar, sizex, sizey, NULL, winmat,
-			        draw_bgpic, draw_sky, is_persp,
-			        oglrender->ofs, oglrender->fx, &fx_settings, viewname);
-			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
-
-			for (i = 0; i < sizex * sizey * 4; i++)
-				accum_buffer[i] = rect[i];
-
-			/* skip the first sample */
-			for (j = 1; j < scene->r.osa; j++) {
-				copy_m4_m4(winmat_jitter, winmat);
-				window_translate_m4(winmat_jitter, rv3d->persmat,
-				                    (jit_ofs[j][0] * 2.0f) / sizex,
-				                    (jit_ofs[j][1] * 2.0f) / sizey);
-
-				ED_view3d_draw_offscreen(
-				        scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
-				        draw_bgpic, draw_sky, is_persp,
-				        oglrender->ofs, oglrender->fx, &fx_settings, viewname);
-				GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
-
-				for (i = 0; i < sizex * sizey * 4; i++)
-					accum_buffer[i] += rect[i];
-			}
-
-			for (i = 0; i < sizex * sizey * 4; i++)
-				rect[i] = accum_buffer[i] / scene->r.osa;
-
-			MEM_freeN(accum_buffer);
-		}
+		ED_view3d_draw_offscreen(
+		        scene, v3d, ar, sizex, sizey, NULL, winmat,
+		        draw_bgpic, draw_sky, is_persp,
+		        oglrender->ofs, oglrender->fx, &fx_settings, viewname);
+		GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
 
 		GPU_offscreen_unbind(oglrender->ofs, true); /* unbind */
 	}
@@ -546,6 +503,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
 	const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
 	const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
 	char err_out[256] = "unknown";
+	int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
 
 	if (G.background) {
 		BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)");
@@ -585,7 +543,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
 	sizey = (scene->r.size * scene->r.ysch) / 100;
 
 	/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
-	ofs = GPU_offscreen_create(sizex, sizey, err_out);
+	ofs = GPU_offscreen_create(sizex, sizey, samples, err_out);
 
 	if (!ofs) {
 		BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 18c178f..bb34497 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1381,7 +1381,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
 		}
 
 		if (!rv3d->gpuoffscreen) {
-			rv3d->gpuoffscreen = GPU_offscreen_create(w, h, error);
+			rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
 
 			if (!rv3d->gpuoffscreen)
 				fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
@@ -3263,7 +3263,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
 	glPushAttrib(GL_LIGHTING_BIT);
 
 	/* bind */
-	ofs = GPU_offscreen_create(sizex, sizey, err_out);
+	ofs = GPU_offscreen_create(sizex, sizey, 4, err_out);
 	if (ofs == NULL) {
 		glPopAttrib();
 		return NULL;
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 0e8d204..2dadd38 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -130,6 +130,8 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
 GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
 GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
 GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
 GPUTexture *GPU_texture_from_blender(struct Image *ima,
 	struct ImageUser *iuser, bool is_data, double time, int mipmap);
 GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
@@ -179,7 +181,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
  * - wrapper around framebuffer and texture for simple offscreen drawing
  * - changes size if graphics card can't support it */
 
-GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]);
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
 void GPU_offscreen_free(GPUOffScreen *ofs);
 void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
 void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e30eeeb..fc3a8d2 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -110,6 +110,7 @@ static struct GPUGlobal {
 	int glslsupport;
 	int extdisabled;
 	int colordepth;
+	int samples_max;
 	int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
 	int dlistsdisabled; /* Legacy ATI driver does not support display lists well */
 	GPUDeviceType device;
@@ -179,6 +180,7 @@ void gpu_extensions_init(void)
 	glGetIntegerv(GL_GREEN_BITS, &g);
 	glGetIntegerv(GL_BLUE_BITS, &b);
 	GG.colordepth = r + g + b; /* assumes same depth for RGB */
+	glGetIntegerv(GL_MAX_SAMPLES, &GG.samples_max);
 
 	vendor = (const char *)glGetString(GL_VENDOR);
 	renderer = (const char *)glGetString(GL_RENDERER);
@@ -384,6 +386,7 @@ struct GPUTexture {
 	int number;         /* number for multitexture binding */
 	int refcount;       /* reference count */
 	GLenum target;      /* GL_TEXTURE_* */
+	GLenum target_simple; /* same as target, (but no multisample) */
 	GLuint bindcode;    /* opengl identifier for texture */
 	int fromblender;    /* we got the texture from Blender */
 
@@ -421,7 +424,7 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i
 }
 
 static GPUTexture *GPU_texture_create_nD(
-        int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components,
+        int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components, int samples,
         char err_out[256])
 {
 	GPUTexture *tex;
@@ -431,12 +434,17 @@ static GPUTexture *GPU_texture_create_nD(
 	if (depth && !GLEW_ARB_depth_texture)
 		return NULL;
 
+	if (samples) {
+		CLAMP_MAX(samples, GG.samples_max);
+	}
+
 	tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
 	tex->w = tex->w_orig = w;
 	tex->h = tex->h_orig = h;
 	tex->number = -1;
 	tex->refcount = 1;
-	tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
+	tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
+	tex->target_simple = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
 	tex->depth = tex->depth_orig = depth;
 	tex->fb_attachment = -1;
 
@@ -523,8 +531,13 @@ static GPUTexture *GPU_texture_create_nD(
 		}
 	}
 	else {
-		glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
-		             format, type, NULL);
+		if (samples) {
+			glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+		}
+		else {
+			glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
+			             format, type, NULL);
+		}
 
 		if (fpixels) {
 			glTexSubImage2D(tex->target, 0, 0, 0, w, h,
@@ -541,23 +554,23 @@ static GPUTexture *GPU_texture_create_nD(
 		MEM_freeN(pixels);
 
 	if (depth) {
-		glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-		glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
-		glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
-		glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);  
+		glTexParameteri(tex->target_simple, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		glTexParameteri(tex->target_simple, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexParameteri(tex->target_simple, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
+		glTexParameteri(tex->target_simple, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+		glTexParameteri(tex->target_simple, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
 	}
 	else {
-		glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-		glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexParameteri(tex->target_simple, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameteri(tex->target_simple, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	}
 
-	if (tex->target != GL_TEXTURE_1D) {
-		glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	if (tex->target_simple != GL_TEXTURE_1D) {
+		glTexParameteri(tex->target_simple, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list