[Bf-blender-cvs] [2c2abcc] opensubdiv-modifier: OpenSubdiv: Support GPU tessellation in edit mode
Sergey Sharybin
noreply at git.blender.org
Wed Jul 30 18:25:57 CEST 2014
Commit: 2c2abcc9c5d4216b6d73b5429ea7a481ad2ff360
Author: Sergey Sharybin
Date: Wed Jul 30 22:24:19 2014 +0600
Branches: opensubdiv-modifier
https://developer.blender.org/rB2c2abcc9c5d4216b6d73b5429ea7a481ad2ff360
OpenSubdiv: Support GPU tessellation in edit mode
This should speed up deformation-only modifications in edit
mode very well (assuming subsurf is the last modifier in the
stack).
This is so-called "seems to work" commit, requires much deeper
tests, mainly shading/texturing-wise.
===================================================================
M source/blender/blenkernel/intern/DerivedMesh.c
M source/blender/blenkernel/intern/subsurf_ccg.c
M source/blender/gpu/intern/gpu_draw.c
M source/blender/modifiers/intern/MOD_subsurf.c
===================================================================
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 76a8831..1c5ff8c 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2029,6 +2029,17 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH);
const float loop_normals_split_angle = ((Mesh *)(ob->data))->smoothresh;
+#ifdef WITH_OPENSUBDIV
+ {
+ ModifierData *last_md = ob->modifiers.last;
+ if (last_md != NULL &&
+ last_md->type == eModifierType_Subsurf)
+ {
+ dataMask &= ~CD_MASK_ORCO;
+ }
+ }
+#endif
+
modifiers_clearErrors(ob);
if (cage_r && cageIndex == -1) {
@@ -2164,9 +2175,9 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
}
if (mti->applyModifierEM)
- ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE);
+ ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
else
- ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE);
+ ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 4bfc918..4811362 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1778,7 +1778,10 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
}
/* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+static void ccgDM_drawFacesSolid(DerivedMesh *dm,
+ float (*partial_redraw_planes)[4],
+ bool fast,
+ DMSetMaterial setMaterial)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
@@ -2300,6 +2303,13 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
int a, i, numVerts, matnr, new_matnr, totface;
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ BLI_assert(!"Not currently supported");
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
@@ -2472,6 +2482,9 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
int gridOffset = 0;
int mat_nr_cache = -1;
+ /* TODO(sergey): Not currently supported, might lead to some wrong
+ * shading/texturing artifacts due to batching in OpenSubdiv.
+ */
(void) compareDrawOptions;
#ifdef WITH_OPENSUBDIV
@@ -2489,9 +2502,6 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
* this we'll need to pass proper compareDrawOptions.
*/
- /* If it happens we've got compare callback let us know. */
- BLI_assert(compareDrawOptions == NULL);
-
if (ccgSubSurf_prepareGLMesh(ss, true) == false) {
return;
}
@@ -2807,6 +2817,93 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
int useColors = flag & DM_DRAW_USE_COLORS;
int gridFaces = gridSize - 1, totface;
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ int i, matnr = -1, shademodel = -1;
+ CCGFaceIterator *fi;
+ int start_partition = 0, num_partitions = 0;
+ DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+
+ if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) {
+ return;
+ }
+
+ for (fi = ccgSubSurf_getFaceIterator(ss), i = 0;
+ !ccgFaceIterator_isStopped(fi);
+ ccgFaceIterator_next(fi), ++i)
+ {
+ CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int origIndex = ccgDM_getFaceMapIndex(ss, f);
+ int new_matnr, new_shademodel;
+
+ if (faceFlags) {
+ new_shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH))
+ ? GL_SMOOTH
+ : GL_FLAT;
+ new_matnr = faceFlags[index].mat_nr + 1;
+ }
+ else {
+ new_shademodel = GL_SMOOTH;
+ new_matnr = 1;
+ }
+
+ if (new_shademodel != shademodel || new_matnr != matnr) {
+ if (num_partitions) {
+ ccgSubSurf_drawGLMesh(ss, true,
+ start_partition, num_partitions);
+ }
+
+ start_partition = i;
+ num_partitions = 0;
+
+ /* Update material settings for the next partitions batch. */
+ if (new_shademodel != shademodel) {
+ glShadeModel(new_shademodel);
+ }
+
+ if (new_matnr != matnr) {
+ if (index == ORIGINDEX_NONE) {
+ /* XXX, no faceFlags no material */
+ draw_option = setMaterial(faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1, NULL);
+ }
+ else if (setDrawOptions) {
+ draw_option = setDrawOptions(userData, index);
+ }
+ }
+
+ /* Cache settings. */
+ shademodel = new_shademodel;
+ matnr = new_matnr;
+ }
+
+ /* TODO(sergey): This isn't actually tested.. */
+ if (draw_option == DM_DRAW_OPTION_SKIP) {
+ if (num_partitions) {
+ ccgSubSurf_drawGLMesh(ss, true,
+ start_partition, num_partitions);
+ }
+
+ start_partition = i;
+ num_partitions = 0;
+
+ continue;
+ }
+
+ num_partitions++;
+ }
+ ccgFaceIterator_free(fi);
+
+ /* Draw residual tail of the partitions. */
+ if (num_partitions) {
+ ccgSubSurf_drawGLMesh(ss, true, start_partition, num_partitions);
+ }
+
+ /* We're done with drawing if drawing happens using OpenSubdiv. */
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
/* currently unused -- each original face is handled separately */
@@ -2969,6 +3066,13 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm,
CCGKey key;
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ BLI_assert(!"Not currently supported");
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
@@ -3006,6 +3110,13 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
CCGEdgeIterator *ei;
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ BLI_assert(!"Not currently supported");
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
@@ -4213,14 +4324,34 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
/* note: editmode calculation can only run once per
* modifier stack evaluation (uses freed cache) [#36299] */
if (flags & SUBSURF_FOR_EDIT_MODE) {
+ bool use_gpu_backend = false;
int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
+ /* TODO(sergey): Same as emCache below. */
+ if ((flags & SUBSURF_IN_EDIT_MODE) && smd->mCache) {
+ ccgSubSurf_free(smd->mCache);
+ smd->mCache = NULL;
+ }
+
smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
+
+#ifdef WITH_OPENSUBDIV
+ use_gpu_backend = (flags & SUBSURF_USE_GPU_BACKEND) != 0 &&
+ openSubdiv_supportGPUDisplay() &&
+ U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE;
+
+ ccgSubSurf_setSkipGrids(smd->emCache, use_gpu_backend);
+#endif
+
ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
result = getCCGDerivedMesh(smd->emCache,
drawInteriorEdges,
- useSubsurfUv, dm, false);
+ useSubsurfUv, dm, use_gpu_backend);
+
+#ifdef WITH_OPENSUBDIV
+ ccgSubSurf_setUVCoordsFromDM(smd->emCache, dm, useSubsurfUv);
+#endif
}
else if (flags & SUBSURF_USE_RENDER_PARAMS) {
/* Do not use cache in render mode. */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index c0e7778..5be7295 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -82,6 +82,9 @@
#include "smoke_API.h"
#ifdef WITH_OPENSUBDIV
+# include "DNA_mesh_types.h"
+# include "BKE_editmesh.h"
+
# include "gpu_codegen.h"
#endif
@@ -1452,11 +1455,25 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
const bool use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) != 0; /* assumes v3d->defmaterial->preview is set */
bool use_opensubdiv = false;
- /* TODO(sergey): What to do if there's no derived final? */
- if (ob->derivedFinal != NULL) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) ob->derivedFinal;
- use_opensubdiv = ccgdm->useGpuBackend;
+#ifdef WITH_OPENSUBDIV
+ {
+ DerivedMesh *derivedFinal = NULL;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+
+ if (em != NULL) {
+ derivedFinal = em->derivedFinal;
+ }
+ else {
+ derivedFinal = ob->derivedFinal;
+ }
+
+ if (derivedFinal != NULL && derivedFinal->type == DM_TYPE_CCGDM) {
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) derivedFinal;
+ use_opensubdiv = ccgdm->useGpuBackend;
+ }
}
+#endif
#ifdef WITH_GAMEENGINE
if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 7d7c0cd..c846f2b 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -138,6 +138,12 @@ static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob),
DerivedMesh *result;
/* 'orco' using editmode flags would cause cache to be used twice in editbmesh_calc_modifiers */
SubsurfFlags ss_flags = (flag & MOD_APPLY_ORCO) ? 0 : (SUBSURF_FOR_EDIT_MODE | SUBSURF_IN_EDIT_MODE);
+ const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0;
+
+ /* TODO(sergey): Not entirely correct, only good for purposes of test. */
+ if (md->next == NULL && allow_gpu) {
+ ss_flags |= SUBSURF_USE_GPU_BACKEND;
+ }
result = subsurf_make_derived_from_derived(derivedData, smd, NULL, ss_flags);
More information about the Bf-blender-cvs
mailing list