Mtl implementation whitespace fixes

Fixed numerous whitespace inconsistencies and violations
in the core osd metal implementation and examples.
This commit is contained in:
David G Yu 2019-05-22 18:00:36 -07:00
parent 24c37eecd3
commit 291eff0bed
21 changed files with 3193 additions and 3212 deletions

View File

@ -48,42 +48,42 @@ const constant float4 patchColors[] = {
float4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2 float4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2
float4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3 float4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3
float4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4 float4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4
float4(1.0f, 0.5f, 0.5f, 1.0f), // single crease float4(1.0f, 0.5f, 0.5f, 1.0f), // single crease
float4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0 float4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0
float4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1 float4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1
float4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2 float4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2
float4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3 float4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3
float4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4 float4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4
float4(0.8f, 0.0f, 0.0f, 1.0f), // boundary float4(0.8f, 0.0f, 0.0f, 1.0f), // boundary
float4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0 float4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0
float4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1 float4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1
float4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2 float4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2
float4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3 float4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3
float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4 float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4
float4(0.0f, 1.0f, 0.0f, 1.0f), // corner float4(0.0f, 1.0f, 0.0f, 1.0f), // corner
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
@ -94,10 +94,10 @@ const constant float4 patchColors[] = {
float4 float4
getAdaptivePatchColor(int3 patchParam, float sharpness) getAdaptivePatchColor(int3 patchParam, float sharpness)
{ {
int pattern = popcount(OsdGetPatchTransitionMask(patchParam)); int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam)); int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
int patchType = 0; int patchType = 0;
#if OSD_PATCH_ENABLE_SINGLE_CREASE #if OSD_PATCH_ENABLE_SINGLE_CREASE
if (sharpness > 0) { if (sharpness > 0) {
@ -111,7 +111,7 @@ getAdaptivePatchColor(int3 patchParam, float sharpness)
if (edgeCount == 2) { if (edgeCount == 2) {
patchType = 3; // CORNER patchType = 3; // CORNER
} }
// XXX: it looks like edgeCount != 0 for some gregory boundary patches. // XXX: it looks like edgeCount != 0 for some gregory boundary patches.
// there might be a bug somewhere... // there might be a bug somewhere...
#if OSD_PATCH_GREGORY #if OSD_PATCH_GREGORY
@ -121,7 +121,7 @@ getAdaptivePatchColor(int3 patchParam, float sharpness)
#elif OSD_PATCH_GREGORY_BASIS #elif OSD_PATCH_GREGORY_BASIS
patchType = 6; patchType = 6;
#endif #endif
return patchColors[6*patchType + pattern]; return patchColors[6*patchType + pattern];
} }
@ -149,7 +149,7 @@ float3 displacement(float3 position, float3 normal, float4 patchCoord, float mip
,device ushort* textureDisplace_Packing ,device ushort* textureDisplace_Packing
#endif #endif
) )
{ {
#if DISPLACEMENT_HW_BILINEAR #if DISPLACEMENT_HW_BILINEAR
float disp = PtexLookupFast(patchCoord, mipmapBias, float disp = PtexLookupFast(patchCoord, mipmapBias,
textureDisplace_Data, textureDisplace_Data,
@ -184,7 +184,7 @@ perturbNormalFromDisplacement(float3 position, float3 normal, float4 patchCoord,
{ {
// by Morten S. Mikkelsen // by Morten S. Mikkelsen
// http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf // http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf
// slightly modified for ptex guttering // slightly modified for ptex guttering
float3 vSigmaS = dfdx(position); float3 vSigmaS = dfdx(position);
float3 vSigmaT = dfdy(position); float3 vSigmaT = dfdy(position);
float3 vN = normal; float3 vN = normal;
@ -198,11 +198,11 @@ perturbNormalFromDisplacement(float3 position, float3 normal, float4 patchCoord,
#else #else
float2 texDx = dfdx(patchCoord.xy); float2 texDx = dfdx(patchCoord.xy);
float2 texDy = dfdy(patchCoord.xy); float2 texDy = dfdy(patchCoord.xy);
// limit forward differencing to the width of ptex gutter // limit forward differencing to the width of ptex gutter
const float resolution = 128.0; const float resolution = 128.0;
float d = min(1.0f, (0.5/resolution)/max(length(texDx), length(texDy))); float d = min(1.0f, (0.5/resolution)/max(length(texDx), length(texDy)));
float4 STll = patchCoord; float4 STll = patchCoord;
float4 STlr = patchCoord + d * float4(texDx.x, texDx.y, 0, 0); float4 STlr = patchCoord + d * float4(texDx.x, texDx.y, 0, 0);
float4 STul = patchCoord + d * float4(texDy.x, texDy.y, 0, 0); float4 STul = patchCoord + d * float4(texDy.x, texDy.y, 0, 0);
@ -218,7 +218,7 @@ perturbNormalFromDisplacement(float3 position, float3 normal, float4 patchCoord,
float dBs = (Hlr - Hll)/d; float dBs = (Hlr - Hll)/d;
float dBt = (Hul - Hll)/d; float dBt = (Hul - Hll)/d;
#endif #endif
float3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2); float3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
return normalize(abs(fDet) * vN - vSurfGrad); return normalize(abs(fDet) * vN - vSurfGrad);
} }
@ -251,7 +251,7 @@ struct FragmentInput
#if OSD_PATCH_REGULAR #if OSD_PATCH_REGULAR
struct ControlPoint struct ControlPoint
{ {
float3 P [[attribute(0)]]; float3 P [[attribute(0)]];
#if OSD_PATCH_ENABLE_SINGLE_CREASE #if OSD_PATCH_ENABLE_SINGLE_CREASE
float3 P1 [[attribute(1)]]; float3 P1 [[attribute(1)]];
@ -274,7 +274,7 @@ struct PatchInput
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY #elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
struct ControlPoint struct ControlPoint
{ {
float3 P [[attribute(0)]]; float3 P [[attribute(0)]];
float3 Ep [[attribute(1)]]; float3 Ep [[attribute(1)]];
float3 Em [[attribute(2)]]; float3 Em [[attribute(2)]];
@ -333,7 +333,7 @@ kernel void compute_main(
if(validThread) if(validThread)
{ {
patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer); patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer);
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++) for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
{ {
const auto vertexId = osdBuffers.indexBuffer[(thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset) * IndexLookupStride]; const auto vertexId = osdBuffers.indexBuffer[(thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset) * IndexLookupStride];
@ -440,20 +440,20 @@ vertex FragmentInput vertex_main(
) )
{ {
FragmentInput out; FragmentInput out;
#if USE_STAGE_IN #if USE_STAGE_IN
int3 patchParam = patchInput.patchParam; int3 patchParam = patchInput.patchParam;
#else #else
int3 patchParam = patchInput.patchParamBuffer[patch_id]; int3 patchParam = patchInput.patchParamBuffer[patch_id];
#endif #endif
int refinementLevel = OsdGetPatchRefinementLevel(patchParam); int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) / float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) /
exp2((float)refinementLevel - 1); exp2((float)refinementLevel - 1);
auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput); auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput);
#if USE_DISPLACEMENT #if USE_DISPLACEMENT
float3 position = displacement(patchVertex.position, float3 position = displacement(patchVertex.position,
patchVertex.normal, patchVertex.normal,
@ -468,7 +468,7 @@ vertex FragmentInput vertex_main(
float3 position = patchVertex.position; float3 position = patchVertex.position;
#endif #endif
out.positionOut = mul(frameConsts.ModelViewProjectionMatrix, float4(position, 1)); out.positionOut = mul(frameConsts.ModelViewProjectionMatrix, float4(position, 1));
out.position = mul(frameConsts.ModelViewMatrix, float4(position,1)).xyz; out.position = mul(frameConsts.ModelViewMatrix, float4(position,1)).xyz;
out.normal = mul(frameConsts.ModelViewMatrix,float4(patchVertex.normal, 0)).xyz; out.normal = mul(frameConsts.ModelViewMatrix,float4(patchVertex.normal, 0)).xyz;
@ -500,29 +500,29 @@ struct LightSource {
float4 diffuse; float4 diffuse;
float4 specular; float4 specular;
}; };
float4 float4
lighting(float4 texColor, float3 Peye, float3 Neye, float occ, const constant LightSource (&lightSource)[NUM_LIGHTS]) lighting(float4 texColor, float3 Peye, float3 Neye, float occ, const constant LightSource (&lightSource)[NUM_LIGHTS])
{ {
float4 color = float4(0.0, 0.0, 0.0, 0.0); float4 color = float4(0.0, 0.0, 0.0, 0.0);
float3 n = Neye; float3 n = Neye;
for (int i = 0; i < NUM_LIGHTS; ++i) { for (int i = 0; i < NUM_LIGHTS; ++i) {
float4 Plight = lightSource[i].position; float4 Plight = lightSource[i].position;
float3 l = (Plight.w == 0.0) float3 l = (Plight.w == 0.0)
? normalize(Plight.xyz) : normalize(Plight.xyz - Peye); ? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
float3 h = normalize(l + float3(0,0,1)); // directional viewer float3 h = normalize(l + float3(0,0,1)); // directional viewer
float d = max(0.0, dot(n, l)); float d = max(0.0, dot(n, l));
float s = pow(max(0.0, dot(n, h)), 64.0f); float s = pow(max(0.0, dot(n, h)), 64.0f);
color += (1.0 - occ) * ((lightSource[i].ambient + color += (1.0 - occ) * ((lightSource[i].ambient +
d * lightSource[i].diffuse) * texColor + d * lightSource[i].diffuse) * texColor +
s * lightSource[i].specular); s * lightSource[i].specular);
} }
color.a = 1.0; color.a = 1.0;
return color; return color;
} }
@ -546,11 +546,11 @@ edgeColor(float4 Cfill, float4 edgeDistance)
#endif #endif
float4 Cedge = float4(1.0, 1.0, 0.0, 1.0); float4 Cedge = float4(1.0, 1.0, 0.0, 1.0);
float p = exp2(-2 * d * d); float p = exp2(-2 * d * d);
#if defined(GEOMETRY_OUT_WIRE) #if defined(GEOMETRY_OUT_WIRE)
if (p < 0.25) discard; if (p < 0.25) discard;
#endif #endif
Cfill.rgb = lerp(Cfill.rgb, Cedge.rgb, p); Cfill.rgb = lerp(Cfill.rgb, Cedge.rgb, p);
#endif #endif
return Cfill; return Cfill;
@ -599,8 +599,8 @@ fragment float4 fragment_main(
,const constant float4& shade [[buffer(2)]] ,const constant float4& shade [[buffer(2)]]
) )
{ {
const auto displacementScale = config.displacementScale; const auto displacementScale = config.displacementScale;
const auto mipmapBias = config.mipmapBias; const auto mipmapBias = config.mipmapBias;
float4 outColor; float4 outColor;
// ------------ normal --------------- // ------------ normal ---------------
#if NORMAL_HW_SCREENSPACE || NORMAL_SCREENSPACE #if NORMAL_HW_SCREENSPACE || NORMAL_SCREENSPACE
@ -617,25 +617,25 @@ fragment float4 fragment_main(
config.mipmapBias, config.mipmapBias,
textureDisplace_Data, textureDisplace_Data,
textureDisplace_Packing); textureDisplace_Packing);
disp *= displacementScale; disp *= displacementScale;
du *= displacementScale; du *= displacementScale;
dv *= displacementScale; dv *= displacementScale;
float3 n = normalize(cross(input.tangent, input.bitangent)); float3 n = normalize(cross(input.tangent, input.bitangent));
float3 tangent = input.tangent + n * du.x; float3 tangent = input.tangent + n * du.x;
float3 bitangent = input.bitangent + n * dv.x; float3 bitangent = input.bitangent + n * dv.x;
#if NORMAL_BIQUADRATIC_WG #if NORMAL_BIQUADRATIC_WG
tangent += input.Nu * disp.x; tangent += input.Nu * disp.x;
bitangent += input.Nv * disp.x; bitangent += input.Nv * disp.x;
#endif #endif
float3 normal = normalize(cross(tangent, bitangent)); float3 normal = normalize(cross(tangent, bitangent));
#else #else
float3 normal = input.normal; float3 normal = input.normal;
#endif #endif
// ------------ color --------------- // ------------ color ---------------
#if COLOR_PTEX_NEAREST #if COLOR_PTEX_NEAREST
float4 texColor = PtexLookupNearest(input.patchCoord, float4 texColor = PtexLookupNearest(input.patchCoord,
@ -653,7 +653,7 @@ fragment float4 fragment_main(
float4 texColor = PtexMipmapLookupQuadratic(input.patchCoord, mipmapBias, float4 texColor = PtexMipmapLookupQuadratic(input.patchCoord, mipmapBias,
textureImage_Data, textureImage_Data,
textureImage_Packing); textureImage_Packing);
#elif COLOR_PATCHTYPE #elif COLOR_PATCHTYPE
float4 texColor = lighting(float4(input.patchColor), input.position.xyz, normal, 0, lightSource); float4 texColor = lighting(float4(input.patchColor), input.position.xyz, normal, 0, lightSource);
outColor = texColor; outColor = texColor;
return outColor; return outColor;
@ -668,9 +668,9 @@ fragment float4 fragment_main(
#else // COLOR_NONE #else // COLOR_NONE
float4 texColor = float4(0.5, 0.5, 0.5, 1); float4 texColor = float4(0.5, 0.5, 0.5, 1);
#endif #endif
// ------------ occlusion --------------- // ------------ occlusion ---------------
#if USE_PTEX_OCCLUSION #if USE_PTEX_OCCLUSION
float occ = PtexMipmapLookup(input.patchCoord, config.mipmapBias, float occ = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
textureOcclusion_Data, textureOcclusion_Data,
@ -678,9 +678,9 @@ fragment float4 fragment_main(
#else #else
float occ = 0.0; float occ = 0.0;
#endif #endif
// ------------ specular --------------- // ------------ specular ---------------
#if USE_PTEX_SPECULAR #if USE_PTEX_SPECULAR
float specular = PtexMipmapLookup(input.patchCoord, config.mipmapBias, float specular = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
textureSpecular_Data, textureSpecular_Data,
@ -690,7 +690,7 @@ fragment float4 fragment_main(
#endif #endif
// ------------ lighting --------------- // ------------ lighting ---------------
float4 Cf = lighting(texColor, input.position.xyz, normal, occ, lightSource); float4 Cf = lighting(texColor, input.position.xyz, normal, occ, lightSource);
// ------------ wireframe --------------- // ------------ wireframe ---------------
outColor = max(Cf, shade); outColor = max(Cf, shade);
return outColor; return outColor;

View File

@ -122,33 +122,33 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
@implementation OSDRenderer { @implementation OSDRenderer {
MTLRingBuffer<Light, 1> _lightsBuffer; MTLRingBuffer<Light, 1> _lightsBuffer;
PerFrameBuffer<PerFrameConstants> _frameConstantsBuffer; PerFrameBuffer<PerFrameConstants> _frameConstantsBuffer;
PerFrameBuffer<MTLQuadTessellationFactorsHalf> _tessFactorsBuffer; PerFrameBuffer<MTLQuadTessellationFactorsHalf> _tessFactorsBuffer;
PerFrameBuffer<unsigned> _patchIndexBuffers[4]; PerFrameBuffer<unsigned> _patchIndexBuffers[4];
PerFrameBuffer<uint8_t> _perPatchDataBuffer; PerFrameBuffer<uint8_t> _perPatchDataBuffer;
PerFrameBuffer<uint8_t> _hsDataBuffer; PerFrameBuffer<uint8_t> _hsDataBuffer;
PerFrameBuffer<MTLDrawPatchIndirectArguments> _drawIndirectCommandsBuffer; PerFrameBuffer<MTLDrawPatchIndirectArguments> _drawIndirectCommandsBuffer;
unsigned _tessFactorOffsets[4]; unsigned _tessFactorOffsets[4];
unsigned _perPatchDataOffsets[4]; unsigned _perPatchDataOffsets[4];
id<MTLComputePipelineState> _computePipelines[10]; id<MTLComputePipelineState> _computePipelines[10];
id<MTLRenderPipelineState> _renderPipelines[10]; id<MTLRenderPipelineState> _renderPipelines[10];
id<MTLDepthStencilState> _readWriteDepthStencilState; id<MTLDepthStencilState> _readWriteDepthStencilState;
id<MTLDepthStencilState> _readOnlyDepthStencilState; id<MTLDepthStencilState> _readOnlyDepthStencilState;
Camera _cameraData; Camera _cameraData;
Osd::MTLContext _context; Osd::MTLContext _context;
std::unique_ptr<MTLMeshInterface> _mesh; std::unique_ptr<MTLMeshInterface> _mesh;
std::unique_ptr<Shape> _shape; std::unique_ptr<Shape> _shape;
std::unique_ptr<MTLPtexMipmapTexture> _colorPtexture; std::unique_ptr<MTLPtexMipmapTexture> _colorPtexture;
std::unique_ptr<MTLPtexMipmapTexture> _displacementPtexture; std::unique_ptr<MTLPtexMipmapTexture> _displacementPtexture;
std::unique_ptr<MTLPtexMipmapTexture> _occlusionPtexture; std::unique_ptr<MTLPtexMipmapTexture> _occlusionPtexture;
std::unique_ptr<MTLPtexMipmapTexture> _specularPtexture; std::unique_ptr<MTLPtexMipmapTexture> _specularPtexture;
bool _needsRebuild, _doAdaptive; bool _needsRebuild, _doAdaptive;
NSString* _osdShaderSource; NSString* _osdShaderSource;
simd::float3 _meshCenter; simd::float3 _meshCenter;
@ -180,27 +180,27 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
self.displacementMode = kDisplacementModeNone; self.displacementMode = kDisplacementModeNone;
self.useAdaptive = true; self.useAdaptive = true;
self.displayStyle = kDisplayStyleShaded; self.displayStyle = kDisplayStyleShaded;
const auto colorFilename = getenv("COLOR_FILENAME"); const auto colorFilename = getenv("COLOR_FILENAME");
const auto displacementFilename = getenv("DISPLACEMENT_FILENAME"); const auto displacementFilename = getenv("DISPLACEMENT_FILENAME");
if(colorFilename) if(colorFilename)
_ptexColorFilename = [NSString stringWithUTF8String:colorFilename]; _ptexColorFilename = [NSString stringWithUTF8String:colorFilename];
if(displacementFilename) if(displacementFilename)
_ptexDisplacementFilename = [NSString stringWithUTF8String:displacementFilename]; _ptexDisplacementFilename = [NSString stringWithUTF8String:displacementFilename];
_delegate = delegate; _delegate = delegate;
_context.device = [delegate deviceFor:self]; _context.device = [delegate deviceFor:self];
_context.commandQueue = [delegate commandQueueFor:self]; _context.commandQueue = [delegate commandQueueFor:self];
_osdShaderSource = @(shaderSource); _osdShaderSource = @(shaderSource);
_needsRebuild = true; _needsRebuild = true;
_numFrames = 0; _numFrames = 0;
_animationFrames = 0; _animationFrames = 0;
[self _initializeBuffers]; [self _initializeBuffers];
[self _initializeCamera]; [self _initializeCamera];
[self _initializeLights]; [self _initializeLights];
@ -213,13 +213,13 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
if(_needsRebuild) { if(_needsRebuild) {
[self _rebuildState]; [self _rebuildState];
} }
if(!_freeze) { if(!_freeze) {
if(_animateVertices) { if(_animateVertices) {
_animatedVertices.resize(_vertexData.size()); _animatedVertices.resize(_vertexData.size());
auto p = _vertexData.data(); auto p = _vertexData.data();
auto n = _animatedVertices.data(); auto n = _animatedVertices.data();
float r = sin(_animationFrames*0.01f) * _animateVertices; float r = sin(_animationFrames*0.01f) * _animateVertices;
for (int i = 0; i < _numVertices; ++i) { for (int i = 0; i < _numVertices; ++i) {
float move = 0.05f*cosf(p[0]*20+_animationFrames*0.01f); float move = 0.05f*cosf(p[0]*20+_animationFrames*0.01f);
@ -228,36 +228,36 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
n[0] = p[0]*ct + p[1]*st; n[0] = p[0]*ct + p[1]*st;
n[1] = -p[0]*st + p[1]*ct; n[1] = -p[0]*st + p[1]*ct;
n[2] = p[2]; n[2] = p[2];
p += _numVertexElements; p += _numVertexElements;
n += _numVertexElements; n += _numVertexElements;
} }
_mesh->UpdateVertexBuffer(_animatedVertices.data(), 0, _numVertices); _mesh->UpdateVertexBuffer(_animatedVertices.data(), 0, _numVertices);
_animationFrames++; _animationFrames++;
} }
_mesh->Refine(); _mesh->Refine();
_mesh->Synchronize(); _mesh->Synchronize();
} }
[self _updateState]; [self _updateState];
if(_doAdaptive) { if(_doAdaptive) {
auto computeEncoder = [commandBuffer computeCommandEncoder]; auto computeEncoder = [commandBuffer computeCommandEncoder];
[self _computeTessFactors:computeEncoder]; [self _computeTessFactors:computeEncoder];
[computeEncoder endEncoding]; [computeEncoder endEncoding];
} }
auto renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:[_delegate renderPassDescriptorFor: self]]; auto renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:[_delegate renderPassDescriptorFor: self]];
if(_usePrimitiveBackfaceCulling) { if(_usePrimitiveBackfaceCulling) {
[renderEncoder setCullMode:MTLCullModeBack]; [renderEncoder setCullMode:MTLCullModeBack];
} else { } else {
[renderEncoder setCullMode:MTLCullModeNone]; [renderEncoder setCullMode:MTLCullModeNone];
} }
[self _renderMesh:renderEncoder]; [self _renderMesh:renderEncoder];
_frameConstantsBuffer.next(); _frameConstantsBuffer.next();
_tessFactorsBuffer.next(); _tessFactorsBuffer.next();
_patchIndexBuffers[0].next(); _patchIndexBuffers[0].next();
@ -268,25 +268,25 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
_perPatchDataBuffer.next(); _perPatchDataBuffer.next();
_hsDataBuffer.next(); _hsDataBuffer.next();
_drawIndirectCommandsBuffer.next(); _drawIndirectCommandsBuffer.next();
_numFrames++; _numFrames++;
return renderEncoder; return renderEncoder;
} }
-(void)_renderMesh:(id<MTLRenderCommandEncoder>)renderCommandEncoder { -(void)_renderMesh:(id<MTLRenderCommandEncoder>)renderCommandEncoder {
auto buffer = _mesh->BindVertexBuffer(); auto buffer = _mesh->BindVertexBuffer();
assert(buffer); assert(buffer);
auto pav = _mesh->GetPatchTable()->GetPatchArrays(); auto pav = _mesh->GetPatchTable()->GetPatchArrays();
auto pib = _mesh->GetPatchTable()->GetPatchIndexBuffer(); auto pib = _mesh->GetPatchTable()->GetPatchIndexBuffer();
[renderCommandEncoder setVertexBuffer:buffer offset:0 atIndex:VERTEX_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:buffer offset:0 atIndex:VERTEX_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer: pib offset:0 atIndex:INDICES_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer: pib offset:0 atIndex:INDICES_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer:_frameConstantsBuffer offset:offsetof(PerFrameConstants, displacementConfig) atIndex:CONFIG_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_frameConstantsBuffer offset:offsetof(PerFrameConstants, displacementConfig) atIndex:CONFIG_BUFFER_INDEX];
if(_doAdaptive) if(_doAdaptive)
{ {
[renderCommandEncoder setVertexBuffer:_hsDataBuffer offset:0 atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_hsDataBuffer offset:0 atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX];
@ -294,49 +294,49 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder setVertexBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX];
} }
[renderCommandEncoder setFragmentBuffer:_frameConstantsBuffer offset:offsetof(PerFrameConstants, displacementConfig) atIndex:1]; [renderCommandEncoder setFragmentBuffer:_frameConstantsBuffer offset:offsetof(PerFrameConstants, displacementConfig) atIndex:1];
[renderCommandEncoder setFragmentBuffer:_lightsBuffer offset:0 atIndex:0]; [renderCommandEncoder setFragmentBuffer:_lightsBuffer offset:0 atIndex:0];
[renderCommandEncoder setFragmentTexture:_colorPtexture->GetTexelsTexture() atIndex:IMAGE_TEXTURE_INDEX]; [renderCommandEncoder setFragmentTexture:_colorPtexture->GetTexelsTexture() atIndex:IMAGE_TEXTURE_INDEX];
[renderCommandEncoder setFragmentBuffer:_colorPtexture->GetLayoutBuffer() offset:0 atIndex:IMAGE_BUFFER_INDEX]; [renderCommandEncoder setFragmentBuffer:_colorPtexture->GetLayoutBuffer() offset:0 atIndex:IMAGE_BUFFER_INDEX];
if(_displacementPtexture) if(_displacementPtexture)
{ {
[renderCommandEncoder setFragmentTexture:_displacementPtexture->GetTexelsTexture() atIndex:DISPLACEMENT_TEXTURE_INDEX]; [renderCommandEncoder setFragmentTexture:_displacementPtexture->GetTexelsTexture() atIndex:DISPLACEMENT_TEXTURE_INDEX];
[renderCommandEncoder setFragmentBuffer:_displacementPtexture->GetLayoutBuffer() offset:0 atIndex:DISPLACEMENT_BUFFER_INDEX]; [renderCommandEncoder setFragmentBuffer:_displacementPtexture->GetLayoutBuffer() offset:0 atIndex:DISPLACEMENT_BUFFER_INDEX];
[renderCommandEncoder setVertexTexture:_displacementPtexture->GetTexelsTexture() atIndex:DISPLACEMENT_TEXTURE_INDEX]; [renderCommandEncoder setVertexTexture:_displacementPtexture->GetTexelsTexture() atIndex:DISPLACEMENT_TEXTURE_INDEX];
[renderCommandEncoder setVertexBuffer:_displacementPtexture->GetLayoutBuffer() offset:0 atIndex:DISPLACEMENT_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_displacementPtexture->GetLayoutBuffer() offset:0 atIndex:DISPLACEMENT_BUFFER_INDEX];
} }
for(int i = 0; i < pav.size(); i++) for(int i = 0; i < pav.size(); i++)
{ {
auto& patch = pav[i]; auto& patch = pav[i];
auto d = patch.GetDescriptor(); auto d = patch.GetDescriptor();
auto patchType = d.GetType(); auto patchType = d.GetType();
auto offset = patchType - Far::PatchDescriptor::REGULAR; auto offset = patchType - Far::PatchDescriptor::REGULAR;
if(_doAdaptive) if(_doAdaptive)
{ {
[renderCommandEncoder setVertexBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX]; [renderCommandEncoder setVertexBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
} }
[renderCommandEncoder setVertexBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX]; [renderCommandEncoder setVertexBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX];
simd::float4 shade{.0f,0.0f,0.0f,1.0f}; simd::float4 shade{.0f,0.0f,0.0f,1.0f};
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2]; [renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
[renderCommandEncoder setDepthBias:0 slopeScale:1.0 clamp:0]; [renderCommandEncoder setDepthBias:0 slopeScale:1.0 clamp:0];
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill];
[renderCommandEncoder setDepthStencilState:_readWriteDepthStencilState]; [renderCommandEncoder setDepthStencilState:_readWriteDepthStencilState];
[renderCommandEncoder setRenderPipelineState:_renderPipelines[patchType]]; [renderCommandEncoder setRenderPipelineState:_renderPipelines[patchType]];
if(_displayStyle == kDisplayStyleWire) if(_displayStyle == kDisplayStyleWire)
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
else else
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill];
switch(patchType) switch(patchType)
{ {
case Far::PatchDescriptor::GREGORY_BASIS: case Far::PatchDescriptor::GREGORY_BASIS:
@ -347,8 +347,8 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder setVertexBufferOffset:_perPatchDataOffsets[offset] atIndex:OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX]; [renderCommandEncoder setVertexBufferOffset:_perPatchDataOffsets[offset] atIndex:OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX];
break; break;
} }
switch(patchType) switch(patchType)
{ {
case Far::PatchDescriptor::POINTS: case Far::PatchDescriptor::POINTS:
@ -379,7 +379,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2]; [renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
[renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0]; [renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0];
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
[renderCommandEncoder drawIndexedPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches() [renderCommandEncoder drawIndexedPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches()
@ -414,14 +414,14 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder drawPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches() [renderCommandEncoder drawPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches()
patchIndexBuffer:nil patchIndexBufferOffset:0 instanceCount:1 baseInstance:0]; patchIndexBuffer:nil patchIndexBufferOffset:0 instanceCount:1 baseInstance:0];
} }
if(_displayStyle == kDisplayStyleWireOnShaded) if(_displayStyle == kDisplayStyleWireOnShaded)
{ {
simd::float4 shade = {1, 1,1,1}; simd::float4 shade = {1, 1,1,1};
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2]; [renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
[renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0]; [renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0];
#if !TARGET_OS_EMBEDDED #if !TARGET_OS_EMBEDDED
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
@ -439,8 +439,8 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
} }
} }
break; break;
case Far::PatchDescriptor::QUADS: case Far::PatchDescriptor::QUADS:
[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:patch.GetNumPatches() * 6]; [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:patch.GetNumPatches() * 6];
break; break;
@ -456,7 +456,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
-(void)_computeTessFactors:(id<MTLComputeCommandEncoder>)computeCommandEncoder { -(void)_computeTessFactors:(id<MTLComputeCommandEncoder>)computeCommandEncoder {
auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays(); auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays();
[computeCommandEncoder setBuffer:_mesh->BindVertexBuffer() offset:0 atIndex:VERTEX_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_mesh->BindVertexBuffer() offset:0 atIndex:VERTEX_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchIndexBuffer() offset:0 atIndex:CONTROL_INDICES_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchIndexBuffer() offset:0 atIndex:CONTROL_INDICES_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
@ -465,40 +465,40 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[computeCommandEncoder setBuffer:_tessFactorsBuffer offset:0 atIndex:QUAD_TESSFACTORS_INDEX]; [computeCommandEncoder setBuffer:_tessFactorsBuffer offset:0 atIndex:QUAD_TESSFACTORS_INDEX];
[computeCommandEncoder setBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX];
for(auto& patch : patchArray) for(auto& patch : patchArray)
{ {
auto usefulControlPoints = patch.GetDescriptor().GetNumControlVertices(); auto usefulControlPoints = patch.GetDescriptor().GetNumControlVertices();
if(patch.GetDescriptor().GetType() == Far::PatchDescriptor::GREGORY_BASIS) if(patch.GetDescriptor().GetType() == Far::PatchDescriptor::GREGORY_BASIS)
usefulControlPoints = 4; usefulControlPoints = 4;
auto threadsPerThreadgroup = MTLSizeMake([_computePipelines[patch.GetPatchType()] threadExecutionWidth], 1, 1); auto threadsPerThreadgroup = MTLSizeMake([_computePipelines[patch.GetPatchType()] threadExecutionWidth], 1, 1);
auto threadsPerControlPoint = std::max<int>(1, usefulControlPoints / threadsPerThreadgroup.width); auto threadsPerControlPoint = std::max<int>(1, usefulControlPoints / threadsPerThreadgroup.width);
auto groupPerControlPoint = MTLSizeMake(patch.GetNumPatches() * usefulControlPoints, 1, 1); auto groupPerControlPoint = MTLSizeMake(patch.GetNumPatches() * usefulControlPoints, 1, 1);
groupPerControlPoint.width /= threadsPerControlPoint; groupPerControlPoint.width /= threadsPerControlPoint;
groupPerControlPoint.width = (groupPerControlPoint.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1); groupPerControlPoint.width = (groupPerControlPoint.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1);
groupPerControlPoint.width = groupPerControlPoint.width / threadsPerThreadgroup.width; groupPerControlPoint.width = groupPerControlPoint.width / threadsPerThreadgroup.width;
auto groupPerPatch = MTLSizeMake(patch.GetNumPatches(), 1, 1); auto groupPerPatch = MTLSizeMake(patch.GetNumPatches(), 1, 1);
groupPerPatch.width = (groupPerPatch.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1); groupPerPatch.width = (groupPerPatch.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1);
groupPerPatch.width = groupPerPatch.width / threadsPerThreadgroup.width; groupPerPatch.width = groupPerPatch.width / threadsPerThreadgroup.width;
[computeCommandEncoder setBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX]; [computeCommandEncoder setBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
[computeCommandEncoder setBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX]; [computeCommandEncoder setBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX];
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
[computeCommandEncoder setBuffer:_patchIndexBuffers[patch.desc.GetType() - Far::PatchDescriptor::REGULAR] offset:0 atIndex:OSD_PATCH_INDEX_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_patchIndexBuffers[patch.desc.GetType() - Far::PatchDescriptor::REGULAR] offset:0 atIndex:OSD_PATCH_INDEX_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_drawIndirectCommandsBuffer offset:sizeof(MTLDrawPatchIndirectArguments) * (patch.desc.GetType() - Far::PatchDescriptor::REGULAR) atIndex:OSD_DRAWINDIRECT_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_drawIndirectCommandsBuffer offset:sizeof(MTLDrawPatchIndirectArguments) * (patch.desc.GetType() - Far::PatchDescriptor::REGULAR) atIndex:OSD_DRAWINDIRECT_BUFFER_INDEX];
} }
[computeCommandEncoder setComputePipelineState:_computePipelines[patch.desc.GetType()]]; [computeCommandEncoder setComputePipelineState:_computePipelines[patch.desc.GetType()]];
unsigned kernelExecutionLimit; unsigned kernelExecutionLimit;
switch(patch.desc.GetType()) switch(patch.desc.GetType())
{ {
@ -514,7 +514,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
break; break;
default: return; default: return;
} }
[computeCommandEncoder setBytes:&kernelExecutionLimit length:sizeof(kernelExecutionLimit) atIndex:OSD_KERNELLIMIT_BUFFER_INDEX]; [computeCommandEncoder setBytes:&kernelExecutionLimit length:sizeof(kernelExecutionLimit) atIndex:OSD_KERNELLIMIT_BUFFER_INDEX];
[computeCommandEncoder dispatchThreadgroups:groupPerControlPoint threadsPerThreadgroup:threadsPerThreadgroup]; [computeCommandEncoder dispatchThreadgroups:groupPerControlPoint threadsPerThreadgroup:threadsPerThreadgroup];
} }
@ -525,7 +525,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[self _rebuildModel]; [self _rebuildModel];
[self _rebuildBuffers]; [self _rebuildBuffers];
[self _rebuildPipelines]; [self _rebuildPipelines];
_needsRebuild = false; _needsRebuild = false;
} }
@ -534,7 +534,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
_displacementPtexture.reset(); _displacementPtexture.reset();
_occlusionPtexture.reset(); _occlusionPtexture.reset();
_specularPtexture.reset(); _specularPtexture.reset();
_colorPtexture = [self _createPtex:_ptexColorFilename]; _colorPtexture = [self _createPtex:_ptexColorFilename];
if(_ptexDisplacementFilename) { if(_ptexDisplacementFilename) {
_displacementPtexture = [self _createPtex:_ptexDisplacementFilename]; _displacementPtexture = [self _createPtex:_ptexDisplacementFilename];
@ -542,7 +542,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
} }
-(std::unique_ptr<MTLPtexMipmapTexture>)_createPtex:(NSString*) filename { -(std::unique_ptr<MTLPtexMipmapTexture>)_createPtex:(NSString*) filename {
Ptex::String ptexError; Ptex::String ptexError;
printf("Loading ptex : %s\n", filename.UTF8String); printf("Loading ptex : %s\n", filename.UTF8String);
#if TARGET_OS_EMBEDDED #if TARGET_OS_EMBEDDED
@ -550,44 +550,44 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
#else #else
const auto path = filename; const auto path = filename;
#endif #endif
#define USE_PTEX_CACHE 1 #define USE_PTEX_CACHE 1
#define PTEX_CACHE_SIZE (512*1024*1024) #define PTEX_CACHE_SIZE (512*1024*1024)
#if USE_PTEX_CACHE #if USE_PTEX_CACHE
PtexCache *cache = PtexCache::create(1, PTEX_CACHE_SIZE); PtexCache *cache = PtexCache::create(1, PTEX_CACHE_SIZE);
PtexTexture *ptex = cache->get(path.UTF8String, ptexError); PtexTexture *ptex = cache->get(path.UTF8String, ptexError);
#else #else
PtexTexture *ptex = PtexTexture::open(path.UTF8String, ptexError, true); PtexTexture *ptex = PtexTexture::open(path.UTF8String, ptexError, true);
#endif #endif
if (ptex == NULL) { if (ptex == NULL) {
printf("Error in reading %s\n", filename.UTF8String); printf("Error in reading %s\n", filename.UTF8String);
exit(1); exit(1);
} }
std::unique_ptr<MTLPtexMipmapTexture> osdPtex(MTLPtexMipmapTexture::Create(&_context, ptex)); std::unique_ptr<MTLPtexMipmapTexture> osdPtex(MTLPtexMipmapTexture::Create(&_context, ptex));
ptex->release(); ptex->release();
#if USE_PTEX_CACHE #if USE_PTEX_CACHE
cache->release(); cache->release();
#endif #endif
return osdPtex; return osdPtex;
} }
-(std::unique_ptr<Shape>)_shapeFromPtex:(Ptex::PtexTexture*) tex { -(std::unique_ptr<Shape>)_shapeFromPtex:(Ptex::PtexTexture*) tex {
const auto meta = tex->getMetaData(); const auto meta = tex->getMetaData();
if (meta->numKeys() < 3) { if (meta->numKeys() < 3) {
return NULL; return NULL;
} }
float const * vp; float const * vp;
int const *vi, *vc; int const *vi, *vc;
int nvp, nvi, nvc; int nvp, nvi, nvc;
meta->getValue("PtexFaceVertCounts", vc, nvc); meta->getValue("PtexFaceVertCounts", vc, nvc);
if (nvc == 0) { if (nvc == 0) {
return NULL; return NULL;
@ -600,26 +600,26 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
if (nvi == 0) { if (nvi == 0) {
return NULL; return NULL;
} }
std::unique_ptr<Shape> shape(new Shape); std::unique_ptr<Shape> shape(new Shape);
shape->scheme = kCatmark; shape->scheme = kCatmark;
shape->verts.resize(nvp); shape->verts.resize(nvp);
for (int i=0; i<nvp; ++i) { for (int i=0; i<nvp; ++i) {
shape->verts[i] = vp[i]; shape->verts[i] = vp[i];
} }
shape->nvertsPerFace.resize(nvc); shape->nvertsPerFace.resize(nvc);
for (int i=0; i<nvc; ++i) { for (int i=0; i<nvc; ++i) {
shape->nvertsPerFace[i] = vc[i]; shape->nvertsPerFace[i] = vc[i];
} }
shape->faceverts.resize(nvi); shape->faceverts.resize(nvi);
for (int i=0; i<nvi; ++i) { for (int i=0; i<nvi; ++i) {
shape->faceverts[i] = vi[i]; shape->faceverts[i] = vi[i];
} }
// compute model bounding // compute model bounding
float min[3] = {vp[0], vp[1], vp[2]}; float min[3] = {vp[0], vp[1], vp[2]};
float max[3] = {vp[0], vp[1], vp[2]}; float max[3] = {vp[0], vp[1], vp[2]};
@ -630,23 +630,23 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
max[j] = std::max(max[j], v); max[j] = std::max(max[j], v);
} }
} }
for (int j = 0; j < 3; ++j) { for (int j = 0; j < 3; ++j) {
_meshCenter[j] = (min[j] + max[j]) * 0.5f; _meshCenter[j] = (min[j] + max[j]) * 0.5f;
_meshSize += (max[j]-min[j])*(max[j]-min[j]); _meshSize += (max[j]-min[j])*(max[j]-min[j]);
} }
_meshSize = sqrtf(_meshSize); _meshSize = sqrtf(_meshSize);
return shape; return shape;
} }
-(void)_rebuildModel { -(void)_rebuildModel {
using namespace OpenSubdiv; using namespace OpenSubdiv;
using namespace Sdc; using namespace Sdc;
using namespace Osd; using namespace Osd;
using namespace Far; using namespace Far;
Ptex::String ptexError; Ptex::String ptexError;
#if TARGET_OS_EMBEDDED #if TARGET_OS_EMBEDDED
const auto ptexColor = PtexTexture::open([[NSBundle mainBundle] pathForResource:_ptexColorFilename ofType:nil].UTF8String, ptexError); const auto ptexColor = PtexTexture::open([[NSBundle mainBundle] pathForResource:_ptexColorFilename ofType:nil].UTF8String, ptexError);
@ -654,31 +654,31 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
const auto ptexColor = PtexTexture::open(_ptexColorFilename.UTF8String, ptexError); const auto ptexColor = PtexTexture::open(_ptexColorFilename.UTF8String, ptexError);
#endif #endif
_shape = [self _shapeFromPtex:ptexColor]; _shape = [self _shapeFromPtex:ptexColor];
// create Far mesh (topology) // create Far mesh (topology)
Sdc::SchemeType sdctype = GetSdcType(*_shape); Sdc::SchemeType sdctype = GetSdcType(*_shape);
Sdc::Options sdcoptions = GetSdcOptions(*_shape); Sdc::Options sdcoptions = GetSdcOptions(*_shape);
std::unique_ptr<OpenSubdiv::Far::TopologyRefiner> refiner; std::unique_ptr<OpenSubdiv::Far::TopologyRefiner> refiner;
refiner.reset( refiner.reset(
Far::TopologyRefinerFactory<Shape>::Create(*_shape, Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions))); Far::TopologyRefinerFactory<Shape>::Create(*_shape, Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)));
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
// Adaptive refinement currently supported only for catmull-clark scheme // Adaptive refinement currently supported only for catmull-clark scheme
_doAdaptive = (_useAdaptive); _doAdaptive = (_useAdaptive);
bool doSingleCreasePatch = (_useSingleCrease); bool doSingleCreasePatch = (_useSingleCrease);
Osd::MeshBitset bits; Osd::MeshBitset bits;
bits.set(Osd::MeshAdaptive, _doAdaptive); bits.set(Osd::MeshAdaptive, _doAdaptive);
bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch); bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
bits.set(Osd::MeshEndCapGregoryBasis, true); bits.set(Osd::MeshEndCapGregoryBasis, true);
int level = _refinementLevel; int level = _refinementLevel;
_numVertexElements = 3; _numVertexElements = 3;
int numVaryingElements = 0; int numVaryingElements = 0;
if(_kernelType == kCPU) if(_kernelType == kCPU)
{ {
_mesh.reset(new CPUMeshType( _mesh.reset(new CPUMeshType(
@ -695,11 +695,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
numVaryingElements, numVaryingElements,
level, bits, nullptr, &_context)); level, bits, nullptr, &_context));
} }
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new]; MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
[_delegate setupRenderPipelineState:desc for:self]; [_delegate setupRenderPipelineState:desc for:self];
const auto vertexDescriptor = desc.vertexDescriptor; const auto vertexDescriptor = desc.vertexDescriptor;
vertexDescriptor.layouts[0].stride = sizeof(float) * _numVertexElements; vertexDescriptor.layouts[0].stride = sizeof(float) * _numVertexElements;
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex; vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
@ -707,19 +707,19 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat3; vertexDescriptor.attributes[0].format = MTLVertexFormatFloat3;
vertexDescriptor.attributes[0].offset = 0; vertexDescriptor.attributes[0].offset = 0;
vertexDescriptor.attributes[0].bufferIndex = 0; vertexDescriptor.attributes[0].bufferIndex = 0;
_numVertices = refBaseLevel.GetNumVertices(); _numVertices = refBaseLevel.GetNumVertices();
_vertexData.resize(refBaseLevel.GetNumVertices() * _numVertexElements); _vertexData.resize(refBaseLevel.GetNumVertices() * _numVertexElements);
_meshCenter = simd::float3{0,0,0}; _meshCenter = simd::float3{0,0,0};
for(int vertexIdx = 0; vertexIdx < refBaseLevel.GetNumVertices(); vertexIdx++) for(int vertexIdx = 0; vertexIdx < refBaseLevel.GetNumVertices(); vertexIdx++)
{ {
_vertexData[vertexIdx * _numVertexElements + 0] = _shape->verts[vertexIdx * 3 + 0]; _vertexData[vertexIdx * _numVertexElements + 0] = _shape->verts[vertexIdx * 3 + 0];
_vertexData[vertexIdx * _numVertexElements + 1] = _shape->verts[vertexIdx * 3 + 1]; _vertexData[vertexIdx * _numVertexElements + 1] = _shape->verts[vertexIdx * 3 + 1];
_vertexData[vertexIdx * _numVertexElements + 2] = _shape->verts[vertexIdx * 3 + 2]; _vertexData[vertexIdx * _numVertexElements + 2] = _shape->verts[vertexIdx * 3 + 2];
_meshCenter[0] += _vertexData[vertexIdx * _numVertexElements + 0]; _meshCenter[0] += _vertexData[vertexIdx * _numVertexElements + 0];
_meshCenter[1] += _vertexData[vertexIdx * _numVertexElements + 1]; _meshCenter[1] += _vertexData[vertexIdx * _numVertexElements + 1];
_meshCenter[2] += _vertexData[vertexIdx * _numVertexElements + 2]; _meshCenter[2] += _vertexData[vertexIdx * _numVertexElements + 2];
@ -734,11 +734,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
-(void)_updateState { -(void)_updateState {
[self _updateCamera]; [self _updateCamera];
auto pData = _frameConstantsBuffer.data(); auto pData = _frameConstantsBuffer.data();
pData->TessLevel = _tessellationLevel; pData->TessLevel = _tessellationLevel;
pData->displacementConfig.mipmapBias = _mipmapBias; pData->displacementConfig.mipmapBias = _mipmapBias;
pData->displacementConfig.displacementScale = _displacementScale; pData->displacementConfig.displacementScale = _displacementScale;
{ {
for(auto& patch : _mesh->GetPatchTable()->GetPatchArrays()) for(auto& patch : _mesh->GetPatchTable()->GetPatchArrays())
{ {
@ -751,7 +751,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
drawCommand[patch.desc.GetType() - Far::PatchDescriptor::REGULAR].patchStart = 0; drawCommand[patch.desc.GetType() - Far::PatchDescriptor::REGULAR].patchStart = 0;
} }
} }
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
_drawIndirectCommandsBuffer.markModified(); _drawIndirectCommandsBuffer.markModified();
@ -765,19 +765,19 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
auto totalPatches = 0; auto totalPatches = 0;
auto totalVertices = 0; auto totalVertices = 0;
auto totalPatchDataSize = 0; auto totalPatchDataSize = 0;
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
_drawIndirectCommandsBuffer.alloc(_context.device, 4, @"draw patch indirect commands"); _drawIndirectCommandsBuffer.alloc(_context.device, 4, @"draw patch indirect commands");
} }
if(_doAdaptive) if(_doAdaptive)
{ {
auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays(); auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays();
for(auto& patch : patchArray) for(auto& patch : patchArray)
{ {
auto patchDescriptor = patch.GetDescriptor(); auto patchDescriptor = patch.GetDescriptor();
switch(patch.desc.GetType()) switch(patch.desc.GetType())
{ {
case Far::PatchDescriptor::REGULAR: { case Far::PatchDescriptor::REGULAR: {
@ -790,7 +790,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
float elementFloats = 3; float elementFloats = 3;
if(_useSingleCrease) if(_useSingleCrease)
elementFloats += 6; elementFloats += 6;
totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * patch.desc.GetNumControlVertices(); totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * patch.desc.GetNumControlVertices();
} }
break; break;
@ -824,15 +824,15 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
// totalPatchDataSize += sizeof(float) * 4 * 2 * patch.GetNumPatches() * patch.desc.GetNumControlVertices(); // totalPatchDataSize += sizeof(float) * 4 * 2 * patch.GetNumPatches() * patch.desc.GetNumControlVertices();
break; break;
} }
totalPatches += patch.GetNumPatches(); totalPatches += patch.GetNumPatches();
totalVertices += patch.GetDescriptor().GetNumControlVertices() * patch.GetNumPatches(); totalVertices += patch.GetDescriptor().GetNumControlVertices() * patch.GetNumPatches();
} }
_perPatchDataBuffer.alloc(_context.device, totalPatchDataSize, @"per patch data", MTLResourceStorageModePrivate); _perPatchDataBuffer.alloc(_context.device, totalPatchDataSize, @"per patch data", MTLResourceStorageModePrivate);
_hsDataBuffer.alloc(_context.device, 20 * sizeof(float) * totalPatches, @"hs constant data", MTLResourceStorageModePrivate); _hsDataBuffer.alloc(_context.device, 20 * sizeof(float) * totalPatches, @"hs constant data", MTLResourceStorageModePrivate);
_tessFactorsBuffer.alloc(_context.device, totalPatches, @"tessellation factors buffer", MTLResourceStorageModePrivate); _tessFactorsBuffer.alloc(_context.device, totalPatches, @"tessellation factors buffer", MTLResourceStorageModePrivate);
} }
} }
@ -841,7 +841,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
_computePipelines[i] = nil; _computePipelines[i] = nil;
_renderPipelines[i] = nil; _renderPipelines[i] = nil;
} }
Osd::MTLPatchShaderSource shaderSource; Osd::MTLPatchShaderSource shaderSource;
auto& patchArrays = _mesh->GetPatchTable()->GetPatchArrays(); auto& patchArrays = _mesh->GetPatchTable()->GetPatchArrays();
for(auto& patch : patchArrays) for(auto& patch : patchArrays)
@ -851,11 +851,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
auto controlPointsPerThread = [&]() { auto controlPointsPerThread = [&]() {
return std::max<int>(1, usefulControlPoints / threadsPerThreadgroup); return std::max<int>(1, usefulControlPoints / threadsPerThreadgroup);
}; };
auto type = patch.GetDescriptor().GetType(); auto type = patch.GetDescriptor().GetType();
auto compileOptions = [[MTLCompileOptions alloc] init]; auto compileOptions = [[MTLCompileOptions alloc] init];
compileOptions.fastMathEnabled = YES; compileOptions.fastMathEnabled = YES;
auto preprocessor = [[NSMutableDictionary alloc] init]; auto preprocessor = [[NSMutableDictionary alloc] init];
#define DEFINE(x, y) preprocessor[@(#x)] = @(y) #define DEFINE(x, y) preprocessor[@(#x)] = @(y)
bool allowsSingleCrease = true; bool allowsSingleCrease = true;
@ -888,11 +888,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
usefulControlPoints = 4; usefulControlPoints = 4;
break; break;
} }
#if TARGET_OS_EMBEDDED #if TARGET_OS_EMBEDDED
shaderBuilder << "#define OSD_UV_CORRECTION if(t > 0.5){ ti += 0.01f; } else { ti += 0.01f; }\n"; shaderBuilder << "#define OSD_UV_CORRECTION if(t > 0.5){ ti += 0.01f; } else { ti += 0.01f; }\n";
#endif #endif
//Need to define the input vertex struct so that it's available everywhere. //Need to define the input vertex struct so that it's available everywhere.
shaderBuilder << R"( shaderBuilder << R"(
#include <metal_stdlib> #include <metal_stdlib>
@ -900,14 +900,14 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
metal::packed_float3 position; metal::packed_float3 position;
}; };
)"; )";
auto fvarType = Far::PatchDescriptor::REGULAR; auto fvarType = Far::PatchDescriptor::REGULAR;
shaderBuilder << shaderSource.GetHullShaderSource(type, fvarType); shaderBuilder << shaderSource.GetHullShaderSource(type, fvarType);
shaderBuilder << MTLPtexMipmapTexture::GetShaderSource(); shaderBuilder << MTLPtexMipmapTexture::GetShaderSource();
shaderBuilder << _osdShaderSource.UTF8String; shaderBuilder << _osdShaderSource.UTF8String;
const auto str = shaderBuilder.str(); const auto str = shaderBuilder.str();
DEFINE(CONFIG_BUFFER_INDEX,CONFIG_BUFFER_INDEX); DEFINE(CONFIG_BUFFER_INDEX,CONFIG_BUFFER_INDEX);
DEFINE(VERTEX_BUFFER_INDEX,VERTEX_BUFFER_INDEX); DEFINE(VERTEX_BUFFER_INDEX,VERTEX_BUFFER_INDEX);
DEFINE(PATCH_INDICES_BUFFER_INDEX,PATCH_INDICES_BUFFER_INDEX); DEFINE(PATCH_INDICES_BUFFER_INDEX,PATCH_INDICES_BUFFER_INDEX);
@ -933,7 +933,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
DEFINE(SPECULAR_BUFFER_INDEX,SPECULAR_BUFFER_INDEX); DEFINE(SPECULAR_BUFFER_INDEX,SPECULAR_BUFFER_INDEX);
DEFINE(OSD_KERNELLIMIT_BUFFER_INDEX,OSD_KERNELLIMIT_BUFFER_INDEX); DEFINE(OSD_KERNELLIMIT_BUFFER_INDEX,OSD_KERNELLIMIT_BUFFER_INDEX);
DEFINE(OSD_PATCH_ENABLE_SINGLE_CREASE, allowsSingleCrease && _useSingleCrease); DEFINE(OSD_PATCH_ENABLE_SINGLE_CREASE, allowsSingleCrease && _useSingleCrease);
DEFINE(COLOR_NORMAL, _colorMode == kColorModeNormal); DEFINE(COLOR_NORMAL, _colorMode == kColorModeNormal);
DEFINE(COLOR_PATCHTYPE, _colorMode == kColorModePatchType); DEFINE(COLOR_PATCHTYPE, _colorMode == kColorModePatchType);
DEFINE(COLOR_PATCHCOORD, _colorMode == kColorModePatchCoord); DEFINE(COLOR_PATCHCOORD, _colorMode == kColorModePatchCoord);
@ -946,11 +946,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
DEFINE(NORMAL_HW_SCREENSPACE, _normalMode == kNormalModeHWScreenspace); DEFINE(NORMAL_HW_SCREENSPACE, _normalMode == kNormalModeHWScreenspace);
DEFINE(NORMAL_BIQUADRATIC_WG, _normalMode == kNormalModeBiQuadraticWG); DEFINE(NORMAL_BIQUADRATIC_WG, _normalMode == kNormalModeBiQuadraticWG);
DEFINE(NORMAL_BIQUADRATIC, _normalMode == kNormalModeBiQuadratic); DEFINE(NORMAL_BIQUADRATIC, _normalMode == kNormalModeBiQuadratic);
DEFINE(DISPLACEMENT_BILINEAR, _displacementMode == kDisplacementModeBilinear); DEFINE(DISPLACEMENT_BILINEAR, _displacementMode == kDisplacementModeBilinear);
DEFINE(DISPLACEMENT_HW_BILINEAR, _displacementMode == kDisplacementModeHWBilinear); DEFINE(DISPLACEMENT_HW_BILINEAR, _displacementMode == kDisplacementModeHWBilinear);
DEFINE(DISPLACEMENT_BIQUADRATIC, _displacementMode == kDisplacementModeBiQuadratic); DEFINE(DISPLACEMENT_BIQUADRATIC, _displacementMode == kDisplacementModeBiQuadratic);
DEFINE(OSD_COMPUTE_NORMAL_DERIVATIVES, _normalMode == kNormalModeBiQuadraticWG); DEFINE(OSD_COMPUTE_NORMAL_DERIVATIVES, _normalMode == kNormalModeBiQuadraticWG);
auto partitionMode = _useScreenspaceTessellation ? MTLTessellationPartitionModeFractionalOdd : MTLTessellationPartitionModePow2; auto partitionMode = _useScreenspaceTessellation ? MTLTessellationPartitionModeFractionalOdd : MTLTessellationPartitionModePow2;
@ -978,7 +978,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
DEFINE(OSD_ENABLE_PATCH_CULL, _usePatchClipCulling); DEFINE(OSD_ENABLE_PATCH_CULL, _usePatchClipCulling);
compileOptions.preprocessorMacros = preprocessor; compileOptions.preprocessorMacros = preprocessor;
NSError* err = nil; NSError* err = nil;
auto librarySource = [NSString stringWithUTF8String:str.data()]; auto librarySource = [NSString stringWithUTF8String:str.data()];
auto library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:&err]; auto library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:&err];
@ -991,67 +991,67 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
assert(vertexFunction && fragmentFunction); assert(vertexFunction && fragmentFunction);
if(vertexFunction && fragmentFunction) if(vertexFunction && fragmentFunction)
{ {
MTLRenderPipelineDescriptor* pipelineDesc = [[MTLRenderPipelineDescriptor alloc] init]; MTLRenderPipelineDescriptor* pipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];
pipelineDesc.tessellationFactorFormat = MTLTessellationFactorFormatHalf; pipelineDesc.tessellationFactorFormat = MTLTessellationFactorFormatHalf;
pipelineDesc.tessellationPartitionMode = partitionMode; pipelineDesc.tessellationPartitionMode = partitionMode;
pipelineDesc.tessellationFactorScaleEnabled = false; pipelineDesc.tessellationFactorScaleEnabled = false;
pipelineDesc.tessellationFactorStepFunction = MTLTessellationFactorStepFunctionPerPatch; pipelineDesc.tessellationFactorStepFunction = MTLTessellationFactorStepFunctionPerPatch;
if(type == Far::PatchDescriptor::GREGORY_BASIS) if(type == Far::PatchDescriptor::GREGORY_BASIS)
pipelineDesc.tessellationControlPointIndexType = MTLTessellationControlPointIndexTypeUInt32; pipelineDesc.tessellationControlPointIndexType = MTLTessellationControlPointIndexTypeUInt32;
[_delegate setupRenderPipelineState:pipelineDesc for:self]; [_delegate setupRenderPipelineState:pipelineDesc for:self];
pipelineDesc.fragmentFunction = fragmentFunction; pipelineDesc.fragmentFunction = fragmentFunction;
pipelineDesc.vertexFunction = vertexFunction; pipelineDesc.vertexFunction = vertexFunction;
auto vertexDesc = pipelineDesc.vertexDescriptor; auto vertexDesc = pipelineDesc.vertexDescriptor;
[vertexDesc reset]; [vertexDesc reset];
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch; vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch;
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stride = sizeof(int) * 3; vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stride = sizeof(int) * 3;
vertexDesc.attributes[10].bufferIndex = OSD_PATCHPARAM_BUFFER_INDEX; vertexDesc.attributes[10].bufferIndex = OSD_PATCHPARAM_BUFFER_INDEX;
vertexDesc.attributes[10].format = MTLVertexFormatInt3; vertexDesc.attributes[10].format = MTLVertexFormatInt3;
vertexDesc.attributes[10].offset = 0; vertexDesc.attributes[10].offset = 0;
switch(type) switch(type)
{ {
case Far::PatchDescriptor::REGULAR: case Far::PatchDescriptor::REGULAR:
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride = sizeof(float) * 3; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride = sizeof(float) * 3;
vertexDesc.attributes[0].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX; vertexDesc.attributes[0].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
vertexDesc.attributes[0].format = MTLVertexFormatFloat3; vertexDesc.attributes[0].format = MTLVertexFormatFloat3;
vertexDesc.attributes[0].offset = 0; vertexDesc.attributes[0].offset = 0;
if(_useSingleCrease) if(_useSingleCrease)
{ {
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride += sizeof(float) * 6; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride += sizeof(float) * 6;
vertexDesc.attributes[1].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX; vertexDesc.attributes[1].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
vertexDesc.attributes[1].format = MTLVertexFormatFloat3; vertexDesc.attributes[1].format = MTLVertexFormatFloat3;
vertexDesc.attributes[1].offset = sizeof(float) * 3; vertexDesc.attributes[1].offset = sizeof(float) * 3;
vertexDesc.attributes[2].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX; vertexDesc.attributes[2].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
vertexDesc.attributes[2].format = MTLVertexFormatFloat3; vertexDesc.attributes[2].format = MTLVertexFormatFloat3;
vertexDesc.attributes[2].offset = sizeof(float) * 6; vertexDesc.attributes[2].offset = sizeof(float) * 6;
} }
if(_useScreenspaceTessellation) if(_useScreenspaceTessellation)
{ {
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch; vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch;
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stride = sizeof(float) * 8; vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stride = sizeof(float) * 8;
vertexDesc.attributes[5].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX; vertexDesc.attributes[5].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
vertexDesc.attributes[5].format = MTLVertexFormatFloat4; vertexDesc.attributes[5].format = MTLVertexFormatFloat4;
vertexDesc.attributes[5].offset = 0; vertexDesc.attributes[5].offset = 0;
vertexDesc.attributes[6].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX; vertexDesc.attributes[6].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
vertexDesc.attributes[6].format = MTLVertexFormatFloat4; vertexDesc.attributes[6].format = MTLVertexFormatFloat4;
vertexDesc.attributes[6].offset = sizeof(float) * 4; vertexDesc.attributes[6].offset = sizeof(float) * 4;
@ -1059,11 +1059,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
break; break;
case Far::PatchDescriptor::GREGORY_BOUNDARY: case Far::PatchDescriptor::GREGORY_BOUNDARY:
case Far::PatchDescriptor::GREGORY: case Far::PatchDescriptor::GREGORY:
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint; vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stride = sizeof(float) * 3 * 5; vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stride = sizeof(float) * 3 * 5;
for(int i = 0; i < 5; i++) for(int i = 0; i < 5; i++)
{ {
vertexDesc.attributes[i].bufferIndex = OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX; vertexDesc.attributes[i].bufferIndex = OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX;
@ -1075,7 +1075,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint; vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stride = sizeof(float) * 3; vertexDesc.layouts[VERTEX_BUFFER_INDEX].stride = sizeof(float) * 3;
vertexDesc.attributes[0].bufferIndex = VERTEX_BUFFER_INDEX; vertexDesc.attributes[0].bufferIndex = VERTEX_BUFFER_INDEX;
vertexDesc.attributes[0].format = MTLVertexFormatFloat3; vertexDesc.attributes[0].format = MTLVertexFormatFloat3;
vertexDesc.attributes[0].offset = 0; vertexDesc.attributes[0].offset = 0;
@ -1085,15 +1085,15 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[vertexDesc reset]; [vertexDesc reset];
break; break;
} }
_renderPipelines[type] = [_context.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&err]; _renderPipelines[type] = [_context.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&err];
if(!_renderPipelines[type] && err) if(!_renderPipelines[type] && err)
{ {
NSLog(@"%s", [[err localizedDescription] UTF8String]); NSLog(@"%s", [[err localizedDescription] UTF8String]);
} }
} }
auto computeFunction = [library newFunctionWithName:@"compute_main"]; auto computeFunction = [library newFunctionWithName:@"compute_main"];
if(computeFunction) if(computeFunction)
{ {
@ -1104,51 +1104,51 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = false; computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = false;
#endif #endif
computeDesc.computeFunction = computeFunction; computeDesc.computeFunction = computeFunction;
NSError* err; NSError* err;
_computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err]; _computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err];
if(err && _computePipelines[type] == nil) if(err && _computePipelines[type] == nil)
{ {
NSLog(@"%s", [[err description] UTF8String]); NSLog(@"%s", [[err description] UTF8String]);
} }
if(_computePipelines[type].threadExecutionWidth != threadsPerThreadgroup) if(_computePipelines[type].threadExecutionWidth != threadsPerThreadgroup)
{ {
preprocessor[@"THREADS_PER_THREADGROUP"] = @(_computePipelines[type].threadExecutionWidth); preprocessor[@"THREADS_PER_THREADGROUP"] = @(_computePipelines[type].threadExecutionWidth);
preprocessor[@"CONTROL_POINTS_PER_THREAD"] = @(std::max<int>(1, usefulControlPoints / _computePipelines[type].threadExecutionWidth)); preprocessor[@"CONTROL_POINTS_PER_THREAD"] = @(std::max<int>(1, usefulControlPoints / _computePipelines[type].threadExecutionWidth));
compileOptions.preprocessorMacros = preprocessor; compileOptions.preprocessorMacros = preprocessor;
library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:nil]; library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:nil];
assert(library); assert(library);
computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = true; computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = true;
computeDesc.computeFunction = [library newFunctionWithName:@"compute_main"]; computeDesc.computeFunction = [library newFunctionWithName:@"compute_main"];
threadsPerThreadgroup = _computePipelines[type].threadExecutionWidth; threadsPerThreadgroup = _computePipelines[type].threadExecutionWidth;
_computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err]; _computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err];
assert(_computePipelines[type].threadExecutionWidth == threadsPerThreadgroup); assert(_computePipelines[type].threadExecutionWidth == threadsPerThreadgroup);
} }
} }
} }
MTLDepthStencilDescriptor* depthStencilDesc = [[MTLDepthStencilDescriptor alloc] init]; MTLDepthStencilDescriptor* depthStencilDesc = [[MTLDepthStencilDescriptor alloc] init];
depthStencilDesc.depthCompareFunction = MTLCompareFunctionLess; depthStencilDesc.depthCompareFunction = MTLCompareFunctionLess;
[_delegate setupDepthStencilState:depthStencilDesc for:self]; [_delegate setupDepthStencilState:depthStencilDesc for:self];
depthStencilDesc.depthWriteEnabled = YES; depthStencilDesc.depthWriteEnabled = YES;
_readWriteDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc]; _readWriteDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc];
depthStencilDesc.depthWriteEnabled = NO; depthStencilDesc.depthWriteEnabled = NO;
_readOnlyDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc]; _readOnlyDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc];
} }
-(void)_updateCamera { -(void)_updateCamera {
auto pData = _frameConstantsBuffer.data(); auto pData = _frameConstantsBuffer.data();
identity(pData->ModelViewMatrix); identity(pData->ModelViewMatrix);
translate(pData->ModelViewMatrix, 0, 0, -_cameraData.dollyDistance); translate(pData->ModelViewMatrix, 0, 0, -_cameraData.dollyDistance);
rotate(pData->ModelViewMatrix, _cameraData.rotationY, 1, 0, 0); rotate(pData->ModelViewMatrix, _cameraData.rotationY, 1, 0, 0);
@ -1156,11 +1156,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
translate(pData->ModelViewMatrix, -_meshCenter[0], -_meshCenter[2], _meshCenter[1]); // z-up model translate(pData->ModelViewMatrix, -_meshCenter[0], -_meshCenter[2], _meshCenter[1]); // z-up model
rotate(pData->ModelViewMatrix, -90, 1, 0, 0); // z-up model rotate(pData->ModelViewMatrix, -90, 1, 0, 0); // z-up model
inverseMatrix(pData->ModelViewInverseMatrix, pData->ModelViewMatrix); inverseMatrix(pData->ModelViewInverseMatrix, pData->ModelViewMatrix);
identity(pData->ProjectionMatrix); identity(pData->ProjectionMatrix);
perspective(pData->ProjectionMatrix, 45.0, _cameraData.aspectRatio, 0.01f, 500.0); perspective(pData->ProjectionMatrix, 45.0, _cameraData.aspectRatio, 0.01f, 500.0);
multMatrix(pData->ModelViewProjectionMatrix, pData->ModelViewMatrix, pData->ProjectionMatrix); multMatrix(pData->ModelViewProjectionMatrix, pData->ModelViewMatrix, pData->ProjectionMatrix);
} }
@ -1184,14 +1184,14 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
{ 0.7f, 0.7f, 0.7f, 1.0f }, { 0.7f, 0.7f, 0.7f, 1.0f },
{ 0.8f, 0.8f, 0.8f, 1.0f }, { 0.8f, 0.8f, 0.8f, 1.0f },
}; };
_lightsBuffer[1] = { _lightsBuffer[1] = {
simd::normalize(simd::float4{ -0.8f, 0.4f, -1.0f, 0.0f }), simd::normalize(simd::float4{ -0.8f, 0.4f, -1.0f, 0.0f }),
{ 0.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f },
{ 0.5f, 0.5f, 0.5f, 1.0f }, { 0.5f, 0.5f, 0.5f, 1.0f },
{ 0.8f, 0.8f, 0.8f, 1.0f } { 0.8f, 0.8f, 0.8f, 1.0f }
}; };
_lightsBuffer.markModified(); _lightsBuffer.markModified();
} }

