Merge pull request #1021 from davidgyu/osd_patch_eval

This is great, David. Thanks
This commit is contained in:
Barry Fowler 2018-11-16 17:14:14 -08:00 committed by GitHub
commit d7e0449fb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 2197 additions and 1036 deletions

View File

@ -117,7 +117,9 @@ int g_tessLevelMin = 1;
GLuint g_transformUB = 0, GLuint g_transformUB = 0,
g_transformBinding = 0, g_transformBinding = 0,
g_tessellationUB = 0, g_tessellationUB = 0,
g_tessellationBinding = 0; g_tessellationBinding = 0,
g_fvarArrayDataUB = 0,
g_fvarArrayDataBinding = 0;
struct Transform { struct Transform {
float ModelViewMatrix[16]; float ModelViewMatrix[16];
@ -685,6 +687,11 @@ public:
if (uboIndex != GL_INVALID_INDEX) if (uboIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, uboIndex, g_tessellationBinding); glUniformBlockBinding(program, uboIndex, g_tessellationBinding);
g_fvarArrayDataBinding = 2;
uboIndex = glGetUniformBlockIndex(program, "FVarArrayData");
if (uboIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, uboIndex, g_fvarArrayDataBinding);
// assign texture locations // assign texture locations
GLint loc; GLint loc;
glUseProgram(program); glUseProgram(program);
@ -708,6 +715,9 @@ ShaderCache g_shaderCache;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void static void
updateUniformBlocks() { updateUniformBlocks() {
using namespace OpenSubdiv;
if (!g_transformUB) { if (!g_transformUB) {
glGenBuffers(1, &g_transformUB); glGenBuffers(1, &g_transformUB);
glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB); glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB);
@ -740,6 +750,28 @@ updateUniformBlocks() {
glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB); glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB);
// Update and bind fvar patch array state
Osd::PatchArrayVector const &fvarPatchArrays =
g_mesh->GetPatchTable()->GetFVarPatchArrays();
if (! fvarPatchArrays.empty()) {
// bind patch arrays UBO (std140 struct size padded to vec4 alignment)
int patchArraySize =
sizeof(GLint) * ((sizeof(Osd::PatchArray)/sizeof(GLint) + 3) & ~3);
if (!g_fvarArrayDataUB) {
glGenBuffers(1, &g_fvarArrayDataUB);
}
glBindBuffer(GL_UNIFORM_BUFFER, g_fvarArrayDataUB);
glBufferData(GL_UNIFORM_BUFFER,
fvarPatchArrays.size()*patchArraySize, NULL, GL_STATIC_DRAW);
for (int i=0; i<(int)fvarPatchArrays.size(); ++i) {
glBufferSubData(GL_UNIFORM_BUFFER,
i*patchArraySize, sizeof(Osd::PatchArray), &fvarPatchArrays[i]);
}
glBindBufferBase(GL_UNIFORM_BUFFER,
g_fvarArrayDataBinding, g_fvarArrayDataUB);
}
} }
static void static void

View File

@ -167,48 +167,32 @@ out block {
} outpt; } outpt;
uniform isamplerBuffer OsdFVarParamBuffer; uniform isamplerBuffer OsdFVarParamBuffer;
layout(std140) uniform FVarArrayData {
OsdPatchArray fvarPatchArray[2];
};
vec2 vec2
interpolateFaceVarying(vec2 uv, int fvarOffset) interpolateFaceVarying(vec2 uv, int fvarOffset)
{ {
int patchIndex = OsdGetPatchIndex(gl_PrimitiveID); int patchIndex = OsdGetPatchIndex(gl_PrimitiveID);
#if defined(SHADING_FACEVARYING_SMOOTH_BSPLINE_BASIS) OsdPatchArray array = fvarPatchArray[0];
float wP[16], wDs[16], wDt[16], wDss[16], wDst[16], wDtt[16];
int patchCVs = 16;
int patchStride = patchCVs;
ivec3 fvarPatchParam = texelFetch(OsdFVarParamBuffer, patchIndex).xyz; ivec3 fvarPatchParam = texelFetch(OsdFVarParamBuffer, patchIndex).xyz;
int boundaryMask = OsdGetPatchBoundaryMask(fvarPatchParam); OsdPatchParam param = OsdPatchParamInit(fvarPatchParam.x,
OsdGetBSplinePatchWeights(uv.s, uv.t, 1.0f, boundaryMask, wP, wDs, wDt, wDss, wDst, wDtt); fvarPatchParam.y,
fvarPatchParam.z);
#elif defined(SHADING_FACEVARYING_SMOOTH_GREGORY_BASIS) int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
int patchCVs = 20;
int patchStride = patchCVs;
ivec3 fvarPatchParam = texelFetch(OsdFVarParamBuffer, patchIndex).xyz;
if (OsdGetPatchIsRegular(fvarPatchParam)) {
float wP16[16], wDs16[16], wDt16[16], wDss16[16], wDst16[16], wDtt16[16];
patchCVs = 16;
int boundaryMask = OsdGetPatchBoundaryMask(fvarPatchParam);
OsdGetBSplinePatchWeights(uv.s, uv.t, 1.0f, boundaryMask, wP16, wDs16, wDt16, wDss16, wDst16, wDtt16);
for (int i=0; i<patchCVs; ++i) {
wP[i] = wP16[i];
}
} else {
OsdGetGregoryPatchWeights(uv.s, uv.t, 1.0f, wP, wDs, wDt, wDss, wDst, wDtt);
}
#else float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
float wP[4], wDs[4], wDt[4], wDss[4], wDst[4], wDtt[4]; int numPoints = OsdEvaluatePatchBasisNormalized(patchType, param,
int patchCVs = 4; uv.s, uv.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
int patchStride = patchCVs;
OsdGetBilinearPatchWeights(uv.s, uv.t, 1.0f, wP, wDs, wDt, wDss, wDst, wDtt);
#endif
int primOffset = patchIndex * patchStride; int primOffset = patchIndex * array.stride;
vec2 result = vec2(0); vec2 result = vec2(0);
for (int i=0; i<patchCVs; ++i) { for (int i=0; i<numPoints; ++i) {
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset;
vec2 cv = vec2(texelFetch(OsdFVarDataBuffer, index).s, vec2 cv = vec2(texelFetch(OsdFVarDataBuffer, index).s,
texelFetch(OsdFVarDataBuffer, index + 1).s); texelFetch(OsdFVarDataBuffer, index + 1).s);
@ -228,8 +212,13 @@ void emit(int index, vec3 normal)
#endif #endif
#ifdef LOOP // ----- scheme : LOOP #ifdef LOOP // ----- scheme : LOOP
vec2 uv; vec2 trist[3] = vec2[](vec2(0,0), vec2(1,0), vec2(0,1));
OSD_COMPUTE_FACE_VARYING_TRI_2(uv, /*fvarOffste=*/0, index); #ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
vec2 st = trist[index];
#else
vec2 st = inpt[index].v.tessCoord;
#endif
vec2 uv = interpolateFaceVarying(st, /*fvarOffset*/0);
#else // ----- scheme : CATMARK / BILINEAR #else // ----- scheme : CATMARK / BILINEAR

View File

@ -53,7 +53,9 @@ set(PUBLIC_HEADER_FILES
) )
list(APPEND KERNEL_FILES list(APPEND KERNEL_FILES
patchBasisCommonTypes.h
patchBasisCommon.h patchBasisCommon.h
patchBasisCommonEval.h
) )
set(DOXY_HEADER_FILES ${PUBLIC_HEADER_FILES}) set(DOXY_HEADER_FILES ${PUBLIC_HEADER_FILES})

View File

@ -41,9 +41,15 @@ namespace Osd {
static const char *clSource = static const char *clSource =
#include "clKernel.gen.h" #include "clKernel.gen.h"
; ;
static const char *patchBasisTypesSource =
#include "patchBasisCommonTypes.gen.h"
;
static const char *patchBasisSource = static const char *patchBasisSource =
#include "patchBasisCommon.gen.h" #include "patchBasisCommon.gen.h"
; ;
static const char *patchBasisEvalSource =
#include "patchBasisCommonEval.gen.h"
;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -166,8 +172,12 @@ CLEvaluator::Compile(BufferDescriptor const &srcDesc,
<< "#define OSD_PATCH_BASIS_OPENCL\n"; << "#define OSD_PATCH_BASIS_OPENCL\n";
std::string defineStr = defines.str(); std::string defineStr = defines.str();
const char *sources[] = { defineStr.c_str(), patchBasisSource, clSource }; const char *sources[] = { defineStr.c_str(),
_program = clCreateProgramWithSource(_clContext, 3, sources, 0, &errNum); patchBasisTypesSource,
patchBasisSource,
patchBasisEvalSource,
clSource };
_program = clCreateProgramWithSource(_clContext, 5, sources, 0, &errNum);
if (errNum != CL_SUCCESS) { if (errNum != CL_SUCCESS) {
Far::Error(Far::FAR_RUNTIME_ERROR, Far::Error(Far::FAR_RUNTIME_ERROR,
"clCreateProgramWithSource (%d)", errNum); "clCreateProgramWithSource (%d)", errNum);

View File

@ -159,66 +159,6 @@ __kernel void computeStencilsDerivatives(
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
struct PatchArray {
int patchType;
int numPatches;
int indexBase; // an offset within the index buffer
int primitiveIdBase; // an offset within the patch param buffer
};
struct PatchCoord {
int arrayIndex;
int patchIndex;
int vertIndex;
float s;
float t;
};
struct PatchParam {
uint field0;
uint field1;
float sharpness;
};
static int getDepth(uint patchBits) {
return (patchBits & 0xf);
}
static float getParamFraction(uint patchBits) {
bool nonQuadRoot = (patchBits >> 4) & 0x1;
int depth = getDepth(patchBits);
if (nonQuadRoot) {
return 1.0f / (float)( 1 << (depth-1) );
} else {
return 1.0f / (float)( 1 << depth );
}
}
static void normalizePatchCoord(uint patchBits, float *uv) {
float frac = getParamFraction(patchBits);
int iu = (patchBits >> 22) & 0x3ff;
int iv = (patchBits >> 12) & 0x3ff;
// top left corner
float pu = (float)iu*frac;
float pv = (float)iv*frac;
// normalize u,v coordinates
uv[0] = (uv[0] - pu) / frac;
uv[1] = (uv[1] - pv) / frac;
}
static bool isRegular(uint patchBits) {
return ((patchBits >> 5) & 0x1) != 0;
}
static int getNumControlVertices(int patchType) {
return (patchType == 3) ? 4 :
(patchType == 6) ? 16 :
(patchType == 9) ? 20 : 0;
}
__kernel void computePatches(__global float *src, int srcOffset, __kernel void computePatches(__global float *src, int srcOffset,
__global float *dst, int dstOffset, __global float *dst, int dstOffset,
__global float *du, int duOffset, int duStride, __global float *du, int duOffset, int duStride,
@ -226,10 +166,10 @@ __kernel void computePatches(__global float *src, int srcOffset,
__global float *duu, int duuOffset, int duuStride, __global float *duu, int duuOffset, int duuStride,
__global float *duv, int duvOffset, int duvStride, __global float *duv, int duvOffset, int duvStride,
__global float *dvv, int dvvOffset, int dvvStride, __global float *dvv, int dvvOffset, int dvvStride,
__global struct PatchCoord *patchCoords, __global struct OsdPatchCoord *patchCoords,
__global struct PatchArray *patchArrayBuffer, __global struct OsdPatchArray *patchArrayBuffer,
__global int *patchIndexBuffer, __global int *patchIndexBuffer,
__global struct PatchParam *patchParamBuffer) { __global struct OsdPatchParam *patchParamBuffer) {
int current = get_global_id(0); int current = get_global_id(0);
if (src) src += srcOffset; if (src) src += srcOffset;
@ -240,41 +180,22 @@ __kernel void computePatches(__global float *src, int srcOffset,
if (duv) duv += duvOffset; if (duv) duv += duvOffset;
if (dvv) dvv += dvvOffset; if (dvv) dvv += dvvOffset;
struct PatchCoord coord = patchCoords[current]; struct OsdPatchCoord coord = patchCoords[current];
struct PatchArray array = patchArrayBuffer[coord.arrayIndex]; struct OsdPatchArray array = patchArrayBuffer[coord.arrayIndex];
struct OsdPatchParam param = patchParamBuffer[coord.patchIndex];
uint patchBits = patchParamBuffer[coord.patchIndex].field1; int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
int patchType = isRegular(patchBits) ? 6 : array.patchType;
float uv[2] = {coord.s, coord.t}; float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
normalizePatchCoord(patchBits, uv); int nPoints = OsdEvaluatePatchBasis(patchType, param,
float dScale = (float)(1 << getDepth(patchBits)); coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
int boundary = (patchBits >> 7) & 0x1f;
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20]; int indexBase = array.indexBase + array.stride *
int numControlVertices = 0;
if (patchType == 3) {
OsdGetBilinearPatchWeights(uv[0], uv[1], dScale,
wP, wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 4;
} else if (patchType == 6) {
OsdGetBSplinePatchWeights(uv[0], uv[1], dScale, boundary,
wP, wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 16;
} else if (patchType == 9) {
OsdGetGregoryPatchWeights(uv[0], uv[1], dScale,
wP, wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 20;
}
int indexStride = getNumControlVertices(array.patchType);
int indexBase = array.indexBase + indexStride *
(coord.patchIndex - array.primitiveIdBase); (coord.patchIndex - array.primitiveIdBase);
struct Vertex v; struct Vertex v;
clear(&v); clear(&v);
for (int i = 0; i < numControlVertices; ++i) { for (int i = 0; i < nPoints; ++i) {
int index = patchIndexBuffer[indexBase + i]; int index = patchIndexBuffer[indexBase + i];
addWithWeight(&v, src, index, wP[i]); addWithWeight(&v, src, index, wP[i]);
} }
@ -283,45 +204,45 @@ __kernel void computePatches(__global float *src, int srcOffset,
if (du) { if (du) {
struct Vertex vdu; struct Vertex vdu;
clear(&vdu); clear(&vdu);
for (int i = 0; i < numControlVertices; ++i) { for (int i = 0; i < nPoints; ++i) {
int index = patchIndexBuffer[indexBase + i]; int index = patchIndexBuffer[indexBase + i];
addWithWeight(&vdu, src, index, wDs[i]); addWithWeight(&vdu, src, index, wDu[i]);
} }
writeVertexStride(du, current, &vdu, duStride); writeVertexStride(du, current, &vdu, duStride);
} }
if (dv) { if (dv) {
struct Vertex vdv; struct Vertex vdv;
clear(&vdv); clear(&vdv);
for (int i = 0; i < numControlVertices; ++i) { for (int i = 0; i < nPoints; ++i) {
int index = patchIndexBuffer[indexBase + i]; int index = patchIndexBuffer[indexBase + i];
addWithWeight(&vdv, src, index, wDt[i]); addWithWeight(&vdv, src, index, wDv[i]);
} }
writeVertexStride(dv, current, &vdv, dvStride); writeVertexStride(dv, current, &vdv, dvStride);
} }
if (duu) { if (duu) {
struct Vertex vduu; struct Vertex vduu;
clear(&vduu); clear(&vduu);
for (int i = 0; i < numControlVertices; ++i) { for (int i = 0; i < nPoints; ++i) {
int index = patchIndexBuffer[indexBase + i]; int index = patchIndexBuffer[indexBase + i];
addWithWeight(&vduu, src, index, wDss[i]); addWithWeight(&vduu, src, index, wDuu[i]);
} }
writeVertexStride(duu, current, &vduu, duuStride); writeVertexStride(duu, current, &vduu, duuStride);
} }
if (duv) { if (duv) {
struct Vertex vduv; struct Vertex vduv;
clear(&vduv); clear(&vduv);
for (int i = 0; i < numControlVertices; ++i) { for (int i = 0; i < nPoints; ++i) {
int index = patchIndexBuffer[indexBase + i]; int index = patchIndexBuffer[indexBase + i];
addWithWeight(&vduv, src, index, wDst[i]); addWithWeight(&vduv, src, index, wDuv[i]);
} }
writeVertexStride(duv, current, &vduv, duvStride); writeVertexStride(duv, current, &vduv, duvStride);
} }
if (dvv) { if (dvv) {
struct Vertex vdvv; struct Vertex vdvv;
clear(&vdvv); clear(&vdvv);
for (int i = 0; i < numControlVertices; ++i) { for (int i = 0; i < nPoints; ++i) {
int index = patchIndexBuffer[indexBase + i]; int index = patchIndexBuffer[indexBase + i];
addWithWeight(&vdvv, src, index, wDtt[i]); addWithWeight(&vdvv, src, index, wDvv[i]);
} }
writeVertexStride(dvv, current, &vdvv, dvvStride); writeVertexStride(dvv, current, &vdvv, dvvStride);
} }

View File

@ -24,7 +24,9 @@
#include "../osd/cpuEvaluator.h" #include "../osd/cpuEvaluator.h"
#include "../osd/cpuKernel.h" #include "../osd/cpuKernel.h"
#include "../far/patchBasis.h" #include "../osd/patchBasisCommonTypes.h"
#include "../osd/patchBasisCommon.h"
#include "../osd/patchBasisCommonEval.h"
#include <cstdlib> #include <cstdlib>
@ -177,20 +179,23 @@ CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride); BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride); BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
float wP[20], wDs[20], wDt[20]; float wP[20];
for (int i = 0; i < numPatchCoords; ++i) { for (int i = 0; i < numPatchCoords; ++i) {
PatchCoord const &coord = patchCoords[i]; PatchCoord const &coord = patchCoords[i];
PatchArray const &array = patchArrays[coord.handle.arrayIndex]; PatchArray const &array = patchArrays[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
patchParamBuffer[coord.handle.patchIndex]; patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
int patchType = OsdPatchParamIsRegular(param)
? array.GetPatchTypeRegular() ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular(); : array.GetPatchTypeIrregular();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int nPoints = OsdEvaluatePatchBasis(patchType, param,
param, coord.s, coord.t, wP, wDs, wDt); coord.s, coord.t, wP, 0, 0, 0, 0, 0);
int indexBase = array.GetIndexBase() + array.GetStride() * int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
@ -198,7 +203,7 @@ CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
const int *cvs = &patchIndexBuffer[indexBase]; const int *cvs = &patchIndexBuffer[indexBase];
dstT.Clear(); dstT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
} }
++dstT; ++dstT;
@ -246,14 +251,17 @@ CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
PatchCoord const &coord = patchCoords[i]; PatchCoord const &coord = patchCoords[i];
PatchArray const &array = patchArrays[coord.handle.arrayIndex]; PatchArray const &array = patchArrays[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
patchParamBuffer[coord.handle.patchIndex]; patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
int patchType = OsdPatchParamIsRegular(param)
? array.GetPatchTypeRegular() ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular(); : array.GetPatchTypeIrregular();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int nPoints = OsdEvaluatePatchBasis(patchType, param,
param, coord.s, coord.t, wP, wDs, wDt); coord.s, coord.t, wP, wDs, wDt, 0, 0, 0);
int indexBase = array.GetIndexBase() + array.GetStride() * int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
@ -263,7 +271,7 @@ CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
dstT.Clear(); dstT.Clear();
duT.Clear(); duT.Clear();
dvT.Clear(); dvT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
duT.AddWithWeight (srcT[cvs[j]], wDs[j]); duT.AddWithWeight (srcT[cvs[j]], wDs[j]);
dvT.AddWithWeight (srcT[cvs[j]], wDt[j]); dvT.AddWithWeight (srcT[cvs[j]], wDt[j]);
@ -333,14 +341,17 @@ CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
PatchCoord const &coord = patchCoords[i]; PatchCoord const &coord = patchCoords[i];
PatchArray const &array = patchArrays[coord.handle.arrayIndex]; PatchArray const &array = patchArrays[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
patchParamBuffer[coord.handle.patchIndex]; patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
int patchType = OsdPatchParamIsRegular(param)
? array.GetPatchTypeRegular() ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular(); : array.GetPatchTypeIrregular();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int nPoints = OsdEvaluatePatchBasis(patchType, param,
param, coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv); coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
int indexBase = array.GetIndexBase() + array.GetStride() * int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
@ -353,7 +364,7 @@ CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
duuT.Clear(); duuT.Clear();
duvT.Clear(); duvT.Clear();
dvvT.Clear(); dvvT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
duT.AddWithWeight (srcT[cvs[j]], wDu[j]); duT.AddWithWeight (srcT[cvs[j]], wDu[j]);
dvT.AddWithWeight (srcT[cvs[j]], wDv[j]); dvT.AddWithWeight (srcT[cvs[j]], wDv[j]);

View File

@ -24,7 +24,9 @@
#include <assert.h> #include <assert.h>
#define OSD_PATCH_BASIS_CUDA #define OSD_PATCH_BASIS_CUDA
#include "../osd/patchBasisCommonTypes.h"
#include "../osd/patchBasisCommon.h" #include "../osd/patchBasisCommon.h"
#include "../osd/patchBasisCommonEval.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
template<int N> struct DeviceVertex { template<int N> struct DeviceVertex {
@ -240,70 +242,6 @@ __global__ void computeStencilsNv_v4(float const *__restrict cvs,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Osd::PatchCoord osd/types.h
struct PatchCoord {
int arrayIndex;
int patchIndex;
int vertIndex;
float s;
float t;
};
struct PatchArray {
int patchType; // Far::PatchDescriptor::Type
int numPatches;
int indexBase; // offset in the index buffer
int primitiveIdBase; // offset in the patch param buffer
};
struct PatchParam {
unsigned int field0;
unsigned int field1;
float sharpness;
};
__device__
int getDepth(unsigned int patchBits) {
return (patchBits & 0xf);
}
__device__
float getParamFraction(unsigned int patchBits) {
bool nonQuadRoot = (patchBits >> 4) & 0x1;
int depth = getDepth(patchBits);
if (nonQuadRoot) {
return 1.0f / float( 1 << (depth-1) );
} else {
return 1.0f / float( 1 << depth );
}
}
__device__
void normalizePatchCoord(unsigned int patchBits, float *u, float *v) {
float frac = getParamFraction(patchBits);
int iu = (patchBits >> 22) & 0x3ff;
int iv = (patchBits >> 12) & 0x3ff;
// top left corner
float pu = (float)iu*frac;
float pv = (float)iv*frac;
// normalize u,v coordinates
*u = (*u - pu) / frac;
*v = (*v - pv) / frac;
}
__device__
bool isRegular(unsigned int patchBits) {
return ((patchBits >> 5) & 0x1) != 0;
}
__device__
int getNumControlVertices(int patchType) {
return (patchType == 3) ? 4 :
(patchType == 6) ? 16 :
(patchType == 9) ? 20 : 0;
}
__global__ void __global__ void
computePatches(const float *src, float *dst, computePatches(const float *src, float *dst,
float *dstDu, float *dstDv, float *dstDu, float *dstDv,
@ -311,97 +249,80 @@ computePatches(const float *src, float *dst,
int length, int srcStride, int dstStride, int length, int srcStride, int dstStride,
int dstDuStride, int dstDvStride, int dstDuStride, int dstDvStride,
int dstDuuStride, int dstDuvStride, int dstDvvStride, int dstDuuStride, int dstDuvStride, int dstDvvStride,
int numPatchCoords, const PatchCoord *patchCoords, int numPatchCoords, const OsdPatchCoord *patchCoords,
const PatchArray *patchArrayBuffer, const OsdPatchArray *patchArrayBuffer,
const int *patchIndexBuffer, const int *patchIndexBuffer,
const PatchParam *patchParamBuffer) { const OsdPatchParam *patchParamBuffer) {
int first = threadIdx.x + blockIdx.x * blockDim.x; int first = threadIdx.x + blockIdx.x * blockDim.x;
// PERFORMANCE: not yet optimized // PERFORMANCE: not yet optimized
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
for (int i = first; i < numPatchCoords; i += blockDim.x * gridDim.x) { for (int i = first; i < numPatchCoords; i += blockDim.x * gridDim.x) {
PatchCoord const &coord = patchCoords[i]; OsdPatchCoord const &coord = patchCoords[i];
PatchArray const &array = patchArrayBuffer[coord.arrayIndex]; int arrayIndex = coord.arrayIndex;
int patchIndex = coord.patchIndex;
unsigned int patchBits = patchParamBuffer[coord.patchIndex].field1; OsdPatchArray const &array = patchArrayBuffer[arrayIndex];
int patchType = isRegular(patchBits) ? 6 : array.patchType; OsdPatchParam const &param = patchParamBuffer[patchIndex];
// normalize int patchType = OsdPatchParamIsRegular(param)
float s = coord.s; ? array.regDesc : array.desc;
float t = coord.t;
normalizePatchCoord(patchBits, &s, &t);
float dScale = (float)(1 << getDepth(patchBits));
int boundary = int((patchBits >> 7) & 0x1fU);
int numControlVertices = 0; float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
if (patchType == 3) { int nPoints = OsdEvaluatePatchBasis(patchType, param,
OsdGetBilinearPatchWeights(s, t, dScale, coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
wP, wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 4;
} else if (patchType == 6) {
OsdGetBSplinePatchWeights(s, t, dScale, boundary,
wP, wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 16;
} else if (patchType == 9) {
OsdGetGregoryPatchWeights(s, t, dScale,
wP, wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 20;
}
int indexStride = getNumControlVertices(array.patchType); int indexBase = array.indexBase + array.stride *
int indexBase = array.indexBase + indexStride * (patchIndex - array.primitiveIdBase);
(coord.patchIndex - array.primitiveIdBase);
const int *cvs = patchIndexBuffer + indexBase; const int *cvs = patchIndexBuffer + indexBase;
float * dstVert = dst + i * dstStride; float * dstVert = dst + i * dstStride;
clear(dstVert, length); clear(dstVert, length);
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
const float * srcVert = src + cvs[j] * srcStride; const float * srcVert = src + cvs[j] * srcStride;
addWithWeight(dstVert, srcVert, wP[j], length); addWithWeight(dstVert, srcVert, wP[j], length);
} }
if (dstDu) { if (dstDu) {
float *d = dstDu + i * dstDuStride; float *d = dstDu + i * dstDuStride;
clear(d, length); clear(d, length);
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
const float * srcVert = src + cvs[j] * srcStride; const float * srcVert = src + cvs[j] * srcStride;
addWithWeight(d, srcVert, wDs[j], length); addWithWeight(d, srcVert, wDu[j], length);
} }
} }
if (dstDv) { if (dstDv) {
float *d = dstDv + i * dstDvStride; float *d = dstDv + i * dstDvStride;
clear(d, length); clear(d, length);
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
const float * srcVert = src + cvs[j] * srcStride; const float * srcVert = src + cvs[j] * srcStride;
addWithWeight(d, srcVert, wDt[j], length); addWithWeight(d, srcVert, wDv[j], length);
} }
} }
if (dstDuu) { if (dstDuu) {
float *d = dstDuu + i * dstDuuStride; float *d = dstDuu + i * dstDuuStride;
clear(d, length); clear(d, length);
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
const float * srcVert = src + cvs[j] * srcStride; const float * srcVert = src + cvs[j] * srcStride;
addWithWeight(d, srcVert, wDss[j], length); addWithWeight(d, srcVert, wDuu[j], length);
} }
} }
if (dstDuv) { if (dstDuv) {
float *d = dstDuv + i * dstDuvStride; float *d = dstDuv + i * dstDuvStride;
clear(d, length); clear(d, length);
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
const float * srcVert = src + cvs[j] * srcStride; const float * srcVert = src + cvs[j] * srcStride;
addWithWeight(d, srcVert, wDst[j], length); addWithWeight(d, srcVert, wDuv[j], length);
} }
} }
if (dstDvv) { if (dstDvv) {
float *d = dstDvv + i * dstDvvStride; float *d = dstDvv + i * dstDvvStride;
clear(d, length); clear(d, length);
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
const float * srcVert = src + cvs[j] * srcStride; const float * srcVert = src + cvs[j] * srcStride;
addWithWeight(d, srcVert, wDtt[j], length); addWithWeight(d, srcVert, wDvv[j], length);
} }
} }
} }
@ -467,10 +388,10 @@ void CudaEvalStencils(
void CudaEvalPatches( void CudaEvalPatches(
const float *src, float *dst, const float *src, float *dst,
int length, int srcStride, int dstStride, int length, int srcStride, int dstStride,
int numPatchCoords, const PatchCoord *patchCoords, int numPatchCoords, const OsdPatchCoord *patchCoords,
const PatchArray *patchArrayBuffer, const OsdPatchArray *patchArrayBuffer,
const int *patchIndexBuffer, const int *patchIndexBuffer,
const PatchParam *patchParamBuffer) { const OsdPatchParam *patchParamBuffer) {
// PERFORMANCE: not optimized at all // PERFORMANCE: not optimized at all
@ -488,10 +409,10 @@ void CudaEvalPatchesWithDerivatives(
int length, int srcStride, int dstStride, int length, int srcStride, int dstStride,
int dstDuStride, int dstDvStride, int dstDuStride, int dstDvStride,
int dstDuuStride, int dstDuvStride, int dstDvvStride, int dstDuuStride, int dstDuvStride, int dstDvvStride,
int numPatchCoords, const PatchCoord *patchCoords, int numPatchCoords, const OsdPatchCoord *patchCoords,
const PatchArray *patchArrayBuffer, const OsdPatchArray *patchArrayBuffer,
const int *patchIndexBuffer, const int *patchIndexBuffer,
const PatchParam *patchParamBuffer) { const OsdPatchParam *patchParamBuffer) {
// PERFORMANCE: not optimized at all // PERFORMANCE: not optimized at all

View File

@ -122,12 +122,17 @@ GLStencilTableSSBO::~GLStencilTableSSBO() {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64) { GLComputeEvaluator::GLComputeEvaluator()
: _workGroupSize(64),
_patchArraysSSBO(0) {
memset (&_stencilKernel, 0, sizeof(_stencilKernel)); memset (&_stencilKernel, 0, sizeof(_stencilKernel));
memset (&_patchKernel, 0, sizeof(_patchKernel)); memset (&_patchKernel, 0, sizeof(_patchKernel));
} }
GLComputeEvaluator::~GLComputeEvaluator() { GLComputeEvaluator::~GLComputeEvaluator() {
if (_patchArraysSSBO) {
glDeleteBuffers(1, &_patchArraysSSBO);
}
} }
static GLuint static GLuint
@ -222,6 +227,11 @@ GLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
return false; return false;
} }
// create a patch arrays buffer
if (!_patchArraysSSBO) {
glGenBuffers(1, &_patchArraysSSBO);
}
return true; return true;
} }
@ -398,16 +408,24 @@ GLComputeEvaluator::EvalPatches(
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, patchCoordsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchCoordsBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchIndexBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchIndexBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchParamsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, patchParamsBuffer);
glUseProgram(_patchKernel.program); glUseProgram(_patchKernel.program);
glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset); glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset); glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset);
glUniform4iv(_patchKernel.uniformPatchArray, (int)patchArrays.size(),
(const GLint*)&patchArrays[0]); int patchArraySize = sizeof(PatchArray);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, _patchArraysSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER,
patchArrays.size()*patchArraySize, NULL, GL_STATIC_DRAW);
for (int i=0; i<(int)patchArrays.size(); ++i) {
glBufferSubData(GL_SHADER_STORAGE_BUFFER,
i*patchArraySize, sizeof(PatchArray), &patchArrays[i]);
}
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, _patchArraysSSBO);
if (_patchKernel.uniformDuDesc > 0) { if (_patchKernel.uniformDuDesc > 0) {
glUniform3i(_patchKernel.uniformDuDesc, glUniform3i(_patchKernel.uniformDuDesc,

View File

@ -2101,6 +2101,7 @@ private:
} _patchKernel; } _patchKernel;
int _workGroupSize; int _workGroupSize;
GLuint _patchArraysSSBO;
}; };
} // end namespace Osd } // end namespace Osd

View File

@ -153,6 +153,7 @@ GLStencilTableTBO::~GLStencilTableTBO() {
GLXFBEvaluator::GLXFBEvaluator(bool interleavedDerivativeBuffers) GLXFBEvaluator::GLXFBEvaluator(bool interleavedDerivativeBuffers)
: _srcBufferTexture(0), : _srcBufferTexture(0),
_patchArraysUBO(0),
_interleavedDerivativeBuffers(interleavedDerivativeBuffers) { _interleavedDerivativeBuffers(interleavedDerivativeBuffers) {
} }
@ -160,6 +161,9 @@ GLXFBEvaluator::~GLXFBEvaluator() {
if (_srcBufferTexture) { if (_srcBufferTexture) {
glDeleteTextures(1, &_srcBufferTexture); glDeleteTextures(1, &_srcBufferTexture);
} }
if (_patchArraysUBO) {
glDeleteBuffers(1, &_patchArraysUBO);
}
} }
static GLuint static GLuint
@ -439,6 +443,9 @@ GLXFBEvaluator::Compile(BufferDescriptor const &srcDesc,
if (!_srcBufferTexture) { if (!_srcBufferTexture) {
glGenTextures(1, &_srcBufferTexture); glGenTextures(1, &_srcBufferTexture);
} }
if (!_patchArraysUBO) {
glGenBuffers(1, &_patchArraysUBO);
}
return true; return true;
} }
@ -735,9 +742,20 @@ GLXFBEvaluator::EvalPatches(
bindTexture(_patchKernel.uniformPatchParamTexture, patchParamTexture, 1); bindTexture(_patchKernel.uniformPatchParamTexture, patchParamTexture, 1);
bindTexture(_patchKernel.uniformPatchIndexTexture, patchIndexTexture, 2); bindTexture(_patchKernel.uniformPatchIndexTexture, patchIndexTexture, 2);
// bind patch arrays UBO (std140 struct size padded to vec4 alignment)
int patchArraySize =
sizeof(GLint) * ((sizeof(PatchArray)/sizeof(GLint) + 3) & ~3);
glBindBuffer(GL_UNIFORM_BUFFER, _patchArraysUBO);
glBufferData(GL_UNIFORM_BUFFER,
patchArrays.size()*patchArraySize, NULL, GL_STATIC_DRAW);
for (int i=0; i<(int)patchArrays.size(); ++i) {
glBufferSubData(GL_UNIFORM_BUFFER,
i*patchArraySize, sizeof(PatchArray), &patchArrays[i]);
}
glBindBufferBase(GL_UNIFORM_BUFFER,
_patchKernel.uniformPatchArraysUBOBinding, _patchArraysUBO);
// set other uniforms // set other uniforms
glUniform4iv(_patchKernel.uniformPatchArray, (int)patchArrays.size(),
(const GLint*)&patchArrays[0]);
glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset); glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
// input patchcoords // input patchcoords
@ -822,6 +840,10 @@ GLXFBEvaluator::EvalPatches(
glBindTexture(GL_TEXTURE_BUFFER, 0); glBindTexture(GL_TEXTURE_BUFFER, 0);
} }
// unbind UBO
glBindBufferBase(GL_UNIFORM_BUFFER,
_patchKernel.uniformPatchArraysUBOBinding, 0);
glDisable(GL_RASTERIZER_DISCARD); glDisable(GL_RASTERIZER_DISCARD);
glUseProgram(0); glUseProgram(0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
@ -921,10 +943,13 @@ GLXFBEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
// cache uniform locations // cache uniform locations
uniformSrcBufferTexture = glGetUniformLocation(program, "vertexBuffer"); uniformSrcBufferTexture = glGetUniformLocation(program, "vertexBuffer");
uniformSrcOffset = glGetUniformLocation(program, "srcOffset"); uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
uniformPatchArray = glGetUniformLocation(program, "patchArray");
uniformPatchParamTexture = glGetUniformLocation(program, "patchParamBuffer"); uniformPatchParamTexture = glGetUniformLocation(program, "patchParamBuffer");
uniformPatchIndexTexture = glGetUniformLocation(program, "patchIndexBuffer"); uniformPatchIndexTexture = glGetUniformLocation(program, "patchIndexBuffer");
uniformPatchArraysUBOBinding = 1;
int uboIndex = glGetUniformBlockIndex(program, "PatchArrays");
glUniformBlockBinding(program, uboIndex , uniformPatchArraysUBOBinding);
return true; return true;
} }

View File

@ -2129,6 +2129,7 @@ public:
private: private:
GLuint _srcBufferTexture; GLuint _srcBufferTexture;
GLuint _patchArraysUBO;
bool _interleavedDerivativeBuffers; bool _interleavedDerivativeBuffers;
struct _StencilKernel { struct _StencilKernel {
@ -2174,7 +2175,7 @@ private:
GLint uniformSrcBufferTexture; GLint uniformSrcBufferTexture;
GLint uniformSrcOffset; // src buffer offset (in elements) GLint uniformSrcOffset; // src buffer offset (in elements)
GLint uniformPatchArray; GLint uniformPatchArraysUBOBinding;
GLint uniformPatchParamTexture; GLint uniformPatchParamTexture;
GLint uniformPatchIndexTexture; GLint uniformPatchIndexTexture;
} _patchKernel; } _patchKernel;

View File

@ -81,22 +81,25 @@ layout(binding=15) buffer stencilDvvWeights { float _dvvWeights[]; };
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES) #if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES)
struct PatchCoord { layout(binding=4) buffer patchArray_buffer { OsdPatchArray patchArrayBuffer[]; };
int arrayIndex; layout(binding=5) buffer patchCoord_buffer { OsdPatchCoord patchCoords[]; };
int patchIndex; layout(binding=6) buffer patchIndex_buffer { int patchIndexBuffer[]; };
int vertIndex; layout(binding=7) buffer patchParam_buffer { OsdPatchParam patchParamBuffer[]; };
float s;
float t; OsdPatchCoord GetPatchCoord(int coordIndex)
}; {
struct PatchParam { return patchCoords[coordIndex];
uint field0; }
uint field1;
float sharpness; OsdPatchArray GetPatchArray(int arrayIndex)
}; {
uniform ivec4 patchArray[2]; return patchArrayBuffer[arrayIndex];
layout(binding=4) buffer patchCoord_buffer { PatchCoord patchCoords[]; }; }
layout(binding=5) buffer patchIndex_buffer { int patchIndexBuffer[]; };
layout(binding=6) buffer patchParam_buffer { PatchParam patchParamBuffer[]; }; OsdPatchParam GetPatchParam(int patchIndex)
{
return patchParamBuffer[patchIndex];
}
#endif #endif
@ -248,99 +251,19 @@ void main() {
// PERFORMANCE: stride could be constant, but not as significant as length // PERFORMANCE: stride could be constant, but not as significant as length
//struct PatchArray {
// int patchType;
// int numPatches;
// int indexBase; // an offset within the index buffer
// int primitiveIdBase; // an offset within the patch param buffer
//};
// # of patcharrays is 1 or 2.
uint getDepth(uint patchBits) {
return (patchBits & 0xf);
}
float getParamFraction(uint patchBits) {
uint nonQuadRoot = (patchBits >> 4) & 0x1;
uint depth = getDepth(patchBits);
if (nonQuadRoot == 1) {
return 1.0f / float( 1 << (depth-1) );
} else {
return 1.0f / float( 1 << depth );
}
}
vec2 normalizePatchCoord(uint patchBits, vec2 uv) {
float frac = getParamFraction(patchBits);
uint iu = (patchBits >> 22) & 0x3ff;
uint iv = (patchBits >> 12) & 0x3ff;
// top left corner
float pu = float(iu*frac);
float pv = float(iv*frac);
// normalize u,v coordinates
return vec2((uv.x - pu) / frac, (uv.y - pv) / frac);
}
bool isRegular(uint patchBits) {
return (((patchBits >> 5) & 0x1u) != 0);
}
int getNumControlVertices(int patchType) {
return (patchType == 3) ? 4 :
(patchType == 6) ? 16 :
(patchType == 9) ? 20 : 0;
}
void main() { void main() {
int current = int(gl_GlobalInvocationID.x); int current = int(gl_GlobalInvocationID.x);
PatchCoord coord = patchCoords[current]; OsdPatchCoord coord = GetPatchCoord(current);
int patchIndex = coord.patchIndex; OsdPatchArray array = GetPatchArray(coord.arrayIndex);
OsdPatchParam param = GetPatchParam(coord.patchIndex);
ivec4 array = patchArray[coord.arrayIndex]; int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
uint patchBits = patchParamBuffer[patchIndex].field1; float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
int patchType = isRegular(patchBits) ? 6 : array.x; int nPoints = OsdEvaluatePatchBasis(patchType, param,
coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
vec2 uv = normalizePatchCoord(patchBits, vec2(coord.s, coord.t));
float dScale = float(1 << getDepth(patchBits));
int boundary = int((patchBits >> 7) & 0x1fU);
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
int numControlVertices = 0;
if (patchType == 3) {
float wP4[4], wDs4[4], wDt4[4], wDss4[4], wDst4[4], wDtt4[4];
OsdGetBilinearPatchWeights(uv.s, uv.t, dScale, wP4, wDs4, wDt4, wDss4, wDst4, wDtt4);
numControlVertices = 4;
for (int i=0; i<numControlVertices; ++i) {
wP[i] = wP4[i];
wDs[i] = wDs4[i];
wDt[i] = wDt4[i];
wDss[i] = wDss4[i];
wDst[i] = wDst4[i];
wDtt[i] = wDtt4[i];
}
} else if (patchType == 6) {
float wP16[16], wDs16[16], wDt16[16], wDss16[16], wDst16[16], wDtt16[16];
OsdGetBSplinePatchWeights(uv.s, uv.t, dScale, boundary, wP16, wDs16, wDt16, wDss16, wDst16, wDtt16);
numControlVertices = 16;
for (int i=0; i<numControlVertices; ++i) {
wP[i] = wP16[i];
wDs[i] = wDs16[i];
wDt[i] = wDt16[i];
wDss[i] = wDss16[i];
wDst[i] = wDst16[i];
wDtt[i] = wDtt16[i];
}
} else if (patchType == 9) {
OsdGetGregoryPatchWeights(uv.s, uv.t, dScale, wP, wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 20;
}
Vertex dst, du, dv, duu, duv, dvv; Vertex dst, du, dv, duu, duv, dvv;
clear(dst); clear(dst);
@ -350,17 +273,17 @@ void main() {
clear(duv); clear(duv);
clear(dvv); clear(dvv);
int indexStride = getNumControlVertices(array.x); int indexBase = array.indexBase + array.stride *
int indexBase = array.z + indexStride * (patchIndex - array.w); (coord.patchIndex - array.primitiveIdBase);
for (int cv = 0; cv < numControlVertices; ++cv) { for (int cv = 0; cv < nPoints; ++cv) {
int index = patchIndexBuffer[indexBase + cv]; int index = patchIndexBuffer[indexBase + cv];
addWithWeight(dst, readVertex(index), wP[cv]); addWithWeight(dst, readVertex(index), wP[cv]);
addWithWeight(du, readVertex(index), wDs[cv]); addWithWeight(du, readVertex(index), wDu[cv]);
addWithWeight(dv, readVertex(index), wDt[cv]); addWithWeight(dv, readVertex(index), wDv[cv]);
addWithWeight(duu, readVertex(index), wDss[cv]); addWithWeight(duu, readVertex(index), wDuu[cv]);
addWithWeight(duv, readVertex(index), wDst[cv]); addWithWeight(duv, readVertex(index), wDuv[cv]);
addWithWeight(dvv, readVertex(index), wDtt[cv]); addWithWeight(dvv, readVertex(index), wDvv[cv]);
} }
writeVertex(current, dst); writeVertex(current, dst);

View File

@ -34,9 +34,15 @@ namespace Osd {
static const char *commonShaderSource = static const char *commonShaderSource =
#include "glslPatchCommon.gen.h" #include "glslPatchCommon.gen.h"
; ;
static const char *patchBasisTypesShaderSource =
#include "patchBasisCommonTypes.gen.h"
;
static const char *patchBasisShaderSource = static const char *patchBasisShaderSource =
#include "patchBasisCommon.gen.h" #include "patchBasisCommon.gen.h"
; ;
static const char *patchBasisEvalShaderSource =
#include "patchBasisCommonEval.gen.h"
;
static const char *bsplineShaderSource = static const char *bsplineShaderSource =
#include "glslPatchBSpline.gen.h" #include "glslPatchBSpline.gen.h"
; ;
@ -60,7 +66,9 @@ GLSLPatchShaderSource::GetPatchBasisShaderSource() {
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES) #if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES\n"; ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES\n";
#endif #endif
ss << std::string(patchBasisTypesShaderSource);
ss << std::string(patchBasisShaderSource); ss << std::string(patchBasisShaderSource);
ss << std::string(patchBasisEvalShaderSource);
return ss.str(); return ss.str();
} }

View File

@ -223,107 +223,38 @@ void main() {
layout (location = 0) in ivec3 patchHandles; layout (location = 0) in ivec3 patchHandles;
layout (location = 1) in vec2 patchCoords; layout (location = 1) in vec2 patchCoords;
//struct PatchArray { layout (std140) uniform PatchArrays {
// int patchType; OsdPatchArray patchArrays[2];
// int numPatches; };
// int indexBase; // an offset within the index buffer
// int primitiveIdBase; // an offset within the patch param buffer
//};
// # of patcharrays is 1 or 2.
uniform ivec4 patchArray[2];
uniform isamplerBuffer patchParamBuffer; uniform isamplerBuffer patchParamBuffer;
uniform isamplerBuffer patchIndexBuffer; uniform isamplerBuffer patchIndexBuffer;
uint getDepth(uint patchBits) { OsdPatchArray GetPatchArray(int arrayIndex) {
return (patchBits & 0xfU); return patchArrays[arrayIndex];
} }
float getParamFraction(uint patchBits) { OsdPatchParam GetPatchParam(int patchIndex) {
uint nonQuadRoot = (patchBits >> 4) & 0x1U; ivec3 patchParamBits = texelFetch(patchParamBuffer, patchIndex).xyz;
uint depth = getDepth(patchBits); return OsdPatchParamInit(patchParamBits.x, patchParamBits.y, patchParamBits.z);
if (nonQuadRoot == 1) {
return 1.0f / float( 1 << (depth-1) );
} else {
return 1.0f / float( 1 << depth );
}
}
vec2 normalizePatchCoord(uint patchBits, vec2 uv) {
float frac = getParamFraction(patchBits);
uint iu = (patchBits >> 22) & 0x3ffU;
uint iv = (patchBits >> 12) & 0x3ffU;
// top left corner
float pu = float(iu*frac);
float pv = float(iv*frac);
// normalize u,v coordinates
return vec2((uv.x - pu) / frac, (uv.y - pv) / frac);
}
bool isRegular(uint patchBits) {
return (((patchBits >> 5) & 0x1u) != 0);
}
int getNumControlVertices(int patchType) {
return (patchType == 3) ? 4 :
(patchType == 6) ? 16 :
(patchType == 9) ? 20 : 0;
} }
void main() { void main() {
int current = gl_VertexID; int current = gl_VertexID;
ivec3 handle = patchHandles; ivec3 handle = patchHandles;
int arrayIndex = handle.x;
int patchIndex = handle.y; int patchIndex = handle.y;
vec2 coord = patchCoords; vec2 coord = patchCoords;
ivec4 array = patchArray[handle.x];
uint patchBits = texelFetch(patchParamBuffer, patchIndex).y; OsdPatchArray array = GetPatchArray(arrayIndex);
int patchType = isRegular(patchBits) ? 6 : array.x; OsdPatchParam param = GetPatchParam(patchIndex);
// normalize int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
coord = normalizePatchCoord(patchBits, coord);
float dScale = float(1 << getDepth(patchBits));
int boundary = int((patchBits >> 7) & 0x1fU);
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20]; float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
int nPoints = OsdEvaluatePatchBasis(patchType, param,
int numControlVertices = 0; coord.x, coord.y, wP, wDu, wDv, wDuu, wDuv, wDvv);
if (patchType == 3) {
float wP4[4], wDs4[4], wDt4[4], wDss4[4], wDst4[4], wDtt4[4];
OsdGetBilinearPatchWeights(coord.s, coord.t, dScale, wP4,
wDs4, wDt4, wDss4, wDst4, wDtt4);
numControlVertices = 4;
for (int i=0; i<numControlVertices; ++i) {
wP[i] = wP4[i];
wDs[i] = wDs4[i];
wDt[i] = wDt4[i];
wDss[i] = wDss4[i];
wDst[i] = wDst4[i];
wDtt[i] = wDtt4[i];
}
} else if (patchType == 6) {
float wP16[16], wDs16[16], wDt16[16], wDss16[16], wDst16[16], wDtt16[16];
OsdGetBSplinePatchWeights(coord.s, coord.t, dScale, boundary, wP16,
wDs16, wDt16, wDss16, wDst16, wDtt16);
numControlVertices = 16;
for (int i=0; i<numControlVertices; ++i) {
wP[i] = wP16[i];
wDs[i] = wDs16[i];
wDt[i] = wDt16[i];
wDss[i] = wDss16[i];
wDst[i] = wDst16[i];
wDtt[i] = wDtt16[i];
}
} else if (patchType == 9) {
OsdGetGregoryPatchWeights(coord.s, coord.t, dScale, wP,
wDs, wDt, wDss, wDst, wDtt);
numControlVertices = 20;
}
Vertex dst, du, dv, duu, duv, dvv; Vertex dst, du, dv, duu, duv, dvv;
clear(dst); clear(dst);
@ -333,17 +264,17 @@ void main() {
clear(duv); clear(duv);
clear(dvv); clear(dvv);
int indexStride = getNumControlVertices(array.x); int indexBase = array.indexBase + array.stride *
int indexBase = array.z + indexStride * (patchIndex - array.w); (patchIndex - array.primitiveIdBase);
for (int cv = 0; cv < numControlVertices; ++cv) { for (int cv = 0; cv < nPoints; ++cv) {
int index = texelFetch(patchIndexBuffer, indexBase + cv).x; int index = texelFetch(patchIndexBuffer, indexBase + cv).x;
addWithWeight(dst, readVertex(index), wP[cv]); addWithWeight(dst, readVertex(index), wP[cv]);
addWithWeight(du, readVertex(index), wDs[cv]); addWithWeight(du, readVertex(index), wDu[cv]);
addWithWeight(dv, readVertex(index), wDt[cv]); addWithWeight(dv, readVertex(index), wDv[cv]);
addWithWeight(duu, readVertex(index), wDss[cv]); addWithWeight(duu, readVertex(index), wDuu[cv]);
addWithWeight(duv, readVertex(index), wDst[cv]); addWithWeight(duv, readVertex(index), wDuv[cv]);
addWithWeight(dvv, readVertex(index), wDtt[cv]); addWithWeight(dvv, readVertex(index), wDvv[cv]);
} }
writeVertex(dst); writeVertex(dst);

View File

@ -36,9 +36,15 @@ namespace Osd {
static const char *commonShaderSource = static const char *commonShaderSource =
#include "hlslPatchCommon.gen.h" #include "hlslPatchCommon.gen.h"
; ;
static const char *patchBasisTypesShaderSource =
#include "patchBasisCommonTypes.gen.h"
;
static const char *patchBasisShaderSource = static const char *patchBasisShaderSource =
#include "patchBasisCommon.gen.h" #include "patchBasisCommon.gen.h"
; ;
static const char *patchBasisEvalShaderSource =
#include "patchBasisCommonEval.gen.h"
;
static const char *bsplineShaderSource = static const char *bsplineShaderSource =
#include "hlslPatchBSpline.gen.h" #include "hlslPatchBSpline.gen.h"
; ;
@ -62,7 +68,9 @@ HLSLPatchShaderSource::GetPatchBasisShaderSource() {
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES) #if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES\n"; ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES\n";
#endif #endif
ss << std::string(patchBasisTypesShaderSource);
ss << std::string(patchBasisShaderSource); ss << std::string(patchBasisShaderSource);
ss << std::string(patchBasisEvalShaderSource);
return ss.str(); return ss.str();
} }

View File

@ -36,29 +36,13 @@
using namespace metal; using namespace metal;
struct PatchCoord
{
int arrayIndex;
int patchIndex;
int vertIndex;
float s;
float t;
};
struct PatchParam
{
uint field0;
uint field1;
float sharpness;
};
struct KernelUniformArgs struct KernelUniformArgs
{ {
int batchStart; int batchStart;
int batchEnd; int batchEnd;
int srcOffset; int srcOffset;
int dstOffset; int dstOffset;
int3 duDesc; int3 duDesc;
int3 dvDesc; int3 dvDesc;
@ -179,7 +163,7 @@ kernel void eval_stencils(
) )
{ {
auto current = thread_position_in_grid + args.batchStart; auto current = thread_position_in_grid + args.batchStart;
if(current >= args.batchEnd) if(current >= (unsigned int)args.batchEnd)
return; return;
Vertex dst; Vertex dst;
@ -240,60 +224,11 @@ kernel void eval_stencils(
// PERFORMANCE: stride could be constant, but not as significant as length // PERFORMANCE: stride could be constant, but not as significant as length
//struct PatchArray {
// int patchType;
// int numPatches;
// int indexBase; // an offset within the index buffer
// int primitiveIdBase; // an offset within the patch param buffer
//};
// # of patcharrays is 1 or 2.
uint getDepth(uint patchBits) {
return (patchBits & 0xf);
}
float getParamFraction(uint patchBits) {
uint nonQuadRoot = (patchBits >> 4) & 0x1;
uint depth = getDepth(patchBits);
if (nonQuadRoot == 1) {
return 1.0f / float( 1 << (depth-1) );
} else {
return 1.0f / float( 1 << depth );
}
}
float2 normalizePatchCoord(uint patchBits, float2 uv) {
float frac = getParamFraction(patchBits);
uint iu = (patchBits >> 22) & 0x3ff;
uint iv = (patchBits >> 12) & 0x3ff;
// top left corner
float pu = float(iu*frac);
float pv = float(iv*frac);
// normalize u,v coordinates
return float2((uv.x - pu) / frac, (uv.y - pv) / frac);
}
bool isRegular(uint patchBits) {
return (((patchBits >> 5) & 0x1u) != 0);
}
int getNumControlVertices(int patchType) {
switch(patchType) {
case 3: return 4;
case 6: return 16;
case 9: return 20;
default: return 0;
}
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
kernel void eval_patches( kernel void eval_patches(
uint thread_position_in_grid [[thread_position_in_grid]], uint thread_position_in_grid [[thread_position_in_grid]],
const constant uint4* patchArrays [[buffer(PATCH_ARRAYS_BUFFER_INDEX)]], const constant int* patchArrays [[buffer(PATCH_ARRAYS_BUFFER_INDEX)]],
const device int* patchCoords [[buffer(PATCH_COORDS_BUFFER_INDEX)]], const device int* patchCoords [[buffer(PATCH_COORDS_BUFFER_INDEX)]],
const device int* patchIndices [[buffer(PATCH_INDICES_BUFFER_INDEX)]], const device int* patchIndices [[buffer(PATCH_INDICES_BUFFER_INDEX)]],
const device uint* patchParams [[buffer(PATCH_PARAMS_BUFFER_INDEX)]], const device uint* patchParams [[buffer(PATCH_PARAMS_BUFFER_INDEX)]],
@ -314,34 +249,29 @@ kernel void eval_patches(
auto current = thread_position_in_grid; auto current = thread_position_in_grid;
// unpack struct (5 ints unaligned) // unpack struct (5 ints unaligned)
PatchCoord patchCoord; OsdPatchCoord patchCoord = OsdPatchCoordInit(patchCoords[current*5+0],
patchCoord.arrayIndex = patchCoords[current*5+0]; patchCoords[current*5+1],
patchCoord.patchIndex = patchCoords[current*5+1]; patchCoords[current*5+2],
patchCoord.vertIndex = patchCoords[current*5+2]; as_type<float>(patchCoords[current*5+3]),
patchCoord.s = as_type<float>(patchCoords[current*5+3]); as_type<float>(patchCoords[current*5+4]));
patchCoord.t = as_type<float>(patchCoords[current*5+4]);
auto patchArray = patchArrays[patchCoord.arrayIndex]; OsdPatchArray patchArray = OsdPatchArrayInit(patchArrays[current*6+0],
patchArrays[current*6+1],
patchArrays[current*6+2],
patchArrays[current*6+3],
patchArrays[current*6+4],
patchArrays[current*6+5]);
// unpack struct (3 uints unaligned) OsdPatchParam patchParam = OsdPatchParamInit(patchParams[current*3+0],
auto patchBits = patchParams[patchCoord.patchIndex*3+1]; // field1 patchParams[current*3+1],
auto patchType = select(patchArray.x, uint(6), isRegular(patchBits)); as_type<float>(patchParams[current*3+2]));
auto numControlVertices = getNumControlVertices(patchType); int patchType = OsdPatchParamIsRegular(patchParam)
auto uv = normalizePatchCoord(patchBits, float2(patchCoord.s, patchCoord.t)); ? patchArray.regDesc : patchArray.desc;
auto dScale = float(1 << getDepth(patchBits));
auto boundary = int((patchBits >> 7) & 0x1FU);
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20]; float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
int nPoints = OsdEvaluatePatchBasis(patchType, patchParam,
patchCoord.s, patchCoord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
if(patchType == 3) {
OsdGetBilinearPatchWeights(uv.x, uv.y, dScale, wP, wDs, wDt, wDss, wDst, wDtt);
} else if(patchType == 6) {
OsdGetBSplinePatchWeights(uv.x, uv.y, dScale, boundary, wP, wDs, wDt, wDss, wDst, wDtt);
} else if(patchType == 9) {
OsdGetGregoryPatchWeights(uv.x, uv.y, dScale, wP, wDs, wDt, wDss, wDst, wDtt);
}
Vertex dst, du, dv, duu, duv, dvv; Vertex dst, du, dv, duu, duv, dvv;
clear(dst); clear(dst);
@ -351,19 +281,18 @@ kernel void eval_patches(
clear(duv); clear(duv);
clear(dvv); clear(dvv);
auto indexBase = patchArray.indexBase + patchArray.stride *
auto indexStride = getNumControlVertices(patchArray.x); (patchCoord.patchIndex - patchArray.primitiveIdBase);
auto indexBase = patchArray.z + indexStride * (patchCoord.patchIndex - patchArray.w); for(auto cv = 0; cv < nPoints; cv++)
for(auto cv = 0; cv < numControlVertices; cv++)
{ {
auto index = patchIndices[indexBase + cv]; auto index = patchIndices[indexBase + cv];
auto src = readVertex(index, srcVertexBuffer, args); auto src = readVertex(index, srcVertexBuffer, args);
addWithWeight(dst, src, wP[cv]); addWithWeight(dst, src, wP[cv]);
addWithWeight(du, src, wDs[cv]); addWithWeight(du, src, wDu[cv]);
addWithWeight(dv, src, wDt[cv]); addWithWeight(dv, src, wDv[cv]);
addWithWeight(duu, src, wDss[cv]); addWithWeight(duu, src, wDuu[cv]);
addWithWeight(duv, src, wDst[cv]); addWithWeight(duv, src, wDuv[cv]);
addWithWeight(dvv, src, wDtt[cv]); addWithWeight(dvv, src, wDvv[cv]);
} }
writeVertex(current, dst, dstVertexBuffer, args); writeVertex(current, dst, dstVertexBuffer, args);

View File

@ -37,9 +37,15 @@ namespace OpenSubdiv {
static std::string commonShaderSource( static std::string commonShaderSource(
#include "mtlPatchCommon.gen.h" #include "mtlPatchCommon.gen.h"
); );
static std::string patchBasisShaderSource( static std::string patchBasisTypesShaderSource(
#include "patchBasisCommonTypes.gen.h"
);
static std::string patchBasisShaderSource(
#include "patchBasisCommon.gen.h" #include "patchBasisCommon.gen.h"
); );
static std::string patchBasisEvalShaderSource(
#include "patchBasisCommonEval.gen.h"
);
static std::string bsplineShaderSource( static std::string bsplineShaderSource(
#include "mtlPatchBSpline.gen.h" #include "mtlPatchBSpline.gen.h"
); );
@ -105,7 +111,9 @@ namespace OpenSubdiv {
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES) #if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES 1\n"; ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES 1\n";
#endif #endif
ss << patchBasisTypesShaderSource;
ss << patchBasisShaderSource; ss << patchBasisShaderSource;
ss << patchBasisEvalShaderSource;
return ss.str(); return ss.str();
} }

View File

@ -24,7 +24,9 @@
#include "../osd/ompEvaluator.h" #include "../osd/ompEvaluator.h"
#include "../osd/ompKernel.h" #include "../osd/ompKernel.h"
#include "../far/patchBasis.h" #include "../osd/patchBasisCommonTypes.h"
#include "../osd/patchBasisCommon.h"
#include "../osd/patchBasisCommonEval.h"
#include <omp.h> #include <omp.h>
namespace OpenSubdiv { namespace OpenSubdiv {
@ -178,27 +180,29 @@ OmpEvaluator::EvalPatches(
for (int i = 0; i < numPatchCoords; ++i) { for (int i = 0; i < numPatchCoords; ++i) {
BufferAdapter<float> dstT(dst + dstDesc.stride*i, dstDesc.length, dstDesc.stride); BufferAdapter<float> dstT(dst + dstDesc.stride*i, dstDesc.length, dstDesc.stride);
float wP[20], wDs[20], wDt[20]; float wP[20];
PatchCoord const &coord = patchCoords[i]; PatchCoord const &coord = patchCoords[i];
PatchArray const &array = patchArrays[coord.handle.arrayIndex]; PatchArray const &array = patchArrays[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
patchParamBuffer[coord.handle.patchIndex]; patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
? Far::PatchDescriptor::REGULAR paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
: array.GetPatchType();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int patchType = OsdPatchParamIsRegular(param)
param, coord.s, coord.t, wP, wDs, wDt); ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular();
int indexStride = Far::PatchDescriptor(array.GetPatchType()).GetNumControlVertices(); int nPoints = OsdEvaluatePatchBasis(patchType, param,
int indexBase = array.GetIndexBase() + indexStride * coord.s, coord.t, wP, 0, 0, 0, 0, 0);
int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
const int *cvs = &patchIndexBuffer[indexBase]; const int *cvs = &patchIndexBuffer[indexBase];
dstT.Clear(); dstT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
} }
} }
@ -235,17 +239,19 @@ OmpEvaluator::EvalPatches(
PatchCoord const &coord = patchCoords[i]; PatchCoord const &coord = patchCoords[i];
PatchArray const &array = patchArrays[coord.handle.arrayIndex]; PatchArray const &array = patchArrays[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
patchParamBuffer[coord.handle.patchIndex]; patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
? Far::PatchDescriptor::REGULAR paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
: array.GetPatchType();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int patchType = OsdPatchParamIsRegular(param)
param, coord.s, coord.t, wP, wDu, wDv); ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular();
int indexStride = Far::PatchDescriptor(array.GetPatchType()).GetNumControlVertices(); int nPoints = OsdEvaluatePatchBasis(patchType, param,
int indexBase = array.GetIndexBase() + indexStride * coord.s, coord.t, wP, wDu, wDv, 0, 0, 0);
int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
const int *cvs = &patchIndexBuffer[indexBase]; const int *cvs = &patchIndexBuffer[indexBase];
@ -253,7 +259,7 @@ OmpEvaluator::EvalPatches(
dstT.Clear(); dstT.Clear();
duT.Clear(); duT.Clear();
dvT.Clear(); dvT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
duT.AddWithWeight(srcT[cvs[j]], wDu[j]); duT.AddWithWeight(srcT[cvs[j]], wDu[j]);
dvT.AddWithWeight(srcT[cvs[j]], wDv[j]); dvT.AddWithWeight(srcT[cvs[j]], wDv[j]);
@ -304,17 +310,19 @@ OmpEvaluator::EvalPatches(
PatchCoord const &coord = patchCoords[i]; PatchCoord const &coord = patchCoords[i];
PatchArray const &array = patchArrays[coord.handle.arrayIndex]; PatchArray const &array = patchArrays[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
patchParamBuffer[coord.handle.patchIndex]; patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
? Far::PatchDescriptor::REGULAR paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
: array.GetPatchType();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int patchType = OsdPatchParamIsRegular(param)
param, coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv); ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular();
int indexStride = Far::PatchDescriptor(array.GetPatchType()).GetNumControlVertices(); int nPoints = OsdEvaluatePatchBasis(patchType, param,
int indexBase = array.GetIndexBase() + indexStride * coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
const int *cvs = &patchIndexBuffer[indexBase]; const int *cvs = &patchIndexBuffer[indexBase];
@ -325,7 +333,7 @@ OmpEvaluator::EvalPatches(
duuT.Clear(); duuT.Clear();
duvT.Clear(); duvT.Clear();
dvvT.Clear(); dvvT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
duT.AddWithWeight(srcT[cvs[j]], wDu[j]); duT.AddWithWeight(srcT[cvs[j]], wDu[j]);
dvT.AddWithWeight(srcT[cvs[j]], wDv[j]); dvT.AddWithWeight(srcT[cvs[j]], wDv[j]);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,196 @@
//
// Copyright 2018 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_PATCH_BASIS_COMMON_EVAL_H
#define OPENSUBDIV3_OSD_PATCH_BASIS_COMMON_EVAL_H
OSD_FUNCTION_STORAGE_CLASS
// template <typename REAL>
int
OsdEvaluatePatchBasisNormalized(
int patchType, OsdPatchParam param,
OSD_REAL s, OSD_REAL t,
OSD_OUT_ARRAY(OSD_REAL, wP, 20),
OSD_OUT_ARRAY(OSD_REAL, wDs, 20),
OSD_OUT_ARRAY(OSD_REAL, wDt, 20),
OSD_OUT_ARRAY(OSD_REAL, wDss, 20),
OSD_OUT_ARRAY(OSD_REAL, wDst, 20),
OSD_OUT_ARRAY(OSD_REAL, wDtt, 20)) {
int boundaryMask = OsdPatchParamGetBoundary(param);
int nPoints = 0;
if (patchType == OSD_PATCH_DESCRIPTOR_REGULAR) {
#if OSD_ARRAY_ARG_BOUND_OPTIONAL
nPoints = Osd_EvalBasisBSpline(s, t, wP, wDs, wDt, wDss, wDst, wDtt);
if (boundaryMask != 0) {
Osd_boundBasisBSpline(
boundaryMask, wP, wDs, wDt, wDss, wDst, wDtt);
}
#else
OSD_REAL wP16[16], wDs16[16], wDt16[16],
wDss16[16], wDst16[16], wDtt16[16];
nPoints = Osd_EvalBasisBSpline(
s, t, wP16, wDs16, wDt16, wDss16, wDst16, wDtt16);
if (boundaryMask != 0) {
Osd_boundBasisBSpline(
boundaryMask, wP16, wDs16, wDt16, wDss16, wDst16, wDtt16);
}
for (int i=0; i<nPoints; ++i) {
wP[i] = wP16[i];
wDs[i] = wDs16[i]; wDt[i] = wDt16[i];
wDss[i] = wDss16[i]; wDst[i] = wDst16[i]; wDtt[i] = wDtt16[i];
}
#endif
} else if (patchType == OSD_PATCH_DESCRIPTOR_LOOP) {
#if OSD_ARRAY_ARG_BOUND_OPTIONAL
nPoints = Osd_EvalBasisBoxSplineTri(
s, t, wP, wDs, wDt, wDss, wDst, wDtt);
if (boundaryMask != 0) {
Osd_boundBasisBoxSplineTri(
boundaryMask, wP, wDs, wDt, wDss, wDst, wDtt);
}
#else
OSD_REAL wP12[12], wDs12[12], wDt12[12],
wDss12[12], wDst12[12], wDtt12[12];
nPoints = Osd_EvalBasisBoxSplineTri(
s, t, wP12, wDs12, wDt12, wDss12, wDst12, wDtt12);
if (boundaryMask != 0) {
Osd_boundBasisBoxSplineTri(
boundaryMask, wP12, wDs12, wDt12, wDss12, wDst12, wDtt12);
}
for (int i=0; i<nPoints; ++i) {
wP[i] = wP12[i];
wDs[i] = wDs12[i]; wDt[i] = wDt12[i];
wDss[i] = wDss12[i]; wDst[i] = wDst12[i]; wDtt[i] = wDtt12[i];
}
#endif
} else if (patchType == OSD_PATCH_DESCRIPTOR_GREGORY_BASIS) {
nPoints = Osd_EvalBasisGregory(s, t, wP, wDs, wDt, wDss, wDst, wDtt);
} else if (patchType == OSD_PATCH_DESCRIPTOR_GREGORY_TRIANGLE) {
#if OSD_ARRAY_ARG_BOUND_OPTIONAL
nPoints = Osd_EvalBasisGregoryTri(s, t, wP, wDs, wDt, wDss, wDst, wDtt);
#else
OSD_REAL wP15[15], wDs15[15], wDt15[15],
wDss15[15], wDst15[15], wDtt15[15];
nPoints = Osd_EvalBasisGregoryTri(
s, t, wP15, wDs15, wDt15, wDss15, wDst15, wDtt15);
for (int i=0; i<nPoints; ++i) {
wP[i] = wP15[i];
wDs[i] = wDs15[i]; wDt[i] = wDt15[i];
wDss[i] = wDss15[i]; wDst[i] = wDst15[i]; wDtt[i] = wDtt15[i];
}
#endif
} else if (patchType == OSD_PATCH_DESCRIPTOR_QUADS) {
#if OSD_ARRAY_ARG_BOUND_OPTIONAL
nPoints = Osd_EvalBasisLinear(s, t, wP, wDs, wDt, wDss, wDst, wDtt);
#else
OSD_REAL wP4[4], wDs4[4], wDt4[4],
wDss4[4], wDst4[4], wDtt4[4];
nPoints = Osd_EvalBasisLinear(
s, t, wP4, wDs4, wDt4, wDss4, wDst4, wDtt4);
for (int i=0; i<nPoints; ++i) {
wP[i] = wP4[i];
wDs[i] = wDs4[i]; wDt[i] = wDt4[i];
wDss[i] = wDss4[i]; wDst[i] = wDst4[i]; wDtt[i] = wDtt4[i];
}
#endif
} else if (patchType == OSD_PATCH_DESCRIPTOR_TRIANGLES) {
#if OSD_ARRAY_ARG_BOUND_OPTIONAL
nPoints = Osd_EvalBasisLinearTri(s, t, wP, wDs, wDt, wDss, wDst, wDtt);
#else
OSD_REAL wP3[3], wDs3[3], wDt3[3],
wDss3[3], wDst3[3], wDtt3[3];
nPoints = Osd_EvalBasisLinearTri(
s, t, wP3, wDs3, wDt3, wDss3, wDst3, wDtt3);
for (int i=0; i<nPoints; ++i) {
wP[i] = wP3[i];
wDs[i] = wDs3[i]; wDt[i] = wDt3[i];
wDss[i] = wDss3[i]; wDst[i] = wDst3[i]; wDtt[i] = wDtt3[i];
}
#endif
} else {
// assert(0);
}
return nPoints;
}
OSD_FUNCTION_STORAGE_CLASS
// template <typename REAL>
int
OsdEvaluatePatchBasis(
int patchType, OsdPatchParam param,
OSD_REAL s, OSD_REAL t,
OSD_OUT_ARRAY(OSD_REAL, wP, 20),
OSD_OUT_ARRAY(OSD_REAL, wDs, 20),
OSD_OUT_ARRAY(OSD_REAL, wDt, 20),
OSD_OUT_ARRAY(OSD_REAL, wDss, 20),
OSD_OUT_ARRAY(OSD_REAL, wDst, 20),
OSD_OUT_ARRAY(OSD_REAL, wDtt, 20)) {
OSD_REAL derivSign = 1.0f;
if ((patchType == OSD_PATCH_DESCRIPTOR_LOOP) ||
(patchType == OSD_PATCH_DESCRIPTOR_GREGORY_TRIANGLE) ||
(patchType == OSD_PATCH_DESCRIPTOR_TRIANGLES)) {
OSD_REAL uv[2] = OSD_ARRAY_2(OSD_REAL, s, t);
OsdPatchParamNormalizeTriangle(param, uv);
s = uv[0];
t = uv[1];
if (OsdPatchParamIsTriangleRotated(param)) {
derivSign = -1.0f;
}
} else {
OSD_REAL uv[2] = OSD_ARRAY_2(OSD_REAL, s, t);
OsdPatchParamNormalize(param, uv);
s = uv[0];
t = uv[1];
}
int nPoints = OsdEvaluatePatchBasisNormalized(
patchType, param, s, t, wP, wDs, wDt, wDss, wDst, wDtt);
if (OSD_OPTIONAL(wDs && wDt)) {
OSD_REAL d1Scale =
derivSign * OSD_REAL_CAST(1 << OsdPatchParamGetDepth(param));
for (int i = 0; i < nPoints; ++i) {
wDs[i] *= d1Scale;
wDt[i] *= d1Scale;
}
if (OSD_OPTIONAL(wDss && wDst && wDtt)) {
OSD_REAL d2Scale = derivSign * d1Scale * d1Scale;
for (int i = 0; i < nPoints; ++i) {
wDss[i] *= d2Scale;
wDst[i] *= d2Scale;
wDtt[i] *= d2Scale;
}
}
}
return nPoints;
}
#endif /* OPENSUBDIV3_OSD_PATCH_BASIS_COMMON_EVAL_H */

View File

@ -0,0 +1,422 @@
//
// Copyright 2018 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_PATCH_BASIS_COMMON_TYPES_H
#define OPENSUBDIV3_OSD_PATCH_BASIS_COMMON_TYPES_H
#if defined(OSD_PATCH_BASIS_GLSL)
#define OSD_FUNCTION_STORAGE_CLASS
#define OSD_DATA_STORAGE_CLASS
#define OSD_REAL float
#define OSD_REAL_CAST float
#define OSD_ARG_ARRAY_BOUND_OPTIONAL false
#define OSD_OPTIONAL(a) true
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
out elementType identifier[arraySize]
#define OSD_INOUT_ARRAY(elementType, identifier, arraySize) \
inout elementType identifier[arraySize]
#define OSD_ARRAY_2(elementType,a0,a1) \
elementType[](a0,a1)
#define OSD_ARRAY_3(elementType,a0,a1,a2) \
elementType[](a0,a1,a2)
#define OSD_ARRAY_4(elementType,a0,a1,a2,a3) \
elementType[](a0,a1,a2,a3)
#define OSD_ARRAY_6(elementType,a0,a1,a2,a3,a4,a5) \
elementType[](a0,a1,a2,a3,a4,a5)
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
elementType[](a0,a1,a2,a3,a4,a5,a6,a7)
#define OSD_ARRAY_9(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8) \
elementType[](a0,a1,a2,a3,a4,a5,a6,a7,a8)
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
elementType[](a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
#elif defined(OSD_PATCH_BASIS_HLSL)
#define OSD_FUNCTION_STORAGE_CLASS
#define OSD_DATA_STORAGE_CLASS
#define OSD_REAL float
#define OSD_REAL_CAST float
#define OSD_ARG_ARRAY_BOUND_OPTIONAL false
#define OSD_OPTIONAL(a) true
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
out elementType identifier[arraySize]
#define OSD_INOUT_ARRAY(elementType, identifier, arraySize) \
inout elementType identifier[arraySize]
#define OSD_ARRAY_2(elementType,a0,a1) \
{a0,a1}
#define OSD_ARRAY_3(elementType,a0,a1,a2) \
{a0,a1,a2}
#define OSD_ARRAY_4(elementType,a0,a1,a2,a3) \
{a0,a1,a2,a3}
#define OSD_ARRAY_6(elementType,a0,a1,a2,a3,a4,a5) \
{a0,a1,a2,a3,a4,a5}
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_9(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11}
#elif defined(OSD_PATCH_BASIS_CUDA)
#define OSD_FUNCTION_STORAGE_CLASS __device__
#define OSD_DATA_STORAGE_CLASS
#define OSD_REAL float
#define OSD_REAL_CAST float
#define OSD_OPTIONAL(a) true
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_ARRAY_ARG_BOUND_OPTIONAL false
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_INOUT_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_ARRAY_2(elementType,a0,a1) \
{a0,a1}
#define OSD_ARRAY_3(elementType,a0,a1,a2) \
{a0,a1,a2}
#define OSD_ARRAY_4(elementType,a0,a1,a2,a3) \
{a0,a1,a2,a3}
#define OSD_ARRAY_6(elementType,a0,a1,a2,a3,a4,a5) \
{a0,a1,a2,a3,a4,a5}
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_9(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11}
#elif defined(OSD_PATCH_BASIS_OPENCL)
#define OSD_FUNCTION_STORAGE_CLASS static
#define OSD_DATA_STORAGE_CLASS
#define OSD_REAL float
#define OSD_REAL_CAST convert_float
#define OSD_OPTIONAL(a) true
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_ARRAY_ARG_BOUND_OPTIONAL false
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_INOUT_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_ARRAY_2(elementType,a0,a1) \
{a0,a1}
#define OSD_ARRAY_3(elementType,a0,a1,a2) \
{a0,a1,a2}
#define OSD_ARRAY_4(elementType,a0,a1,a2,a3) \
{a0,a1,a2,a3}
#define OSD_ARRAY_6(elementType,a0,a1,a2,a3,a4,a5) \
{a0,a1,a2,a3,a4,a5}
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_9(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11}
#elif defined(OSD_PATCH_BASIS_METAL)
#define OSD_FUNCTION_STORAGE_CLASS
#define OSD_DATA_STORAGE_CLASS
#define OSD_REAL float
#define OSD_REAL_CAST float
#define OSD_OPTIONAL(a) true
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_ARRAY_ARG_BOUND_OPTIONAL false
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
thread elementType* identifier
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
thread elementType* identifier
#define OSD_INOUT_ARRAY(elementType, identifier, arraySize) \
thread elementType* identifier
#define OSD_ARRAY_2(elementType,a0,a1) \
{a0,a1}
#define OSD_ARRAY_3(elementType,a0,a1,a2) \
{a0,a1,a2}
#define OSD_ARRAY_4(elementType,a0,a1,a2,a3) \
{a0,a1,a2,a3}
#define OSD_ARRAY_6(elementType,a0,a1,a2,a3,a4,a5) \
{a0,a1,a2,a3,a4,a5}
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_9(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11}
#else
#define OSD_FUNCTION_STORAGE_CLASS static inline
#define OSD_DATA_STORAGE_CLASS static
#define OSD_REAL float
#define OSD_REAL_CAST float
#define OSD_OPTIONAL(a) (a)
#define OSD_OPTIONAL_INIT(a,b) (a ? b : 0)
#define OSD_ARRAY_ARG_BOUND_OPTIONAL true
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_INOUT_ARRAY(elementType, identifier, arraySize) \
elementType identifier[arraySize]
#define OSD_ARRAY_2(elementType,a0,a1) \
{a0,a1}
#define OSD_ARRAY_3(elementType,a0,a1,a2) \
{a0,a1,a2}
#define OSD_ARRAY_4(elementType,a0,a1,a2,a3) \
{a0,a1,a2,a3}
#define OSD_ARRAY_6(elementType,a0,a1,a2,a3,a4,a5) \
{a0,a1,a2,a3,a4,a5}
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_9(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11}
#endif
#if defined(OSD_PATCH_BASIS_OPENCL)
// OpenCL binding uses typedef to provide the required "struct" type specifier.
typedef struct OsdPatchParam OsdPatchParam;
typedef struct OsdPatchArray OsdPatchArray;
typedef struct OsdPatchCoord OsdPatchCoord;
#endif
// Osd reflection of Far::PatchDescriptor
#define OSD_PATCH_DESCRIPTOR_QUADS 3
#define OSD_PATCH_DESCRIPTOR_TRIANGLES 4
#define OSD_PATCH_DESCRIPTOR_LOOP 5
#define OSD_PATCH_DESCRIPTOR_REGULAR 6
#define OSD_PATCH_DESCRIPTOR_GREGORY_BASIS 9
#define OSD_PATCH_DESCRIPTOR_GREGORY_TRIANGLE 10
// Osd reflection of Osd::PatchCoord
struct OsdPatchCoord {
int arrayIndex;
int patchIndex;
int vertIndex;
float s;
float t;
};
OSD_FUNCTION_STORAGE_CLASS
OsdPatchCoord
OsdPatchCoordInit(
int arrayIndex, int patchIndex, int vertIndex, float s, float t)
{
OsdPatchCoord coord;
coord.arrayIndex = arrayIndex;
coord.patchIndex = patchIndex;
coord.vertIndex = vertIndex;
coord.s = s;
coord.t = t;
return coord;
}
// Osd reflection of Osd::PatchArray
struct OsdPatchArray {
int regDesc;
int desc;
int numPatches;
int indexBase;
int stride;
int primitiveIdBase;
};
OSD_FUNCTION_STORAGE_CLASS
OsdPatchArray
OsdPatchArrayInit(
int regDesc, int desc,
int numPatches, int indexBase, int stride, int primitiveIdBase)
{
OsdPatchArray array;
array.regDesc = regDesc;
array.desc = desc;
array.numPatches = numPatches;
array.indexBase = indexBase;
array.stride = stride;
array.primitiveIdBase = primitiveIdBase;
return array;
}
// Osd reflection of Osd::PatchParam
struct OsdPatchParam {
int field0;
int field1;
float sharpness;
};
OSD_FUNCTION_STORAGE_CLASS
OsdPatchParam
OsdPatchParamInit(int field0, int field1, float sharpness)
{
OsdPatchParam param;
param.field0 = field0;
param.field1 = field1;
param.sharpness = sharpness;
return param;
}
OSD_FUNCTION_STORAGE_CLASS
int
OsdPatchParamGetFaceId(OsdPatchParam param)
{
return (param.field0 & 0xfffffff);
}
OSD_FUNCTION_STORAGE_CLASS
int
OsdPatchParamGetU(OsdPatchParam param)
{
return ((param.field1 >> 22) & 0x3ff);
}
OSD_FUNCTION_STORAGE_CLASS
int
OsdPatchParamGetV(OsdPatchParam param)
{
return ((param.field1 >> 12) & 0x3ff);
}
OSD_FUNCTION_STORAGE_CLASS
int
OsdPatchParamGetTransition(OsdPatchParam param)
{
return ((param.field0 >> 28) & 0xf);
}
OSD_FUNCTION_STORAGE_CLASS
int
OsdPatchParamGetBoundary(OsdPatchParam param)
{
return ((param.field1 >> 7) & 0x1f);
}
OSD_FUNCTION_STORAGE_CLASS
int
OsdPatchParamGetNonQuadRoot(OsdPatchParam param)
{
return ((param.field1 >> 4) & 0x1);
}
OSD_FUNCTION_STORAGE_CLASS
int
OsdPatchParamGetDepth(OsdPatchParam param)
{
return (param.field1 & 0xf);
}
OSD_FUNCTION_STORAGE_CLASS
OSD_REAL
OsdPatchParamGetParamFraction(OsdPatchParam param)
{
return 1.0f / OSD_REAL_CAST(1 <<
(OsdPatchParamGetDepth(param) - OsdPatchParamGetNonQuadRoot(param)));
}
OSD_FUNCTION_STORAGE_CLASS
bool
OsdPatchParamIsRegular(OsdPatchParam param)
{
return (((param.field1 >> 5) & 0x1) != 0);
}
OSD_FUNCTION_STORAGE_CLASS
bool
OsdPatchParamIsTriangleRotated(OsdPatchParam param)
{
return ((OsdPatchParamGetU(param) + OsdPatchParamGetV(param)) >=
(1 << OsdPatchParamGetDepth(param)));
}
OSD_FUNCTION_STORAGE_CLASS
void
OsdPatchParamNormalize(
OsdPatchParam param,
OSD_INOUT_ARRAY(OSD_REAL, uv, 2))
{
OSD_REAL fracInv = 1.0f / OsdPatchParamGetParamFraction(param);
uv[0] = uv[0] * fracInv - OSD_REAL_CAST(OsdPatchParamGetU(param));
uv[1] = uv[1] * fracInv - OSD_REAL_CAST(OsdPatchParamGetV(param));
}
OSD_FUNCTION_STORAGE_CLASS
void
OsdPatchParamUnnormalize(
OsdPatchParam param,
OSD_INOUT_ARRAY(OSD_REAL, uv, 2))
{
OSD_REAL frac = OsdPatchParamGetParamFraction(param);
uv[0] = (uv[0] + OSD_REAL_CAST(OsdPatchParamGetU(param))) * frac;
uv[1] = (uv[1] + OSD_REAL_CAST(OsdPatchParamGetV(param))) * frac;
}
OSD_FUNCTION_STORAGE_CLASS
void
OsdPatchParamNormalizeTriangle(
OsdPatchParam param,
OSD_INOUT_ARRAY(OSD_REAL, uv, 2))
{
if (OsdPatchParamIsTriangleRotated(param)) {
OSD_REAL fracInv = 1.0f / OsdPatchParamGetParamFraction(param);
int depthFactor = 1 << OsdPatchParamGetDepth(param);
uv[0] = OSD_REAL_CAST(depthFactor - OsdPatchParamGetU(param)) - (uv[0] * fracInv);
uv[1] = OSD_REAL_CAST(depthFactor - OsdPatchParamGetV(param)) - (uv[1] * fracInv);
} else {
OsdPatchParamNormalize(param, uv);
}
}
OSD_FUNCTION_STORAGE_CLASS
void
OsdPatchParamUnnormalizeTriangle(
OsdPatchParam param,
OSD_INOUT_ARRAY(OSD_REAL, uv, 2))
{
if (OsdPatchParamIsTriangleRotated(param)) {
OSD_REAL frac = OsdPatchParamGetParamFraction(param);
int depthFactor = 1 << OsdPatchParamGetDepth(param);
uv[0] = (OSD_REAL_CAST(depthFactor - OsdPatchParamGetU(param)) - uv[0]) * frac;
uv[1] = (OSD_REAL_CAST(depthFactor - OsdPatchParamGetV(param)) - uv[1]) * frac;
} else {
OsdPatchParamUnnormalize(param, uv);
}
}
#endif /* OPENSUBDIV3_OSD_PATCH_BASIS_COMMON_TYPES_H */

View File

@ -26,7 +26,9 @@
#include "../osd/tbbKernel.h" #include "../osd/tbbKernel.h"
#include "../osd/types.h" #include "../osd/types.h"
#include "../osd/bufferDescriptor.h" #include "../osd/bufferDescriptor.h"
#include "../far/patchBasis.h" #include "../osd/patchBasisCommonTypes.h"
#include "../osd/patchBasisCommon.h"
#include "../osd/patchBasisCommonEval.h"
#include <cassert> #include <cassert>
#include <cstdlib> #include <cstdlib>
@ -382,7 +384,7 @@ public:
} }
void compute(tbb::blocked_range<int> const &r) const { void compute(tbb::blocked_range<int> const &r) const {
float wP[20], wDu[20], wDv[20]; float wP[20];
BufferAdapter<const float> srcT(_src + _srcDesc.offset, BufferAdapter<const float> srcT(_src + _srcDesc.offset,
_srcDesc.length, _srcDesc.length,
_srcDesc.stride); _srcDesc.stride);
@ -396,23 +398,25 @@ public:
PatchCoord const &coord = _patchCoords[i]; PatchCoord const &coord = _patchCoords[i];
PatchArray const &array = _patchArrayBuffer[coord.handle.arrayIndex]; PatchArray const &array = _patchArrayBuffer[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
_patchParamBuffer[coord.handle.patchIndex]; _patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
? Far::PatchDescriptor::REGULAR paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
: array.GetPatchType();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int patchType = OsdPatchParamIsRegular(param)
param, coord.s, coord.t, wP, wDu, wDv); ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular();
int indexStride = Far::PatchDescriptor(array.GetPatchType()).GetNumControlVertices(); int nPoints = OsdEvaluatePatchBasis(patchType, param,
int indexBase = array.GetIndexBase() + indexStride * coord.s, coord.t, wP, 0, 0, 0, 0, 0);
int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
const int *cvs = &_patchIndexBuffer[indexBase]; const int *cvs = &_patchIndexBuffer[indexBase];
dstT.Clear(); dstT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
} }
++dstT; ++dstT;
@ -441,17 +445,19 @@ public:
PatchCoord const &coord = _patchCoords[i]; PatchCoord const &coord = _patchCoords[i];
PatchArray const &array = _patchArrayBuffer[coord.handle.arrayIndex]; PatchArray const &array = _patchArrayBuffer[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
_patchParamBuffer[coord.handle.patchIndex]; _patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
? Far::PatchDescriptor::REGULAR paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
: array.GetPatchType();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int patchType = OsdPatchParamIsRegular(param)
param, coord.s, coord.t, wP, wDu, wDv); ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular();
int indexStride = Far::PatchDescriptor(array.GetPatchType()).GetNumControlVertices(); int nPoints = OsdEvaluatePatchBasis(patchType, param,
int indexBase = array.GetIndexBase() + indexStride * coord.s, coord.t, wP, wDu, wDv, 0, 0, 0);
int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
const int *cvs = &_patchIndexBuffer[indexBase]; const int *cvs = &_patchIndexBuffer[indexBase];
@ -459,7 +465,7 @@ public:
dstT.Clear(); dstT.Clear();
dstDuT.Clear(); dstDuT.Clear();
dstDvT.Clear(); dstDvT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
dstDuT.AddWithWeight(srcT[cvs[j]], wDu[j]); dstDuT.AddWithWeight(srcT[cvs[j]], wDu[j]);
dstDvT.AddWithWeight(srcT[cvs[j]], wDv[j]); dstDvT.AddWithWeight(srcT[cvs[j]], wDv[j]);
@ -504,17 +510,19 @@ public:
PatchCoord const &coord = _patchCoords[i]; PatchCoord const &coord = _patchCoords[i];
PatchArray const &array = _patchArrayBuffer[coord.handle.arrayIndex]; PatchArray const &array = _patchArrayBuffer[coord.handle.arrayIndex];
Far::PatchParam const & param = Osd::PatchParam const & paramStruct =
_patchParamBuffer[coord.handle.patchIndex]; _patchParamBuffer[coord.handle.patchIndex];
int patchType = param.IsRegular() OsdPatchParam param = OsdPatchParamInit(
? Far::PatchDescriptor::REGULAR paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
: array.GetPatchType();
int numControlVertices = Far::internal::EvaluatePatchBasis(patchType, int patchType = OsdPatchParamIsRegular(param)
param, coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv); ? array.GetPatchTypeRegular()
: array.GetPatchTypeIrregular();
int indexStride = Far::PatchDescriptor(array.GetPatchType()).GetNumControlVertices(); int nPoints = OsdEvaluatePatchBasis(patchType, param,
int indexBase = array.GetIndexBase() + indexStride * coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
int indexBase = array.GetIndexBase() + array.GetStride() *
(coord.handle.patchIndex - array.GetPrimitiveIdBase()); (coord.handle.patchIndex - array.GetPrimitiveIdBase());
const int *cvs = &_patchIndexBuffer[indexBase]; const int *cvs = &_patchIndexBuffer[indexBase];
@ -525,7 +533,7 @@ public:
dstDuuT.Clear(); dstDuuT.Clear();
dstDuvT.Clear(); dstDuvT.Clear();
dstDvvT.Clear(); dstDvvT.Clear();
for (int j = 0; j < numControlVertices; ++j) { for (int j = 0; j < nPoints; ++j) {
dstT.AddWithWeight(srcT[cvs[j]], wP[j]); dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
dstDuT.AddWithWeight(srcT[cvs[j]], wDu[j]); dstDuT.AddWithWeight(srcT[cvs[j]], wDu[j]);
dstDvT.AddWithWeight(srcT[cvs[j]], wDv[j]); dstDvT.AddWithWeight(srcT[cvs[j]], wDv[j]);