diff --git a/examples/mtlViewer/mtlViewer.metal b/examples/mtlViewer/mtlViewer.metal index 95c782b9..c0693ec1 100644 --- a/examples/mtlViewer/mtlViewer.metal +++ b/examples/mtlViewer/mtlViewer.metal @@ -183,6 +183,8 @@ getAdaptivePatchColor(int3 patchParam patchType = 5; #elif OSD_PATCH_GREGORY_BASIS patchType = 6; +#elif OSD_PATCH_GREGORY_TRIANGLE + patchType = 6; #endif int pattern = popcount(OsdGetPatchTransitionMask(patchParam)); @@ -205,7 +207,7 @@ getAdaptiveDepthColor(int3 patchParam) #if OSD_IS_ADAPTIVE #if USE_STAGE_IN -#if OSD_PATCH_REGULAR +#if OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE struct ControlPoint { float3 P [[attribute(0)]]; @@ -226,7 +228,7 @@ struct ControlPoint float3 Fp [[attribute(3)]]; float3 Fm [[attribute(4)]]; }; -#elif OSD_PATCH_GREGORY_BASIS +#elif OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE struct ControlPoint { float3 position [[attribute(0)]]; @@ -244,6 +246,13 @@ struct PatchInput }; #endif +#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY +typedef MTLQuadTessellationFactorsHalf PatchTessFactors; +#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE +typedef MTLTriangleTessellationFactorsHalf PatchTessFactors; +#endif + + //---------------------------------------------------------- // OSD Kernel //---------------------------------------------------------- @@ -256,7 +265,7 @@ kernel void compute_main( unsigned thread_position_in_threadgroup [[thread_position_in_threadgroup]], unsigned threadgroup_position_in_grid [[threadgroup_position_in_grid]], OsdPatchParamBufferSet osdBuffers, //This struct contains all of the buffers needed by OSD - device MTLQuadTessellationFactorsHalf* patchTessellationFactors [[buffer(PATCH_TESSFACTORS_INDEX)]] + device PatchTessFactors* patchTessellationFactors [[buffer(PATCH_TESSFACTORS_INDEX)]] #if OSD_USE_PATCH_INDEX_BUFFER ,device unsigned* patchIndex [[buffer(OSD_PATCH_INDEX_BUFFER_INDEX)]] ,device MTLDrawPatchIndirectArguments* drawIndirectCommands [[buffer(OSD_DRAWINDIRECT_BUFFER_INDEX)]] @@ -318,12 +327,19 @@ kernel void compute_main( if (!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix)) { #if !OSD_USE_PATCH_INDEX_BUFFER +#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY patchTessellationFactors[primitiveID].edgeTessellationFactor[0] = 0.0h; patchTessellationFactors[primitiveID].edgeTessellationFactor[1] = 0.0h; patchTessellationFactors[primitiveID].edgeTessellationFactor[2] = 0.0h; patchTessellationFactors[primitiveID].edgeTessellationFactor[3] = 0.0h; patchTessellationFactors[primitiveID].insideTessellationFactor[0] = 0.0h; patchTessellationFactors[primitiveID].insideTessellationFactor[1] = 0.0h; +#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE + patchTessellationFactors[primitiveID].edgeTessellationFactor[0] = 0.0h; + patchTessellationFactors[primitiveID].edgeTessellationFactor[1] = 0.0h; + patchTessellationFactors[primitiveID].edgeTessellationFactor[2] = 0.0h; + patchTessellationFactors[primitiveID].insideTessellationFactor = 0.0h; +#endif #endif patchParam[primitiveIDInTG].z = -1; @@ -431,7 +447,11 @@ interpolateFaceVaryingColor( } #endif +#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY [[patch(quad, VERTEX_CONTROL_POINTS_PER_PATCH)]] +#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE +[[patch(triangle, VERTEX_CONTROL_POINTS_PER_PATCH)]] +#endif vertex OutputVertex vertex_main( const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]], #if USE_STAGE_IN @@ -443,7 +463,11 @@ vertex OutputVertex vertex_main( const device int* osdFaceVaryingIndices [[buffer(OSD_FVAR_INDICES_BUFFER_INDEX)]], const device packed_int3* osdFaceVaryingPatchParams [[buffer(OSD_FVAR_PATCHPARAM_BUFFER_INDEX)]], const constant int* osdFaceVaryingPatchArrays [[buffer(OSD_FVAR_PATCH_ARRAYS_BUFFER_INDEX)]], +#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY float2 position_in_patch [[position_in_patch]], +#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE + float3 position_in_patch [[position_in_patch]], +#endif uint patch_id [[patch_id]] ) { diff --git a/examples/mtlViewer/mtlViewer.mm b/examples/mtlViewer/mtlViewer.mm index 22aff359..8336152b 100644 --- a/examples/mtlViewer/mtlViewer.mm +++ b/examples/mtlViewer/mtlViewer.mm @@ -65,6 +65,7 @@ #define OSD_PERPATCHTESSFACTORS_BUFFER_INDEX 8 #define PATCH_TESSFACTORS_INDEX 10 #define QUAD_TESSFACTORS_INDEX PATCH_TESSFACTORS_INDEX +#define TRIANGLE_TESSFACTORS_INDEX PATCH_TESSFACTORS_INDEX #define OSD_PATCH_INDEX_BUFFER_INDEX 13 #define OSD_DRAWINDIRECT_BUFFER_INDEX 14 #define OSD_KERNELLIMIT_BUFFER_INDEX 15 @@ -187,7 +188,6 @@ using PerFrameBuffer = MTLRingBuffer; NSString* _osdShaderSource; simd::float3 _meshCenter; NSMutableArray* _loadedModels; - bool _doAdaptive; int _patchCounts[DISPATCHSLOTS]; } @@ -202,6 +202,7 @@ using PerFrameBuffer = MTLRingBuffer; struct PipelineConfig { Far::PatchDescriptor::Type patchType; bool useTessellation; + bool useTriangleTessellation; bool useSingleCreasePatch; bool useLegacyBuffers; bool drawIndexed; @@ -218,6 +219,7 @@ struct PipelineConfig { config.patchType = patchType; config.useTessellation = false; + config.useTriangleTessellation = false; config.useSingleCreasePatch = false; config.useLegacyBuffers = false; config.drawIndexed = false; @@ -237,6 +239,15 @@ struct PipelineConfig { config.numControlPointsPerThreadToDraw = 3; config.numThreadsPerPatch = 1; break; + case Far::PatchDescriptor::LOOP: + config.useTessellation = true; + config.useTriangleTessellation = true; + config.numControlPointsPerPatchRefined = 12; + config.numControlPointsPerPatchToDraw = 15; + config.numControlPointsPerThreadRefined = 3; + config.numControlPointsPerThreadToDraw = 4; + config.numThreadsPerPatch = 4; + break; case Far::PatchDescriptor::REGULAR: config.useTessellation = true; config.useSingleCreasePatch = useSingleCreasePatch; @@ -273,6 +284,16 @@ struct PipelineConfig { config.numControlPointsPerThreadToDraw = 5; config.numThreadsPerPatch = 4; break; + case Far::PatchDescriptor::GREGORY_TRIANGLE: + config.useTessellation = true; + config.useTriangleTessellation = true; + config.drawIndexed = true; + config.numControlPointsPerPatchRefined = 18; + config.numControlPointsPerPatchToDraw = 18; + config.numControlPointsPerThreadRefined = 5; + config.numControlPointsPerThreadToDraw = 5; + config.numThreadsPerPatch = 4; + break; default: assert("Unsupported patch type" && 0); break; } @@ -356,7 +377,7 @@ struct PipelineConfig { [self _updateState]; - if(_doAdaptive) { + if (_useAdaptive) { auto computeEncoder = [commandBuffer computeCommandEncoder]; [self _computeTessFactors:computeEncoder]; [computeEncoder endEncoding]; @@ -364,7 +385,7 @@ struct PipelineConfig { auto renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:[_delegate renderPassDescriptorFor: self]]; - if(_usePrimitiveBackfaceCulling) { + if (_usePrimitiveBackfaceCulling) { [renderEncoder setCullMode:MTLCullModeBack]; } else { [renderEncoder setCullMode:MTLCullModeNone]; @@ -401,7 +422,7 @@ struct PipelineConfig { if (_numFaceVaryingElements > 0) { #if FVAR_SINGLE_BUFFER - int faceVaryingDataBufferOffset = _doAdaptive ? 0 : _shape->uvs.size() * sizeof(float); + int faceVaryingDataBufferOffset = _useAdaptive ? 0 : _shape->uvs.size() * sizeof(float); [renderCommandEncoder setVertexBuffer:_faceVaryingDataBuffer offset:faceVaryingDataBufferOffset atIndex:OSD_FVAR_DATA_BUFFER_INDEX]; #else [renderCommandEncoder setVertexBuffer:_faceVaryingDataBuffer offset:0 atIndex:OSD_FVAR_DATA_BUFFER_INDEX]; @@ -415,7 +436,7 @@ struct PipelineConfig { atIndex:OSD_FVAR_PATCH_ARRAYS_BUFFER_INDEX]; } - if(_doAdaptive) + if (_useAdaptive) { [renderCommandEncoder setVertexBuffer:_perPatchTessFactorsBuffer offset:0 atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX]; [renderCommandEncoder setVertexBuffer:_perPatchVertexBuffer offset:0 atIndex:OSD_PERPATCHVERTEX_BUFFER_INDEX]; @@ -473,7 +494,7 @@ struct PipelineConfig { [renderCommandEncoder setVertexBufferOffset:(fvarPatch.indexBase+(patch.primitiveIdBase*fvarPatch.desc.GetNumControlVertices())) * sizeof(unsigned) atIndex:OSD_FVAR_INDICES_BUFFER_INDEX]; } - if(_usePatchIndexBuffer) { + if (_usePatchIndexBuffer) { if (pipelineConfig.drawIndexed) { [renderCommandEncoder drawIndexedPatches:pipelineConfig.numControlPointsPerPatchToDraw patchStart:0 patchCount:patch.GetNumPatches() @@ -662,12 +683,8 @@ struct PipelineConfig { Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); _numVertices = refBaseLevel.GetNumVertices(); - - // Adaptive refinement currently supported only for catmull-clark scheme - _doAdaptive = (_useAdaptive && scheme == kCatmark); - Osd::MeshBitset bits; - bits.set(Osd::MeshAdaptive, _doAdaptive); + bits.set(Osd::MeshAdaptive, _useAdaptive); bits.set(Osd::MeshUseSmoothCornerPatch, _useSmoothCornerPatch); bits.set(Osd::MeshUseSingleCreasePatch, _useSingleCreasePatch); bits.set(Osd::MeshUseInfSharpPatch, _useInfinitelySharpPatch); @@ -756,7 +773,7 @@ struct PipelineConfig { stencilTableFactoryOptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_FACE_VARYING; stencilTableFactoryOptions.generateOffsets = true; stencilTableFactoryOptions.generateControlVerts = false; - stencilTableFactoryOptions.generateIntermediateLevels = _doAdaptive; + stencilTableFactoryOptions.generateIntermediateLevels = _useAdaptive; stencilTableFactoryOptions.factorizeIntermediateLevels = true; stencilTableFactoryOptions.maxLevel = level; stencilTableFactoryOptions.fvarChannel = 0; @@ -841,7 +858,7 @@ struct PipelineConfig { pData->TessLevel = static_cast(1 << _tessellationLevel); - if(_doAdaptive && _usePatchIndexBuffer) + if (_useAdaptive && _usePatchIndexBuffer) { for (auto& patch : _mesh->GetPatchTable()->GetPatchArrays()) { @@ -870,7 +887,7 @@ struct PipelineConfig { _drawIndirectCommandsBuffer.alloc(_context.device, DISPATCHSLOTS, @"draw patch indirect commands"); } - if(_doAdaptive) + if (_useAdaptive) { for (auto& patch : _mesh->GetPatchTable()->GetPatchArrays()) { @@ -892,7 +909,9 @@ struct PipelineConfig { _perPatchVertexOffsets[patchType] = totalPatchDataSize; _tessFactorOffsets[patchType] = totalTessFactorsSize; totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * pipelineConfig.numControlPointsPerPatchToDraw; - totalTessFactorsSize += patch.GetNumPatches() * sizeof(MTLQuadTessellationFactorsHalf); + totalTessFactorsSize += patch.GetNumPatches() * (pipelineConfig.useTriangleTessellation + ? sizeof(MTLTriangleTessellationFactorsHalf) + : sizeof(MTLQuadTessellationFactorsHalf)); } totalPatches += patch.GetNumPatches(); @@ -965,6 +984,7 @@ struct PipelineConfig { DEFINE(INDICES_BUFFER_INDEX,INDICES_BUFFER_INDEX); DEFINE(PATCH_TESSFACTORS_INDEX,PATCH_TESSFACTORS_INDEX); DEFINE(QUAD_TESSFACTORS_INDEX,QUAD_TESSFACTORS_INDEX); + DEFINE(TRIANGLE_TESSFACTORS_INDEX,TRIANGLE_TESSFACTORS_INDEX); DEFINE(OSD_PATCH_INDEX_BUFFER_INDEX,OSD_PATCH_INDEX_BUFFER_INDEX); DEFINE(OSD_DRAWINDIRECT_BUFFER_INDEX,OSD_DRAWINDIRECT_BUFFER_INDEX); DEFINE(OSD_KERNELLIMIT_BUFFER_INDEX,OSD_KERNELLIMIT_BUFFER_INDEX); @@ -1007,7 +1027,7 @@ struct PipelineConfig { DEFINE(SHADING_TYPE, _shadingMode); DEFINE(OSD_USE_PATCH_INDEX_BUFFER, _usePatchIndexBuffer); DEFINE(OSD_ENABLE_SCREENSPACE_TESSELLATION, _useScreenspaceTessellation); - DEFINE(OSD_ENABLE_PATCH_CULL, _usePatchClipCulling && _doAdaptive); + DEFINE(OSD_ENABLE_PATCH_CULL, _usePatchClipCulling && _useAdaptive); DEFINE(OSD_FVAR_DATA_BUFFER_INDEX, OSD_FVAR_DATA_BUFFER_INDEX); DEFINE(OSD_FVAR_INDICES_BUFFER_INDEX, OSD_FVAR_INDICES_BUFFER_INDEX); DEFINE(OSD_FVAR_PATCHPARAM_BUFFER_INDEX, OSD_FVAR_PATCHPARAM_BUFFER_INDEX); @@ -1063,7 +1083,7 @@ struct PipelineConfig { auto vertexDesc = pipelineDesc.vertexDescriptor; [vertexDesc reset]; - if(_doAdaptive) + if (_useAdaptive) { vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch; vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepRate = 1; @@ -1077,8 +1097,10 @@ struct PipelineConfig { switch(patchType) { + case Far::PatchDescriptor::LOOP: case Far::PatchDescriptor::REGULAR: case Far::PatchDescriptor::GREGORY_BASIS: + case Far::PatchDescriptor::GREGORY_TRIANGLE: if (pipelineConfig.drawIndexed) { vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatchControlPoint; vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepRate = 1;