View File

@ -45,7 +45,7 @@ struct OutputVertex {
float4 positionOut [[position]]; float4 positionOut [[position]];
float3 position; float3 position;
float3 normal; float3 normal;
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD || SHADING_TYPE_FACE_VARYING #if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD || SHADING_TYPE_FACE_VARYING
float3 patchColor; float3 patchColor;
#endif #endif
@ -53,15 +53,15 @@ struct OutputVertex {
struct SolidColorVertex { struct SolidColorVertex {
float4 positionOut [[position]]; float4 positionOut [[position]];
half4 getColor() const { half4 getColor() const {
return unpack_unorm4x8_to_half(_color); return unpack_unorm4x8_to_half(_color);
} }
void setColor(half4 color) { void setColor(half4 color) {
_color = pack_half_to_unorm4x8(color); _color = pack_half_to_unorm4x8(color);
} }
private: private:
uint _color [[flat, user(color)]]; uint _color [[flat, user(color)]];
}; };
@ -69,7 +69,7 @@ private:
struct PackedInputVertex { struct PackedInputVertex {
packed_float3 position; packed_float3 position;
}; };
struct Light { struct Light {
float3 Position; float3 Position;
float3 ambient; float3 ambient;
@ -79,7 +79,7 @@ struct Light {
float3 lighting(float3 diffuseColor, const constant Light* lightData, float3 eyePos, float3 eyeN) float3 lighting(float3 diffuseColor, const constant Light* lightData, float3 eyePos, float3 eyeN)
{ {
float3 color(0); float3 color(0);
for(int i = 0; i < 2; i++) for(int i = 0; i < 2; i++)
{ {
@ -87,12 +87,12 @@ float3 lighting(float3 diffuseColor, const constant Light* lightData, float3 eye
const auto h = normalize(l + float3(0,0,1)); const auto h = normalize(l + float3(0,0,1));
const auto d = max(0.0, dot(eyeN, l)); const auto d = max(0.0, dot(eyeN, l));
const auto s = powr(max(0.0, dot(eyeN, h)), 500.0f); const auto s = powr(max(0.0, dot(eyeN, h)), 500.0f);
color += lightData[i].ambient color += lightData[i].ambient
+ d * lightData[i].diffuse * diffuseColor + d * lightData[i].diffuse * diffuseColor
+ s * lightData[i].specular; + s * lightData[i].specular;
} }
return color; return color;
} }
@ -104,42 +104,42 @@ const constant float4 patchColors[] = {
float4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2 float4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2
float4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3 float4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3
float4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4 float4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4
float4(1.0f, 0.5f, 0.5f, 1.0f), // single crease float4(1.0f, 0.5f, 0.5f, 1.0f), // single crease
float4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0 float4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0
float4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1 float4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1
float4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2 float4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2
float4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3 float4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3
float4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4 float4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4
float4(0.8f, 0.0f, 0.0f, 1.0f), // boundary float4(0.8f, 0.0f, 0.0f, 1.0f), // boundary
float4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0 float4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0
float4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1 float4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1
float4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2 float4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2
float4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3 float4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3
float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4 float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4
float4(0.0f, 1.0f, 0.0f, 1.0f), // corner float4(0.0f, 1.0f, 0.0f, 1.0f), // corner
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4 float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
@ -156,10 +156,10 @@ getAdaptivePatchColor(int3 patchParam
#endif #endif
) )
{ {
int patchType = 0; int patchType = 0;
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam)); int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
if (edgeCount == 1) { if (edgeCount == 1) {
patchType = 2; // BOUNDARY patchType = 2; // BOUNDARY
@ -167,7 +167,7 @@ getAdaptivePatchColor(int3 patchParam
if (edgeCount == 2) { if (edgeCount == 2) {
patchType = 3; // CORNER patchType = 3; // CORNER
} }
#if OSD_PATCH_ENABLE_SINGLE_CREASE #if OSD_PATCH_ENABLE_SINGLE_CREASE
// check this after boundary/corner since single crease patch also has edgeCount. // check this after boundary/corner since single crease patch also has edgeCount.
if (vSegments.y > 0) { if (vSegments.y > 0) {
@ -180,9 +180,9 @@ getAdaptivePatchColor(int3 patchParam
#elif OSD_PATCH_GREGORY_BASIS #elif OSD_PATCH_GREGORY_BASIS
patchType = 6; patchType = 6;
#endif #endif
int pattern = popcount(OsdGetPatchTransitionMask(patchParam)); int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
return patchColors[6*patchType + pattern]; return patchColors[6*patchType + pattern];
} }
@ -287,7 +287,7 @@ kernel void compute_main(
if(validThread) if(validThread)
{ {
patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer); patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer);
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++) for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
{ {
const auto vertexId = osdBuffers.indexBuffer[(thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset) * IndexLookupStride]; const auto vertexId = osdBuffers.indexBuffer[(thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset) * IndexLookupStride];
@ -365,7 +365,7 @@ kernel void compute_main(
#endif #endif
//---------------------------------------------------------- //----------------------------------------------------------
// OSD Tessellation Factors // OSD Tessellation Factors
//---------------------------------------------------------- //----------------------------------------------------------
if(validThread && real_thread_in_threadgroup == 0) if(validThread && real_thread_in_threadgroup == 0)
{ {
@ -406,22 +406,22 @@ vertex OutputVertex vertex_main(
) )
{ {
OutputVertex out; OutputVertex out;
#if USE_STAGE_IN #if USE_STAGE_IN
int3 patchParam = patchInput.patchParam; int3 patchParam = patchInput.patchParam;
#else #else
int3 patchParam = patchInput.patchParamBuffer[patch_id]; int3 patchParam = patchInput.patchParamBuffer[patch_id];
#endif #endif
int refinementLevel = OsdGetPatchRefinementLevel(patchParam); int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) / float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) /
exp2((float)refinementLevel - 1); exp2((float)refinementLevel - 1);
auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput); auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput);
out.position = (frameConsts.ModelViewMatrix * float4(patchVertex.position, 1.0f)).xyz; out.position = (frameConsts.ModelViewMatrix * float4(patchVertex.position, 1.0f)).xyz;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(patchVertex.position, 1.0f); out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(patchVertex.position, 1.0f);
out.normal = mul(frameConsts.ModelViewMatrix, patchVertex.normal); out.normal = mul(frameConsts.ModelViewMatrix, patchVertex.normal);
#if SHADING_TYPE == SHADING_TYPE_PATCH #if SHADING_TYPE == SHADING_TYPE_PATCH
#if OSD_PATCH_ENABLE_SINGLE_CREASE #if OSD_PATCH_ENABLE_SINGLE_CREASE
@ -479,7 +479,7 @@ vertex OutputVertex vertex_main(
out.patchColor.rg = fvarUV; out.patchColor.rg = fvarUV;
#endif #endif
return out; return out;
} }
#endif #endif
@ -498,25 +498,25 @@ const constant unsigned BSplineControlLineIndices[] = {
12, 8, 12, 8,
8, 4, 8, 4,
4, 0, 4, 0,
//Inner lines //Inner lines
5, 6, 5, 6,
6, 10, 6, 10,
10, 9, 10, 9,
9, 5, 9, 5,
//TL edge lines //TL edge lines
1, 5, 1, 5,
4, 5, 4, 5,
//TR edge lines //TR edge lines
2, 6, 2, 6,
6, 7, 6, 7,
//BL edge lines //BL edge lines
8, 9, 8, 9,
9, 13, 9, 13,
//BR edge lines //BR edge lines
10, 14, 10, 14,
10, 11 10, 11
@ -539,7 +539,7 @@ vertex SolidColorVertex vertex_lines(
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.P, 1.0); out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.P, 1.0);
out.positionOut.z -= 0.001; out.positionOut.z -= 0.001;
if(idx > 22) { if(idx > 22) {
out.setColor(half4(0,1,0,1)); out.setColor(half4(0,1,0,1));
} }
@ -555,18 +555,18 @@ vertex SolidColorVertex vertex_lines(
#if OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_BOUNDARY || OSD_PATCH_GREGORY #if OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_BOUNDARY || OSD_PATCH_GREGORY
const constant uint GregoryBasisControlLineIndices[] = { const constant uint GregoryBasisControlLineIndices[] = {
//Outer Edge //Outer Edge
0, 2, 0, 2,
2, 16, 2, 16,
16, 15, 16, 15,
15, 17, 15, 17,
17, 11, 17, 11,
11, 10, 11, 10,
10, 12, 10, 12,
12, 6, 12, 6,
6, 5, 6, 5,
5, 7, 5, 7,
7, 1, 7, 1,
1, 0, 1, 0,
//Outside-Inside Edges //Outside-Inside Edges
1, 3, 1, 3,
@ -581,7 +581,7 @@ const constant uint GregoryBasisControlLineIndices[] = {
//Inner Edge //Inner Edge
3, 4, 3, 4,
4, 18, 4, 18,
18, 19, 18, 19,
19, 13, 19, 13,
13, 14, 13, 14,
14, 8, 14, 8,
@ -603,7 +603,7 @@ vertex SolidColorVertex vertex_lines(
{ {
const auto idx_size = sizeof(GregoryBasisControlLineIndices) / sizeof(GregoryBasisControlLineIndices[0]); const auto idx_size = sizeof(GregoryBasisControlLineIndices) / sizeof(GregoryBasisControlLineIndices[0]);
const auto idx = vertex_id % idx_size; const auto idx = vertex_id % idx_size;
const auto patch_id = vertex_id / idx_size; const auto patch_id = vertex_id / idx_size;
#if OSD_PATCH_GREGORY_BASIS #if OSD_PATCH_GREGORY_BASIS
const auto in = vertexBuffer[indicesBuffer[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + GregoryBasisControlLineIndices[idx]]]; const auto in = vertexBuffer[indicesBuffer[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + GregoryBasisControlLineIndices[idx]]];
@ -666,12 +666,12 @@ vertex OutputVertex vertex_main(
float3 normal = normalize(cross(p2 - p1, p0 - p1)); float3 normal = normalize(cross(p2 - p1, p0 - p1));
OutputVertex out; OutputVertex out;
out.position = (frameConsts.ModelViewMatrix * float4(position, 1.0)).xyz; out.position = (frameConsts.ModelViewMatrix * float4(position, 1.0)).xyz;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0); out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0);
out.normal = (frameConsts.ModelViewMatrix * float4(normal, 0.0)).xyz; out.normal = (frameConsts.ModelViewMatrix * float4(normal, 0.0)).xyz;
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD #if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD
out.patchColor = out.normal; out.patchColor = out.normal;
#elif SHADING_TYPE == SHADING_TYPE_FACE_VARYING #elif SHADING_TYPE == SHADING_TYPE_FACE_VARYING
@ -679,7 +679,7 @@ vertex OutputVertex vertex_main(
#endif #endif
return out; return out;
} }
vertex SolidColorVertex vertex_lines( vertex SolidColorVertex vertex_lines(
device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]], device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
@ -702,9 +702,9 @@ vertex SolidColorVertex vertex_lines(
SolidColorVertex out; SolidColorVertex out;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0); out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0);
return out; return out;
} }
#endif #endif
fragment half4 fragment_solidcolor(SolidColorVertex in [[stage_in]]) fragment half4 fragment_solidcolor(SolidColorVertex in [[stage_in]])
@ -719,7 +719,7 @@ fragment float4 fragment_main(OutputVertex in [[stage_in]],
const constant float4& shade [[buffer(2)]]) const constant float4& shade [[buffer(2)]])
{ {
float4 color; float4 color;
#if SHADING_TYPE == SHADING_TYPE_MATERIAL #if SHADING_TYPE == SHADING_TYPE_MATERIAL
const float3 diffuseColor = float3(0.4f, 0.4f, 0.8f); const float3 diffuseColor = float3(0.4f, 0.4f, 0.8f);
#elif SHADING_TYPE == SHADING_TYPE_PATCH #elif SHADING_TYPE == SHADING_TYPE_PATCH

View File

@ -134,18 +134,18 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
@implementation OSDRenderer { @implementation OSDRenderer {
MTLRingBuffer<Light, 1> _lightsBuffer; MTLRingBuffer<Light, 1> _lightsBuffer;
PerFrameBuffer<PerFrameConstants> _frameConstantsBuffer; PerFrameBuffer<PerFrameConstants> _frameConstantsBuffer;
PerFrameBuffer<MTLQuadTessellationFactorsHalf> _tessFactorsBuffer; PerFrameBuffer<MTLQuadTessellationFactorsHalf> _tessFactorsBuffer;
PerFrameBuffer<unsigned> _patchIndexBuffers[4]; PerFrameBuffer<unsigned> _patchIndexBuffers[4];
PerFrameBuffer<uint8_t> _perPatchDataBuffer; PerFrameBuffer<uint8_t> _perPatchDataBuffer;
PerFrameBuffer<uint8_t> _hsDataBuffer; PerFrameBuffer<uint8_t> _hsDataBuffer;
PerFrameBuffer<MTLDrawPatchIndirectArguments> _drawIndirectCommandsBuffer; PerFrameBuffer<MTLDrawPatchIndirectArguments> _drawIndirectCommandsBuffer;
unsigned _tessFactorOffsets[4]; unsigned _tessFactorOffsets[4];
unsigned _perPatchDataOffsets[4]; unsigned _perPatchDataOffsets[4];
unsigned _threadgroupSizes[10]; unsigned _threadgroupSizes[10];
id<MTLComputePipelineState> _computePipelines[10]; id<MTLComputePipelineState> _computePipelines[10];
id<MTLRenderPipelineState> _renderPipelines[10]; id<MTLRenderPipelineState> _renderPipelines[10];
id<MTLRenderPipelineState> _controlLineRenderPipelines[10]; id<MTLRenderPipelineState> _controlLineRenderPipelines[10];
@ -157,11 +157,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
id<MTLBuffer> _faceVaryingIndicesBuffer; id<MTLBuffer> _faceVaryingIndicesBuffer;
id<MTLBuffer> _faceVaryingPatchParamBuffer; id<MTLBuffer> _faceVaryingPatchParamBuffer;
Camera _cameraData; Camera _cameraData;
Osd::MTLContext _context; Osd::MTLContext _context;
int _numVertexElements; int _numVertexElements;
int _numVaryingElements; int _numVaryingElements;
int _numFaceVaryingElements; int _numFaceVaryingElements;
@ -173,7 +173,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
std::unique_ptr<MTLControlMeshDisplay> _controlMesh; std::unique_ptr<MTLControlMeshDisplay> _controlMesh;
std::unique_ptr<Osd::MTLLegacyGregoryPatchTable> _legacyGregoryPatchTable; std::unique_ptr<Osd::MTLLegacyGregoryPatchTable> _legacyGregoryPatchTable;
std::unique_ptr<Shape> _shape; std::unique_ptr<Shape> _shape;
bool _needsRebuild; bool _needsRebuild;
NSString* _osdShaderSource; NSString* _osdShaderSource;
simd::float3 _meshCenter; simd::float3 _meshCenter;
@ -206,17 +206,17 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
self.tessellationLevel = 8; self.tessellationLevel = 8;
self.shadingMode = kShadingMaterial; self.shadingMode = kShadingMaterial;
self.displayStyle = kDisplayStyleShaded; self.displayStyle = kDisplayStyleShaded;
_frameCount = 0; _frameCount = 0;
_animationFrames = 0; _animationFrames = 0;
_delegate = delegate; _delegate = delegate;
_context.device = [delegate deviceFor:self]; _context.device = [delegate deviceFor:self];
_context.commandQueue = [delegate commandQueueFor:self]; _context.commandQueue = [delegate commandQueueFor:self];
_osdShaderSource = @(shaderSource); _osdShaderSource = @(shaderSource);
_needsRebuild = true; _needsRebuild = true;
[self _initializeBuffers]; [self _initializeBuffers];
[self _initializeCamera]; [self _initializeCamera];
[self _initializeLights]; [self _initializeLights];
@ -235,7 +235,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
_animatedVertices.resize(_vertexData.size()); _animatedVertices.resize(_vertexData.size());
auto p = _vertexData.data(); auto p = _vertexData.data();
auto n = _animatedVertices.data(); auto n = _animatedVertices.data();
int numElements = _numVertexElements + _numVaryingElements; int numElements = _numVertexElements + _numVaryingElements;
float r = sin(_animationFrames*0.01f) * _animateVertices; float r = sin(_animationFrames*0.01f) * _animateVertices;
@ -246,7 +246,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
n[0] = p[0]*ct + p[1]*st; n[0] = p[0]*ct + p[1]*st;
n[1] = -p[0]*st + p[1]*ct; n[1] = -p[0]*st + p[1]*ct;
n[2] = p[2]; n[2] = p[2];
for (int j = 0; j < _numVaryingElements; ++j) { for (int j = 0; j < _numVaryingElements; ++j) {
n[3 + j] = p[3 + j]; n[3 + j] = p[3 + j];
} }
@ -254,30 +254,30 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
p += numElements; p += numElements;
n += numElements; n += numElements;
} }
_mesh->UpdateVertexBuffer(_animatedVertices.data(), 0, _numVertices); _mesh->UpdateVertexBuffer(_animatedVertices.data(), 0, _numVertices);
_animationFrames++; _animationFrames++;
} }
_mesh->Refine(); _mesh->Refine();
_mesh->Synchronize(); _mesh->Synchronize();
} }
[self _updateState]; [self _updateState];
if(_doAdaptive) { if(_doAdaptive) {
auto computeEncoder = [commandBuffer computeCommandEncoder]; auto computeEncoder = [commandBuffer computeCommandEncoder];
[self _computeTessFactors:computeEncoder]; [self _computeTessFactors:computeEncoder];
[computeEncoder endEncoding]; [computeEncoder endEncoding];
} }
auto renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:[_delegate renderPassDescriptorFor: self]]; auto renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:[_delegate renderPassDescriptorFor: self]];
if(_usePrimitiveBackfaceCulling) { if(_usePrimitiveBackfaceCulling) {
[renderEncoder setCullMode:MTLCullModeBack]; [renderEncoder setCullMode:MTLCullModeBack];
} else { } else {
[renderEncoder setCullMode:MTLCullModeNone]; [renderEncoder setCullMode:MTLCullModeNone];
} }
[self _renderMesh:renderEncoder]; [self _renderMesh:renderEncoder];
_frameConstantsBuffer.next(); _frameConstantsBuffer.next();
@ -290,20 +290,20 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
_perPatchDataBuffer.next(); _perPatchDataBuffer.next();
_hsDataBuffer.next(); _hsDataBuffer.next();
_drawIndirectCommandsBuffer.next(); _drawIndirectCommandsBuffer.next();
_frameCount++; _frameCount++;
return renderEncoder; return renderEncoder;
} }
-(void)_renderMesh:(id<MTLRenderCommandEncoder>)renderCommandEncoder { -(void)_renderMesh:(id<MTLRenderCommandEncoder>)renderCommandEncoder {
auto buffer = _mesh->BindVertexBuffer(); auto buffer = _mesh->BindVertexBuffer();
assert(buffer); assert(buffer);
auto pav = _mesh->GetPatchTable()->GetPatchArrays(); auto pav = _mesh->GetPatchTable()->GetPatchArrays();
auto pib = _mesh->GetPatchTable()->GetPatchIndexBuffer(); auto pib = _mesh->GetPatchTable()->GetPatchIndexBuffer();
auto pfvarav = _mesh->GetPatchTable()->GetFVarPatchArrays(); auto pfvarav = _mesh->GetPatchTable()->GetFVarPatchArrays();
[renderCommandEncoder setVertexBuffer:buffer offset:0 atIndex:VERTEX_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:buffer offset:0 atIndex:VERTEX_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer:pib offset:0 atIndex:INDICES_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:pib offset:0 atIndex:INDICES_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX];
@ -314,7 +314,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder setVertexBuffer:_faceVaryingDataBuffer offset:0 atIndex:OSD_FVAR_DATA_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_faceVaryingDataBuffer offset:0 atIndex:OSD_FVAR_DATA_BUFFER_INDEX];
#endif #endif
[renderCommandEncoder setVertexBuffer:_faceVaryingIndicesBuffer offset:0 atIndex:OSD_FVAR_INDICES_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_faceVaryingIndicesBuffer offset:0 atIndex:OSD_FVAR_INDICES_BUFFER_INDEX];
if(_doAdaptive) if(_doAdaptive)
{ {
[renderCommandEncoder setVertexBuffer:_hsDataBuffer offset:0 atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_hsDataBuffer offset:0 atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX];
@ -323,31 +323,31 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder setVertexBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer:_faceVaryingPatchParamBuffer offset:0 atIndex:OSD_FVAR_PATCHPARAM_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_faceVaryingPatchParamBuffer offset:0 atIndex:OSD_FVAR_PATCHPARAM_BUFFER_INDEX];
} }
if(_endCapMode == kEndCapLegacyGregory) if(_endCapMode == kEndCapLegacyGregory)
{ {
[renderCommandEncoder setVertexBuffer:_legacyGregoryPatchTable->GetQuadOffsetsBuffer() offset:0 atIndex:OSD_QUADOFFSET_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_legacyGregoryPatchTable->GetQuadOffsetsBuffer() offset:0 atIndex:OSD_QUADOFFSET_BUFFER_INDEX];
[renderCommandEncoder setVertexBuffer:_legacyGregoryPatchTable->GetVertexValenceBuffer() offset:0 atIndex:OSD_VALENCE_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_legacyGregoryPatchTable->GetVertexValenceBuffer() offset:0 atIndex:OSD_VALENCE_BUFFER_INDEX];
} }
[renderCommandEncoder setFragmentBuffer:_lightsBuffer offset:0 atIndex:0]; [renderCommandEncoder setFragmentBuffer:_lightsBuffer offset:0 atIndex:0];
if(_displayStyle == kDisplayStyleWire) if(_displayStyle == kDisplayStyleWire)
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
else else
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill];
std::fill_n(_patchCounts, 12, 0); std::fill_n(_patchCounts, 12, 0);
for(int i = 0; i < pav.size(); i++) for(int i = 0; i < pav.size(); i++)
{ {
auto& patch = pav[i]; auto& patch = pav[i];
auto d = patch.GetDescriptor(); auto d = patch.GetDescriptor();
auto patchType = d.GetType(); auto patchType = d.GetType();
auto offset = patchType - Far::PatchDescriptor::REGULAR; auto offset = patchType - Far::PatchDescriptor::REGULAR;
_patchCounts[patchType] = patch.GetNumPatches(); _patchCounts[patchType] = patch.GetNumPatches();
if(_doAdaptive) if(_doAdaptive)
{ {
[renderCommandEncoder setVertexBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX]; [renderCommandEncoder setVertexBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
@ -358,15 +358,15 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder setVertexBufferOffset:(fvarPatch.primitiveIdBase+patch.primitiveIdBase) * sizeof(int) * 3 atIndex:OSD_FVAR_PATCHPARAM_BUFFER_INDEX]; [renderCommandEncoder setVertexBufferOffset:(fvarPatch.primitiveIdBase+patch.primitiveIdBase) * sizeof(int) * 3 atIndex:OSD_FVAR_PATCHPARAM_BUFFER_INDEX];
[renderCommandEncoder setVertexBufferOffset:(fvarPatch.indexBase+(patch.primitiveIdBase*fvarPatch.desc.GetNumControlVertices())) * sizeof(unsigned) atIndex:OSD_FVAR_INDICES_BUFFER_INDEX]; [renderCommandEncoder setVertexBufferOffset:(fvarPatch.indexBase+(patch.primitiveIdBase*fvarPatch.desc.GetNumControlVertices())) * sizeof(unsigned) atIndex:OSD_FVAR_INDICES_BUFFER_INDEX];
} }
[renderCommandEncoder setVertexBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX]; [renderCommandEncoder setVertexBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX];
simd::float4 shade{.0f,0.0f,0.0f,1.0f}; simd::float4 shade{.0f,0.0f,0.0f,1.0f};
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2]; [renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
[renderCommandEncoder setDepthBias:0 slopeScale:1.0 clamp:0]; [renderCommandEncoder setDepthBias:0 slopeScale:1.0 clamp:0];
[renderCommandEncoder setDepthStencilState:_readWriteDepthStencilState]; [renderCommandEncoder setDepthStencilState:_readWriteDepthStencilState];
[renderCommandEncoder setRenderPipelineState:_renderPipelines[patchType]]; [renderCommandEncoder setRenderPipelineState:_renderPipelines[patchType]];
switch(patchType) switch(patchType)
{ {
case Far::PatchDescriptor::GREGORY_BOUNDARY: case Far::PatchDescriptor::GREGORY_BOUNDARY:
@ -378,7 +378,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
break; break;
default: break; default: break;
} }
switch(patchType) switch(patchType)
{ {
case Far::PatchDescriptor::GREGORY_BASIS: case Far::PatchDescriptor::GREGORY_BASIS:
@ -405,7 +405,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2]; [renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
[renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0]; [renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0];
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
[renderCommandEncoder drawIndexedPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches() [renderCommandEncoder drawIndexedPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches()
@ -420,7 +420,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
controlPointIndexBuffer:pib controlPointIndexBufferOffset:patch.indexBase * sizeof(unsigned) controlPointIndexBuffer:pib controlPointIndexBufferOffset:patch.indexBase * sizeof(unsigned)
instanceCount:1 baseInstance:0]; instanceCount:1 baseInstance:0];
} }
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill];
} }
break; break;
@ -442,14 +442,14 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder drawPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches() [renderCommandEncoder drawPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches()
patchIndexBuffer:nil patchIndexBufferOffset:0 instanceCount:1 baseInstance:0]; patchIndexBuffer:nil patchIndexBufferOffset:0 instanceCount:1 baseInstance:0];
} }
if(_displayStyle == kDisplayStyleWireOnShaded) if(_displayStyle == kDisplayStyleWireOnShaded)
{ {
simd::float4 shade = {1, 1,1,1}; simd::float4 shade = {1, 1,1,1};
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2]; [renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
[renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0]; [renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0];
#if !TARGET_OS_EMBEDDED #if !TARGET_OS_EMBEDDED
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
@ -463,13 +463,13 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[renderCommandEncoder drawPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches() [renderCommandEncoder drawPatches:d.GetNumControlVertices() patchStart:0 patchCount:patch.GetNumPatches()
patchIndexBuffer:nil patchIndexBufferOffset:0 instanceCount:1 baseInstance:0]; patchIndexBuffer:nil patchIndexBufferOffset:0 instanceCount:1 baseInstance:0];
} }
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill]; [renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeFill];
} }
} }
break; break;
case Far::PatchDescriptor::QUADS: case Far::PatchDescriptor::QUADS:
[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:patch.GetNumPatches() * 6]; [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:patch.GetNumPatches() * 6];
if(_displayStyle == kDisplayStyleWireOnShaded) if(_displayStyle == kDisplayStyleWireOnShaded)
@ -498,13 +498,13 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
default: default:
assert("Unsupported patch type" && 0); break; assert("Unsupported patch type" && 0); break;
} }
if(_displayControlMeshEdges) if(_displayControlMeshEdges)
{ {
if(_displayControlMeshEdges && _controlLineRenderPipelines[patchType]) if(_displayControlMeshEdges && _controlLineRenderPipelines[patchType])
{ {
[renderCommandEncoder setRenderPipelineState:_controlLineRenderPipelines[patchType]]; [renderCommandEncoder setRenderPipelineState:_controlLineRenderPipelines[patchType]];
unsigned primPerPatch = 0; unsigned primPerPatch = 0;
switch(patchType) switch(patchType)
{ {
@ -517,12 +517,12 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
primPerPatch = 56; primPerPatch = 56;
break; break;
} }
[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:patch.GetNumPatches() * primPerPatch]; [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:patch.GetNumPatches() * primPerPatch];
} }
} }
} }
if(_displayControlMeshEdges) if(_displayControlMeshEdges)
{ {
[renderCommandEncoder setDepthStencilState:_readOnlyDepthStencilState]; [renderCommandEncoder setDepthStencilState:_readOnlyDepthStencilState];
@ -532,7 +532,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
-(void)_computeTessFactors:(id<MTLComputeCommandEncoder>)computeCommandEncoder { -(void)_computeTessFactors:(id<MTLComputeCommandEncoder>)computeCommandEncoder {
auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays(); auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays();
[computeCommandEncoder setBuffer:_mesh->BindVertexBuffer() offset:0 atIndex:VERTEX_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_mesh->BindVertexBuffer() offset:0 atIndex:VERTEX_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchIndexBuffer() offset:0 atIndex:CONTROL_INDICES_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchIndexBuffer() offset:0 atIndex:CONTROL_INDICES_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
@ -541,46 +541,46 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[computeCommandEncoder setBuffer:_tessFactorsBuffer offset:0 atIndex:QUAD_TESSFACTORS_INDEX]; [computeCommandEncoder setBuffer:_tessFactorsBuffer offset:0 atIndex:QUAD_TESSFACTORS_INDEX];
[computeCommandEncoder setBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX];
if(_legacyGregoryPatchTable) if(_legacyGregoryPatchTable)
{ {
[computeCommandEncoder setBuffer:_legacyGregoryPatchTable->GetQuadOffsetsBuffer() offset:0 atIndex:OSD_QUADOFFSET_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_legacyGregoryPatchTable->GetQuadOffsetsBuffer() offset:0 atIndex:OSD_QUADOFFSET_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_legacyGregoryPatchTable->GetVertexValenceBuffer() offset:0 atIndex:OSD_VALENCE_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_legacyGregoryPatchTable->GetVertexValenceBuffer() offset:0 atIndex:OSD_VALENCE_BUFFER_INDEX];
} }
for(auto& patch : patchArray) for(auto& patch : patchArray)
{ {
auto usefulControlPoints = patch.GetDescriptor().GetNumControlVertices(); auto usefulControlPoints = patch.GetDescriptor().GetNumControlVertices();
if(patch.GetDescriptor().GetType() == Far::PatchDescriptor::GREGORY_BASIS) if(patch.GetDescriptor().GetType() == Far::PatchDescriptor::GREGORY_BASIS)
usefulControlPoints = 4; usefulControlPoints = 4;
auto threadsPerThreadgroup = MTLSizeMake(_threadgroupSizes[patch.desc.GetType()], 1, 1); auto threadsPerThreadgroup = MTLSizeMake(_threadgroupSizes[patch.desc.GetType()], 1, 1);
auto threadsPerControlPoint = std::max<int>(1, usefulControlPoints / threadsPerThreadgroup.width); auto threadsPerControlPoint = std::max<int>(1, usefulControlPoints / threadsPerThreadgroup.width);
auto groupPerControlPoint = MTLSizeMake(patch.GetNumPatches() * usefulControlPoints, 1, 1); auto groupPerControlPoint = MTLSizeMake(patch.GetNumPatches() * usefulControlPoints, 1, 1);
groupPerControlPoint.width /= threadsPerControlPoint; groupPerControlPoint.width /= threadsPerControlPoint;
groupPerControlPoint.width = (groupPerControlPoint.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1); groupPerControlPoint.width = (groupPerControlPoint.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1);
groupPerControlPoint.width = groupPerControlPoint.width / threadsPerThreadgroup.width; groupPerControlPoint.width = groupPerControlPoint.width / threadsPerThreadgroup.width;
auto groupPerPatch = MTLSizeMake(patch.GetNumPatches(), 1, 1); auto groupPerPatch = MTLSizeMake(patch.GetNumPatches(), 1, 1);
groupPerPatch.width = (groupPerPatch.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1); groupPerPatch.width = (groupPerPatch.width + threadsPerThreadgroup.width - 1) & ~(threadsPerThreadgroup.width - 1);
groupPerPatch.width = groupPerPatch.width / threadsPerThreadgroup.width; groupPerPatch.width = groupPerPatch.width / threadsPerThreadgroup.width;
[computeCommandEncoder setBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX]; [computeCommandEncoder setBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
[computeCommandEncoder setBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX]; [computeCommandEncoder setBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX];
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
[computeCommandEncoder setBuffer:_patchIndexBuffers[patch.desc.GetType() - Far::PatchDescriptor::REGULAR] offset:0 atIndex:OSD_PATCH_INDEX_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_patchIndexBuffers[patch.desc.GetType() - Far::PatchDescriptor::REGULAR] offset:0 atIndex:OSD_PATCH_INDEX_BUFFER_INDEX];
[computeCommandEncoder setBuffer:_drawIndirectCommandsBuffer offset:sizeof(MTLDrawPatchIndirectArguments) * (patch.desc.GetType() - Far::PatchDescriptor::REGULAR) atIndex:OSD_DRAWINDIRECT_BUFFER_INDEX]; [computeCommandEncoder setBuffer:_drawIndirectCommandsBuffer offset:sizeof(MTLDrawPatchIndirectArguments) * (patch.desc.GetType() - Far::PatchDescriptor::REGULAR) atIndex:OSD_DRAWINDIRECT_BUFFER_INDEX];
} }
[computeCommandEncoder setComputePipelineState:_computePipelines[patch.desc.GetType()]]; [computeCommandEncoder setComputePipelineState:_computePipelines[patch.desc.GetType()]];
unsigned kernelExecutionLimit; unsigned kernelExecutionLimit;
switch(patch.desc.GetType()) switch(patch.desc.GetType())
{ {
@ -608,7 +608,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
break; break;
default: assert("Unsupported patch type" && 0); break; default: assert("Unsupported patch type" && 0); break;
} }
[computeCommandEncoder setBytes:&kernelExecutionLimit length:sizeof(kernelExecutionLimit) atIndex:OSD_KERNELLIMIT_BUFFER_INDEX]; [computeCommandEncoder setBytes:&kernelExecutionLimit length:sizeof(kernelExecutionLimit) atIndex:OSD_KERNELLIMIT_BUFFER_INDEX];
[computeCommandEncoder dispatchThreadgroups:groupPerControlPoint threadsPerThreadgroup:threadsPerThreadgroup]; [computeCommandEncoder dispatchThreadgroups:groupPerControlPoint threadsPerThreadgroup:threadsPerThreadgroup];
} }
@ -618,12 +618,12 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[self _rebuildModel]; [self _rebuildModel];
[self _rebuildBuffers]; [self _rebuildBuffers];
[self _rebuildPipelines]; [self _rebuildPipelines];
_needsRebuild = false; _needsRebuild = false;
} }
-(void)_rebuildModel { -(void)_rebuildModel {
using namespace OpenSubdiv; using namespace OpenSubdiv;
using namespace Sdc; using namespace Sdc;
using namespace Osd; using namespace Osd;
@ -631,7 +631,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
auto shapeDesc = &g_defaultShapes[[_loadedModels indexOfObject:_currentModel]]; auto shapeDesc = &g_defaultShapes[[_loadedModels indexOfObject:_currentModel]];
_shape.reset(Shape::parseObj(shapeDesc->data.c_str(), shapeDesc->scheme)); _shape.reset(Shape::parseObj(shapeDesc->data.c_str(), shapeDesc->scheme));
const auto scheme = shapeDesc->scheme; const auto scheme = shapeDesc->scheme;
// create Far mesh (topology) // create Far mesh (topology)
Sdc::SchemeType sdctype = GetSdcType(*_shape); Sdc::SchemeType sdctype = GetSdcType(*_shape);
Sdc::Options sdcoptions = GetSdcOptions(*_shape); Sdc::Options sdcoptions = GetSdcOptions(*_shape);
@ -640,17 +640,17 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
std::unique_ptr<OpenSubdiv::Far::TopologyRefiner> refiner; std::unique_ptr<OpenSubdiv::Far::TopologyRefiner> refiner;
refiner.reset(Far::TopologyRefinerFactory<Shape>::Create(*_shape, Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions))); refiner.reset(Far::TopologyRefinerFactory<Shape>::Create(*_shape, Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)));
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
_numVertices = refBaseLevel.GetNumVertices(); _numVertices = refBaseLevel.GetNumVertices();
// Adaptive refinement currently supported only for catmull-clark scheme // Adaptive refinement currently supported only for catmull-clark scheme
_doAdaptive = (_useAdaptive && scheme == kCatmark); _doAdaptive = (_useAdaptive && scheme == kCatmark);
bool doSingleCreasePatch = (_useSingleCrease && scheme == kCatmark); bool doSingleCreasePatch = (_useSingleCrease && scheme == kCatmark);
bool doInfSharpPatch = (_useInfinitelySharpPatch && scheme == kCatmark); bool doInfSharpPatch = (_useInfinitelySharpPatch && scheme == kCatmark);
Osd::MeshBitset bits; Osd::MeshBitset bits;
bits.set(Osd::MeshAdaptive, _doAdaptive); bits.set(Osd::MeshAdaptive, _doAdaptive);
bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch); bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
@ -658,7 +658,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
bits.set(Osd::MeshEndCapBSplineBasis, _endCapMode == kEndCapBSplineBasis); bits.set(Osd::MeshEndCapBSplineBasis, _endCapMode == kEndCapBSplineBasis);
bits.set(Osd::MeshEndCapGregoryBasis, _endCapMode == kEndCapGregoryBasis); bits.set(Osd::MeshEndCapGregoryBasis, _endCapMode == kEndCapGregoryBasis);
bits.set(Osd::MeshEndCapLegacyGregory, _endCapMode == kEndCapLegacyGregory); bits.set(Osd::MeshEndCapLegacyGregory, _endCapMode == kEndCapLegacyGregory);
int level = _refinementLevel; int level = _refinementLevel;
_numVertexElements = 3; _numVertexElements = 3;
@ -675,7 +675,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
bits.set(OpenSubdiv::Osd::MeshFVarAdaptive, _doAdaptive); bits.set(OpenSubdiv::Osd::MeshFVarAdaptive, _doAdaptive);
int numElements = _numVertexElements + _numVaryingElements; int numElements = _numVertexElements + _numVaryingElements;
if(_kernelType == kCPU) if(_kernelType == kCPU)
{ {
_mesh.reset(new CPUMeshType(refiner.get(), _mesh.reset(new CPUMeshType(refiner.get(),
@ -690,11 +690,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
_numVaryingElements, _numVaryingElements,
level, bits, nullptr, &_context)); level, bits, nullptr, &_context));
} }
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new]; MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
[_delegate setupRenderPipelineState:desc for:self]; [_delegate setupRenderPipelineState:desc for:self];
const auto vertexDescriptor = desc.vertexDescriptor; const auto vertexDescriptor = desc.vertexDescriptor;
vertexDescriptor.layouts[0].stride = sizeof(float) * numElements; vertexDescriptor.layouts[0].stride = sizeof(float) * numElements;
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex; vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
@ -702,36 +702,36 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat3; vertexDescriptor.attributes[0].format = MTLVertexFormatFloat3;
vertexDescriptor.attributes[0].offset = 0; vertexDescriptor.attributes[0].offset = 0;
vertexDescriptor.attributes[0].bufferIndex = 0; vertexDescriptor.attributes[0].bufferIndex = 0;
_controlMesh.reset(new MTLControlMeshDisplay(_context.device, desc)); _controlMesh.reset(new MTLControlMeshDisplay(_context.device, desc));
_controlMesh->SetTopology(refBaseLevel); _controlMesh->SetTopology(refBaseLevel);
_controlMesh->SetEdgesDisplay(true); _controlMesh->SetEdgesDisplay(true);
_controlMesh->SetVerticesDisplay(false); _controlMesh->SetVerticesDisplay(false);
_legacyGregoryPatchTable.reset(); _legacyGregoryPatchTable.reset();
if(_endCapMode == kEndCapLegacyGregory) if(_endCapMode == kEndCapLegacyGregory)
{ {
_legacyGregoryPatchTable.reset(Osd::MTLLegacyGregoryPatchTable::Create(_mesh->GetFarPatchTable(), _legacyGregoryPatchTable.reset(Osd::MTLLegacyGregoryPatchTable::Create(_mesh->GetFarPatchTable(),
&_context)); &_context));
} }
_vertexData.resize(refBaseLevel.GetNumVertices() * numElements); _vertexData.resize(refBaseLevel.GetNumVertices() * numElements);
_meshCenter = simd::float3{0,0,0}; _meshCenter = simd::float3{0,0,0};
for(int i = 0; i < refBaseLevel.GetNumVertices(); i++) for(int i = 0; i < refBaseLevel.GetNumVertices(); i++)
{ {
_vertexData[i * numElements + 0] = _shape->verts[i * 3 + 0]; _vertexData[i * numElements + 0] = _shape->verts[i * 3 + 0];
_vertexData[i * numElements + 1] = _shape->verts[i * 3 + 1]; _vertexData[i * numElements + 1] = _shape->verts[i * 3 + 1];
_vertexData[i * numElements + 2] = _shape->verts[i * 3 + 2]; _vertexData[i * numElements + 2] = _shape->verts[i * 3 + 2];
} }
for(auto vertexIdx = 0; vertexIdx < refBaseLevel.GetNumVertices(); vertexIdx++) for(auto vertexIdx = 0; vertexIdx < refBaseLevel.GetNumVertices(); vertexIdx++)
{ {
_meshCenter[0] += _vertexData[vertexIdx * numElements + 0]; _meshCenter[0] += _vertexData[vertexIdx * numElements + 0];
_meshCenter[1] += _vertexData[vertexIdx * numElements + 1]; _meshCenter[1] += _vertexData[vertexIdx * numElements + 1];
_meshCenter[2] += _vertexData[vertexIdx * numElements + 2]; _meshCenter[2] += _vertexData[vertexIdx * numElements + 2];
} }
_meshCenter /= (_shape->verts.size() / 3); _meshCenter /= (_shape->verts.size() / 3);
_mesh->UpdateVertexBuffer(_vertexData.data(), 0, refBaseLevel.GetNumVertices()); _mesh->UpdateVertexBuffer(_vertexData.data(), 0, refBaseLevel.GetNumVertices());
_mesh->Refine(); _mesh->Refine();
@ -825,9 +825,9 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
-(void)_updateState { -(void)_updateState {
[self _updateCamera]; [self _updateCamera];
auto pData = _frameConstantsBuffer.data(); auto pData = _frameConstantsBuffer.data();
pData->TessLevel = _tessellationLevel; pData->TessLevel = _tessellationLevel;
if(_doAdaptive) if(_doAdaptive)
{ {
for(auto& patch : _mesh->GetPatchTable()->GetPatchArrays()) for(auto& patch : _mesh->GetPatchTable()->GetPatchArrays())
@ -841,7 +841,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
drawCommand[patch.desc.GetType() - Far::PatchDescriptor::REGULAR].patchStart = 0; drawCommand[patch.desc.GetType() - Far::PatchDescriptor::REGULAR].patchStart = 0;
} }
} }
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
_drawIndirectCommandsBuffer.markModified(); _drawIndirectCommandsBuffer.markModified();
@ -855,19 +855,19 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
auto totalPatches = 0; auto totalPatches = 0;
auto totalVertices = 0; auto totalVertices = 0;
auto totalPatchDataSize = 0; auto totalPatchDataSize = 0;
if(_usePatchIndexBuffer) if(_usePatchIndexBuffer)
{ {
_drawIndirectCommandsBuffer.alloc(_context.device, 4, @"draw patch indirect commands"); _drawIndirectCommandsBuffer.alloc(_context.device, 4, @"draw patch indirect commands");
} }
if(_doAdaptive) if(_doAdaptive)
{ {
auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays(); auto& patchArray = _mesh->GetPatchTable()->GetPatchArrays();
for(auto& patch : patchArray) for(auto& patch : patchArray)
{ {
auto patchDescriptor = patch.GetDescriptor(); auto patchDescriptor = patch.GetDescriptor();
switch(patch.desc.GetType()) switch(patch.desc.GetType())
{ {
case Far::PatchDescriptor::REGULAR: { case Far::PatchDescriptor::REGULAR: {
@ -881,7 +881,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
float elementFloats = 3; float elementFloats = 3;
if(_useSingleCrease) if(_useSingleCrease)
elementFloats += 6; elementFloats += 6;
totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * patch.desc.GetNumControlVertices(); // OsdPerPatchVertexBezier totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * patch.desc.GetNumControlVertices(); // OsdPerPatchVertexBezier
} }
@ -918,15 +918,15 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
break; break;
} }
totalPatches += patch.GetNumPatches(); totalPatches += patch.GetNumPatches();
totalVertices += patch.GetDescriptor().GetNumControlVertices() * patch.GetNumPatches(); totalVertices += patch.GetDescriptor().GetNumControlVertices() * patch.GetNumPatches();
} }
_perPatchDataBuffer.alloc(_context.device, totalPatchDataSize, @"per patch data", MTLResourceStorageModePrivate); _perPatchDataBuffer.alloc(_context.device, totalPatchDataSize, @"per patch data", MTLResourceStorageModePrivate);
_hsDataBuffer.alloc(_context.device, 20 * sizeof(float) * totalPatches, @"hs constant data", MTLResourceStorageModePrivate); _hsDataBuffer.alloc(_context.device, 20 * sizeof(float) * totalPatches, @"hs constant data", MTLResourceStorageModePrivate);
_tessFactorsBuffer.alloc(_context.device, totalPatches, @"tessellation factors buffer", MTLResourceStorageModePrivate); _tessFactorsBuffer.alloc(_context.device, totalPatches, @"tessellation factors buffer", MTLResourceStorageModePrivate);
} }
} }
@ -936,7 +936,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
_renderPipelines[i] = nil; _renderPipelines[i] = nil;
_renderControlEdgesPipeline = nil; _renderControlEdgesPipeline = nil;
} }
Osd::MTLPatchShaderSource shaderSource; Osd::MTLPatchShaderSource shaderSource;
auto patchArrays = _mesh->GetPatchTable()->GetPatchArrays(); auto patchArrays = _mesh->GetPatchTable()->GetPatchArrays();
auto pFVarArray = _mesh->GetPatchTable()->GetFVarPatchArrays(); auto pFVarArray = _mesh->GetPatchTable()->GetFVarPatchArrays();
@ -947,7 +947,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
auto& threadsPerThreadgroup = _threadgroupSizes[type]; auto& threadsPerThreadgroup = _threadgroupSizes[type];
threadsPerThreadgroup = 32; //Initial guess of 32 threadsPerThreadgroup = 32; //Initial guess of 32
int usefulControlPoints = patchArrays[i].GetDescriptor().GetNumControlVertices(); int usefulControlPoints = patchArrays[i].GetDescriptor().GetNumControlVertices();
auto compileOptions = [[MTLCompileOptions alloc] init]; auto compileOptions = [[MTLCompileOptions alloc] init];
auto preprocessor = [[NSMutableDictionary alloc] init]; auto preprocessor = [[NSMutableDictionary alloc] init];
@ -981,11 +981,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
usefulControlPoints = 4; usefulControlPoints = 4;
break; break;
} }
#if TARGET_OS_EMBEDDED #if TARGET_OS_EMBEDDED
shaderBuilder << "#define OSD_UV_CORRECTION if(t > 0.5){ ti += 0.01f; } else { ti += 0.01f; }\n"; shaderBuilder << "#define OSD_UV_CORRECTION if(t > 0.5){ ti += 0.01f; } else { ti += 0.01f; }\n";
#endif #endif
//Need to define the input vertex struct so that it's available everywhere. //Need to define the input vertex struct so that it's available everywhere.
{ {
@ -998,14 +998,14 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
}; };
)"; )";
} }
shaderBuilder << shaderSource.GetHullShaderSource(type, fvarType); shaderBuilder << shaderSource.GetHullShaderSource(type, fvarType);
if(_numFaceVaryingElements > 0) if(_numFaceVaryingElements > 0)
shaderBuilder << shaderSource.GetPatchBasisShaderSource(); shaderBuilder << shaderSource.GetPatchBasisShaderSource();
shaderBuilder << _osdShaderSource.UTF8String; shaderBuilder << _osdShaderSource.UTF8String;
const auto str = shaderBuilder.str(); const auto str = shaderBuilder.str();
int numElements = _numVertexElements + _numVaryingElements; int numElements = _numVertexElements + _numVaryingElements;
DEFINE(VERTEX_BUFFER_INDEX,VERTEX_BUFFER_INDEX); DEFINE(VERTEX_BUFFER_INDEX,VERTEX_BUFFER_INDEX);
@ -1026,7 +1026,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
DEFINE(OSD_PATCH_ENABLE_SINGLE_CREASE, allowsSingleCrease && _useSingleCrease); DEFINE(OSD_PATCH_ENABLE_SINGLE_CREASE, allowsSingleCrease && _useSingleCrease);
auto partitionMode = _useFractionalTessellation ? MTLTessellationPartitionModeFractionalOdd : MTLTessellationPartitionModePow2; auto partitionMode = _useFractionalTessellation ? MTLTessellationPartitionModeFractionalOdd : MTLTessellationPartitionModePow2;
DEFINE(OSD_FRACTIONAL_EVEN_SPACING, partitionMode == MTLTessellationPartitionModeFractionalEven); DEFINE(OSD_FRACTIONAL_EVEN_SPACING, partitionMode == MTLTessellationPartitionModeFractionalEven);
DEFINE(OSD_FRACTIONAL_ODD_SPACING, partitionMode == MTLTessellationPartitionModeFractionalOdd); DEFINE(OSD_FRACTIONAL_ODD_SPACING, partitionMode == MTLTessellationPartitionModeFractionalOdd);
#if TARGET_OS_EMBEDDED #if TARGET_OS_EMBEDDED
DEFINE(OSD_MAX_TESS_LEVEL, 16); DEFINE(OSD_MAX_TESS_LEVEL, 16);
#else #else
@ -1050,7 +1050,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
DEFINE(OSD_FVAR_PATCHPARAM_BUFFER_INDEX, OSD_FVAR_PATCHPARAM_BUFFER_INDEX); DEFINE(OSD_FVAR_PATCHPARAM_BUFFER_INDEX, OSD_FVAR_PATCHPARAM_BUFFER_INDEX);
compileOptions.preprocessorMacros = preprocessor; compileOptions.preprocessorMacros = preprocessor;
NSError* err = nil; NSError* err = nil;
auto librarySource = [NSString stringWithUTF8String:str.data()]; auto librarySource = [NSString stringWithUTF8String:str.data()];
auto library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:&err]; auto library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:&err];
@ -1062,71 +1062,71 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
auto fragmentFunction = [library newFunctionWithName:@"fragment_main"]; auto fragmentFunction = [library newFunctionWithName:@"fragment_main"];
if(vertexFunction && fragmentFunction) if(vertexFunction && fragmentFunction)
{ {
MTLRenderPipelineDescriptor* pipelineDesc = [[MTLRenderPipelineDescriptor alloc] init]; MTLRenderPipelineDescriptor* pipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];
pipelineDesc.tessellationFactorFormat = MTLTessellationFactorFormatHalf; pipelineDesc.tessellationFactorFormat = MTLTessellationFactorFormatHalf;
pipelineDesc.tessellationPartitionMode = partitionMode; pipelineDesc.tessellationPartitionMode = partitionMode;
pipelineDesc.tessellationFactorScaleEnabled = false; pipelineDesc.tessellationFactorScaleEnabled = false;
pipelineDesc.tessellationFactorStepFunction = MTLTessellationFactorStepFunctionPerPatch; pipelineDesc.tessellationFactorStepFunction = MTLTessellationFactorStepFunctionPerPatch;
if(type == Far::PatchDescriptor::GREGORY_BASIS && _useStageIn) if(type == Far::PatchDescriptor::GREGORY_BASIS && _useStageIn)
pipelineDesc.tessellationControlPointIndexType = MTLTessellationControlPointIndexTypeUInt32; pipelineDesc.tessellationControlPointIndexType = MTLTessellationControlPointIndexTypeUInt32;
[_delegate setupRenderPipelineState:pipelineDesc for:self]; [_delegate setupRenderPipelineState:pipelineDesc for:self];
{ {
pipelineDesc.fragmentFunction = [library newFunctionWithName:@"fragment_solidcolor"]; pipelineDesc.fragmentFunction = [library newFunctionWithName:@"fragment_solidcolor"];
pipelineDesc.vertexFunction = [library newFunctionWithName:@"vertex_lines"]; pipelineDesc.vertexFunction = [library newFunctionWithName:@"vertex_lines"];
if(pipelineDesc.vertexFunction) if(pipelineDesc.vertexFunction)
_controlLineRenderPipelines[type] = [_context.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&err]; _controlLineRenderPipelines[type] = [_context.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&err];
else else
_controlLineRenderPipelines[type] = nil; _controlLineRenderPipelines[type] = nil;
} }
pipelineDesc.fragmentFunction = fragmentFunction; pipelineDesc.fragmentFunction = fragmentFunction;
pipelineDesc.vertexFunction = vertexFunction; pipelineDesc.vertexFunction = vertexFunction;
if(_useStageIn) if(_useStageIn)
{ {
auto vertexDesc = pipelineDesc.vertexDescriptor; auto vertexDesc = pipelineDesc.vertexDescriptor;
[vertexDesc reset]; [vertexDesc reset];
if(_doAdaptive) if(_doAdaptive)
{ {
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch; vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch;
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stride = sizeof(int) * 3; vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stride = sizeof(int) * 3;
// PatchInput :: int3 patchParam [[attribute(10)]]; // PatchInput :: int3 patchParam [[attribute(10)]];
vertexDesc.attributes[10].bufferIndex = OSD_PATCHPARAM_BUFFER_INDEX; vertexDesc.attributes[10].bufferIndex = OSD_PATCHPARAM_BUFFER_INDEX;
vertexDesc.attributes[10].format = MTLVertexFormatInt3; vertexDesc.attributes[10].format = MTLVertexFormatInt3;
vertexDesc.attributes[10].offset = 0; vertexDesc.attributes[10].offset = 0;
} }
switch(type) switch(type)
{ {
case Far::PatchDescriptor::REGULAR: case Far::PatchDescriptor::REGULAR:
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride = sizeof(float) * 3; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride = sizeof(float) * 3;
// ControlPoint :: float3 P [[attribute(0)]]; // ControlPoint :: float3 P [[attribute(0)]];
// OsdPerPatchVertexBezier :: packed_float3 P // OsdPerPatchVertexBezier :: packed_float3 P
vertexDesc.attributes[0].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX; vertexDesc.attributes[0].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
vertexDesc.attributes[0].format = MTLVertexFormatFloat3; vertexDesc.attributes[0].format = MTLVertexFormatFloat3;
vertexDesc.attributes[0].offset = 0; vertexDesc.attributes[0].offset = 0;
if(_useSingleCrease) if(_useSingleCrease)
{ {
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride += sizeof(float) * 3 * 2; vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride += sizeof(float) * 3 * 2;
// ControlPoint :: float3 P1 [[attribute(1)]]; // ControlPoint :: float3 P1 [[attribute(1)]];
// OsdPerPatchVertexBezier :: packed_float3 P1 // OsdPerPatchVertexBezier :: packed_float3 P1
vertexDesc.attributes[1].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX; vertexDesc.attributes[1].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
vertexDesc.attributes[1].format = MTLVertexFormatFloat3; vertexDesc.attributes[1].format = MTLVertexFormatFloat3;
vertexDesc.attributes[1].offset = sizeof(float) * 3; vertexDesc.attributes[1].offset = sizeof(float) * 3;
// ControlPoint :: float3 P2 [[attribute(2)]]; // ControlPoint :: float3 P2 [[attribute(2)]];
// OsdPerPatchVertexBezier :: packed_float3 P2 // OsdPerPatchVertexBezier :: packed_float3 P2
vertexDesc.attributes[2].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX; vertexDesc.attributes[2].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
@ -1135,19 +1135,19 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
// USE_PTVS_SHARPNESS is true and so OsdPerPatchVertexBezier :: float2 vSegments is not used // USE_PTVS_SHARPNESS is true and so OsdPerPatchVertexBezier :: float2 vSegments is not used
} }
if(_useScreenspaceTessellation) if(_useScreenspaceTessellation)
{ {
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch; vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch;
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stride = sizeof(float) * 4 * 2; vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stride = sizeof(float) * 4 * 2;
// PatchInput :: float4 tessOuterLo [[attribute(5)]]; // PatchInput :: float4 tessOuterLo [[attribute(5)]];
// OsdPerPatchTessFactors :: float4 tessOuterLo; // OsdPerPatchTessFactors :: float4 tessOuterLo;
vertexDesc.attributes[5].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX; vertexDesc.attributes[5].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
vertexDesc.attributes[5].format = MTLVertexFormatFloat4; vertexDesc.attributes[5].format = MTLVertexFormatFloat4;
vertexDesc.attributes[5].offset = 0; vertexDesc.attributes[5].offset = 0;
// PatchInput :: float4 tessOuterHi [[attribute(6)]]; // PatchInput :: float4 tessOuterHi [[attribute(6)]];
// OsdPerPatchTessFactors :: float4 tessOuterHi; // OsdPerPatchTessFactors :: float4 tessOuterHi;
vertexDesc.attributes[6].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX; vertexDesc.attributes[6].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
@ -1157,11 +1157,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
break; break;
case Far::PatchDescriptor::GREGORY_BOUNDARY: case Far::PatchDescriptor::GREGORY_BOUNDARY:
case Far::PatchDescriptor::GREGORY: case Far::PatchDescriptor::GREGORY:
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint; vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stride = sizeof(float) * 3 * 5; vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stride = sizeof(float) * 3 * 5;
// ControlPoint :: float3 P [[attribute(0)]]; // ControlPoint :: float3 P [[attribute(0)]];
// ControlPoint :: float3 Ep [[attribute(1)]]; // ControlPoint :: float3 Ep [[attribute(1)]];
// ControlPoint :: float3 Em [[attribute(2)]]; // ControlPoint :: float3 Em [[attribute(2)]];
@ -1178,7 +1178,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint; vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepRate = 1; vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepRate = 1;
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stride = sizeof(float) * 3; vertexDesc.layouts[VERTEX_BUFFER_INDEX].stride = sizeof(float) * 3;
// ControlPoint :: float3 position [[attribute(0)]]; // ControlPoint :: float3 position [[attribute(0)]];
vertexDesc.attributes[0].bufferIndex = VERTEX_BUFFER_INDEX; vertexDesc.attributes[0].bufferIndex = VERTEX_BUFFER_INDEX;
vertexDesc.attributes[0].format = MTLVertexFormatFloat3; vertexDesc.attributes[0].format = MTLVertexFormatFloat3;
@ -1192,16 +1192,16 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
[vertexDesc reset]; [vertexDesc reset];
break; break;
} }
} }
_renderPipelines[type] = [_context.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&err]; _renderPipelines[type] = [_context.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&err];
if(!_renderPipelines[type] && err) if(!_renderPipelines[type] && err)
{ {
NSLog(@"%s", [[err localizedDescription] UTF8String]); NSLog(@"%s", [[err localizedDescription] UTF8String]);
} }
} }
auto computeFunction = [library newFunctionWithName:@"compute_main"]; auto computeFunction = [library newFunctionWithName:@"compute_main"];
if(computeFunction) if(computeFunction)
{ {
@ -1212,69 +1212,69 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = false; computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = false;
#endif #endif
computeDesc.computeFunction = computeFunction; computeDesc.computeFunction = computeFunction;
NSError* err; NSError* err;
_computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err]; _computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err];
if(err && _computePipelines[type] == nil) if(err && _computePipelines[type] == nil)
{ {
NSLog(@"%s", [[err description] UTF8String]); NSLog(@"%s", [[err description] UTF8String]);
} }
if(_computePipelines[type].threadExecutionWidth != threadsPerThreadgroup) if(_computePipelines[type].threadExecutionWidth != threadsPerThreadgroup)
{ {
DEFINE(THREADS_PER_THREADGROUP, _computePipelines[type].threadExecutionWidth); DEFINE(THREADS_PER_THREADGROUP, _computePipelines[type].threadExecutionWidth);
DEFINE(CONTROL_POINTS_PER_THREAD, std::max<int>(1, usefulControlPoints / _computePipelines[type].threadExecutionWidth)); DEFINE(CONTROL_POINTS_PER_THREAD, std::max<int>(1, usefulControlPoints / _computePipelines[type].threadExecutionWidth));
compileOptions.preprocessorMacros = preprocessor; compileOptions.preprocessorMacros = preprocessor;
library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:nil]; library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:nil];
assert(library); assert(library);
computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = true; computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = true;
computeDesc.computeFunction = [library newFunctionWithName:@"compute_main"]; computeDesc.computeFunction = [library newFunctionWithName:@"compute_main"];
threadsPerThreadgroup = _computePipelines[type].threadExecutionWidth; threadsPerThreadgroup = _computePipelines[type].threadExecutionWidth;
_computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err]; _computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err];
if(_computePipelines[type].threadExecutionWidth != threadsPerThreadgroup) if(_computePipelines[type].threadExecutionWidth != threadsPerThreadgroup)
{ {
DEFINE(THREADS_PER_THREADGROUP, threadsPerThreadgroup); DEFINE(THREADS_PER_THREADGROUP, threadsPerThreadgroup);
DEFINE(CONTROL_POINTS_PER_THREAD, std::max<int>(1, usefulControlPoints / threadsPerThreadgroup)); DEFINE(CONTROL_POINTS_PER_THREAD, std::max<int>(1, usefulControlPoints / threadsPerThreadgroup));
DEFINE(NEEDS_BARRIER, 1); DEFINE(NEEDS_BARRIER, 1);
compileOptions.preprocessorMacros = preprocessor; compileOptions.preprocessorMacros = preprocessor;
library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:nil]; library = [_context.device newLibraryWithSource:librarySource options:compileOptions error:nil];
assert(library); assert(library);
computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = false; computeDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = false;
computeDesc.computeFunction = [library newFunctionWithName:@"compute_main"]; computeDesc.computeFunction = [library newFunctionWithName:@"compute_main"];
threadsPerThreadgroup = _computePipelines[type].threadExecutionWidth; threadsPerThreadgroup = _computePipelines[type].threadExecutionWidth;
_computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err]; _computePipelines[type] = [_context.device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionNone reflection:nil error:&err];
} }
} }
} }
} }
MTLDepthStencilDescriptor* depthStencilDesc = [[MTLDepthStencilDescriptor alloc] init]; MTLDepthStencilDescriptor* depthStencilDesc = [[MTLDepthStencilDescriptor alloc] init];
depthStencilDesc.depthCompareFunction = MTLCompareFunctionLess; depthStencilDesc.depthCompareFunction = MTLCompareFunctionLess;
[_delegate setupDepthStencilState:depthStencilDesc for:self]; [_delegate setupDepthStencilState:depthStencilDesc for:self];
depthStencilDesc.depthWriteEnabled = YES; depthStencilDesc.depthWriteEnabled = YES;
_readWriteDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc]; _readWriteDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc];
depthStencilDesc.depthWriteEnabled = NO; depthStencilDesc.depthWriteEnabled = NO;
_readOnlyDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc]; _readOnlyDepthStencilState = [_context.device newDepthStencilStateWithDescriptor:depthStencilDesc];
} }
-(void)_updateCamera { -(void)_updateCamera {
auto pData = _frameConstantsBuffer.data(); auto pData = _frameConstantsBuffer.data();
identity(pData->ModelViewMatrix); identity(pData->ModelViewMatrix);
translate(pData->ModelViewMatrix, 0, 0, -_cameraData.dollyDistance); translate(pData->ModelViewMatrix, 0, 0, -_cameraData.dollyDistance);
rotate(pData->ModelViewMatrix, _cameraData.rotationY, 1, 0, 0); rotate(pData->ModelViewMatrix, _cameraData.rotationY, 1, 0, 0);
@ -1282,11 +1282,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
translate(pData->ModelViewMatrix, -_meshCenter[0], -_meshCenter[2], _meshCenter[1]); // z-up model translate(pData->ModelViewMatrix, -_meshCenter[0], -_meshCenter[2], _meshCenter[1]); // z-up model
rotate(pData->ModelViewMatrix, -90, 1, 0, 0); // z-up model rotate(pData->ModelViewMatrix, -90, 1, 0, 0); // z-up model
inverseMatrix(pData->ModelViewInverseMatrix, pData->ModelViewMatrix); inverseMatrix(pData->ModelViewInverseMatrix, pData->ModelViewMatrix);
identity(pData->ProjectionMatrix); identity(pData->ProjectionMatrix);
perspective(pData->ProjectionMatrix, 45.0, _cameraData.aspectRatio, 0.01f, 500.0); perspective(pData->ProjectionMatrix, 45.0, _cameraData.aspectRatio, 0.01f, 500.0);
multMatrix(pData->ModelViewProjectionMatrix, pData->ModelViewMatrix, pData->ProjectionMatrix); multMatrix(pData->ModelViewProjectionMatrix, pData->ModelViewMatrix, pData->ProjectionMatrix);
} }
@ -1310,14 +1310,14 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
{ 0.7f, 0.7f, 0.7f, 1.0f }, { 0.7f, 0.7f, 0.7f, 1.0f },
{ 0.8f, 0.8f, 0.8f, 1.0f }, { 0.8f, 0.8f, 0.8f, 1.0f },
}; };
_lightsBuffer[1] = { _lightsBuffer[1] = {
simd::normalize(simd::float4{ -0.8f, 0.4f, -1.0f, 0.0f }), simd::normalize(simd::float4{ -0.8f, 0.4f, -1.0f, 0.0f }),
{ 0.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f },
{ 0.5f, 0.5f, 0.5f, 1.0f }, { 0.5f, 0.5f, 0.5f, 1.0f },
{ 0.8f, 0.8f, 0.8f, 1.0f } { 0.8f, 0.8f, 0.8f, 1.0f }
}; };
_lightsBuffer.markModified(); _lightsBuffer.markModified();
} }

