[Bf-blender-cvs] [2466c4f] master: OpenSubdiv: Add OpenSubdiv files which are related on the CCGSubSurf and GPU

Sergey Sharybin noreply at git.blender.org
Mon Jul 20 22:31:01 CEST 2015


Commit: 2466c4f8cebd3977f29524d79050feff44b40fff
Author: Sergey Sharybin
Date:   Mon Jul 20 15:27:47 2015 +0200
Branches: master
https://developer.blender.org/rB2466c4f8cebd3977f29524d79050feff44b40fff

OpenSubdiv: Add OpenSubdiv files which are related on the CCGSubSurf and GPU

Those files are still not in use (SCons will tyr to compile new CCGSubSurf files
but no code will be in use at all because those new files are fully wrapped by
ifdef WITH_OPENSUBDIV check).

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

A	source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
A	source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
A	source/blender/gpu/shaders/gpu_shader_geometry.glsl

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

diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
new file mode 100644
index 0000000..d3898d9
--- /dev/null
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -0,0 +1,883 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+ *  \ingroup bke
+ */
+
+#ifdef WITH_OPENSUBDIV
+
+#include "MEM_guardedalloc.h"
+#include "BLI_sys_types.h" // for intptr_t support
+
+#include "BLI_utildefines.h" /* for BLI_assert */
+#include "BLI_math.h"
+
+#include "CCGSubSurf.h"
+#include "CCGSubSurf_intern.h"
+
+#include "BKE_DerivedMesh.h"
+
+#include "DNA_userdef_types.h"
+
+#include "opensubdiv_capi.h"
+#include "opensubdiv_converter_capi.h"
+
+#include "GL/glew.h"
+
+#define OSD_LOG if (false) printf
+
+static bool compare_ccg_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
+{
+	const int num_verts = dm->getNumVerts(dm);
+	const int num_edges = dm->getNumEdges(dm);
+	const int num_polys = dm->getNumPolys(dm);
+	const MEdge *medge = dm->getEdgeArray(dm);
+	const MLoop *mloop = dm->getLoopArray(dm);
+	const MPoly *mpoly = dm->getPolyArray(dm);
+
+	/* Quick preliminary tests based on the number of verts and facces. */
+	{
+		if (num_verts != ss->vMap->numEntries ||
+		    num_edges != ss->eMap->numEntries ||
+		    num_polys != ss->fMap->numEntries)
+		{
+			return false;
+		}
+	}
+
+	/* Rather slow check for faces topology change. */
+	{
+		CCGFaceIterator ccg_face_iter;
+		for (ccgSubSurf_initFaceIterator(ss, &ccg_face_iter);
+		     !ccgFaceIterator_isStopped(&ccg_face_iter);
+		     ccgFaceIterator_next(&ccg_face_iter))
+		{
+			/*const*/ CCGFace *ccg_face = ccgFaceIterator_getCurrent(&ccg_face_iter);
+			const int poly_index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
+			const MPoly *mp = &mpoly[poly_index];
+			int corner;
+			if (ccg_face->numVerts != mp->totloop) {
+				return false;
+			}
+			for (corner = 0; corner < ccg_face->numVerts; corner++) {
+				/*const*/ CCGVert *ccg_vert = FACE_getVerts(ccg_face)[corner];
+				const int vert_index = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert));
+				if (vert_index != mloop[mp->loopstart + corner].v) {
+					return false;
+				}
+			}
+		}
+	}
+
+	/* Check for edge topology change. */
+	{
+		CCGEdgeIterator ccg_edge_iter;
+		for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter);
+		     !ccgEdgeIterator_isStopped(&ccg_edge_iter);
+		     ccgEdgeIterator_next(&ccg_edge_iter))
+		{
+			/* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter);
+			/* const */ CCGVert *ccg_vert1 = ccg_edge->v0;
+			/* const */ CCGVert *ccg_vert2 = ccg_edge->v1;
+			const int ccg_vert1_index = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert1));
+			const int ccg_vert2_index = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert2));
+			const int edge_index = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
+			const MEdge *me = &medge[edge_index];
+			if (me->v1 != ccg_vert1_index || me->v2 != ccg_vert2_index) {
+				return false;
+			}
+		}
+	}
+
+	/* TODO(sergey): Crease topology changes detection. */
+	{
+		CCGEdgeIterator ccg_edge_iter;
+		for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter);
+		     !ccgEdgeIterator_isStopped(&ccg_edge_iter);
+		     ccgEdgeIterator_next(&ccg_edge_iter))
+		{
+			/* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter);
+			const int edge_index = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
+			if (ccg_edge->crease != medge[edge_index].crease) {
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+static bool compare_osd_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
+{
+	const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+	OpenSubdiv_Converter converter;
+	bool result;
+	if (ss->osd_mesh == NULL && ss->osd_topology_refiner == NULL) {
+		return true;
+	}
+	/* TODO(sergey): De-duplicate with topology counter at the bottom of
+	 * the file.
+	 */
+	if (ss->osd_topology_refiner != NULL) {
+		topology_refiner = ss->osd_topology_refiner;
+	}
+	else {
+		topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+	}
+	ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter);
+	result = openSubdiv_topologyRefnerCompareConverter(topology_refiner,
+	                                                   &converter);
+	ccgSubSurf_converter_free(&converter);
+	return result;
+}
+
+static bool opensubdiv_is_topology_changed(CCGSubSurf *ss, DerivedMesh *dm)
+{
+	if (ss->osd_compute != U.opensubdiv_compute_type) {
+		return true;
+	}
+	if (ss->osd_topology_refiner != NULL) {
+		int levels = openSubdiv_topologyRefinerGetSubdivLevel(
+		        ss->osd_topology_refiner);
+		BLI_assert(ss->osd_mesh_invalid == true);
+		if (levels != ss->subdivLevels) {
+			return true;
+		}
+	}
+	if (ss->osd_mesh != NULL && ss->osd_mesh_invalid == false) {
+		const OpenSubdiv_TopologyRefinerDescr *topology_refiner =
+		        openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+		int levels = openSubdiv_topologyRefinerGetSubdivLevel(topology_refiner);
+		BLI_assert(ss->osd_topology_refiner == NULL);
+		if (levels != ss->subdivLevels) {
+			return true;
+		}
+	}
+	if (ss->skip_grids == false) {
+		return compare_ccg_derivedmesh_topology(ss, dm) == false;
+	}
+	else {
+		return compare_osd_derivedmesh_topology(ss, dm) == false;
+	}
+	return false;
+}
+
+void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
+{
+	if (opensubdiv_is_topology_changed(ss, dm)) {
+		/* ** Make sure both GPU and CPU backends are properly reset. ** */
+
+		ss->osd_coarse_coords_invalid = true;
+		ss->osd_uvs_invalid = true;
+
+		/* Reset GPU part. */
+		ss->osd_mesh_invalid = true;
+		if (ss->osd_topology_refiner != NULL) {
+			openSubdiv_deleteTopologyRefinerDescr(ss->osd_topology_refiner);
+			ss->osd_topology_refiner = NULL;
+		}
+
+		/* Reste CPU side. */
+		if (ss->osd_evaluator != NULL) {
+			openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
+			ss->osd_evaluator = NULL;
+		}
+	}
+}
+
+static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss)
+{
+	BLI_assert(ss->meshIFC.numLayers == 3);
+	openSubdiv_osdGLMeshUpdateVertexBuffer(ss->osd_mesh,
+	                                       (float *) ss->osd_coarse_coords,
+	                                       0,
+	                                       ss->osd_num_coarse_coords);
+}
+
+bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
+{
+	int compute_type;
+
+	switch (U.opensubdiv_compute_type) {
+#define CHECK_COMPUTE_TYPE(type) \
+		case USER_OPENSUBDIV_COMPUTE_ ## type: \
+			compute_type = OPENSUBDIV_EVALUATOR_ ## type; \
+			break;
+		CHECK_COMPUTE_TYPE(CPU)
+		CHECK_COMPUTE_TYPE(OPENMP)
+		CHECK_COMPUTE_TYPE(OPENCL)
+		CHECK_COMPUTE_TYPE(CUDA)
+		CHECK_COMPUTE_TYPE(GLSL_TRANSFORM_FEEDBACK)
+		CHECK_COMPUTE_TYPE(GLSL_COMPUTE)
+#undef CHECK_COMPUTE_TYPE
+	}
+
+	if (ss->osd_vao == 0) {
+		glGenVertexArrays(1, &ss->osd_vao);
+	}
+
+	if (ss->osd_mesh_invalid) {
+		if (ss->osd_mesh != NULL) {
+			openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+			ss->osd_mesh = NULL;
+		}
+		ss->osd_mesh_invalid = false;
+	}
+
+	if (ss->osd_mesh == NULL) {
+		ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(
+		        ss->osd_topology_refiner,
+		        compute_type,
+		        ss->subdivLevels,
+		        ss->osd_subsurf_uv);
+		ss->osd_topology_refiner = NULL;
+
+		if (UNLIKELY(ss->osd_mesh == NULL)) {
+			/* Most likely compute device is not available. */
+			return false;
+		}
+
+		ccgSubSurf__updateGLMeshCoords(ss);
+
+		openSubdiv_osdGLMeshRefine(ss->osd_mesh);
+		openSubdiv_osdGLMeshSynchronize(ss->osd_mesh);
+
+		glBindVertexArray(ss->osd_vao);
+		glBindBuffer(GL_ARRAY_BUFFER,
+		             openSubdiv_getOsdGLMeshVertexBuffer(ss->osd_mesh));
+
+		glEnableVertexAttribArray(0);
+		glEnableVertexAttribArray(1);
+		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
+		                      sizeof(GLfloat) * 6, 0);
+		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
+		                      sizeof(GLfloat) * 6, (float *)12);
+
+		glBindBuffer(GL_ARRAY_BUFFER, 0);
+	}
+	else if (ss->osd_coarse_coords_invalid) {
+		ccgSubSurf__updateGLMeshCoords(ss);
+		openSubdiv_osdGLMeshRefine(ss->osd_mesh);
+		openSubdiv_osdGLMeshSynchronize(ss->osd_mesh);
+		ss->osd_coarse_coords_invalid = false;
+	}
+
+	openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, ss->osd_uv_index);
+
+	return true;
+}
+
+void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
+                           int start_partition, int num_partitions)
+{
+	if (LIKELY(ss->osd_mesh != NULL)) {
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
+		             openSubdiv_getOsdGLMeshPatchIndexBuffer(ss->osd_mesh));
+
+		openSubdiv_osdGLMeshBindVertexBuffer(ss->osd_mesh);
+		glBindVertexArray(ss->osd_vao);
+		openSubdiv_osdGLMeshDisplay(ss->osd_mesh, fill_quads,
+		                            start_partition, num_partitions);
+		glBindVertexArray(0);
+		glBindBuffer(GL_ARRAY_BUFFER, 0);
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+	}
+}
+
+void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids)
+{
+	ss->skip_grids = skip_grids;
+}
+
+bool ccgSubSurf_needGrids(CCGSubSurf *ss)
+{
+	return ss->skip_grids == false;
+}
+
+BLI_INLINE void ccgSubSurf__mapGridToFace(int S, float grid_u, float grid_v,
+                                          float *face_u, float *face_v)

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list