View File

@ -32,21 +32,22 @@
@protocol MTLDevice; @protocol MTLDevice;
@protocol MTLCommandQueue; @protocol MTLCommandQueue;
namespace OpenSubdiv namespace OpenSubdiv {
{ namespace OPENSUBDIV_VERSION {
namespace OPENSUBDIV_VERSION
{ namespace Osd {
namespace Osd
{ class MTLContext {
class MTLContext public:
{ id<MTLDevice> device = nullptr;
public: id<MTLCommandQueue> commandQueue = nullptr;
id<MTLDevice> device = nullptr; };
id<MTLCommandQueue> commandQueue = nullptr;
}; } // end namespace Osd
}
} } // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION; using namespace OPENSUBDIV_VERSION;
}
} // end namespace OpenSubdiv
#endif //OPENSUBDIV3_OSD_MTL_COMMON_H #endif //OPENSUBDIV3_OSD_MTL_COMMON_H

File diff suppressed because it is too large Load Diff

View File

@ -34,8 +34,6 @@
#include "../far/stencilTable.h" #include "../far/stencilTable.h"
#include "../far/error.h" #include "../far/error.h"
#define PARAMETER_BUFFER_INDEX 0 #define PARAMETER_BUFFER_INDEX 0
#define SIZES_BUFFER_INDEX 1 #define SIZES_BUFFER_INDEX 1
#define OFFSETS_BUFFER_INDEX 2 #define OFFSETS_BUFFER_INDEX 2
@ -141,73 +139,73 @@ using namespace Osd;
MTLStencilTable::MTLStencilTable(Far::StencilTable const *stencilTable, MTLStencilTable::MTLStencilTable(Far::StencilTable const *stencilTable,
MTLContext* context) MTLContext* context)
{ {
assert(context != nil); assert(context != nil);
assert(context->device != nil && context->commandQueue != nil); assert(context->device != nil && context->commandQueue != nil);
_numStencils = stencilTable->GetNumStencils(); _numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0) if (_numStencils > 0)
{ {
auto sizes = stencilTable->GetSizes(); auto sizes = stencilTable->GetSizes();
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context); _sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context); _offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context); _indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context); _weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
_sizesBuffer.label = @"StencilTable Sizes"; _sizesBuffer.label = @"StencilTable Sizes";
_offsetsBuffer.label = @"StencilTable Offsets"; _offsetsBuffer.label = @"StencilTable Offsets";
_indicesBuffer.label = @"StencilTable Indices"; _indicesBuffer.label = @"StencilTable Indices";
_weightsBuffer.label = @"StencilTable Weights"; _weightsBuffer.label = @"StencilTable Weights";
} }
_duWeightsBuffer = nil; _duWeightsBuffer = nil;
_dvWeightsBuffer = nil; _dvWeightsBuffer = nil;
_duuWeightsBuffer = nil; _duuWeightsBuffer = nil;
_duvWeightsBuffer = nil; _duvWeightsBuffer = nil;
_dvvWeightsBuffer = nil; _dvvWeightsBuffer = nil;
} }
MTLStencilTable::MTLStencilTable(Far::LimitStencilTable const *stencilTable, MTLStencilTable::MTLStencilTable(Far::LimitStencilTable const *stencilTable,
MTLContext* context) MTLContext* context)
{ {
assert(context != nil); assert(context != nil);
assert(context->device != nil && context->commandQueue != nil); assert(context->device != nil && context->commandQueue != nil);
_numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0)
{
auto sizes = stencilTable->GetSizes();
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context); _numStencils = stencilTable->GetNumStencils();
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context); if (_numStencils > 0)
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context); {
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context); auto sizes = stencilTable->GetSizes();
_duWeightsBuffer = createBuffer(stencilTable->GetDuWeights(), context);
_dvWeightsBuffer = createBuffer(stencilTable->GetDvWeights(), context);
_duuWeightsBuffer = createBuffer(stencilTable->GetDuuWeights(), context);
_duvWeightsBuffer = createBuffer(stencilTable->GetDuvWeights(), context);
_dvvWeightsBuffer = createBuffer(stencilTable->GetDvvWeights(), context);
_sizesBuffer.label = @"StencilTable Sizes"; _sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
_offsetsBuffer.label = @"StencilTable Offsets"; _offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
_indicesBuffer.label = @"StencilTable Indices"; _indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
_weightsBuffer.label = @"StencilTable Weights"; _weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
if (_duWeightsBuffer) { _duWeightsBuffer = createBuffer(stencilTable->GetDuWeights(), context);
_duWeightsBuffer.label = @"StencilTable duWeights"; _dvWeightsBuffer = createBuffer(stencilTable->GetDvWeights(), context);
_duuWeightsBuffer = createBuffer(stencilTable->GetDuuWeights(), context);
_duvWeightsBuffer = createBuffer(stencilTable->GetDuvWeights(), context);
_dvvWeightsBuffer = createBuffer(stencilTable->GetDvvWeights(), context);
_sizesBuffer.label = @"StencilTable Sizes";
_offsetsBuffer.label = @"StencilTable Offsets";
_indicesBuffer.label = @"StencilTable Indices";
_weightsBuffer.label = @"StencilTable Weights";
if (_duWeightsBuffer) {
_duWeightsBuffer.label = @"StencilTable duWeights";
}
if (_dvWeightsBuffer) {
_dvWeightsBuffer.label = @"StencilTable dvWeights";
}
if (_duuWeightsBuffer) {
_duuWeightsBuffer.label = @"StencilTable duuWeights";
}
if (_duvWeightsBuffer) {
_duvWeightsBuffer.label = @"StencilTable duvWeights";
}
if (_dvvWeightsBuffer) {
_dvvWeightsBuffer.label = @"StencilTable dvvWeights";
}
} }
if (_dvWeightsBuffer) {
_dvWeightsBuffer.label = @"StencilTable dvWeights";
}
if (_duuWeightsBuffer) {
_duuWeightsBuffer.label = @"StencilTable duuWeights";
}
if (_duvWeightsBuffer) {
_duvWeightsBuffer.label = @"StencilTable duvWeights";
}
if (_dvvWeightsBuffer) {
_dvvWeightsBuffer.label = @"StencilTable dvvWeights";
}
}
} }
MTLStencilTable::~MTLStencilTable() {} MTLStencilTable::~MTLStencilTable() {}
@ -217,20 +215,20 @@ MTLComputeEvaluator *MTLComputeEvaluator::Create(
BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc, BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc,
MTLContext* context) MTLContext* context)
{ {
assert(context != nil); assert(context != nil);
assert(context->device != nil && context->commandQueue != nil); assert(context->device != nil && context->commandQueue != nil);
auto instance = new MTLComputeEvaluator(); auto instance = new MTLComputeEvaluator();
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc,
BufferDescriptor(), BufferDescriptor(),
BufferDescriptor(), BufferDescriptor(),
BufferDescriptor(), BufferDescriptor(),
context)) context))
return instance; return instance;
delete instance; delete instance;
return nullptr; return nullptr;
} }
MTLComputeEvaluator *MTLComputeEvaluator::Create( MTLComputeEvaluator *MTLComputeEvaluator::Create(
@ -239,17 +237,18 @@ MTLComputeEvaluator *MTLComputeEvaluator::Create(
BufferDescriptor const &duuDesc, BufferDescriptor const &duvDesc, BufferDescriptor const &dvvDesc, BufferDescriptor const &duuDesc, BufferDescriptor const &duvDesc, BufferDescriptor const &dvvDesc,
MTLContext* context) MTLContext* context)
{ {
assert(context != nil); assert(context != nil);
assert(context->device != nil && context->commandQueue != nil); assert(context->device != nil && context->commandQueue != nil);
auto instance = new MTLComputeEvaluator(); auto instance = new MTLComputeEvaluator();
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc,
duuDesc, duvDesc, dvvDesc, context)) duuDesc, duvDesc, dvvDesc, context)) {
return instance; return instance;
}
delete instance; delete instance;
return nullptr; return nullptr;
} }
bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc, bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
@ -321,7 +320,7 @@ bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
#if !__has_feature(objc_arc) #if !__has_feature(objc_arc)
[compileOptions release]; [compileOptions release];
#endif #endif
if (!_computeLibrary) if (!_computeLibrary)
{ {
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Shader: %s\n", Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Shader: %s\n",
@ -332,13 +331,12 @@ bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
auto evalStencilsFunction = [_computeLibrary newFunctionWithName:@"eval_stencils"]; auto evalStencilsFunction = [_computeLibrary newFunctionWithName:@"eval_stencils"];
_evalStencils = _evalStencils =
[context->device newComputePipelineStateWithFunction:evalStencilsFunction [context->device newComputePipelineStateWithFunction:evalStencilsFunction
error:&err]; error:&err];
#if !__has_feature(objc_arc) #if !__has_feature(objc_arc)
[evalStencilsFunction release]; [evalStencilsFunction release];
#endif #endif
if (!_evalStencils) if (!_evalStencils)
{ {
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_stencils: %s\n", Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_stencils: %s\n",
@ -350,11 +348,11 @@ bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
_evalPatches = _evalPatches =
[context->device newComputePipelineStateWithFunction:evalPatchesFunction [context->device newComputePipelineStateWithFunction:evalPatchesFunction
error:&err]; error:&err];
#if !__has_feature(objc_arc) #if !__has_feature(objc_arc)
[evalPatchesFunction release]; [evalPatchesFunction release];
#endif #endif
if (!_evalPatches) if (!_evalPatches)
{ {
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_patches: %s\n", Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_patches: %s\n",
@ -444,7 +442,7 @@ bool MTLComputeEvaluator::EvalStencils(
return true; return true;
assert(context != nullptr); assert(context != nullptr);
auto device = context->device; auto device = context->device;
auto commandQueue = context->commandQueue; auto commandQueue = context->commandQueue;
@ -556,7 +554,7 @@ MTLComputeEvaluator::EvalPatches(
return false; return false;
assert(context != nullptr); assert(context != nullptr);
auto device = context->device; auto device = context->device;
auto commandQueue = context->commandQueue; auto commandQueue = context->commandQueue;
@ -609,5 +607,6 @@ MTLComputeEvaluator::EvalPatches(
} }
} //end namespace Osd } //end namespace Osd
} //end namespace OPENSUBDIV_VERSION } //end namespace OPENSUBDIV_VERSION
} //end namespace OpenSubdiv } //end namespace OpenSubdiv

View File

@ -315,6 +315,4 @@ kernel void eval_patches(
if(args.dvvDesc.y > 0) if(args.dvvDesc.y > 0)
writeDvv(current, dvv, dvvDerivativeBuffer, args); writeDvv(current, dvv, dvvDerivativeBuffer, args);
#endif #endif
} }

View File

@ -33,58 +33,60 @@
@protocol MTLDevice; @protocol MTLDevice;
@protocol MTLBuffer; @protocol MTLBuffer;
namespace OpenSubdiv namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
class MTLLegacyGregoryPatchTable
: private NonCopyable<MTLLegacyGregoryPatchTable>
{ {
namespace OPENSUBDIV_VERSION public:
~MTLLegacyGregoryPatchTable();
template<typename DEVICE_CONTEXT>
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, DEVICE_CONTEXT context) {
return Create(farPatchTable, context);
}
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, MTLContext* context);
void UpdateVertexBuffer(id<MTLBuffer> vbo, int numVertices, int numVertexElements, MTLContext* context);
id<MTLBuffer> GetVertexBuffer() const
{ {
namespace Osd return _vertexBuffer;
{ }
class MTLLegacyGregoryPatchTable
: private NonCopyable<MTLLegacyGregoryPatchTable>
{
public:
~MTLLegacyGregoryPatchTable();
template<typename DEVICE_CONTEXT> id<MTLBuffer> GetVertexValenceBuffer() const
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, DEVICE_CONTEXT context) { {
return Create(farPatchTable, context); return _vertexValenceBuffer;
} }
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, MTLContext* context); id<MTLBuffer> GetQuadOffsetsBuffer() const
{
return _quadOffsetsBuffer;
}
void UpdateVertexBuffer(id<MTLBuffer> vbo, int numVertices, int numVertexElements, MTLContext* context); int GetQuadOffsetsBase(Far::PatchDescriptor::Type type)
{
if(type == Far::PatchDescriptor::GREGORY_BOUNDARY)
return _quadOffsetsBase[1];
return _quadOffsetsBase[0];
}
id<MTLBuffer> GetVertexBuffer() const private:
{ id<MTLBuffer> _vertexBuffer;
return _vertexBuffer; id<MTLBuffer> _vertexValenceBuffer;
} id<MTLBuffer> _quadOffsetsBuffer;
int _quadOffsetsBase[2];
};
id<MTLBuffer> GetVertexValenceBuffer() const } //end namespace Osd
{
return _vertexValenceBuffer;
}
id<MTLBuffer> GetQuadOffsetsBuffer() const } //end namespace OPENSUBDIV_VERSION
{ using namespace OPENSUBDIV_VERSION;
return _quadOffsetsBuffer;
}
int GetQuadOffsetsBase(Far::PatchDescriptor::Type type)
{
if(type == Far::PatchDescriptor::GREGORY_BOUNDARY)
return _quadOffsetsBase[1];
return _quadOffsetsBase[0];
}
private:
id<MTLBuffer> _vertexBuffer;
id<MTLBuffer> _vertexValenceBuffer;
id<MTLBuffer> _quadOffsetsBuffer;
int _quadOffsetsBase[2];
};
} //end namespace Osd
} //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSuddiv } //end namespace OpenSuddiv
#endif // OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H #endif // OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H

View File

@ -96,5 +96,6 @@ void MTLLegacyGregoryPatchTable::UpdateVertexBuffer(id<MTLBuffer> vbo, int numVe
} }
} //end namespace Osd } //end namespace Osd
} //end namespace OPENSUBDIV_VERSION } //end namespace OPENSUBDIV_VERSION
} //end namespace OpenSubdiv } //end namespace OpenSubdiv

View File

@ -30,17 +30,18 @@
#include "../osd/mtlPatchTable.h" #include "../osd/mtlPatchTable.h"
namespace OpenSubdiv namespace OpenSubdiv {
{ namespace OPENSUBDIV_VERSION {
namespace OPENSUBDIV_VERSION
{ namespace Osd {
namespace Osd
{ typedef MeshInterface<MTLPatchTable> MTLMeshInterface;
typedef MeshInterface<MTLPatchTable> MTLMeshInterface;
} // end namespace Osd } // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv } // end namespace OpenSubdiv
#endif // OPENSUBDIV3_OSD_MTL_MESH_H #endif // OPENSUBDIV3_OSD_MTL_MESH_H

View File

@ -29,23 +29,23 @@
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerVertex( void OsdComputePerVertex(
float4 vertexPosition, float4 vertexPosition,
threadgroup HullVertex& hullVertex, threadgroup HullVertex& hullVertex,
int vertexId, int vertexId,
float4x4 ModelViewProjectionMatrix, float4x4 ModelViewProjectionMatrix,
OsdPatchParamBufferSet osdBuffers OsdPatchParamBufferSet osdBuffers
) )
{ {
hullVertex.position = vertexPosition; hullVertex.position = vertexPosition;
#if OSD_ENABLE_PATCH_CULL #if OSD_ENABLE_PATCH_CULL
float4 clipPos = mul(ModelViewProjectionMatrix, vertexPosition); float4 clipPos = mul(ModelViewProjectionMatrix, vertexPosition);
short3 clip0 = short3(clipPos.x < clipPos.w, short3 clip0 = short3(clipPos.x < clipPos.w,
clipPos.y < clipPos.w, clipPos.y < clipPos.w,
clipPos.z < clipPos.w); clipPos.z < clipPos.w);
short3 clip1 = short3(clipPos.x > -clipPos.w, short3 clip1 = short3(clipPos.x > -clipPos.w,
clipPos.y > -clipPos.w, clipPos.y > -clipPos.w,
clipPos.z > -clipPos.w); clipPos.z > -clipPos.w);
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1); hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
#endif #endif
} }
@ -54,16 +54,16 @@ void OsdComputePerVertex(
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerPatchBSplineFactors( void OsdComputePerPatchBSplineFactors(
int3 patchParam, int3 patchParam,
float tessLevel, float tessLevel,
float4x4 projectionMatrix, float4x4 projectionMatrix,
float4x4 modelViewMatrix, float4x4 modelViewMatrix,
device OsdPerPatchVertexBezier* patch device OsdPerPatchVertexBezier* patch
#if !USE_PTVS_FACTORS #if !USE_PTVS_FACTORS
,device OsdPerPatchTessFactors& patchFactors ,device OsdPerPatchTessFactors& patchFactors
#endif #endif
,device MTLQuadTessellationFactorsHalf& quadFactors ,device MTLQuadTessellationFactorsHalf& quadFactors
) )
{ {
float4 tessLevelOuter = float4(0,0,0,0); float4 tessLevelOuter = float4(0,0,0,0);
float2 tessLevelInner = float2(0,0); float2 tessLevelInner = float2(0,0);
@ -72,8 +72,8 @@ void OsdComputePerPatchBSplineFactors(
#if OSD_ENABLE_SCREENSPACE_TESSELLATION #if OSD_ENABLE_SCREENSPACE_TESSELLATION
OsdGetTessLevelsAdaptiveLimitPoints( OsdGetTessLevelsAdaptiveLimitPoints(
tessLevel, tessLevel,
projectionMatrix, projectionMatrix,
modelViewMatrix, modelViewMatrix,
patch, patch,
patchParam, patchParam,
@ -84,8 +84,8 @@ void OsdComputePerPatchBSplineFactors(
); );
#else #else
OsdGetTessLevelsUniform( OsdGetTessLevelsUniform(
tessLevel, tessLevel,
patchParam, patchParam,
tessLevelOuter, tessLevelOuter,
tessLevelInner, tessLevelInner,
tessOuterLo, tessOuterLo,
@ -106,27 +106,27 @@ void OsdComputePerPatchBSplineFactors(
} }
void OsdComputePerPatchFactors( void OsdComputePerPatchFactors(
int3 patchParam, int3 patchParam,
float tessLevel, float tessLevel,
unsigned patchID, unsigned patchID,
float4x4 projectionMatrix, float4x4 projectionMatrix,
float4x4 modelViewMatrix, float4x4 modelViewMatrix,
OsdPatchParamBufferSet osdBuffer, OsdPatchParamBufferSet osdBuffer,
threadgroup PatchVertexType* patchVertices, threadgroup PatchVertexType* patchVertices,
device MTLQuadTessellationFactorsHalf& quadFactors device MTLQuadTessellationFactorsHalf& quadFactors
) )
{ {
OsdComputePerPatchBSplineFactors( OsdComputePerPatchBSplineFactors(
patchParam, patchParam,
tessLevel, tessLevel,
projectionMatrix, projectionMatrix,
modelViewMatrix, modelViewMatrix,
osdBuffer.perPatchVertexBuffer + patchID * CONTROL_POINTS_PER_PATCH, osdBuffer.perPatchVertexBuffer + patchID * CONTROL_POINTS_PER_PATCH,
#if !USE_PTVS_FACTORS #if !USE_PTVS_FACTORS
osdBuffer.patchTessBuffer[patchID], osdBuffer.patchTessBuffer[patchID],
#endif #endif
quadFactors quadFactors
); );
} }
//---------------------------------------------------------- //----------------------------------------------------------
@ -134,15 +134,16 @@ void OsdComputePerPatchFactors(
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerPatchVertex( void OsdComputePerPatchVertex(
int3 patchParam, int3 patchParam,
unsigned ID, unsigned ID,
unsigned PrimitiveID, unsigned PrimitiveID,
unsigned ControlID, unsigned ControlID,
threadgroup PatchVertexType* patchVertices, threadgroup PatchVertexType* patchVertices,
OsdPatchParamBufferSet osdBuffers OsdPatchParamBufferSet osdBuffers
) )
{ {
OsdComputePerPatchVertexBSpline(patchParam, ID, patchVertices, osdBuffers.perPatchVertexBuffer[ControlID]); OsdComputePerPatchVertexBSpline(patchParam, ID,
patchVertices, osdBuffers.perPatchVertexBuffer[ControlID]);
} }
//---------------------------------------------------------- //----------------------------------------------------------
@ -151,20 +152,22 @@ void OsdComputePerPatchVertex(
template<typename PerPatchVertexBezier> template<typename PerPatchVertexBezier>
OsdPatchVertex ds_regular_patches( OsdPatchVertex ds_regular_patches(
const float TessLevel, const float TessLevel,
#if !USE_PTVS_FACTORS #if !USE_PTVS_FACTORS
float4 tessOuterHi, float4 tessOuterHi,
float4 tessOuterLo, float4 tessOuterLo,
#endif #endif
PerPatchVertexBezier cv, PerPatchVertexBezier cv,
int3 patchParam, int3 patchParam,
float2 domainCoord) float2 domainCoord
)
{ {
OsdPatchVertex output; OsdPatchVertex output;
float3 P, dPu, dPv; float3 P, dPu, dPv;
float3 N, dNu, dNv; float3 N, dNu, dNv;
float2 vSegments; float2 vSegments;
#if !USE_PTVS_FACTORS #if !USE_PTVS_FACTORS
float2 UV = OsdGetTessParameterization(domainCoord, float2 UV = OsdGetTessParameterization(domainCoord,
tessOuterLo, tessOuterLo,
@ -183,7 +186,6 @@ OsdPatchVertex ds_regular_patches(
#endif #endif
OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv, vSegments); OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv, vSegments);
output.normal = N; output.normal = N;
output.tangent = dPu; output.tangent = dPu;
output.bitangent = dPv; output.bitangent = dPv;
@ -204,35 +206,35 @@ OsdPatchVertex ds_regular_patches(
template<typename PerPatchVertexBezier> template<typename PerPatchVertexBezier>
#endif #endif
OsdPatchVertex OsdComputePatch( OsdPatchVertex OsdComputePatch(
float tessLevel, float tessLevel,
float2 domainCoord, float2 domainCoord,
unsigned patchID, unsigned patchID,
#if USE_STAGE_IN #if USE_STAGE_IN
PerPatchVertexBezier osdPatch PerPatchVertexBezier osdPatch
#else #else
OsdVertexBufferSet osdBuffers OsdVertexBufferSet osdBuffers
#endif #endif
) )
{ {
return ds_regular_patches( return ds_regular_patches(
tessLevel, tessLevel,
#if !USE_PTVS_FACTORS #if !USE_PTVS_FACTORS
#if USE_STAGE_IN #if USE_STAGE_IN
osdPatch.tessOuterHi, osdPatch.tessOuterHi,
osdPatch.tessOuterLo, osdPatch.tessOuterLo,
#else #else
osdBuffers.patchTessBuffer[patchID].tessOuterHi, osdBuffers.patchTessBuffer[patchID].tessOuterHi,
osdBuffers.patchTessBuffer[patchID].tessOuterLo, osdBuffers.patchTessBuffer[patchID].tessOuterLo,
#endif #endif
#endif #endif
#if USE_STAGE_IN #if USE_STAGE_IN
osdPatch.cv, osdPatch.cv,
osdPatch.patchParam, osdPatch.patchParam,
#else #else
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH, osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
osdBuffers.patchParamBuffer[patchID], osdBuffers.patchParamBuffer[patchID],
#endif #endif
domainCoord domainCoord
); );
} }

View File

@ -47,7 +47,7 @@ static_assert(sizeof(OsdInputVertexType) > 0, "OsdInputVertexType must be define
#if OSD_IS_ADAPTIVE #if OSD_IS_ADAPTIVE
#if OSD_PATCH_GREGORY_BASIS #if OSD_PATCH_GREGORY_BASIS
constant constexpr unsigned IndexLookupStride = 5; constant constexpr unsigned IndexLookupStride = 5;
#else #else
constant constexpr unsigned IndexLookupStride = 1; constant constexpr unsigned IndexLookupStride = 1;
#endif #endif
@ -61,7 +61,7 @@ static_assert(OSD_ENABLE_SCREENSPACE_TESSELLATION && (OSD_FRACTIONAL_ODD_SPACING
#endif #endif
//Adjustments to the UV reparameterization can be defined here. //Adjustments to the UV reparameterization can be defined here.
#ifndef OSD_UV_CORRECTION #ifndef OSD_UV_CORRECTION
#define OSD_UV_CORRECTION #define OSD_UV_CORRECTION
#endif #endif
@ -147,7 +147,7 @@ struct HullVertex {
void SetPosition(float3 v) threadgroup void SetPosition(float3 v) threadgroup
{ {
position.xyz = v; position.xyz = v;
} }
}; };
@ -204,36 +204,35 @@ using PerPatchVertexType = OsdInputVertexType;
//Shared buffers used by OSD that are common to all kernels //Shared buffers used by OSD that are common to all kernels
struct OsdPatchParamBufferSet struct OsdPatchParamBufferSet
{ {
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]]; const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]]; const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]]; device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]];
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]]; #if !USE_PTVS_FACTORS
#if !USE_PTVS_FACTORS
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]]; device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
#endif #endif
#if OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY #if OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
const device int* quadOffsetBuffer [[buffer(OSD_QUADOFFSET_BUFFER_INDEX)]]; const device int* quadOffsetBuffer [[buffer(OSD_QUADOFFSET_BUFFER_INDEX)]];
const device int* valenceBuffer [[buffer(OSD_VALENCE_BUFFER_INDEX)]]; const device int* valenceBuffer [[buffer(OSD_VALENCE_BUFFER_INDEX)]];
#endif #endif
const constant unsigned& kernelExecutionLimit [[buffer(OSD_KERNELLIMIT_BUFFER_INDEX)]]; const constant unsigned& kernelExecutionLimit [[buffer(OSD_KERNELLIMIT_BUFFER_INDEX)]];
}; };
//Shared buffers used by OSD that are common to all PTVS implementations //Shared buffers used by OSD that are common to all PTVS implementations
struct OsdVertexBufferSet struct OsdVertexBufferSet
{ {
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]]; const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]]; const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]]; const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]]; device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]];
#if !USE_PTVS_FACTORS #if !USE_PTVS_FACTORS
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]]; device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
#endif #endif
}; };
@ -323,11 +322,11 @@ OsdUnivar4x4(float u, thread float* B)
{ {
float t = u; float t = u;
float s = 1.0f - u; float s = 1.0f - u;
float A0 = s * s; float A0 = s * s;
float A1 = 2 * s * t; float A1 = 2 * s * t;
float A2 = t * t; float A2 = t * t;
B[0] = s * A0; B[0] = s * A0;
B[1] = t * A0 + s * A1; B[1] = t * A0 + s * A1;
B[2] = t * A1 + s * A2; B[2] = t * A1 + s * A2;
@ -413,9 +412,9 @@ OsdEvalBezier(float3 cp[16], float2 uv)
} }
bool OsdCullPerPatchVertex( bool OsdCullPerPatchVertex(
threadgroup PatchVertexType* patch, threadgroup PatchVertexType* patch,
float4x4 ModelViewMatrix float4x4 ModelViewMatrix
) )
{ {
#if OSD_ENABLE_BACKPATCH_CULL && OSD_PATCH_REGULAR #if OSD_ENABLE_BACKPATCH_CULL && OSD_PATCH_REGULAR
auto v0 = float3(ModelViewMatrix * patch[5].position); auto v0 = float3(ModelViewMatrix * patch[5].position);
@ -529,7 +528,7 @@ template<typename VertexType>
void void
OsdComputeBSplineBoundaryPoints(threadgroup VertexType* cpt, int3 patchParam) OsdComputeBSplineBoundaryPoints(threadgroup VertexType* cpt, int3 patchParam)
{ {
//APPL TODO - multithread this //APPL TODO - multithread this
int boundaryMask = OsdGetPatchBoundaryMask(patchParam); int boundaryMask = OsdGetPatchBoundaryMask(patchParam);
if ((boundaryMask & 1) != 0) { if ((boundaryMask & 1) != 0) {
@ -806,9 +805,6 @@ OsdComputeTessLevels(thread float4& tessOuterLo, thread float4& tessOuterHi,
tessLevelInner[1] = (combinedOuter[0] + combinedOuter[2]) * 0.5; tessLevelInner[1] = (combinedOuter[0] + combinedOuter[2]) * 0.5;
} }
float OsdComputeTessLevel(const float OsdTessLevel, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix, float3 p0, float3 p1) float OsdComputeTessLevel(const float OsdTessLevel, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix, float3 p0, float3 p1)
{ {
// Adaptive factor can be any computation that depends only on arg values. // Adaptive factor can be any computation that depends only on arg values.
@ -841,15 +837,6 @@ OsdGetTessLevelsUniform(const float OsdTessLevel, int3 patchParam,
float tessLevel = min(OsdTessLevel, ((float)OSD_MAX_TESS_LEVEL / 2)) / float tessLevel = min(OsdTessLevel, ((float)OSD_MAX_TESS_LEVEL / 2)) /
pow(2, refinementLevel - 1.0f); pow(2, refinementLevel - 1.0f);
// float tessLevel = min(OsdTessLevel, (float)OSD_MAX_TESS_LEVEL);
// if(refinementLevel != 0)
// tessLevel /= (1 << (refinementLevel - 1));
// else
// {
// tessLevel /= pow(2.0, (0 - 1));
// tessLevel /= pow(2.0, (refinementLevel - 1));
// }
// tessLevels of transition edge should be clamped to 2. // tessLevels of transition edge should be clamped to 2.
int transitionMask = OsdGetPatchTransitionMask(patchParam); int transitionMask = OsdGetPatchTransitionMask(patchParam);
float4 tessLevelMin = float4(1) float4 tessLevelMin = float4(1)
@ -858,22 +845,17 @@ OsdGetTessLevelsUniform(const float OsdTessLevel, int3 patchParam,
((transitionMask & 2) >> 1), ((transitionMask & 2) >> 1),
((transitionMask & 4) >> 2)); ((transitionMask & 4) >> 2));
// tessLevelMin = (tessLevelMin - 1.0) * 2.0f + 1.0;
// tessLevelMin = float4(OsdTessLevel);
tessOuterLo = max(float4(tessLevel,tessLevel,tessLevel,tessLevel), tessOuterLo = max(float4(tessLevel,tessLevel,tessLevel,tessLevel),
tessLevelMin); tessLevelMin);
tessOuterHi = float4(0,0,0,0); tessOuterHi = float4(0,0,0,0);
// tessOuterLo.x = refinementLevel;
} }
void void
OsdGetTessLevelsRefinedPoints(const float OsdTessLevel, OsdGetTessLevelsRefinedPoints(
const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix, const float OsdTessLevel,
float3 cp[16], int3 patchParam, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix,
thread float4& tessOuterLo, thread float4& tessOuterHi) float3 cp[16], int3 patchParam,
thread float4& tessOuterLo, thread float4& tessOuterHi)
{ {
// Each edge of a transition patch is adjacent to one or two patches // Each edge of a transition patch is adjacent to one or two patches
// at the next refined level of subdivision. We compute the corresponding // at the next refined level of subdivision. We compute the corresponding
@ -985,7 +967,7 @@ OsdGetTessLevelsLimitPoints(const float OsdTessLevel, const float4x4 OsdProjecti
tPt = &p12; tPt = &p12;
} }
tessOuterLo[0] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,p0, *tPt); tessOuterLo[0] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,p0, *tPt);
if ((transitionMask & 1) != 0) { // EV01 if ((transitionMask & 1) != 0) { // EV01
ev = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 0.0)); ev = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 0.0));
@ -997,7 +979,7 @@ OsdGetTessLevelsLimitPoints(const float OsdTessLevel, const float4x4 OsdProjecti
tPt = &p3; tPt = &p3;
} }
tessOuterLo[1] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,p0, *tPt); tessOuterLo[1] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,p0, *tPt);
if ((transitionMask & 2) != 0) { // EV12 if ((transitionMask & 2) != 0) { // EV12
ev = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.5)); ev = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.5));
@ -1009,7 +991,7 @@ OsdGetTessLevelsLimitPoints(const float OsdTessLevel, const float4x4 OsdProjecti
tPt = &p15; tPt = &p15;
} }
tessOuterLo[2] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,p3, *tPt); tessOuterLo[2] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,p3, *tPt);
if ((transitionMask & 4) != 0) { // EV23 if ((transitionMask & 4) != 0) { // EV23
ev = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 1.0)); ev = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 1.0));
@ -1037,8 +1019,6 @@ OsdGetTessLevelsLimitPoints(const float OsdTessLevel, const float4x4 OsdProjecti
float3 c12 = miniMul(OsdModelViewMatrix, cpBezier[12].P); float3 c12 = miniMul(OsdModelViewMatrix, cpBezier[12].P);
float3 c03 = miniMul(OsdModelViewMatrix, cpBezier[3].P); float3 c03 = miniMul(OsdModelViewMatrix, cpBezier[3].P);
float3 c15 = miniMul(OsdModelViewMatrix, cpBezier[15].P); float3 c15 = miniMul(OsdModelViewMatrix, cpBezier[15].P);
if ((transitionMask & 8) != 0) { if ((transitionMask & 8) != 0) {
tessOuterLo[0] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,c00, p0); tessOuterLo[0] = OsdComputeTessLevel(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,c00, p0);
@ -1068,44 +1048,55 @@ OsdGetTessLevelsLimitPoints(const float OsdTessLevel, const float4x4 OsdProjecti
} }
void void
OsdGetTessLevelsUniform(const float OsdTessLevel, int3 patchParam, OsdGetTessLevelsUniform(
thread float4& tessLevelOuter, thread float2& tessLevelInner, const float OsdTessLevel, int3 patchParam,
thread float4& tessOuterLo, thread float4& tessOuterHi) thread float4& tessLevelOuter, thread float2& tessLevelInner,
thread float4& tessOuterLo, thread float4& tessOuterHi)
{ {
OsdGetTessLevelsUniform(OsdTessLevel, patchParam, tessOuterLo, tessOuterHi); OsdGetTessLevelsUniform(OsdTessLevel, patchParam, tessOuterLo, tessOuterHi);
OsdComputeTessLevels(tessOuterLo, tessOuterHi, tessLevelOuter, tessLevelInner); OsdComputeTessLevels(tessOuterLo, tessOuterHi, tessLevelOuter, tessLevelInner);
} }
void void
OsdGetTessLevelsAdaptiveRefinedPoints(const float OsdTessLevel, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix, OsdGetTessLevelsAdaptiveRefinedPoints(
float3 cpRefined[16], int3 patchParam, const float OsdTessLevel,
thread float4& tessLevelOuter, thread float2& tessLevelInner, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix,
thread float4& tessOuterLo, thread float4& tessOuterHi) float3 cpRefined[16], int3 patchParam,
thread float4& tessLevelOuter, thread float2& tessLevelInner,
thread float4& tessOuterLo, thread float4& tessOuterHi)
{ {
OsdGetTessLevelsRefinedPoints(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cpRefined, patchParam, tessOuterLo, tessOuterHi); OsdGetTessLevelsRefinedPoints(
OsdTessLevel,
OsdProjectionMatrix, OsdModelViewMatrix,
cpRefined, patchParam, tessOuterLo, tessOuterHi);
OsdComputeTessLevels(tessOuterLo, tessOuterHi, OsdComputeTessLevels(tessOuterLo, tessOuterHi,
tessLevelOuter, tessLevelInner); tessLevelOuter, tessLevelInner);
} }
void void
OsdGetTessLevelsAdaptiveLimitPoints(const float OsdTessLevel, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix, OsdGetTessLevelsAdaptiveLimitPoints(
device OsdPerPatchVertexBezier* cpBezier, const float OsdTessLevel,
int3 patchParam, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix,
thread float4& tessLevelOuter, thread float2& tessLevelInner, device OsdPerPatchVertexBezier* cpBezier, int3 patchParam,
thread float4& tessOuterLo, thread float4& tessOuterHi) thread float4& tessLevelOuter, thread float2& tessLevelInner,
thread float4& tessOuterLo, thread float4& tessOuterHi)
{ {
OsdGetTessLevelsLimitPoints(OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cpBezier, patchParam, tessOuterLo, tessOuterHi); OsdGetTessLevelsLimitPoints(
OsdTessLevel,
OsdProjectionMatrix, OsdModelViewMatrix,
cpBezier, patchParam, tessOuterLo, tessOuterHi);
OsdComputeTessLevels(tessOuterLo, tessOuterHi, OsdComputeTessLevels(tessOuterLo, tessOuterHi,
tessLevelOuter, tessLevelInner); tessLevelOuter, tessLevelInner);
} }
void void
OsdGetTessLevels(const float OsdTessLevel, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix, OsdGetTessLevels(
float3 cp0, float3 cp1, float3 cp2, float3 cp3, const float OsdTessLevel,
int3 patchParam, const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix,
thread float4& tessLevelOuter, thread float2& tessLevelInner) float3 cp0, float3 cp1, float3 cp2, float3 cp3, int3 patchParam,
thread float4& tessLevelOuter, thread float2& tessLevelInner)
{ {
float4 tessOuterLo = float4(0,0,0,0); float4 tessOuterLo = float4(0,0,0,0);
float4 tessOuterHi = float4(0,0,0,0); float4 tessOuterHi = float4(0,0,0,0);
@ -1172,53 +1163,53 @@ float
OsdGetTessTransitionSplit(float t, float lo, float hi ) OsdGetTessTransitionSplit(float t, float lo, float hi )
{ {
#if OSD_FRACTIONAL_EVEN_SPACING #if OSD_FRACTIONAL_EVEN_SPACING
float loRoundUp = OsdRoundUpEven(lo); float loRoundUp = OsdRoundUpEven(lo);
float hiRoundUp = OsdRoundUpEven(hi); float hiRoundUp = OsdRoundUpEven(hi);
// Convert the parametric t into a segment index along the combined edge. // Convert the parametric t into a segment index along the combined edge.
float ti = round(t * (loRoundUp + hiRoundUp)); float ti = round(t * (loRoundUp + hiRoundUp));
if (ti <= loRoundUp) { if (ti <= loRoundUp) {
float t0 = ti / loRoundUp; float t0 = ti / loRoundUp;
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5; return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
} else { } else {
float t1 = (ti - loRoundUp) / hiRoundUp; float t1 = (ti - loRoundUp) / hiRoundUp;
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5; return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
} }
#elif OSD_FRACTIONAL_ODD_SPACING #elif OSD_FRACTIONAL_ODD_SPACING
float loRoundUp = OsdRoundUpOdd(lo); float loRoundUp = OsdRoundUpOdd(lo);
float hiRoundUp = OsdRoundUpOdd(hi); float hiRoundUp = OsdRoundUpOdd(hi);
// Convert the parametric t into a segment index along the combined edge. // Convert the parametric t into a segment index along the combined edge.
// The +1 below is to account for the extra segment produced by the // The +1 below is to account for the extra segment produced by the
// tessellator since the sum of two odd tess levels will be rounded // tessellator since the sum of two odd tess levels will be rounded
// up by one to the next odd integer tess level. // up by one to the next odd integer tess level.
float ti = (t * (loRoundUp + hiRoundUp + 1)); float ti = (t * (loRoundUp + hiRoundUp + 1));
OSD_UV_CORRECTION OSD_UV_CORRECTION
ti = round(ti); ti = round(ti);
if (ti <= loRoundUp) { if (ti <= loRoundUp) {
float t0 = ti / loRoundUp; float t0 = ti / loRoundUp;
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5; return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
} else if (ti > (loRoundUp+1)) { } else if (ti > (loRoundUp+1)) {
float t1 = (ti - (loRoundUp+1)) / hiRoundUp; float t1 = (ti - (loRoundUp+1)) / hiRoundUp;
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5; return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
} else { } else {
return 0.5; return 0.5;
} }
#else //OSD_FRACTIONAL_ODD_SPACING #else //OSD_FRACTIONAL_ODD_SPACING
// Convert the parametric t into a segment index along the combined edge. // Convert the parametric t into a segment index along the combined edge.
float ti = round(t * (lo + hi)); float ti = round(t * (lo + hi));
if (ti <= lo) { if (ti <= lo) {
return (ti / lo) * 0.5; return (ti / lo) * 0.5;
} else { } else {
return ((ti - lo) / hi) * 0.5 + 0.5; return ((ti - lo) / hi) * 0.5 + 0.5;
} }
#endif //OSD_FRACTIONAL_ODD_SPACING #endif //OSD_FRACTIONAL_ODD_SPACING
} }
@ -1226,28 +1217,21 @@ float2
OsdGetTessParameterization(float2 uv, float4 tessOuterLo, float4 tessOuterHi) OsdGetTessParameterization(float2 uv, float4 tessOuterLo, float4 tessOuterHi)
{ {
float2 UV = uv; float2 UV = uv;
if (UV.x == 0 && tessOuterHi[0] > 0) if (UV.x == 0 && tessOuterHi[0] > 0) {
{ UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]); } else
} if (UV.y == 0 && tessOuterHi[1] > 0) {
else if (UV.y == 0 && tessOuterHi[1] > 0) UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
{ } else
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]); if (UV.x == 1 && tessOuterHi[2] > 0) {
} UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[2], tessOuterHi[2]);
else if (UV.x == 1 && tessOuterHi[2] > 0) } else
{ if (UV.y == 1 && tessOuterHi[3] > 0) {
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[2], tessOuterHi[2]); UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[3], tessOuterHi[3]);
} }
else if (UV.y == 1 && tessOuterHi[3] > 0)
{
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[3], tessOuterHi[3]);
}
return UV; return UV;
} }
int4 OsdGetPatchCoord(int3 patchParam) int4 OsdGetPatchCoord(int3 patchParam)
{ {
int faceId = OsdGetPatchFaceId(patchParam); int faceId = OsdGetPatchFaceId(patchParam);
@ -1296,7 +1280,7 @@ constant float4x4 Mi(
float4(0.f, 0.f, 1.f, 0.f) float4(0.f, 0.f, 1.f, 0.f)
); );
float4x4 OsdComputeMs2(float sharpness, float factor) float4x4 OsdComputeMs2(float sharpness, float factor)
{ {
float s = exp2(sharpness); float s = exp2(sharpness);
@ -1308,34 +1292,31 @@ float4x4 OsdComputeMs2(float sharpness, float factor)
float ssub1 = s-1; float ssub1 = s-1;
float ssub1_2 = ssub1 * ssub1; float ssub1_2 = ssub1 * ssub1;
float div6 = 1.0/6.0; float div6 = 1.0/6.0;
float4x4 m( float4x4 m(
float4(0, s + 1 + 3*s2 - s3, 7*s - 2 - 6*s2 + 2*s3, sfrac1 * ssub1_2), float4(0, s + 1 + 3*s2 - s3, 7*s - 2 - 6*s2 + 2*s3, sfrac1 * ssub1_2),
float4(0, 1 + 2*s + s2, sx6m2 - 2*s2, ssub1_2), float4(0, 1 + 2*s + s2, sx6m2 - 2*s2, ssub1_2),
float4(0, 1+s, sx6m2, sfrac1), float4(0, 1+s, sx6m2, sfrac1),
float4(0, 1, sx6m2, 1)); float4(0, 1, sx6m2, 1));
m *= factor * (1/sx6); m *= factor * (1/sx6);
m[0][0] = div6 * factor; m[0][0] = div6 * factor;
return m; return m;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// BSpline // BSpline
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// convert BSpline cv to Bezier cv // convert BSpline cv to Bezier cv
template<typename VertexType> //VertexType should be some type that implements float3 VertexType::GetPosition() template<typename VertexType> //VertexType should be some type that implements float3 VertexType::GetPosition()
void OsdComputePerPatchVertexBSpline(int3 patchParam, unsigned ID, threadgroup VertexType* cv, device OsdPerPatchVertexBezier& result) void OsdComputePerPatchVertexBSpline(int3 patchParam, unsigned ID, threadgroup VertexType* cv, device OsdPerPatchVertexBezier& result)
{ {
int i = ID%4; int i = ID%4;
int j = ID/4; int j = ID/4;
#if OSD_PATCH_ENABLE_SINGLE_CREASE #if OSD_PATCH_ENABLE_SINGLE_CREASE
float3 P = float3(0,0,0); // 0 to 1-2^(-Sf) float3 P = float3(0,0,0); // 0 to 1-2^(-Sf)
@ -1362,7 +1343,7 @@ void OsdComputePerPatchVertexBSpline(int3 patchParam, unsigned ID, threadgroup V
float s1 = 1 - exp2(-Sc); float s1 = 1 - exp2(-Sc);
result.vSegments = float2(s0, s1); result.vSegments = float2(s0, s1);
#endif #endif
bool isBoundary[2]; bool isBoundary[2];
isBoundary[0] = (((boundaryMask & 8) != 0) || ((boundaryMask & 2) != 0)) ? true : false; isBoundary[0] = (((boundaryMask & 8) != 0) || ((boundaryMask & 2) != 0)) ? true : false;
isBoundary[1] = (((boundaryMask & 4) != 0) || ((boundaryMask & 1) != 0)) ? true : false; isBoundary[1] = (((boundaryMask & 4) != 0) || ((boundaryMask & 1) != 0)) ? true : false;
@ -1370,7 +1351,7 @@ void OsdComputePerPatchVertexBSpline(int3 patchParam, unsigned ID, threadgroup V
needsFlip[0] = (boundaryMask & 8) ? true : false; needsFlip[0] = (boundaryMask & 8) ? true : false;
needsFlip[1] = (boundaryMask & 1) ? true : false; needsFlip[1] = (boundaryMask & 1) ? true : false;
float3 Hi[4], Hj[4], Hs[4]; float3 Hi[4], Hj[4], Hs[4];
if (isBoundary[0]) if (isBoundary[0])
{ {
int t[4] = {0,1,2,3}; int t[4] = {0,1,2,3};
@ -1448,7 +1429,7 @@ void OsdComputePerPatchVertexBSpline(int3 patchParam, unsigned ID, threadgroup V
for (int k=0; k<4; ++k) { for (int k=0; k<4; ++k) {
P += Q[j][k]*Hi[k]; P += Q[j][k]*Hi[k];
} }
result.P = P; result.P = P;
result.P1 = P; result.P1 = P;
@ -2051,9 +2032,3 @@ OsdComputePerPatchVertexGregory(int3 patchParam, unsigned ID, unsigned primitive
} }
#endif // OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY #endif // OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY

View File

@ -29,23 +29,23 @@
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerVertex( void OsdComputePerVertex(
float4 position, float4 position,
threadgroup OsdPerVertexGregory& hullVertex, threadgroup OsdPerVertexGregory& hullVertex,
int vertexId, int vertexId,
float4x4 modelViewProjectionMatrix, float4x4 modelViewProjectionMatrix,
OsdPatchParamBufferSet osdBuffers OsdPatchParamBufferSet osdBuffers
) )
{ {
OsdComputePerVertexGregory(vertexId, position.xyz, hullVertex, osdBuffers); OsdComputePerVertexGregory(vertexId, position.xyz, hullVertex, osdBuffers);
#if OSD_ENABLE_PATCH_CULL #if OSD_ENABLE_PATCH_CULL
float4 clipPos = mul(modelViewProjectionMatrix, position); float4 clipPos = mul(modelViewProjectionMatrix, position);
short3 clip0 = short3(clipPos.x < clipPos.w, short3 clip0 = short3(clipPos.x < clipPos.w,
clipPos.y < clipPos.w, clipPos.y < clipPos.w,
clipPos.z < clipPos.w); clipPos.z < clipPos.w);
short3 clip1 = short3(clipPos.x > -clipPos.w, short3 clip1 = short3(clipPos.x > -clipPos.w,
clipPos.y > -clipPos.w, clipPos.y > -clipPos.w,
clipPos.z > -clipPos.w); clipPos.z > -clipPos.w);
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1); hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
#endif #endif
} }
@ -55,31 +55,31 @@ void OsdComputePerVertex(
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerPatchFactors( void OsdComputePerPatchFactors(
int3 patchParam, int3 patchParam,
float tessLevel, float tessLevel,
unsigned patchID, unsigned patchID,
float4x4 projectionMatrix, float4x4 projectionMatrix,
float4x4 modelViewMatrix, float4x4 modelViewMatrix,
OsdPatchParamBufferSet osdBuffer, OsdPatchParamBufferSet osdBuffer,
threadgroup PatchVertexType* patchVertices, threadgroup PatchVertexType* patchVertices,
device MTLQuadTessellationFactorsHalf& quadFactors device MTLQuadTessellationFactorsHalf& quadFactors
) )
{ {
float4 tessLevelOuter = float4(0,0,0,0); float4 tessLevelOuter = float4(0,0,0,0);
float2 tessLevelInner = float2(0,0); float2 tessLevelInner = float2(0,0);
OsdGetTessLevels( OsdGetTessLevels(
tessLevel, tessLevel,
projectionMatrix, projectionMatrix,
modelViewMatrix, modelViewMatrix,
patchVertices[0].P, patchVertices[0].P,
patchVertices[3].P, patchVertices[3].P,
patchVertices[2].P, patchVertices[2].P,
patchVertices[1].P, patchVertices[1].P,
patchParam, patchParam,
tessLevelOuter, tessLevelOuter,
tessLevelInner tessLevelInner
); );
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0]; quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1]; quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
@ -94,21 +94,21 @@ void OsdComputePerPatchFactors(
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerPatchVertex( void OsdComputePerPatchVertex(
int3 patchParam, int3 patchParam,
unsigned ID, unsigned ID,
unsigned PrimitiveID, unsigned PrimitiveID,
unsigned ControlID, unsigned ControlID,
threadgroup PatchVertexType* patchVertices, threadgroup PatchVertexType* patchVertices,
OsdPatchParamBufferSet osdBuffers OsdPatchParamBufferSet osdBuffers
) )
{ {
OsdComputePerPatchVertexGregory( OsdComputePerPatchVertexGregory(
patchParam, patchParam,
ID, ID,
PrimitiveID, PrimitiveID,
patchVertices, patchVertices,
osdBuffers.perPatchVertexBuffer[ControlID], osdBuffers.perPatchVertexBuffer[ControlID],
osdBuffers); osdBuffers);
} }
//---------------------------------------------------------- //----------------------------------------------------------
@ -117,43 +117,43 @@ void OsdComputePerPatchVertex(
template<typename PerPatchVertexGregory> template<typename PerPatchVertexGregory>
OsdPatchVertex ds_gregory_patches( OsdPatchVertex ds_gregory_patches(
PerPatchVertexGregory patch, PerPatchVertexGregory patch,
int3 patchParam, int3 patchParam,
float2 UV float2 UV
) )
{ {
OsdPatchVertex output; OsdPatchVertex output;
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0); float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0); float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
float3 cv[20]; float3 cv[20];
cv[0] = patch[0].P; cv[0] = patch[0].P;
cv[1] = patch[0].Ep; cv[1] = patch[0].Ep;
cv[2] = patch[0].Em; cv[2] = patch[0].Em;
cv[3] = patch[0].Fp; cv[3] = patch[0].Fp;
cv[4] = patch[0].Fm; cv[4] = patch[0].Fm;
cv[5] = patch[1].P; cv[5] = patch[1].P;
cv[6] = patch[1].Ep; cv[6] = patch[1].Ep;
cv[7] = patch[1].Em; cv[7] = patch[1].Em;
cv[8] = patch[1].Fp; cv[8] = patch[1].Fp;
cv[9] = patch[1].Fm; cv[9] = patch[1].Fm;
cv[10] = patch[2].P; cv[10] = patch[2].P;
cv[11] = patch[2].Ep; cv[11] = patch[2].Ep;
cv[12] = patch[2].Em; cv[12] = patch[2].Em;
cv[13] = patch[2].Fp; cv[13] = patch[2].Fp;
cv[14] = patch[2].Fm; cv[14] = patch[2].Fm;
cv[15] = patch[3].P; cv[15] = patch[3].P;
cv[16] = patch[3].Ep; cv[16] = patch[3].Ep;
cv[17] = patch[3].Em; cv[17] = patch[3].Em;
cv[18] = patch[3].Fp; cv[18] = patch[3].Fp;
cv[19] = patch[3].Fm; cv[19] = patch[3].Fm;
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv); OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
// all code below here is client code // all code below here is client code
output.position = P; output.position = P;
output.normal = N; output.normal = N;
@ -165,7 +165,7 @@ OsdPatchVertex ds_gregory_patches(
#endif #endif
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam); output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
return output; return output;
} }
@ -173,23 +173,23 @@ OsdPatchVertex ds_gregory_patches(
template<typename PerPatchVertexGregoryBasis> template<typename PerPatchVertexGregoryBasis>
#endif #endif
OsdPatchVertex OsdComputePatch( OsdPatchVertex OsdComputePatch(
float tessLevel, float tessLevel,
float2 domainCoord, float2 domainCoord,
unsigned patchID, unsigned patchID,
#if USE_STAGE_IN #if USE_STAGE_IN
PerPatchVertexGregoryBasis osdPatch PerPatchVertexGregoryBasis osdPatch
#else #else
OsdVertexBufferSet osdBuffers OsdVertexBufferSet osdBuffers
#endif #endif
) )
{ {
return ds_gregory_patches( return ds_gregory_patches(
#if USE_STAGE_IN #if USE_STAGE_IN
osdPatch.cv, osdPatch.cv,
osdPatch.patchParam, osdPatch.patchParam,
#else #else
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH, osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
osdBuffers.patchParamBuffer[patchID], osdBuffers.patchParamBuffer[patchID],
#endif #endif
domainCoord); domainCoord);
} }

View File

@ -29,23 +29,23 @@
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerVertex( void OsdComputePerVertex(
float4 position, float4 position,
threadgroup HullVertex& hullVertex, threadgroup HullVertex& hullVertex,
int vertexId, int vertexId,
float4x4 modelViewProjectionMatrix, float4x4 modelViewProjectionMatrix,
OsdPatchParamBufferSet osdBuffers OsdPatchParamBufferSet osdBuffers
) )
{ {
hullVertex.position = position; hullVertex.position = position;
#if OSD_ENABLE_PATCH_CULL #if OSD_ENABLE_PATCH_CULL
float4 clipPos = mul(modelViewProjectionMatrix, position); float4 clipPos = mul(modelViewProjectionMatrix, position);
short3 clip0 = short3(clipPos.x < clipPos.w, short3 clip0 = short3(clipPos.x < clipPos.w,
clipPos.y < clipPos.w, clipPos.y < clipPos.w,
clipPos.z < clipPos.w); clipPos.z < clipPos.w);
short3 clip1 = short3(clipPos.x > -clipPos.w, short3 clip1 = short3(clipPos.x > -clipPos.w,
clipPos.y > -clipPos.w, clipPos.y > -clipPos.w,
clipPos.z > -clipPos.w); clipPos.z > -clipPos.w);
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1); hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
#endif #endif
} }
@ -54,31 +54,31 @@ void OsdComputePerVertex(
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerPatchFactors( void OsdComputePerPatchFactors(
int3 patchParam, int3 patchParam,
float tessLevel, float tessLevel,
unsigned patchID, unsigned patchID,
float4x4 projectionMatrix, float4x4 projectionMatrix,
float4x4 modelViewMatrix, float4x4 modelViewMatrix,
OsdPatchParamBufferSet osdBuffer, OsdPatchParamBufferSet osdBuffer,
threadgroup PatchVertexType* patchVertices, threadgroup PatchVertexType* patchVertices,
device MTLQuadTessellationFactorsHalf& quadFactors device MTLQuadTessellationFactorsHalf& quadFactors
) )
{ {
float4 tessLevelOuter = float4(0,0,0,0); float4 tessLevelOuter = float4(0,0,0,0);
float2 tessLevelInner = float2(0,0); float2 tessLevelInner = float2(0,0);
OsdGetTessLevels( OsdGetTessLevels(
tessLevel, tessLevel,
projectionMatrix, projectionMatrix,
modelViewMatrix, modelViewMatrix,
patchVertices[0].position.xyz, patchVertices[0].position.xyz,
patchVertices[3].position.xyz, patchVertices[3].position.xyz,
patchVertices[2].position.xyz, patchVertices[2].position.xyz,
patchVertices[1].position.xyz, patchVertices[1].position.xyz,
patchParam, patchParam,
tessLevelOuter, tessLevelOuter,
tessLevelInner tessLevelInner
); );
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0]; quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1]; quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
@ -93,15 +93,15 @@ void OsdComputePerPatchFactors(
//---------------------------------------------------------- //----------------------------------------------------------
void OsdComputePerPatchVertex( void OsdComputePerPatchVertex(
int3 patchParam, int3 patchParam,
unsigned ID, unsigned ID,
unsigned PrimitiveID, unsigned PrimitiveID,
unsigned ControlID, unsigned ControlID,
threadgroup PatchVertexType* patchVertices, threadgroup PatchVertexType* patchVertices,
OsdPatchParamBufferSet osdBuffers OsdPatchParamBufferSet osdBuffers
) )
{ {
//Does nothing, all transforms are in the PTVS //Does nothing, all transforms are in the PTVS
} }
@ -116,31 +116,30 @@ void OsdComputePerPatchVertex(
template<typename PerPatchVertexGregoryBasis> template<typename PerPatchVertexGregoryBasis>
#endif #endif
OsdPatchVertex ds_gregory_basis_patches( OsdPatchVertex ds_gregory_basis_patches(
#if USE_STAGE_IN #if USE_STAGE_IN
PerPatchVertexGregoryBasis patch, PerPatchVertexGregoryBasis patch,
#else #else
const device OsdInputVertexType* patch, const device OsdInputVertexType* patch,
const device unsigned* patchIndices, const device unsigned* patchIndices,
#endif #endif
int3 patchParam, int3 patchParam,
float2 UV float2 UV
) )
{ {
OsdPatchVertex output; OsdPatchVertex output;
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0); float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0); float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
#if USE_STAGE_IN #if USE_STAGE_IN
float3 cv[20]; float3 cv[20];
for(int i = 0; i < 20; i++) for(int i = 0; i < 20; i++)
cv[i] = patch[i].position; cv[i] = patch[i].position;
#else #else
#if USE_128BIT_GREGORY_BASIS_INDICES_READ #if USE_128BIT_GREGORY_BASIS_INDICES_READ
float3 cv[20]; float3 cv[20];
for(int i = 0; i < 5; i++) { for(int i = 0; i < 5; i++) {
int4 indices = ((device int4*)patchIndices)[i]; int4 indices = ((device int4*)patchIndices)[i];
int n = i * 4; int n = i * 4;
cv[n + 0] = (patch + indices[0])->position; cv[n + 0] = (patch + indices[0])->position;
cv[n + 1] = (patch + indices[1])->position; cv[n + 1] = (patch + indices[1])->position;
@ -154,9 +153,9 @@ OsdPatchVertex ds_gregory_basis_patches(
} }
#endif #endif
#endif #endif
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv); OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
output.position = P; output.position = P;
output.normal = N; output.normal = N;
output.tangent = dPu; output.tangent = dPu;
@ -165,9 +164,9 @@ OsdPatchVertex ds_gregory_basis_patches(
output.Nu = dNu; output.Nu = dNu;
output.Nv = dNv; output.Nv = dNv;
#endif #endif
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam); output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
return output; return output;
} }
@ -175,25 +174,25 @@ OsdPatchVertex ds_gregory_basis_patches(
template<typename PerPatchVertexGregoryBasis> template<typename PerPatchVertexGregoryBasis>
#endif #endif
OsdPatchVertex OsdComputePatch( OsdPatchVertex OsdComputePatch(
float tessLevel, float tessLevel,
float2 domainCoord, float2 domainCoord,
unsigned patchID, unsigned patchID,
#if USE_STAGE_IN #if USE_STAGE_IN
PerPatchVertexGregoryBasis osdPatch PerPatchVertexGregoryBasis osdPatch
#else #else
OsdVertexBufferSet osdBuffers OsdVertexBufferSet osdBuffers
#endif #endif
) )
{ {
return ds_gregory_basis_patches( return ds_gregory_basis_patches(
#if USE_STAGE_IN #if USE_STAGE_IN
osdPatch.cv, osdPatch.cv,
osdPatch.patchParam, osdPatch.patchParam,
#else #else
osdBuffers.vertexBuffer, osdBuffers.vertexBuffer,
osdBuffers.indexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH, osdBuffers.indexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
osdBuffers.patchParamBuffer[patchID], osdBuffers.patchParamBuffer[patchID],
#endif #endif
domainCoord domainCoord
); );
} }

View File

@ -22,36 +22,39 @@
// language governing permissions and limitations under the Apache License. // language governing permissions and limitations under the Apache License.
// //
#pragma once #ifndef OPENSUBDIV3_OSD_MTL_PATCH_SHADER_SOURCE_H
#define OPENSUBDIV3_OSD_MTL_PATCH_SHADER_SOURCE_H
#import <string> #import <string>
#import "../version.h" #import "../version.h"
#import "../far/patchDescriptor.h" #import "../far/patchDescriptor.h"
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Osd {
class MTLPatchShaderSource {
public:
static std::string GetCommonShaderSource();
static std::string GetPatchBasisShaderSource(); namespace Osd {
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type, class MTLPatchShaderSource {
Far::PatchDescriptor::Type fvarType); public:
static std::string GetCommonShaderSource();
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type,
Far::PatchDescriptor::Type fvarType); static std::string GetPatchBasisShaderSource();
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type, static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type,
Far::PatchDescriptor::Type fvarType); Far::PatchDescriptor::Type fvarType);
};
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type,
} // end namespace Osd Far::PatchDescriptor::Type fvarType);
} // end namespace OPENSUBDIV_VERSION static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type,
using namespace OPENSUBDIV_VERSION; Far::PatchDescriptor::Type fvarType);
};
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv } // end namespace OpenSubdiv
#endif // OPENSUBDIV3_OSD_MTL_PATCH_SHADER_SOURCE

View File

@ -30,127 +30,131 @@
#include <TargetConditionals.h> #include <TargetConditionals.h>
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Osd { namespace Osd {
static std::string commonShaderSource( static std::string commonShaderSource(
#include "mtlPatchCommon.gen.h" #include "mtlPatchCommon.gen.h"
); );
static std::string patchBasisTypesShaderSource( static std::string patchBasisTypesShaderSource(
#include "patchBasisCommonTypes.gen.h" #include "patchBasisCommonTypes.gen.h"
); );
static std::string patchBasisShaderSource( static std::string patchBasisShaderSource(
#include "patchBasisCommon.gen.h" #include "patchBasisCommon.gen.h"
); );
static std::string patchBasisEvalShaderSource( static std::string patchBasisEvalShaderSource(
#include "patchBasisCommonEval.gen.h" #include "patchBasisCommonEval.gen.h"
); );
static std::string bsplineShaderSource( static std::string bsplineShaderSource(
#include "mtlPatchBSpline.gen.h" #include "mtlPatchBSpline.gen.h"
); );
static std::string gregoryShaderSource( static std::string gregoryShaderSource(
#include "mtlPatchGregory.gen.h" #include "mtlPatchGregory.gen.h"
); );
static std::string gregoryBasisShaderSource( static std::string gregoryBasisShaderSource(
#include "mtlPatchGregoryBasis.gen.h" #include "mtlPatchGregoryBasis.gen.h"
); );
static std::string GetPatchTypeDefine(Far::PatchDescriptor::Type type, static std::string
Far::PatchDescriptor::Type fvarType) { GetPatchTypeDefine(Far::PatchDescriptor::Type type,
std::stringstream ss; Far::PatchDescriptor::Type fvarType) {
switch(type) {
case Far::PatchDescriptor::LINES: ss << "#define OSD_PATCH_LINES 1\n"; break;
case Far::PatchDescriptor::TRIANGLES: ss << "#define OSD_PATCH_TRIANGLES 1\n"; break;
case Far::PatchDescriptor::QUADS: ss << "#define OSD_PATCH_QUADS 1\n"; break;
case Far::PatchDescriptor::REGULAR: ss << "#define OSD_PATCH_BSPLINE 1\n#define OSD_PATCH_REGULAR 1\n"; break;
case Far::PatchDescriptor::GREGORY: ss << "#define OSD_PATCH_GREGORY 1\n"; break;
case Far::PatchDescriptor::GREGORY_BOUNDARY: ss << "#define OSD_PATCH_GREGORY_BOUNDRY 1\n"; break;
case Far::PatchDescriptor::GREGORY_BASIS: ss << "#define OSD_PATCH_GREGORY_BASIS 1\n"; break;
default:
assert("Unknown Far::PatchDescriptor::Type" && 0);
return "";
}
switch(fvarType) {
case Far::PatchDescriptor::REGULAR: ss << "#define OSD_FACEVARYING_PATCH_REGULAR 1\n"; break;
case Far::PatchDescriptor::GREGORY_BASIS: ss << "#define OSD_FACEVARYING_PATCH_GREGORY_BASIS 1\n"; break;
default:
return ss.str();
}
return ss.str();
}
static std::string GetPatchTypeSource(Far::PatchDescriptor::Type type) { std::stringstream ss;
switch(type) { switch(type) {
case Far::PatchDescriptor::QUADS: return ""; case Far::PatchDescriptor::LINES: ss << "#define OSD_PATCH_LINES 1\n"; break;
case Far::PatchDescriptor::REGULAR: return bsplineShaderSource; case Far::PatchDescriptor::TRIANGLES: ss << "#define OSD_PATCH_TRIANGLES 1\n"; break;
case Far::PatchDescriptor::GREGORY: return gregoryShaderSource; case Far::PatchDescriptor::QUADS: ss << "#define OSD_PATCH_QUADS 1\n"; break;
case Far::PatchDescriptor::GREGORY_BOUNDARY: return gregoryShaderSource; case Far::PatchDescriptor::REGULAR: ss << "#define OSD_PATCH_BSPLINE 1\n#define OSD_PATCH_REGULAR 1\n"; break;
case Far::PatchDescriptor::GREGORY_BASIS: return gregoryBasisShaderSource; case Far::PatchDescriptor::GREGORY: ss << "#define OSD_PATCH_GREGORY 1\n"; break;
default: case Far::PatchDescriptor::GREGORY_BOUNDARY: ss << "#define OSD_PATCH_GREGORY_BOUNDRY 1\n"; break;
assert("Unknown Far::PatchDescriptor::Type" && 0); case Far::PatchDescriptor::GREGORY_BASIS: ss << "#define OSD_PATCH_GREGORY_BASIS 1\n"; break;
return ""; default:
} assert("Unknown Far::PatchDescriptor::Type" && 0);
} return "";
}
/*static*/ switch(fvarType) {
std::string case Far::PatchDescriptor::REGULAR: ss << "#define OSD_FACEVARYING_PATCH_REGULAR 1\n"; break;
MTLPatchShaderSource::GetCommonShaderSource() { case Far::PatchDescriptor::GREGORY_BASIS: ss << "#define OSD_FACEVARYING_PATCH_GREGORY_BASIS 1\n"; break;
#if TARGET_OS_IOS || TARGET_OS_TV default:
return std::string("#define OSD_METAL_IOS 1\n").append(commonShaderSource); return ss.str();
#elif TARGET_OS_OSX }
return std::string("#define OSD_METAL_OSX 1\n").append(commonShaderSource); return ss.str();
#endif }
}
/*static*/ static std::string
std::string GetPatchTypeSource(Far::PatchDescriptor::Type type) {
MTLPatchShaderSource::GetPatchBasisShaderSource() {
std::stringstream ss; switch(type) {
ss << "#define OSD_PATCH_BASIS_METAL 1\n"; case Far::PatchDescriptor::QUADS: return "";
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES) case Far::PatchDescriptor::REGULAR: return bsplineShaderSource;
ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES 1\n"; case Far::PatchDescriptor::GREGORY: return gregoryShaderSource;
case Far::PatchDescriptor::GREGORY_BOUNDARY: return gregoryShaderSource;
case Far::PatchDescriptor::GREGORY_BASIS: return gregoryBasisShaderSource;
default:
assert("Unknown Far::PatchDescriptor::Type" && 0);
return "";
}
}
/*static*/
std::string
MTLPatchShaderSource::GetCommonShaderSource() {
#if TARGET_OS_IOS || TARGET_OS_TV
return std::string("#define OSD_METAL_IOS 1\n").append(commonShaderSource);
#elif TARGET_OS_OSX
return std::string("#define OSD_METAL_OSX 1\n").append(commonShaderSource);
#endif #endif
ss << patchBasisTypesShaderSource; }
ss << patchBasisShaderSource;
ss << patchBasisEvalShaderSource; /*static*/
return ss.str(); std::string
} MTLPatchShaderSource::GetPatchBasisShaderSource() {
std::stringstream ss;
/*static*/ ss << "#define OSD_PATCH_BASIS_METAL 1\n";
std::string #if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type, ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES 1\n";
Far::PatchDescriptor::Type fvarType) { #endif
std::stringstream ss; ss << patchBasisTypesShaderSource;
ss << GetPatchTypeDefine(type, fvarType); ss << patchBasisShaderSource;
ss << GetCommonShaderSource(); ss << patchBasisEvalShaderSource;
ss << GetPatchTypeSource(type); return ss.str();
return ss.str(); }
}
/*static*/
/*static*/ std::string
std::string MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type,
MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type, Far::PatchDescriptor::Type fvarType) {
Far::PatchDescriptor::Type fvarType) { std::stringstream ss;
std::stringstream ss; ss << GetPatchTypeDefine(type, fvarType);
ss << GetPatchTypeDefine(type, fvarType); ss << GetCommonShaderSource();
ss << GetCommonShaderSource(); ss << GetPatchTypeSource(type);
ss << GetPatchTypeSource(type); return ss.str();
return ss.str(); }
}
/*static*/
/*static*/ std::string
std::string MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type,
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type, Far::PatchDescriptor::Type fvarType) {
Far::PatchDescriptor::Type fvarType) { std::stringstream ss;
std::stringstream ss; ss << GetPatchTypeDefine(type, fvarType);
ss << GetPatchTypeDefine(type, fvarType); ss << GetCommonShaderSource();
ss << GetCommonShaderSource(); ss << GetPatchTypeSource(type);
ss << GetPatchTypeSource(type); return ss.str();
return ss.str(); }
}
/*static*/
} // end namespace Osd std::string
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type,
} // end namespace OPENSUBDIV_VERSION Far::PatchDescriptor::Type fvarType) {
} // end namespace OpenSubdiv std::stringstream ss;
ss << GetPatchTypeDefine(type, fvarType);
ss << GetCommonShaderSource();
ss << GetPatchTypeSource(type);
return ss.str();
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -34,65 +34,64 @@
@protocol MTLDevice; @protocol MTLDevice;
@protocol MTLBuffer; @protocol MTLBuffer;
namespace OpenSubdiv namespace OpenSubdiv {
{ namespace OPENSUBDIV_VERSION {
namespace OPENSUBDIV_VERSION
namespace Far {
class PatchTable;
};
namespace Osd {
class MTLPatchTable : private NonCopyable<MTLPatchTable> {
public:
typedef id<MTLBuffer> VertexBufferBinding;
MTLPatchTable();
~MTLPatchTable();
template<typename DEVICE_CONTEXT>
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context)
{ {
namespace Far return Create(farPatchTable, context);
{ }
class PatchTable;
}
namespace Osd static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, MTLContext* context);
{
class MTLPatchTable : private NonCopyable<MTLPatchTable>
{
public:
typedef id<MTLBuffer> VertexBufferBinding;
MTLPatchTable(); PatchArrayVector const &GetPatchArrays() const { return _patchArrays; }
~MTLPatchTable(); id<MTLBuffer> GetPatchIndexBuffer() const { return _indexBuffer; }
id<MTLBuffer> GetPatchParamBuffer() const { return _patchParamBuffer; }
template<typename DEVICE_CONTEXT> PatchArrayVector const &GetVaryingPatchArrays() const { return _varyingPatchArrays; }
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context) id<MTLBuffer> GetVaryingPatchIndexBuffer() const { return _varyingPatchIndexBuffer; }
{
return Create(farPatchTable, context);
}
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, MTLContext* context); int GetNumFVarChannels() const { return (int)_fvarPatchArrays.size(); }
PatchArrayVector const &GetFVarPatchArrays(int fvarChannel = 0) const { return _fvarPatchArrays[fvarChannel]; }
id<MTLBuffer> GetFVarPatchIndexBuffer(int fvarChannel = 0) const { return _fvarIndexBuffers[fvarChannel]; }
id<MTLBuffer> GetFVarPatchParamBuffer(int fvarChannel = 0) const { return _fvarParamBuffers[fvarChannel]; }
PatchArrayVector const &GetPatchArrays() const { return _patchArrays; } protected:
id<MTLBuffer> GetPatchIndexBuffer() const { return _indexBuffer; } bool allocate(Far::PatchTable const *farPatchTable, MTLContext* context);
id<MTLBuffer> GetPatchParamBuffer() const { return _patchParamBuffer; }
PatchArrayVector const &GetVaryingPatchArrays() const { return _varyingPatchArrays; } PatchArrayVector _patchArrays;
id<MTLBuffer> GetVaryingPatchIndexBuffer() const { return _varyingPatchIndexBuffer; }
int GetNumFVarChannels() const { return (int)_fvarPatchArrays.size(); } id<MTLBuffer> _indexBuffer;
PatchArrayVector const &GetFVarPatchArrays(int fvarChannel = 0) const { return _fvarPatchArrays[fvarChannel]; } id<MTLBuffer> _patchParamBuffer;
id<MTLBuffer> GetFVarPatchIndexBuffer(int fvarChannel = 0) const { return _fvarIndexBuffers[fvarChannel]; }
id<MTLBuffer> GetFVarPatchParamBuffer(int fvarChannel = 0) const { return _fvarParamBuffers[fvarChannel]; }
protected: PatchArrayVector _varyingPatchArrays;
bool allocate(Far::PatchTable const *farPatchTable, MTLContext* context);
PatchArrayVector _patchArrays; id<MTLBuffer> _varyingPatchIndexBuffer;
id<MTLBuffer> _indexBuffer;
id<MTLBuffer> _patchParamBuffer;
PatchArrayVector _varyingPatchArrays; std::vector<PatchArrayVector> _fvarPatchArrays;
std::vector<id<MTLBuffer>> _fvarIndexBuffers;
std::vector<id<MTLBuffer>> _fvarParamBuffers;
};
id<MTLBuffer> _varyingPatchIndexBuffer; } // end namespace Osd
std::vector<PatchArrayVector> _fvarPatchArrays; } //end namespace OPENSUBDIV_VERSION
std::vector<id<MTLBuffer>> _fvarIndexBuffers; using namespace OPENSUBDIV_VERSION;
std::vector<id<MTLBuffer>> _fvarParamBuffers;
};
} // end namespace Osd
} //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSubdiv } //end namespace OpenSubdiv
#endif //end OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H #endif //end OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H

View File

@ -29,6 +29,7 @@
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Osd { namespace Osd {
MTLPatchTable::MTLPatchTable() MTLPatchTable::MTLPatchTable()
@ -43,7 +44,7 @@ _varyingPatchIndexBuffer(nil)
MTLPatchTable::~MTLPatchTable() MTLPatchTable::~MTLPatchTable()
{ {
} }
static id<MTLBuffer> createBuffer(const void* data, const size_t length, static id<MTLBuffer> createBuffer(const void* data, const size_t length,
@ -97,7 +98,7 @@ bool MTLPatchTable::allocate(Far::PatchTable const *farPatchTable, MTLContext* c
auto patchParamSize = cpuTable.GetPatchParamSize(); auto patchParamSize = cpuTable.GetPatchParamSize();
_patchArrays.assign(cpuTable.GetPatchArrayBuffer(), cpuTable.GetPatchArrayBuffer() + numPatchArrays); _patchArrays.assign(cpuTable.GetPatchArrayBuffer(), cpuTable.GetPatchArrayBuffer() + numPatchArrays);
_indexBuffer = createBuffer(cpuTable.GetPatchIndexBuffer(), indexSize * sizeof(unsigned), context); _indexBuffer = createBuffer(cpuTable.GetPatchIndexBuffer(), indexSize * sizeof(unsigned), context);
if(_indexBuffer == nil) if(_indexBuffer == nil)
return false; return false;
@ -130,7 +131,7 @@ bool MTLPatchTable::allocate(Far::PatchTable const *farPatchTable, MTLContext* c
_fvarParamBuffers[fvc] = createBuffer(cpuTable.GetFVarPatchParamBuffer(fvc), cpuTable.GetFVarPatchParamSize(fvc) * sizeof(PatchParam), context); _fvarParamBuffers[fvc] = createBuffer(cpuTable.GetFVarPatchParamBuffer(fvc), cpuTable.GetFVarPatchParamSize(fvc) * sizeof(PatchParam), context);
if(_fvarParamBuffers[fvc] == nil) if(_fvarParamBuffers[fvc] == nil)
return false; return false;
} }
return true; return true;

View File

@ -31,54 +31,53 @@
@protocol MTLDevice; @protocol MTLDevice;
@protocol MTLBuffer; @protocol MTLBuffer;
namespace OpenSubdiv namespace OpenSubdiv {
{ namespace OPENSUBDIV_VERSION {
namespace OPENSUBDIV_VERSION
{ namespace Osd {
namespace Osd
{ class CPUMTLVertexBuffer {
class CPUMTLVertexBuffer public:
static CPUMTLVertexBuffer* Create(int numElements, int numVertices, MTLContext* context);
void UpdateData(const float* src, int startVertex, int numVertices, MTLContext* context);
int GetNumElements() const
{ {
public: return _numElements;
static CPUMTLVertexBuffer* Create(int numElements, int numVertices, MTLContext* context); }
void UpdateData(const float* src, int startVertex, int numVertices, MTLContext* context); int GetNumVertices() const
{
return _numVertices;
}
int GetNumElements() const float* BindCpuBuffer();
{ id<MTLBuffer> BindMTLBuffer(MTLContext* context);
return _numElements;
}
int GetNumVertices() const id<MTLBuffer> BindVBO(MTLContext* context)
{ {
return _numVertices; return BindMTLBuffer(context);
} }
float* BindCpuBuffer(); protected:
id<MTLBuffer> BindMTLBuffer(MTLContext* context);
id<MTLBuffer> BindVBO(MTLContext* context) CPUMTLVertexBuffer(int numElements, int numVertices);
{
return BindMTLBuffer(context);
}
protected: bool allocate(MTLContext* context);
CPUMTLVertexBuffer(int numElements, int numVertices); private:
int _numElements;
bool allocate(MTLContext* context); int _numVertices;
id<MTLBuffer> _buffer;
private: bool _dirty;
int _numElements; };
int _numVertices;
id<MTLBuffer> _buffer;
bool _dirty;
};
} //end namespace Osd } //end namespace Osd
} //end namespace OPENSUBDIV_VERSION } //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION; using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSubdiv } //end namespace OpenSubdiv
#endif // OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H #endif // OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H

View File

@ -26,12 +26,11 @@
#include <Metal/Metal.h> #include <Metal/Metal.h>
#include <TargetConditionals.h> #include <TargetConditionals.h>
namespace OpenSubdiv namespace OpenSubdiv {
{ namespace OPENSUBDIV_VERSION {
namespace OPENSUBDIV_VERSION
{ namespace Osd {
namespace Osd
{
CPUMTLVertexBuffer::CPUMTLVertexBuffer(int numElements, int numVertices) CPUMTLVertexBuffer::CPUMTLVertexBuffer(int numElements, int numVertices)
: :
_numElements(numElements), _numVertices(numVertices), _numElements(numElements), _numVertices(numVertices),
@ -83,7 +82,7 @@ float* CPUMTLVertexBuffer::BindCpuBuffer()
id<MTLBuffer> CPUMTLVertexBuffer::BindMTLBuffer(MTLContext* context) id<MTLBuffer> CPUMTLVertexBuffer::BindMTLBuffer(MTLContext* context)
{ {
#if TARGET_OS_OSX #if TARGET_OS_OSX
if(_dirty) if(_dirty)
[_buffer didModifyRange:NSMakeRange(0, _buffer.length)]; [_buffer didModifyRange:NSMakeRange(0, _buffer.length)];
_dirty = false; _dirty = false;
#endif #endif
@ -93,6 +92,6 @@ id<MTLBuffer> CPUMTLVertexBuffer::BindMTLBuffer(MTLContext* context)
} //end namepsace Osd } //end namepsace Osd
} //end namespace OPENSUBDIV_VERSION } //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSubdiv } //end namespace OpenSubdiv