Added Metal support

This commit is contained in:
Michael Harris 2016-07-26 12:41:18 -07:00 committed by David G Yu
parent 023a2b8649
commit 30cd2df37c
84 changed files with 15875 additions and 40 deletions

1
.gitignore vendored Normal file → Executable file
View File

@ -6,3 +6,4 @@
*.pyc
osdshim_wrap.cpp
shim.py
.DS_Store

View File

@ -74,6 +74,10 @@ if (NOT DEFINED CMAKE_LIBDIR_BASE)
set( CMAKE_LIBDIR_BASE lib )
endif()
if (NOT DEFINED CMAKE_FRAMEWORKDIR_BASE)
set( CMAKE_FRAMEWORKDIR_BASE Frameworks )
endif()
if (NOT DEFINED CMAKE_PLUGINDIR_BASE)
set( CMAKE_PLUGINDIR_BASE plugin )
endif()
@ -140,6 +144,11 @@ endif()
# which point to directories outside the build tree to the install RPATH
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# ensure that ARC is shown as enabled in the Xcode UI
if(CMAKE_GENERATOR STREQUAL "Xcode")
set (CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES")
endif()
set(OSD_COMPILER_FLAGS)
@ -293,6 +302,7 @@ option(NO_CUDA "Disable CUDA backend" OFF)
option(NO_OPENCL "Disable OpenCL backend" OFF)
option(NO_CLEW "Disable CLEW wrapper library" OFF)
option(NO_OPENGL "Disable OpenGL support")
option(NO_METAL "Disable Metal support" OFF)
option(NO_DX "Disable DirectX support")
option(NO_TESTS "Disable all tests")
option(NO_GLTESTS "Disable GL tests")
@ -332,6 +342,9 @@ if(NOT NO_PTEX)
find_package(PTex 2.0)
find_package(ZLIB 1.2)
endif()
if(APPLE AND NOT NO_METAL)
find_package(Metal)
endif()
if (OPENGL_FOUND AND NOT IOS)
add_definitions(
-DOPENSUBDIV_HAS_OPENGL
@ -390,6 +403,10 @@ else()
endif()
endif()
if( METAL_FOUND AND NOT NO_METAL)
set(OSD_GPU TRUE)
endif()
if( OPENGL_FOUND AND NOT NO_OPENGL)
set(OSD_GPU TRUE)
endif()
@ -657,6 +674,11 @@ macro(_add_executable target folder)
if(CMAKE_COMPILER_IS_ICC)
target_link_libraries(${target} ${ICC_LIBRARIES})
endif()
if(APPLE)
set_property (TARGET ${target} APPEND_STRING PROPERTY
COMPILE_FLAGS " -fobjc-arc ")
endif()
endmacro()
@ -674,6 +696,11 @@ macro(_add_possibly_cuda_executable target folder)
if(CMAKE_COMPILER_IS_ICC)
target_link_libraries(${target} ${ICC_LIBRARIES})
endif()
if(APPLE)
set_property (TARGET ${target} APPEND_STRING PROPERTY
COMPILE_FLAGS " -fobjc-arc ")
endif()
endmacro()
@ -686,6 +713,11 @@ macro(_add_possibly_cuda_library target folder)
add_library(${target} ${ARGN})
endif()
set_target_properties(${target} PROPERTIES FOLDER ${folder})
if(APPLE)
set_property (TARGET ${target} APPEND_STRING PROPERTY
COMPILE_FLAGS " -fobjc-arc ")
endif()
endmacro()
@ -716,6 +748,11 @@ macro(_add_glfw_executable target folder)
# endforeach()
# endif()
if(APPLE)
set_property (TARGET ${target} APPEND_STRING PROPERTY
COMPILE_FLAGS " -fobjc-arc ")
endif()
endmacro()
#-------------------------------------------------------------------------------
@ -738,7 +775,7 @@ endif()
add_subdirectory(opensubdiv)
if (NOT ANDROID AND NOT IOS) # XXXdyu
if (NOT ANDROID) # XXXdyu
add_subdirectory(regression)
endif()

View File

@ -8,8 +8,8 @@ Feel free to use it and let us know what you think.
For more details about OpenSubdiv, see [Pixar Graphics Technologies](http://graphics.pixar.com).
| | Linux | Windows |
|:------:|:-------:|:---------:|
| | Linux | Windows | macOS | iOS |
|:------:|:-------:|:---------:|:------:|:---:|
| master | [![Linux Build Status](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv.svg?branch=master)](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/mcmwg4q9m8kgi9im/branch/master?svg=true)](https://ci.appveyor.com/project/c64kernal/opensubdiv-ddr8q) |
| dev | [![Linux Build Status](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv.svg?branch=dev)](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/mcmwg4q9m8kgi9im/branch/dev?svg=true)](https://ci.appveyor.com/project/c64kernal/opensubdiv-ddr8q) |
@ -40,6 +40,7 @@ For more details about OpenSubdiv, see [Pixar Graphics Technologies](http://grap
| TBB <br> https://www.threadingbuildingblocks.org | 4.0 | TBB backend |
| OpenCL <br> http://www.khronos.org/opencl | 1.1 | CL backend |
| DX11 SDK <br> http://www.microsoft.com/download/details.aspx?id=6812| | DX backend |
| Metal <br> https://developer.apple.com/metal/ | 1.2 | Metal backend |
* Examples/Documents optional requirements:
@ -102,16 +103,30 @@ cmake -D NO_PTEX=1 -D NO_DOC=1 \
make
```
### OSX
### macOS
```
cmake -D NO_PTEX=1 -D NO_DOC=1 \
cmake -G Xcode -D NO_PTEX=1 -D NO_DOC=1 \
-D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 \
-D GLFW_LOCATION="*YOUR GLFW INSTALL LOCATION*" \
..
make
```
### iOS
* Because OpenSubdiv uses a self-built build tool (stringify) as part of the build process, you'll want to build for macOS and build the stringify target
```
SDKROOT=$(xcrun --sdk iphoneos --show-sdk-path) cmake -D NO_PTEX=1 -D NO_DOC=1 \
-D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 \
-D STRINGIFY_LOCATION="*YOUR MACOS BUILD LOCATION*"/bin/stringify \
-D CMAKE_TOOLCHAIN_FILE=../cmake/iOSToolchain.cmake -G Xcode \
..
```
* This will produce an "OpenSubdiv.xcodeproj" that can be open and the targets 'mtlViewer' and 'mtlPtexViewer' (if NO_PTEX is ommitted and libPtex.a is installed in the iOS SDK) that can be run
### Useful cmake options and environment variables
````
@ -119,11 +134,13 @@ make
-DCMAKE_INSTALL_PREFIX=[base path to install OpenSubdiv]
-DCMAKE_LIBDIR_BASE=[library directory basename (default: lib)]
-DCMAKE_TOOLCHAIN_FILE=[toolchain file for crossplatform builds]
-DCUDA_TOOLKIT_ROOT_DIR=[path to CUDA Toolkit]
-DPTEX_LOCATION=[path to Ptex]
-DGLEW_LOCATION=[path to GLEW]
-DGLFW_LOCATION=[path to GLFW]
-DSTRINGIFY_LOCATION=[path to stringify utility]
-DNO_LIB=1 // disable the opensubdiv libs build (caveat emptor)
-DNO_EXAMPLES=1 // disable examples build
@ -137,5 +154,6 @@ make
-DNO_OPENCL=1 // disable OpenCL
-DNO_OPENGL=1 // disable OpenGL
-DNO_CLEW=1 // disable CLEW wrapper library
-DNO_METAL=1 // disable Metal
````

22
cmake/FindMetal.cmake Normal file
View File

@ -0,0 +1,22 @@
if(APPLE)
find_path( METAL_INCLUDE_DIR
Metal/Metal.h
)
find_library( METAL_FRAMEWORKS Metal )
if(METAL_FRAMEWORKS)
set( METAL_LIBRARIES "-framework Metal -framework Foundation" )
endif()
endif()
set( METAL_FOUND "NO" )
if(METAL_LIBRARIES)
set( METAL_FOUND "YES" )
endif(METAL_LIBRARIES)
mark_as_advanced(
METAL_INCLUDE_DIR
METAL_LIBRARIES
)

View File

@ -63,13 +63,24 @@ elseif (APPLE)
"$ENV{PTEX_LOCATION}/include"
PATHS
DOC "The directory where Ptexture.h resides")
find_library( PTEX_LIBRARY
NAMES
Ptex libPtex.a
PATHS
"${PTEX_LOCATION}/lib"
"$ENV{PTEX_LOCATION}/lib"
DOC "The Ptex Library")
if (IOS)
#IOS needs to link with the static version of ptex
find_library( PTEX_LIBRARY
NAMES
libPtex.a
PATHS
"${PTEX_LOCATION}/lib"
"$ENV{PTEX_LOCATION}/lib"
DOC "The Ptex Library")
else ()
find_library( PTEX_LIBRARY
NAMES
Ptex libPtex.a
PATHS
"${PTEX_LOCATION}/lib"
"$ENV{PTEX_LOCATION}/lib"
DOC "The Ptex Library")
endif()
else ()
find_path( PTEX_INCLUDE_DIR
NAMES

50
cmake/iOSToolchain.cmake Normal file
View File

@ -0,0 +1,50 @@
set(SDKROOT $ENV{SDKROOT})
set(RC_ARCHS $ENV{RC_ARCHS})
separate_arguments(RC_ARCHS)
set(ARCH_FLAGS "-arch arm64")
foreach(ARCH ${RC_ARCHS})
set(ARCH_FLAGS "${ARCH_FLAGS} -arch ${ARCH}")
endforeach(ARCH)
execute_process(COMMAND xcodebuild -version -sdk ${SDKROOT} PlatformPath OUTPUT_VARIABLE DEVROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND xcodebuild -version -sdk ${SDKROOT} ProductVersion OUTPUT_VARIABLE SDKVER OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND xcodebuild -version -sdk ${SDKROOT} Path OUTPUT_VARIABLE SDKROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND xcrun -sdk ${SDKROOT} -f cc OUTPUT_VARIABLE CC OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND xcrun -sdk ${SDKROOT} -f c++ OUTPUT_VARIABLE CXX OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_VERSION 9)
set(CMAKE_SYSTEM_PROCESSOR arm)
set (iPhone 1)
set (iPhoneOS 1)
set (iPhoneOS_VERSION ${SDKVER})
set (IOS 1)
set(CMAKE_FIND_ROOT_PATH "${SDKROOT}" "${DEVROOT}")
set(CMAKE_OSX_SYSROOT "${SDKROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_MACOSX_BUNDLE YES)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
string(FIND ${DEVROOT} ".platform" PLATFORM_END REVERSE)
string(FIND ${DEVROOT} "/" PLATFORM_START REVERSE)
math(EXPR PLATFORM_START "${PLATFORM_START} + 1")
math(EXPR PLATFORM_LENGTH "${PLATFORM_END} - ${PLATFORM_START}")
string(SUBSTRING ${DEVROOT} ${PLATFORM_START} ${PLATFORM_LENGTH} PLATFORM)
string(TOLOWER ${PLATFORM} PLATFORM)
set(VERSIONMIN "-m${PLATFORM}-version-min=${SDKVER}")
set(DEPLOYMENT_TARGET "${SDKVER}")
set(CMAKE_C_COMPILER "${CC}")
set(CMAKE_CXX_COMPILER "${CXX}")
set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_C_FLAGS "${ARCH_FLAGS} ${VERSIONMIN} -isysroot ${SDKROOT}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${ARCH_FLAGS} ${VERSIONMIN} -isysroot ${SDKROOT}" CACHE STRING "" FORCE)

View File

@ -79,3 +79,9 @@ if (DXSDK_FOUND AND NOT NO_DX)
endif()
if (METAL_FOUND AND NOT NO_METAL)
add_subdirectory(mtlViewer)
if(PTEX_FOUND)
add_subdirectory(mtlPtexViewer)
endif()
endif()

View File

@ -25,6 +25,7 @@
set(EXAMPLES_COMMON_SHADER_FILES
glslPtexCommon.glsl
hlslPtexCommon.hlsl
mtlPtexCommon.metal
)
set(EXAMPLES_COMMON_SOURCE_FILES
@ -120,6 +121,21 @@ if(CUDA_FOUND)
)
endif()
if(METAL_FOUND)
include_directories("${METAL_INCLUDE_DIR}")
list(APPEND EXAMPLES_COMMON_SOURCE_FILES
mtlControlMeshDisplay.mm
mtlUtils.mm
mtlHud.mm
)
list(APPEND EXAMPLES_COMMON_HEADER_FILES
mtlControlMeshDisplay.h
mtlUtils.h
mtlHud.h
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
endif()
#-------------------------------------------------------------------------------
if( PTEX_FOUND )
list(APPEND EXAMPLES_COMMON_HEADER_FILES
@ -144,6 +160,14 @@ if( PTEX_FOUND )
d3d11PtexMipmapTexture.h
)
endif()
if( METAL_FOUND )
list(APPEND EXAMPLES_COMMON_SOURCE_FILES
mtlPtexMipmapTexture.mm
)
list(APPEND EXAMPLES_COMMON_HEADER_FILES
mtlPtexMipmapTexture.h
)
endif()
include_directories( "${PTEX_INCLUDE_DIR}" )
list(APPEND PLATFORM_CPU_LIBRARIES
${PTEX_LIBRARY}
@ -158,7 +182,7 @@ include_directories(
set(INC_FILES )
if(OPENGL_FOUND OR DXSDK_FOUND)
if(OPENGL_FOUND OR DXSDK_FOUND OR METAL_FOUND)
_stringify("${EXAMPLES_COMMON_SHADER_FILES}" INC_FILES)
source_group("Shaders" FILES ${EXAMPLES_COMMON_SHADER_FILES})

View File

@ -31,15 +31,28 @@
#include <string>
#include <vector>
#define OSD_HUD_USE_FUNCTION_POINTERS (__cplusplus <= 199711L)
#if !OSD_HUD_USE_FUNCTION_POINTERS
#include <functional>
#endif
#include "hud.h"
class Hud
{
public:
#if OSD_HUD_USE_FUNCTION_POINTERS
typedef void (*RadioButtonCallback)(int c);
typedef void (*CheckBoxCallback)(bool checked, int data);
typedef void (*SliderCallback)(float value, int data);
typedef void (*PullDownCallback)(int value);
#else
typedef std::function<void(int)> RadioButtonCallback;
typedef std::function<void(bool,int)> CheckBoxCallback;
typedef std::function<void(float, int)> SliderCallback;
typedef std::function<void(int)> PullDownCallback;
#endif
Hud();
virtual ~Hud();

View File

@ -0,0 +1,62 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV_EXAMPLES_MTL_CONTROL_MESH_DISPLAY_H
#define OPENSUBDIV_EXAMPLES_MTL_CONTROL_MESH_DISPLAY_H
#include <Metal/Metal.h>
#include <far/topologyLevel.h>
class MTLControlMeshDisplay {
public:
MTLControlMeshDisplay(id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor);
~MTLControlMeshDisplay() = default;
void Draw(id<MTLRenderCommandEncoder> encoder,
id<MTLBuffer> vertexBuffer,
const float *modelViewProjectionMatrix);
void SetTopology(OpenSubdiv::Far::TopologyLevel const &level);
bool GetEdgesDisplay() const { return _displayEdges; }
void SetEdgesDisplay(bool display) { _displayEdges = display; }
bool GetVerticesDisplay() const { return _displayVertices; }
void SetVerticesDisplay(bool display) { _displayVertices = display; }
private:
bool createProgram(MTLRenderPipelineDescriptor* pipelineDescriptor);
bool _displayEdges;
bool _displayVertices;
id<MTLDevice> _device;
int _numEdges, _numPoints;
id<MTLRenderPipelineState> _renderPipelineState;
id<MTLBuffer> _vertexSharpnessBuffer;
id<MTLBuffer> _edgeSharpnessBuffer;
id<MTLBuffer> _edgeIndicesBuffer;
};
#endif // OPENSUBDIV_EXAMPLES_MTL_CONTROL_MESH_DISPLAY_H

View File

@ -0,0 +1,167 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "mtlControlMeshDisplay.h"
#include <cassert>
#include "mtlUtils.h"
static const char* s_Shader = R"(
#include <metal_stdlib>
using namespace metal;
float4 sharpnessToColor(float s) {
// 0.0 2.0 4.0
// green --- yellow --- red
return float4(min(1.0, s * 0.5),
min(1.0, 2.0 - s * 0.5),
0.0, 1.0);
}
struct DrawData
{
float4x4 ModelViewProjectionMatrix;
};
struct VertexData
{
float3 position [[attribute(0)]];
float sharpness [[attribute(1)]];
};
struct FragmentData
{
float4 position [[position]];
float4 color;
};
vertex FragmentData vs_main(VertexData in [[stage_in]],
const constant DrawData& drawData [[buffer(2)]]
)
{
FragmentData out;
out.position = drawData.ModelViewProjectionMatrix * float4(in.position, 1.0);
out.color = sharpnessToColor(in.sharpness);
return out;
}
fragment float4 fs_main(FragmentData in [[stage_in]])
{
return in.color;
}
)";
MTLControlMeshDisplay::MTLControlMeshDisplay(id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor)
: _device(device), _displayEdges(false), _displayVertices(false), _numEdges(0), _numPoints(0) {
const auto result = createProgram(pipelineDescriptor);
assert(result && "Failed to create program for MTLControlMeshDisplay");
}
void MTLControlMeshDisplay::SetTopology(OpenSubdiv::Far::TopologyLevel const &level) {
using namespace OpenSubdiv;
_numEdges = level.GetNumEdges();
_numPoints = level.GetNumVertices();
std::vector<int> edgeIndices;
std::vector<float> edgeSharpness;
std::vector<float> vertSharpness;
edgeIndices.reserve(_numEdges * 2);
edgeSharpness.reserve(_numEdges);
vertSharpness.reserve(_numPoints);
for(int i = 0; i < _numEdges; i++) {
const auto verts = level.GetEdgeVertices(i);
edgeIndices.emplace_back(verts[0]);
edgeIndices.emplace_back(verts[1]);
edgeSharpness.emplace_back(level.GetEdgeSharpness(i));
}
for(int i = 0; i < _numPoints; i++) {
vertSharpness.emplace_back(level.GetVertexSharpness(i));
}
_edgeIndicesBuffer = Osd::MTLNewBufferFromVector(_device, edgeIndices);
_edgeSharpnessBuffer = Osd::MTLNewBufferFromVector(_device, edgeSharpness);
_vertexSharpnessBuffer = Osd::MTLNewBufferFromVector(_device, vertSharpness);
}
bool MTLControlMeshDisplay::createProgram(MTLRenderPipelineDescriptor* _pipelineDescriptor) {
const auto options = [MTLCompileOptions new];
NSError* error = nil;
const auto library = [_device newLibraryWithSource:@(s_Shader) options:options error:&error];
if(!library) {
printf("Failed to create library for MTLControlMeshDisplay\n%s\n", error ? [[error localizedDescription] UTF8String] : "");
return false;
}
const auto vertexFunction = [library newFunctionWithName:@"vs_main"];
const auto fragmentFunction = [library newFunctionWithName:@"fs_main"];
MTLRenderPipelineDescriptor* pipelineDescriptor = [_pipelineDescriptor copy];
pipelineDescriptor.vertexFunction = vertexFunction;
pipelineDescriptor.fragmentFunction = fragmentFunction;
const auto vertexDescriptor = pipelineDescriptor.vertexDescriptor;
vertexDescriptor.layouts[1].stride = sizeof(float) * 6;
vertexDescriptor.layouts[1].stepFunction = MTLVertexStepFunctionPerVertex;
vertexDescriptor.layouts[1].stepRate = 1;
vertexDescriptor.attributes[1].bufferIndex = 1;
vertexDescriptor.attributes[1].offset = 0;
vertexDescriptor.attributes[1].format = MTLVertexFormatFloat3;
_renderPipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
if(!_renderPipelineState) {
printf("Failed to create render pipeline state for MTLControlMeshDisplay\n%s\n", error ? [[error localizedDescription] UTF8String] : "");
}
return true;
}
void MTLControlMeshDisplay::Draw(id<MTLRenderCommandEncoder> encoder,
id<MTLBuffer> vertexBuffer,
const float *modelViewProjectionMatrix) {
[encoder setRenderPipelineState: _renderPipelineState];
[encoder setVertexBuffer:vertexBuffer offset:0 atIndex:0];
[encoder setVertexBytes:modelViewProjectionMatrix length: sizeof(float) * 16 atIndex:2];
if(_displayEdges) {
[encoder setVertexBuffer:_edgeSharpnessBuffer offset:0 atIndex:1];
[encoder drawIndexedPrimitives:MTLPrimitiveTypeLine
indexCount:_numEdges * 2
indexType:MTLIndexTypeUInt32
indexBuffer:_edgeIndicesBuffer
indexBufferOffset:0
instanceCount:1
baseVertex:0
baseInstance:0];
}
if(_displayVertices) {
[encoder setVertexBuffer:_vertexSharpnessBuffer offset:0 atIndex:1];
[encoder drawPrimitives:MTLPrimitiveTypePoint
vertexStart:0
vertexCount:_numPoints];
}
}

72
examples/common/mtlHud.h Normal file
View File

@ -0,0 +1,72 @@
//
// Copyright 2016 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV_EXAMPLES_MTL_HUD_H
#define OPENSUBDIV_EXAMPLES_MTL_HUD_H
@protocol MTLTexture;
@protocol MTLBuffer;
@protocol MTLRenderCommandEncoder;
@protocol MTLRenderPipelineState;
@protocol MTLDevice;
@class MTLRenderPipelineDescriptor;
@class MTLDepthStencilDescriptor;
#include "hud.h"
#include "mtlUtils.h"
class MTLhud : public Hud {
public:
MTLhud();
~MTLhud();
virtual void Init(id<MTLDevice> device, MTLRenderPipelineDescriptor* parentPipelineDescriptor, MTLDepthStencilDescriptor* depthStencilStateDescriptor,
int width, int height, int framebufferWidth, int framebufferHeight);
virtual void Rebuild(int width, int height,
int framebufferWidth, int framebufferHeight);
virtual bool Flush(id<MTLRenderCommandEncoder> encoder);
id<MTLTexture> GetFontTexture() const {
return _fontTexture;
}
void FillBackground(id<MTLRenderCommandEncoder> encoder);
float UIScale = 1.0f;
private:
id<MTLDevice> _device;
id<MTLTexture> _fontTexture;
OpenSubdiv::OPENSUBDIV_VERSION::Osd::MTLRingBuffer<float, 1> _staticBuffer;
OpenSubdiv::OPENSUBDIV_VERSION::Osd::MTLRingBuffer<float, 3> _dynamicBuffer;
id<MTLRenderPipelineState> _fgPipelineState, _bgPipelineState;
id<MTLDepthStencilState> _depthStencilState;
};
#endif //OPENSUBDIV_EXAMPLES_MTL_HUD_H

208
examples/common/mtlHud.mm Normal file
View File

@ -0,0 +1,208 @@
//
// Copyright 2016 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "mtlHud.h"
#include "font_image.h"
#include "simple_math.h"
#include <Metal/Metal.h>
static const char* shaderSource = R"(
#include <metal_stdlib>
using namespace metal;
struct VertexInput {
float2 position [[attribute(0)]];
float3 color [[attribute(1)]];
float2 uv [[attribute(2)]];
};
struct VertexOutput {
float4 position [[position]];
float4 color;
float2 uv;
};
vertex VertexOutput fg_vertex(
VertexInput in [[stage_in]],
constant const float4x4& ModelViewProjectionMatrix [[buffer(1)]],
constant const float& UIScale [[buffer(2)]]
) {
VertexOutput out;
out.position = ModelViewProjectionMatrix * float4(in.position * UIScale, 0, 1);
out.color = float4(in.color, 1);
out.uv = in.uv;
return out;
}
fragment float4 fg_fragment(
VertexOutput in [[stage_in]],
texture2d<float, access::sample> fontTexture [[texture(0)]]
) {
constexpr sampler s = sampler(coord::normalized, address::clamp_to_zero, filter::nearest);
auto c = fontTexture.sample(s, in.uv);
if(c.a == 0)
discard_fragment();
return c * in.color;
}
constant float4 bgVertices[] = {
{-1, 1, 0, 1},
{1, 1, 0, 1},
{-1, -1, 0, 1},
{1, -1, 0, 1}
};
vertex VertexOutput bg_vertex(uint vertex_id [[vertex_id]]) {
VertexOutput out;
out.position = bgVertices[vertex_id];
out.uv = bgVertices[vertex_id].xy * 0.5 + 0.5 * 3.14159;
return out;
}
fragment float4 bg_fragment(VertexOutput in [[stage_in]]) {
return float4(float3(mix(0.1, 0.5, sin(in.uv.y))), 1);
}
)";
MTLhud::MTLhud() {
}
MTLhud::~MTLhud() {
}
void
MTLhud::Init(id<MTLDevice> device, MTLRenderPipelineDescriptor* parentPipelineDescriptor, MTLDepthStencilDescriptor* depthStencilStateDescriptor, int width, int height, int framebufferWidth, int framebufferHeight) {
Hud::Init(width, height, framebufferWidth, framebufferHeight);
@autoreleasepool {
_device = device;
const auto textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm width:FONT_TEXTURE_WIDTH height:FONT_TEXTURE_HEIGHT mipmapped:false];
_fontTexture = [_device newTextureWithDescriptor:textureDescriptor];
[_fontTexture replaceRegion: { {0, 0, 0}, {FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, 1} } mipmapLevel:0 withBytes:font_image bytesPerRow:4 * FONT_TEXTURE_WIDTH];
NSError* err = nil;
const auto library = [_device newLibraryWithSource:@(shaderSource) options:nil error:&err];
assert(err == nil);
const auto renderPipelineDescriptor = (MTLRenderPipelineDescriptor*)[parentPipelineDescriptor copy];
renderPipelineDescriptor.vertexFunction = [library newFunctionWithName:@"bg_vertex"];
renderPipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"bg_fragment"];
_bgPipelineState = [_device newRenderPipelineStateWithDescriptor:renderPipelineDescriptor error:&err];
renderPipelineDescriptor.vertexFunction = [library newFunctionWithName:@"fg_vertex"];
renderPipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"fg_fragment"];
const auto vertexDescriptor = renderPipelineDescriptor.vertexDescriptor;
vertexDescriptor.layouts[0].stride = sizeof(float) * 7;
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
vertexDescriptor.layouts[0].stepRate = 1;
vertexDescriptor.attributes[0].offset = 0;
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2;
vertexDescriptor.attributes[0].bufferIndex = 0;
vertexDescriptor.attributes[1].offset = sizeof(float) * 2;
vertexDescriptor.attributes[1].format = MTLVertexFormatFloat3;
vertexDescriptor.attributes[1].bufferIndex = 0;
vertexDescriptor.attributes[2].offset = sizeof(float) * 5;
vertexDescriptor.attributes[2].format = MTLVertexFormatFloat2;
vertexDescriptor.attributes[2].bufferIndex = 0;
_fgPipelineState = [_device newRenderPipelineStateWithDescriptor:renderPipelineDescriptor error:&err];
_depthStencilState = [_device newDepthStencilStateWithDescriptor:depthStencilStateDescriptor];
}
}
void
MTLhud::Rebuild(int width, int height, int framebufferWidth, int framebufferHeight) {
Hud::Rebuild(width, height, framebufferWidth, framebufferHeight);
_staticBuffer.alloc(_device, getStaticVboSource().size(), @"MTLhud static buffer");
std::copy(getStaticVboSource().begin(), getStaticVboSource().end(), _staticBuffer.data());
_staticBuffer.markModified();
}
bool
MTLhud::Flush(id<MTLRenderCommandEncoder> encoder) {
if(!Hud::Flush())
return false;
if(_dynamicBuffer.buffer().length < sizeof(float) * getVboSource().size()) {
_dynamicBuffer.alloc(_device, getVboSource().size(), @"MTLhud dynamic buffer");
} else {
_dynamicBuffer.next();
}
std::copy(getVboSource().begin(), getVboSource().end(), _dynamicBuffer.data());
_dynamicBuffer.markModified();
const auto numVertices = getVboSource().size() / 7;
getVboSource().clear();
float proj[16];
ortho(proj, 0, 0, float(GetWidth()), float(GetHeight()));
[encoder setVertexBuffer: _dynamicBuffer.buffer() offset:0 atIndex:0];
[encoder setRenderPipelineState: _fgPipelineState];
[encoder setDepthStencilState: _depthStencilState];
[encoder setVertexBytes: proj length: sizeof(proj) atIndex:1];
[encoder setVertexBytes: &UIScale length:sizeof(UIScale) atIndex:2];
[encoder setFragmentTexture: _fontTexture atIndex:0];
if(numVertices > 0) {
[encoder setVertexBuffer:_dynamicBuffer.buffer() offset:0 atIndex:0];
[encoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart:0 vertexCount: numVertices];
}
auto numStaticVertices = [_staticBuffer.buffer() length] / (7 * sizeof(float));
if(numStaticVertices > 0) {
[encoder setVertexBuffer:_staticBuffer.buffer() offset:0 atIndex:0];
[encoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart:0 vertexCount: numStaticVertices];
}
return true;
}
void
MTLhud::FillBackground(id<MTLRenderCommandEncoder> encoder) {
[encoder setRenderPipelineState: _bgPipelineState];
[encoder setDepthStencilState: _depthStencilState];
[encoder drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount: 4];
}

View File

@ -0,0 +1,383 @@
#line 0 "examples/common/mtlPtexCommon.metal"
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
//----------------------------------------------------------
// Ptex.Common
//----------------------------------------------------------
template<typename T>
T lerp(T x, T y, float a)
{
return x + (y - x) * a;
}
template<>
int lerp<int>(int x, int y, float a)
{
return x + (y - x) * a;
}
struct PtexPacking {
int page;
int nMipmap;
int uOffset;
int vOffset;
int adjSizeDiffs[4];
int width;
int height;
};
PtexPacking getPtexPacking(device ushort* packings, int faceID)
{
PtexPacking packing;
packing.page = packings[faceID*6+0];
packing.nMipmap = packings[faceID*6+1];
packing.uOffset = packings[faceID*6+2];
packing.vOffset = packings[faceID*6+3];
int wh = packings[faceID*6+5];
packing.width = 1 << (wh >> 8);
packing.height = 1 << (wh & 0xff);
int adjSizeDiffs = packings[faceID*6+4];
packing.adjSizeDiffs[0] = (adjSizeDiffs >> 12) & 0xf;
packing.adjSizeDiffs[1] = (adjSizeDiffs >> 8) & 0xf;
packing.adjSizeDiffs[2] = (adjSizeDiffs >> 4) & 0xf;
packing.adjSizeDiffs[3] = (adjSizeDiffs >> 0) & 0xf;
return packing;
}
int computeMipmapOffsetU(int w, int level)
{
int width = 1 << w;
int m = (0x55555555 & (width | (width-1))) << (w&1);
int x = ~((1 << (w -((level-1)&~1))) - 1);
return (m & x) + ((level+1)&~1);
}
int computeMipmapOffsetV(int h, int level)
{
int height = 1 << h;
int m = (0x55555555 & (height-1)) << ((h+1)&1);;
int x = ~((1 << (h - (level&~1))) - 1 );
return (m & x) + (level&~1);
}
PtexPacking getPtexPacking(device ushort* packings, int faceID, int level)
{
PtexPacking packing;
packing.page = packings[faceID*6+0];
packing.nMipmap = packings[faceID*6+1];
packing.uOffset = packings[faceID*6+2];
packing.vOffset = packings[faceID*6+3];
//int sizeDiffs = packings[faceID*6+4];
int wh = packings[faceID*6+5];
int w = wh >> 8;
int h = wh & 0xff;
// clamp max level
level = min(level, packing.nMipmap);
packing.uOffset += computeMipmapOffsetU(w, level);
packing.vOffset += computeMipmapOffsetV(h, level);
packing.width = 1 << (w-level);
packing.height = 1 << (h-level);
return packing;
}
void evalQuadraticBSpline(float u, thread float3& B, thread float3& BU)
{
B[0] = 0.5 * (u*u - 2.0*u + 1);
B[1] = 0.5 + u - u*u;
B[2] = 0.5 * u*u;
BU[0] = u - 1.0;
BU[1] = 1 - 2 * u;
BU[2] = u;
}
// ----------------------------------------------------------------------------
// Non-Mipmap Lookups
// ----------------------------------------------------------------------------
template<typename Texture>
auto PtexLookupNearest(float4 patchCoord,
Texture data,
device ushort* packings) -> decltype(data.read(uint2(), int()))
{
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
int faceID = int(patchCoord.w);
PtexPacking ppack = getPtexPacking(packings, faceID);
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
uv.y * ppack.height + ppack.vOffset);
return float4(data.read(uint2(coords.x, coords.y), ppack.page));
}
template<typename Texture>
auto PtexLookupNearest(float4 patchCoord,
int level,
Texture data,
device ushort* packings) -> decltype(data.read(uint2(), int()))
{
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
int faceID = int(patchCoord.w);
PtexPacking ppack = getPtexPacking(packings, faceID, level);
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
uv.y * ppack.height + ppack.vOffset);
return float4(data.read(uint2(coords.x, coords.y), ppack.page));
}
template<typename Texture>
auto PtexLookupFast(float4 patchCoord,
Texture data,
device ushort* packings) -> decltype(data.sample(sampler(), float2(), int()))
{
constexpr sampler smp(coord::normalized, address::clamp_to_edge, filter::linear);
float2 uv = clamp(patchCoord.xy, float2(0), float2(1));
int faceID = int(patchCoord.w);
PtexPacking ppack = getPtexPacking(packings, faceID);
float2 coords = float2((uv.x * ppack.width + ppack.uOffset),
(uv.y * ppack.height + ppack.vOffset)) / float2(data.get_width(), data.get_height());
return data.sample(smp, coords, ppack.page);
}
template<typename Texture>
auto PtexLookupFast(float4 patchCoord,
float level,
Texture data,
device ushort* packings) -> decltype(data.sample(sampler(), float2(), int(), bias(level)))
{
constexpr sampler smp(coord::normalized, address::clamp_to_edge, filter::linear);
float2 uv = clamp(patchCoord.xy, float2(0), float2(1));
int faceID = int(patchCoord.w);
PtexPacking ppack = getPtexPacking(packings, faceID, level);
float2 coords = float2((uv.x * ppack.width + ppack.uOffset),
(uv.y * ppack.height + ppack.vOffset)) / float2(data.get_width(), data.get_height());
return data.sample(smp, coords, ppack.page, bias(level));
}
template<typename Texture>
auto PtexLookup(float4 patchCoord,
int level,
Texture data,
device ushort* packings) -> decltype(data.read(uint2(), int()))
{
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
int faceID = int(patchCoord.w);
PtexPacking ppack = getPtexPacking(packings, faceID, level);
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
uv.y * ppack.height + ppack.vOffset);
coords -= float2(0.5, 0.5);
int c0X = int(floor(coords.x));
int c1X = int(ceil(coords.x));
int c0Y = int(floor(coords.y));
int c1Y = int(ceil(coords.y));
float t = coords.x - float(c0X);
float s = coords.y - float(c0Y);
const auto d0 = float4(data.read(uint2(c0X, c0Y), ppack.page));
const auto d1 = float4(data.read(uint2(c0X, c1Y), ppack.page));
const auto d2 = float4(data.read(uint2(c1X, c0Y), ppack.page));
const auto d3 = float4(data.read(uint2(c1X, c1Y), ppack.page));
const auto result = (1.0f-t) * ((1.0f-s)*d0 + s*d1) + t * ((1.0f-s)*d2 + s*d3);
return result;
}
template<typename Texture>
auto PtexLookupQuadratic(thread float4& du,
thread float4& dv,
float4 patchCoord,
int level,
Texture data,
device ushort* packings) -> decltype(data.read(uint2(), int()))
{
using dataType = decltype(data.read(uint2(), int()));
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
int faceID = int(patchCoord.w);
PtexPacking ppack = getPtexPacking(packings, faceID, level);
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
uv.y * ppack.height + ppack.vOffset);
coords -= float2(0.5, 0.5);
int cX = int(round(coords.x));
int cY = int(round(coords.y));
float x = 0.5 - (float(cX) - coords.x);
float y = 0.5 - (float(cY) - coords.y);
dataType d[9];
d[0] = data.read(uint2(cX-1, cY-1), ppack.page);
d[1] = data.read(uint2(cX-1, cY-0), ppack.page);
d[2] = data.read(uint2(cX-1, cY+1), ppack.page);
d[3] = data.read(uint2(cX-0, cY-1), ppack.page);
d[4] = data.read(uint2(cX-0, cY-0), ppack.page);
d[5] = data.read(uint2(cX-0, cY+1), ppack.page);
d[6] = data.read(uint2(cX+1, cY-1), ppack.page);
d[7] = data.read(uint2(cX+1, cY-0), ppack.page);
d[8] = data.read(uint2(cX+1, cY+1), ppack.page);
float3 B, D;
dataType BUCP[3] = {dataType(0), dataType(0), dataType(0)},
DUCP[3] = {dataType(0), dataType(0), dataType(0)};
evalQuadraticBSpline(y, B, D);
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; j++) {
float4 A = d[i*3+j];
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
}
}
evalQuadraticBSpline(x, B, D);
dataType result = dataType(0);
du = dataType(0);
dv = dataType(0);
for (int i = 0; i < 3; ++i) {
result += B[i] * BUCP[i];
du += D[i] * BUCP[i];
dv += B[i] * DUCP[i];
}
du *= ppack.width;
dv *= ppack.height;
return result;
}
// ----------------------------------------------------------------------------
// MipMap Lookups
// ----------------------------------------------------------------------------
template<typename Texture>
auto PtexMipmapLookupNearest(float4 patchCoord,
float level,
Texture data,
device ushort* packings) -> decltype(PtexLookupNearest(patchCoord, int(), data, packings))
{
#if SEAMLESS_MIPMAP
// diff level
int faceID = int(patchCoord.w);
float2 uv = patchCoord.xy;
PtexPacking packing = getPtexPacking(packings, faceID);
level += lerp(lerp(packing.adjSizeDiffs[0], packing.adjSizeDiffs[1], uv.x),
lerp(packing.adjSizeDiffs[3], packing.adjSizeDiffs[2], uv.x),
uv.y);
#endif
int levelm = int(floor(level));
int levelp = int(ceil(level));
float t = level - float(levelm);
const auto result = (1-t) * PtexLookupNearest(patchCoord, levelm, data, packings)
+ t * PtexLookupNearest(patchCoord, levelp, data, packings);
return result;
}
template<typename Texture>
auto PtexMipmapLookup(float4 patchCoord,
float level,
Texture data,
device ushort* packings) -> decltype(PtexLookup(patchCoord, int(), data, packings))
{
#if SEAMLESS_MIPMAP
// diff level
int faceID = int(patchCoord.w);
float2 uv = patchCoord.xy;
PtexPacking packing = getPtexPacking(packings, faceID);
level += lerp(lerp(packing.adjSizeDiffs[0], packing.adjSizeDiffs[1], uv.x),
lerp(packing.adjSizeDiffs[3], packing.adjSizeDiffs[2], uv.x),
uv.y);
#endif
int levelm = int(floor(level));
int levelp = int(ceil(level));
float t = level - float(levelm);
const auto result = (1-t) * PtexLookup(patchCoord, levelm, data, packings)
+ t * PtexLookup(patchCoord, levelp, data, packings);
return result;
}
template<typename Texture>
auto PtexMipmapLookupQuadratic(thread float4& du,
thread float4& dv,
float4 patchCoord,
float level,
Texture data,
device ushort* packings) -> decltype(PtexLookupQuadratic(du, dv, patchCoord, int(), data, packings))
{
using dataType = decltype(PtexLookupQuadratic(du, dv, patchCoord, int(), data, packings));
#if SEAMLESS_MIPMAP
// diff level
int faceID = int(patchCoord.w);
float2 uv = patchCoord.xy;
PtexPacking packing = getPtexPacking(packings, faceID);
level += lerp(lerp(packing.adjSizeDiffs[0], packing.adjSizeDiffs[1], uv.x),
lerp(packing.adjSizeDiffs[3], packing.adjSizeDiffs[2], uv.x),
uv.y);
#endif
int levelm = int(floor(level));
int levelp = int(ceil(level));
float t = level - float(levelm);
float4 du0, du1, dv0, dv1;
const auto r0 = PtexLookupQuadratic(du0, dv0, patchCoord, levelm, data, packings);
const auto r1 = PtexLookupQuadratic(du1, dv1, patchCoord, levelp, data, packings);
const auto result = lerp(r0, r1, t);
du = lerp(du0, du1, t);
dv = lerp(dv0, dv1, t);
return result;
}
template<typename Texture>
auto PtexMipmapLookupQuadratic(float4 patchCoord,
float level,
Texture data,
device ushort* packings) -> decltype(data.read(uint2(), int())) //decltype(PtexMipmapLookupQuadratic(float4(), float4(), patchCoord, level, packings)) //Not using the correct decltpye due to the need for thread& types
{
float4 du, dv;
return PtexMipmapLookupQuadratic(du, dv, patchCoord, level, data, packings);
}

View File

@ -0,0 +1,58 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV_EXAMPLES_MTL_PTEX_MIPMAP_TEXTURE_H
#define OPENSUBDIV_EXAMPLES_MTL_PTEX_MIPMAP_TEXTURE_H
#include <osd/mtlCommon.h>
#include <osd/nonCopyable.h>
#include <Ptexture.h>
@protocol MTLBuffer;
@protocol MTLTexture;
@class MTLTextureDescriptor;
class MTLPtexMipmapTexture : OpenSubdiv::Osd::NonCopyable<MTLPtexMipmapTexture> {
public:
static MTLPtexMipmapTexture * Create(OpenSubdiv::Osd::MTLContext * deviceContext,
PtexTexture * reader,
int maxLevels = 10);
static const char* GetShaderSource();
id<MTLBuffer> GetLayoutBuffer() const { return _layout; }
id<MTLTexture> GetTexelsTexture() const { return _texels; }
private:
MTLPtexMipmapTexture();
id<MTLBuffer> _layout;
id<MTLTexture> _texels;
MTLTextureDescriptor* _textureDescriptor;
};
#endif // OPENSUBDIV_EXAMPLES_MTL_PTEX_TEXTURE_H

View File

@ -0,0 +1,121 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "mtlPtexMipmapTexture.h"
#include "ptexMipmapTextureLoader.h"
#include <far/error.h>
#include <Metal/Metal.h>
#include <cassert>
#include "mtlUtils.h"
using namespace OpenSubdiv;
MTLPtexMipmapTexture::MTLPtexMipmapTexture() :
_layout(nil), _texels(nil), _textureDescriptor(nil) {
}
const char* MTLPtexMipmapTexture::GetShaderSource() {
static const char* shaderSource =
#include "mtlPtexCommon.gen.h"
;
return shaderSource;
}
MTLPtexMipmapTexture * MTLPtexMipmapTexture::Create(Osd::MTLContext *deviceContext, PtexTexture *reader, int maxLevels) {
const auto maxNumPages = 2048;
PtexMipmapTextureLoader loader(reader, maxNumPages, maxLevels);
const auto numFaces = loader.GetNumFaces();
const auto layoutBuffer = [deviceContext->device newBufferWithBytes:loader.GetLayoutBuffer() length:numFaces * 6 * sizeof(short) options:Osd::MTLDefaultStorageMode];
const auto textureDescriptor = [MTLTextureDescriptor new];
int bpp = 0;
textureDescriptor.pixelFormat = [&]() {
const auto numChannels = reader->numChannels();
switch(reader->dataType()) {
case Ptex::dt_uint16:
bpp = sizeof(short) * numChannels;
switch(numChannels) {
case 1: return MTLPixelFormatR16Unorm;
case 2: return MTLPixelFormatRG16Unorm;
case 3: assert("RGB16Uint not supported"); break;
case 4: return MTLPixelFormatRGBA16Unorm;
}
case Ptex::dt_float:
bpp = sizeof(float) * numChannels;
switch(numChannels) {
case 1: return MTLPixelFormatR32Float;
case 2: return MTLPixelFormatRG32Float;
case 3: assert("RGB32Float not supported"); break;
case 4: return MTLPixelFormatRGBA32Float;
}
case Ptex::dt_half:
bpp = sizeof(short) * numChannels;
switch(numChannels) {
case 1: return MTLPixelFormatR16Float;
case 2: return MTLPixelFormatRG16Float;
case 3: assert("RGB16Float not supported"); break;
case 4: return MTLPixelFormatRGBA16Float;
}
default:
bpp = numChannels;
switch(numChannels) {
case 1: return MTLPixelFormatR8Unorm;
case 2: return MTLPixelFormatRG8Unorm;
case 3: assert("RGB8Unorm not supported"); break;
case 4: return MTLPixelFormatRGBA8Unorm;
}
}
return MTLPixelFormatInvalid;
}();
textureDescriptor.width = loader.GetPageWidth();
textureDescriptor.height = loader.GetPageHeight();
textureDescriptor.arrayLength = loader.GetNumPages();
textureDescriptor.mipmapLevelCount = 1;
textureDescriptor.usage = MTLTextureUsageShaderRead;
textureDescriptor.textureType = MTLTextureType2DArray;
const auto texelsTexture = [deviceContext->device newTextureWithDescriptor:textureDescriptor];
if(!texelsTexture)
return nullptr;
auto result = new MTLPtexMipmapTexture();
result->_textureDescriptor = textureDescriptor;
result->_layout = layoutBuffer;
result->_texels = texelsTexture;
MTLRegion replaceRegion = MTLRegionMake2D(0, 0, loader.GetPageWidth(), loader.GetPageHeight());
const auto bytesPerRow = loader.GetPageWidth() * bpp;
const auto bytesPerImage = bytesPerRow * loader.GetPageHeight();
for(auto i = 0; i < loader.GetNumPages(); i++) {
[texelsTexture replaceRegion:replaceRegion mipmapLevel:0 slice:i
withBytes:loader.GetTexelBuffer() + i * bytesPerImage bytesPerRow:bytesPerRow bytesPerImage:bytesPerImage];
}
return result;
}

121
examples/common/mtlUtils.h Normal file
View File

@ -0,0 +1,121 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV_EXAMPLES_MTL_UTILS_H
#define OPENSUBDIV_EXAMPLES_MTL_UTILS_H
#include <Metal/Metal.h>
#include <cstring>
#include <TargetConditionals.h>
#include <vector>
namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Osd {
#if TARGET_OS_EMBEDDED
constexpr auto MTLDefaultStorageMode = MTLResourceStorageModeShared;
#else
constexpr auto MTLDefaultStorageMode = MTLResourceStorageModeManaged;
#endif
template<typename T>
id<MTLBuffer> MTLNewBufferFromVector(id<MTLDevice> device, const std::vector<T>& vec) {
const auto typeSize = sizeof(T);
const auto bufferSize = typeSize * vec.size();
return [device newBufferWithBytes:vec.data() length:bufferSize options:MTLDefaultStorageMode];
}
template<typename DataType, size_t RingLength>
class MTLRingBuffer {
private:
id<MTLBuffer> _buffers[RingLength];
uint _bufferIndex;
public:
template<typename SizedType = DataType>
MTLRingBuffer(id<MTLDevice> device, size_t count, NSString* label, MTLResourceOptions options = MTLDefaultStorageMode) {
alloc<SizedType>(device, count, options, label);
}
MTLRingBuffer() {
for(uint i = 0; i < RingLength; i++) {
_buffers[i] = nil;
}
_bufferIndex = 0;
}
void markModified() const {
#if !TARGET_OS_EMBEDDED
const auto bufferLength = [buffer() length];
[buffer() didModifyRange: NSMakeRange(0, bufferLength)];
#endif
}
template<typename SizedType = DataType>
void alloc(id<MTLDevice> device, size_t count, NSString* label, MTLResourceOptions options = MTLDefaultStorageMode) {
if(count) {
for(uint i = 0; i < RingLength; i++) {
_buffers[i] = [device newBufferWithLength: count * sizeof(SizedType) options:options];
_buffers[i].label = label;
_bufferIndex = i;
if((options & MTLResourceStorageModePrivate) == 0)
{
memset(data(), 0, count * sizeof(SizedType));
markModified();
}
}
} else {
for(uint i = 0; i < RingLength; i++) {
_buffers[i] = nil;
}
}
_bufferIndex = 0;
}
id<MTLBuffer> buffer() const {
return _buffers[_bufferIndex];
}
DataType* data() const {
return reinterpret_cast<DataType*>([buffer() contents]);
}
void next() {
_bufferIndex = (_bufferIndex + 1) % RingLength;
}
operator id<MTLBuffer>() const {
return buffer();
}
DataType* operator->() const {
return data();
}
DataType& operator[](int idx) const {
return (data())[idx];
}
};
#endif // OPENSUBDIV_EXAMPLES_MTL_UTILS_H
} } using namespace OPENSUBDIV_VERSION; }

View File

@ -0,0 +1,25 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "mtlUtils.h"

View File

@ -0,0 +1,119 @@
#
# Copyright 2013 Pixar
#
# Licensed under the Apache License, Version 2.0 (the "Apache License")
# with the following modification; you may not use this file except in
# compliance with the Apache License and the following modification to it:
# Section 6. Trademarks. is deleted and replaced with:
#
# 6. Trademarks. This License does not grant permission to use the trade
# names, trademarks, service marks, or product names of the Licensor
# and its affiliates, except as required to comply with Section 4(c) of
# the License and to reproduce the content of the NOTICE file.
#
# You may obtain a copy of the Apache License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Apache License with the above modification is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
# *** mtlPtexViewer ***
if(IOS)
set(BUNDLE_FILES
"iOS/Base.lproj/LaunchScreen.storyboard"
"iOS/Base.lproj/Main.storyboard"
)
set(PLATFORM_PLIST "iOS/Info.plist")
set(PLATFORM_FILES
"iOS/AppDelegate.h"
"iOS/AppDelegate.m"
"iOS/main.m"
"iOS/ViewController.h"
"iOS/ViewController.mm"
)
list(APPEND PLATFORM_LIBRARIES
"-framework UIKit"
"z"
)
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
else()
set(BUNDLE_FILES
"OSX/MainMenu.xib"
)
set(PLATFORM_PLIST "OSX/Info.plist")
set(PLATFORM_FILES
"OSX/AppDelegate.h"
"OSX/AppDelegate.m"
"OSX/main.m"
"OSX/ViewController.h"
"OSX/ViewController.mm"
)
list(APPEND PLATFORM_LIBRARIES
"-framework OpenGL"
"-framework AppKit"
)
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
endif()
include_directories(
"${OPENSUBDIV_INCLUDE_DIR}"
"${METAL_INCLUDE_DIR}"
"${PTEX_INCLUDE_DIR}"
)
list(APPEND PLATFORM_FILES
"mtlPtexViewer.h"
"mtlPtexViewer.mm"
)
list(APPEND PLATFORM_LIBRARIES
"osd_static_framework"
"${METAL_LIBRARY}"
"-framework MetalKit"
"-framework Foundation"
"-framework QuartzCore"
"${PTEX_LIBRARY}"
)
_stringify("mtlPtexViewer.metal" INC_FILES)
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
_add_executable(mtlPtexViewer "examples/mtlPtexViewer"
MACOSX_BUNDLE
"${PLATFORM_FILES}"
"${INC_FILES}"
"${BUNDLE_FILES}"
$<TARGET_OBJECTS:regression_common_obj>
$<TARGET_OBJECTS:regression_far_utils_obj>
$<TARGET_OBJECTS:examples_common_obj>
)
set_target_properties (mtlPtexViewer PROPERTIES
LINKER_LANGUAGE CXX
RESOURCE "${BUNDLE_FILES}"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_LIST_DIR}/${PLATFORM_PLIST}"
)
if(IOS)
set_target_properties(mtlPtexViewer PROPERTIES
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
)
endif()
set_property (TARGET mtlPtexViewer PROPERTY CXX_STANDARD 14)
target_link_libraries(mtlPtexViewer
${PLATFORM_LIBRARIES}
)
install(TARGETS mtlPtexViewer DESTINATION "${CMAKE_BINDIR_BASE}")

View File

@ -0,0 +1,31 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@end

View File

@ -0,0 +1,42 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "AppDelegate.h"
@implementation AppDelegate
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return true;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
@end

View File

@ -0,0 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Apple. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
</dict>
</plist>

View File

@ -0,0 +1,686 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16C20" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject">
<connections>
<outlet property="delegate" destination="aZQ-9t-9YL" id="ke3-sq-jK1"/>
</connections>
</customObject>
<customObject id="aZQ-9t-9YL" customClass="AppDelegate"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Test" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Test" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About NewApplication" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide NewApplication" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit NewApplication" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="File" id="bib-Uj-vzu">
<items>
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
<connections>
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
<connections>
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="tXI-mr-wws">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
<items>
<menuItem title="Clear Menu" id="vNY-rz-j42">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
<connections>
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
<connections>
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
</connections>
</menuItem>
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
<connections>
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="KaW-ft-85H">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
<connections>
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<items>
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
<connections>
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
<connections>
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
<connections>
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
<connections>
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
<connections>
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
<connections>
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
<menuItem title="Find" id="4EN-yA-p0u">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Find" id="1b7-l0-nxx">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
<connections>
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
<connections>
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
<connections>
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
<connections>
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
<connections>
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
<connections>
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="9ic-FL-obx">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
<items>
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
</connections>
</menuItem>
<menuItem title="Smart Links" id="cwL-P1-jid">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
</connections>
</menuItem>
<menuItem title="Data Detectors" id="tRr-pd-1PS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="2oI-Rn-ZJC">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
<items>
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="xrE-MZ-jX0">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
<items>
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
<items>
<menuItem title="Font" id="Gi5-1S-RQB">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
<connections>
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
<connections>
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
<menuItem title="Kern" id="jBQ-r6-VK2">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
<items>
<menuItem title="Use Default" id="GUa-eO-cwY">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
</connections>
</menuItem>
<menuItem title="Use None" id="cDB-IK-hbR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="46P-cB-AYj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="ogc-rX-tC1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="o6e-r0-MWq">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
<items>
<menuItem title="Use Default" id="agt-UL-0e3">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
</connections>
</menuItem>
<menuItem title="Use None" id="J7y-lM-qPV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
</connections>
</menuItem>
<menuItem title="Use All" id="xQD-1f-W4t">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="OaQ-X3-Vso">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
<items>
<menuItem title="Use Default" id="3Om-Ey-2VK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="Rqc-34-cIF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="I0S-gh-46l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
</connections>
</menuItem>
<menuItem title="Raise" id="2h7-ER-AoG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
</connections>
</menuItem>
<menuItem title="Lower" id="1tx-W0-xDw">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
<connections>
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="Fal-I4-PZk">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="d9c-me-L2H">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
<connections>
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
<connections>
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
</connections>
</menuItem>
<menuItem title="Justify" id="J5U-5w-g23">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
<connections>
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
<menuItem title="Writing Direction" id="H1b-Si-o9J">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
<items>
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="YGs-j5-SAR">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
</connections>
</menuItem>
<menuItem id="Lbh-J2-qVU">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
</connections>
</menuItem>
<menuItem id="jFq-tB-4Kx">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="Nop-cj-93Q">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
</connections>
</menuItem>
<menuItem id="BgM-ve-c93">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
</connections>
</menuItem>
<menuItem id="RB4-Sm-HuC">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
<menuItem title="Show Ruler" id="vLm-3I-IUL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="NewApplication Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hasShadow="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="1920" height="1080"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
<view key="contentView" id="se5-gp-TjO" customClass="OSDView">
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<connections>
<outlet property="menu" destination="AYu-sK-qS6" id="0eg-gK-PK4"/>
</connections>
</view>
<point key="canvasLocation" x="172" y="11"/>
</window>
<viewController id="tdF-Vh-f4K" customClass="ViewController">
<connections>
<outlet property="view" destination="se5-gp-TjO" id="fc1-e3-wEk"/>
</connections>
</viewController>
</objects>
</document>

View File

@ -0,0 +1,66 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <AppKit/AppKit.h>
#import <MetalKit/MetalKit.h>
#import "../mtlPtexViewer.h"
#import "../../common/mtlHud.h"
@class ViewController;
@interface OSDView : MTKView {
@public
MTLhud hud;
};
@property (nonatomic) ViewController* controller;
@end
@interface ViewController : NSViewController<MTKViewDelegate, OSDRendererDelegate>
@property (weak) IBOutlet OSDView *view;
@property (nonatomic) OSDRenderer* osdRenderer;
- (IBAction)checkboxChanged:(NSButton *)sender;
- (IBAction)popupChanged:(NSPopUpButton *)sender;
- (IBAction)sliderChanged:(NSSlider *)sender;
@property (weak) IBOutlet NSTextField *frameTimeLabel;
@property (weak) IBOutlet NSButton *wireframeCheckbox;
@property (weak) IBOutlet NSButton *singleCreaseCheckbox;
@property (weak) IBOutlet NSButton *patchIndexCheckbox;
@property (weak) IBOutlet NSButton *patchClipCullingCheckbox;
@property (weak) IBOutlet NSButton *backfaceCullingCheckbox;
@property (weak) IBOutlet NSButton *backpatchCullingCheckbox;
@property (weak) IBOutlet NSButton *screenspaceTessellationCheckbox;
@property (weak) IBOutlet NSPopUpButton *modelPopup;
@property (weak) IBOutlet NSPopUpButton *refinementLevelPopup;
@property (weak) IBOutlet NSPopUpButton *tessellationLevelPopup;
@property (weak) IBOutlet NSPopUpButton *displacementModePopup;
@property (weak) IBOutlet NSPopUpButton *normalModePopup;
@property (weak) IBOutlet NSPopUpButton *colorModePopup;
@property (weak) IBOutlet NSSlider *displacementScaleSlider;
@property (weak) IBOutlet NSSlider *mipmapBiasSlider;
@end

View File

@ -0,0 +1,461 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "ViewController.h"
enum {
kHUD_RB_COLOR,
kHUD_RB_SCHEME,
kHUD_RB_LEVEL,
kHUD_RB_DISPLACEMENT,
kHUD_RB_NORMAL
};
enum {
kHUD_SL_MIPMAPBIAS,
kHUD_SL_DISPLACEMENT,
};
enum {
kHUD_CB_DISPLAY_OCCLUSION,
kHUD_CB_DISPLAY_SPECULAR,
kHUD_CB_ANIMATE_VERTICES,
kHUD_CB_VIEW_LOD,
kHUD_CB_FRACTIONAL_SPACING,
kHUD_CB_PATCH_CULL,
kHUD_CB_FREEZE,
kHUD_CB_ADAPTIVE,
kHUD_CB_SEAMLESS_MIPMAP,
};
@implementation OSDView {
bool _mouseDown;
NSPoint _lastMouse;
}
-(void)mouseDown:(NSEvent *)event {
if(event.buttonNumber == 0) {
_lastMouse = [event locationInWindow];
_mouseDown = !hud.MouseClick(_lastMouse.x, (self.bounds.size.height - _lastMouse.y));
}
[super mouseDown:event];
}
-(void)mouseUp:(NSEvent *)event {
if(event.buttonNumber == 0) {
_mouseDown = false;
_lastMouse = [event locationInWindow];
hud.MouseRelease();
}
[super mouseUp:event];
}
-(void)mouseDragged:(NSEvent *)event {
auto mouse = [NSEvent mouseLocation];
hud.MouseMotion(mouse.x, mouse.y);
if(_mouseDown) {
CGPoint delta;
delta.x = mouse.x - _lastMouse.x;
delta.y = mouse.y - _lastMouse.y;
_lastMouse = mouse;
_controller.osdRenderer.camera->rotationX += delta.x / 2.0;
_controller.osdRenderer.camera->rotationY -= delta.y / 2.0;
}
[super mouseDragged:event];
}
-(void)keyDown:(NSEvent *)event {
const auto key = [event.charactersIgnoringModifiers characterAtIndex:0];
if(key == '=') {
_controller.osdRenderer.tessellationLevel = std::min(_controller.osdRenderer.tessellationLevel + 1, 16.0f);
} else if (key == '-') {
_controller.osdRenderer.tessellationLevel = std::max(_controller.osdRenderer.tessellationLevel - 1, 0.0f);
} else if(!hud.KeyDown(key))
[super keyDown:event];
}
-(void)scrollWheel:(NSEvent *)event {
_controller.osdRenderer.camera->dollyDistance += event.deltaY / 100.0;
}
-(BOOL)acceptsFirstResponder {
return true;
}
@end
#define FRAME_HISTORY 30
@implementation ViewController {
id<MTLDevice> _device;
id<MTLCommandQueue> _commandQueue;
dispatch_semaphore_t _frameSemaphore;
OSDRenderer* _osdRenderer;
unsigned _currentFrame;
double _frameBeginTimestamp[FRAME_HISTORY];
NSMagnificationGestureRecognizer* _magnificationGesture;
}
-(void)viewDidLoad {
_device = MTLCreateSystemDefaultDevice();
_commandQueue = [_device newCommandQueue];
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
_frameSemaphore = dispatch_semaphore_create(3);
self.view.device = _device;
self.view.delegate = self;
self.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
self.view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
self.view.controller = self;
self.view.sampleCount = 2;
_osdRenderer.camera->aspectRatio = self.view.bounds.size.width / self.view.bounds.size.height;
_currentFrame = 0;
auto renderPipelineDescriptor = [MTLRenderPipelineDescriptor new];
renderPipelineDescriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
renderPipelineDescriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
renderPipelineDescriptor.sampleCount = self.view.sampleCount;
auto depthStencilDescriptor = [MTLDepthStencilDescriptor new];
depthStencilDescriptor.depthWriteEnabled = false;
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
auto& hud = self.view->hud;
hud.Init(_device, renderPipelineDescriptor, depthStencilDescriptor, self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
auto callbackCheckbox = [=](bool checked, int ID) {
switch(ID) {
case kHUD_CB_FREEZE:
self.osdRenderer.freeze = checked;
break;
case kHUD_CB_ADAPTIVE:
self.osdRenderer.useAdaptive = checked;
break;
case kHUD_CB_VIEW_LOD:
self.osdRenderer.useScreenspaceTessellation = checked;
break;
case kHUD_CB_PATCH_CULL:
self.osdRenderer.usePatchClipCulling = checked;
break;
case kHUD_CB_ANIMATE_VERTICES:
self.osdRenderer.animateVertices = checked;
break;
case kHUD_CB_DISPLAY_SPECULAR:
self.osdRenderer.displaySpecular = checked;
break;
case kHUD_CB_DISPLAY_OCCLUSION:
self.osdRenderer.displayOcclusion = checked;
break;
case kHUD_CB_FRACTIONAL_SPACING:
self.osdRenderer.useFractionalTessellation = checked;
break;
default:
assert("Unknown checkbox ID" && 0);
}
};
auto callbackScheme = [=](int scheme) {
return;
};
auto callbackLevel = [=](int level) {
self.osdRenderer.refinementLevel = level;
};
auto callbackKernel = [=](int kernelType) {
switch((KernelType)kernelType) {
case kCPU:
case kMetal:
self.osdRenderer.kernelType = (KernelType)(kernelType);
break;
default:
assert("Unknown kernelType" && 0);
}
};
auto callbackDisplayStyle = [=](int displayStyle) {
switch((DisplayStyle)displayStyle) {
case kDisplayStyleWire:
case kDisplayStyleShaded:
case kDisplayStyleWireOnShaded:
self.osdRenderer.displayStyle = (DisplayStyle)displayStyle;
break;
default:
assert("Unknown displayStyle" && 0);
}
};
auto callbackColor = [=](int colorMode) {
switch((ColorMode)colorMode) {
case kColorModeNone:
case kColorModeNormal:
case kColorModePatchType:
case kColorModePatchCoord:
case kColorModePtexNearest:
case kColorModePtexBilinear:
case kColorModePtexHWBilinear:
case kColorModePtexBiQuadratic:
self.osdRenderer.colorMode = (ColorMode)colorMode;
break;
default:
assert("Unknown colorMode" && 0);
}
};
auto callbackDisplacement = [=](int displacementMode) {
switch((DisplacementMode)displacementMode) {
case kDisplacementModeNone:
case kDisplacementModeBilinear:
case kDisplacementModeHWBilinear:
case kDisplacementModeBiQuadratic:
self.osdRenderer.displacementMode = (DisplacementMode)displacementMode;
break;
default:
assert("Unknown displacementMode" && 0);
}
};
auto callbackNormal = [=](int normalMode) {
switch((NormalMode)normalMode) {
case kNormalModeBiQuadraticWG:
case kNormalModeBiQuadratic:
case kNormalModeScreenspace:
case kNormalModeHWScreenspace:
case kNormalModeSurface:
self.osdRenderer.normalMode = (NormalMode)normalMode;
break;
default:
assert("Unknown normalMode" && 0);
}
};
auto callbackSlider = [=](float sliderValue, int sliderID) {
switch(sliderID) {
case kHUD_SL_DISPLACEMENT:
self.osdRenderer.displacementScale = sliderValue;
break;
case kHUD_SL_MIPMAPBIAS:
self.osdRenderer.mipmapBias = sliderValue;
break;
default:
assert("Unknown slider ID" && 0);
}
};
if (_osdRenderer.ptexOcclusionFilename != NULL) {
hud.AddCheckBox("Ambient Occlusion (A)", _osdRenderer.ptexOcclusionFilename,
-200, 570, callbackCheckbox, kHUD_CB_DISPLAY_OCCLUSION, 'a');
}
if (_osdRenderer.ptexSpecularFilename != NULL)
hud.AddCheckBox("Specular (S)", _osdRenderer.ptexSpecularFilename,
-200, 590, callbackCheckbox, kHUD_CB_DISPLAY_SPECULAR, 's');
// if (_osdRenderer.ptexColorFilename || g_diffuseEnvironmentMap) {
// hud.AddCheckBox("IBL (I)", g_ibl,
// -200, 610, callbackCheckbox, HUD_CB_IBL, 'i');
// }
hud.AddCheckBox("Animate vertices (M)", _osdRenderer.animateVertices,
10, 30, callbackCheckbox, kHUD_CB_ANIMATE_VERTICES, 'm');
hud.AddCheckBox("Screen space LOD (V)", _osdRenderer.useScreenspaceTessellation,
10, 50, callbackCheckbox, kHUD_CB_VIEW_LOD, 'v');
hud.AddCheckBox("Fractional spacing (T)", _osdRenderer.useFractionalTessellation,
10, 70, callbackCheckbox, kHUD_CB_FRACTIONAL_SPACING, 't');
hud.AddCheckBox("Frustum Patch Culling (B)", _osdRenderer.usePatchClipCulling,
10, 90, callbackCheckbox, kHUD_CB_PATCH_CULL, 'b');
hud.AddCheckBox("Freeze (spc)", _osdRenderer.freeze,
10, 110, callbackCheckbox, kHUD_CB_FREEZE, ' ');
// hud.AddCheckBox("Bloom (Y)", g_bloom,
// 10, 130, callbackCheckbox, HUD_CB_BLOOM, 'y');
hud.AddRadioButton(kHUD_RB_SCHEME, "CATMARK", true, 10, 190, callbackScheme, 0);
// Ptex without Adaptive is not supported
// hud.AddCheckBox("Adaptive (`)", _osdRenderer.useAdaptive,
// 10, 300, callbackCheckbox, kHUD_CB_ADAPTIVE, '`');
for (int i = 1; i < 8; ++i) {
char level[16];
sprintf(level, "Lv. %d", i);
hud.AddRadioButton(kHUD_RB_LEVEL, level, _osdRenderer.refinementLevel == i,
10, 320+i*20, callbackLevel, i, '0'+i);
}
int compute_pulldown = hud.AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k');
hud.AddPullDownButton(compute_pulldown, "CPU", kCPU);
hud.AddPullDownButton(compute_pulldown, "Metal", kMetal);
int shading_pulldown = hud.AddPullDown("Shading (W)", 250, 10, 250, callbackDisplayStyle, 'w');
hud.AddPullDownButton(shading_pulldown, "Wire", kDisplayStyleWire, _osdRenderer.displayStyle == kDisplayStyleWire);
hud.AddPullDownButton(shading_pulldown, "Shaded", kDisplayStyleShaded, _osdRenderer.displayStyle == kDisplayStyleShaded);
hud.AddPullDownButton(shading_pulldown, "Wire+Shaded", kDisplayStyleWireOnShaded, _osdRenderer.displayStyle ==kDisplayStyleWireOnShaded);
hud.AddLabel("Color (C)", -200, 10);
hud.AddRadioButton(kHUD_RB_COLOR, "None", (_osdRenderer.colorMode == kColorModeNone),
-200, 30, callbackColor, kColorModeNone, 'c');
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex Nearest", (_osdRenderer.colorMode == kColorModePtexNearest),
-200, 50, callbackColor, kColorModePtexNearest, 'c');
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex HW bilinear", (_osdRenderer.colorMode == kColorModePtexHWBilinear),
-200, 70, callbackColor, kColorModePtexHWBilinear, 'c');
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex bilinear", (_osdRenderer.colorMode == kColorModePtexBilinear),
-200, 90, callbackColor, kColorModePtexBilinear, 'c');
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex biquadratic", (_osdRenderer.colorMode == kColorModePtexBiQuadratic),
-200, 110, callbackColor, kColorModePtexBiQuadratic, 'c');
hud.AddRadioButton(kHUD_RB_COLOR, "Patch type", (_osdRenderer.colorMode == kColorModePatchType),
-200, 130, callbackColor, kColorModePatchType, 'c');
hud.AddRadioButton(kHUD_RB_COLOR, "Patch coord", (_osdRenderer.colorMode == kColorModePatchCoord),
-200, 150, callbackColor, kColorModePatchCoord, 'c');
hud.AddRadioButton(kHUD_RB_COLOR, "Normal", (_osdRenderer.colorMode == kColorModeNormal),
-200, 170, callbackColor, kColorModeNormal, 'c');
if (_osdRenderer.ptexDisplacementFilename) {
hud.AddLabel("Displacement (D)", -200, 200);
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "None",
(_osdRenderer.displacementMode == kDisplacementModeNone),
-200, 220, callbackDisplacement, kDisplacementModeNone, 'd');
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "HW bilinear",
(_osdRenderer.displacementMode == kDisplacementModeHWBilinear),
-200, 240, callbackDisplacement, kDisplacementModeHWBilinear, 'd');
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "Bilinear",
(_osdRenderer.displacementMode == kDisplacementModeBilinear),
-200, 260, callbackDisplacement, kDisplacementModeBilinear, 'd');
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "Biquadratic",
(_osdRenderer.displacementMode == kDisplacementModeBiQuadratic),
-200, 280, callbackDisplacement, kDisplacementModeBiQuadratic, 'd');
{
int y = 310;
hud.AddLabel("Normal (N)", -200, y); y += 20;
hud.AddRadioButton(kHUD_RB_NORMAL, "Surface",
(_osdRenderer.normalMode == kNormalModeSurface),
-200, y, callbackNormal, kNormalModeSurface, 'n'); y += 20;
// hud.AddRadioButton(kHUD_RB_NORMAL, "Facet", //We can't really do NORMAL_FACET
// (_osdRenderer.normalMode == NORMAL_FACET),
// -200, y, callbackNormal, NORMAL_FACET, 'n'); y += 20;
hud.AddRadioButton(kHUD_RB_NORMAL, "HW Screen space",
(_osdRenderer.normalMode == kNormalModeHWScreenspace),
-200, y, callbackNormal, kNormalModeHWScreenspace, 'n'); y += 20;
hud.AddRadioButton(kHUD_RB_NORMAL, "Screen space",
(_osdRenderer.normalMode == kNormalModeScreenspace),
-200, y, callbackNormal, kNormalModeScreenspace, 'n'); y += 20;
hud.AddRadioButton(kHUD_RB_NORMAL, "Biquadratic",
(_osdRenderer.normalMode == kNormalModeBiQuadratic),
-200, y, callbackNormal, kNormalModeBiQuadratic, 'n'); y += 20;
hud.AddRadioButton(kHUD_RB_NORMAL, "Biquadratic WG",
(_osdRenderer.normalMode == kNormalModeBiQuadraticWG),
-200, y, callbackNormal, kNormalModeBiQuadraticWG, 'n'); y += 20;
}
}
hud.AddSlider("Mipmap Bias", 0, 5, 0,
-200, 450, 20, false, callbackSlider, kHUD_SL_MIPMAPBIAS);
hud.AddSlider("Displacement", 0, 5, 1,
-200, 490, 20, false, callbackSlider, kHUD_SL_DISPLACEMENT);
hud.AddCheckBox("Seamless Mipmap", _osdRenderer.useSeamlessMipmap,
-200, 530, callbackCheckbox, kHUD_CB_SEAMLESS_MIPMAP, 'j');
hud.Rebuild(self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
}
-(void)drawInMTKView:(MTKView *)view {
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
auto commandBuffer = [_commandQueue commandBuffer];
_osdRenderer.displacementScale = 3;
double avg = 0;
for(int i = 0; i < FRAME_HISTORY; i++)
avg += _frameBeginTimestamp[i];
avg /= FRAME_HISTORY;
auto renderEncoder = [_osdRenderer drawFrame:commandBuffer];
auto& hud = self.view->hud;
if(hud.IsVisible()) {
hud.DrawString(10, -120, "Tess level : %f", _osdRenderer.tessellationLevel);
hud.DrawString(10, -20, "FPS = %3.1f", 1.0 / avg);
//Disable Culling & Force Fill mode when drawing the UI
[renderEncoder setTriangleFillMode:MTLTriangleFillModeFill];
[renderEncoder setCullMode:MTLCullModeNone];
self.view->hud.Flush(renderEncoder);
};
[renderEncoder endEncoding];
__weak auto blockSemaphore = _frameSemaphore;
unsigned frameId = _currentFrame % FRAME_HISTORY;
auto frameBeginTime = CACurrentMediaTime();
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
dispatch_semaphore_signal(blockSemaphore);
_frameBeginTimestamp[frameId] = CACurrentMediaTime() - frameBeginTime;
}];
[commandBuffer presentDrawable:view.currentDrawable];
[commandBuffer commit];
_currentFrame++;
}
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
_osdRenderer.camera->aspectRatio = size.width / size.height;
}
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
}
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
descriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
descriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
descriptor.sampleCount = self.view.sampleCount;
}
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
return _commandQueue;
}
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
return _device;
}
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
return self.view.currentRenderPassDescriptor;
}
@end

View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {
return NSApplicationMain(argc, argv);
}

View File

@ -0,0 +1,33 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@ -0,0 +1,61 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end

View File

@ -0,0 +1,73 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11147" systemVersion="16A201u" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11119"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="1024" height="1366"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,265 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11173.2" systemVersion="16A264" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11143.2"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="MTKView">
<rect key="frame" x="0.0" y="0.0" width="1366" height="1024"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Information Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ze8-2s-lED">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minimumValue="1" maximumValue="5" translatesAutoresizingMaskIntoConstraints="NO" id="QQ6-5o-gla">
<connections>
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="uHZ-dB-XZV"/>
</connections>
</stepper>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Ref Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N12-GK-yLY">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="16" translatesAutoresizingMaskIntoConstraints="NO" id="eYp-5M-Rgk">
<connections>
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="mBg-38-OPM"/>
</connections>
</stepper>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="8kP-4Y-wzA">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="UsH-Nw-M31"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Wireframe" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FvR-NK-6s0" userLabel="Wireframe">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backpatch Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="esT-7h-XLG">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="P8z-O2-OLV">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="w7T-KH-L3E"/>
</connections>
</switch>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="5Ns-3P-r13">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ym1-Xw-wU6"/>
</connections>
</switch>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="fw1-9C-P6U">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="8kp-Rh-Yua"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backface Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iw4-VH-Zwm">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Patch Clip Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5xP-bY-PgM">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Crease" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kuw-3r-nzl">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7yA-a6-Sq7">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="Yg5-z5-avS"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Screenspace Tessellation" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ioY-T2-PEM">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Tes Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlx-hC-oDg">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sDC-ZC-b6I">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ebT-0s-gYR"/>
</connections>
</switch>
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lKi-xk-48C">
<constraints>
<constraint firstAttribute="width" constant="229" id="Wpt-NP-71K"/>
<constraint firstAttribute="height" constant="100" id="zRD-L8-taf"/>
</constraints>
<connections>
<outlet property="dataSource" destination="BYZ-38-t0r" id="9Fy-8F-lh4"/>
<outlet property="delegate" destination="BYZ-38-t0r" id="AGI-ts-ucC"/>
</connections>
</pickerView>
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MhN-MJ-gcY">
<constraints>
<constraint firstAttribute="width" constant="229" id="2un-1F-Mel"/>
<constraint firstAttribute="height" constant="100" id="e85-YP-l4W"/>
</constraints>
<connections>
<outlet property="dataSource" destination="BYZ-38-t0r" id="fva-Gz-Lm9"/>
<outlet property="delegate" destination="BYZ-38-t0r" id="vnc-OK-4c7"/>
</connections>
</pickerView>
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pci-qy-cH2">
<constraints>
<constraint firstAttribute="width" constant="229" id="ZYQ-3j-No7"/>
<constraint firstAttribute="height" constant="100" id="iBl-mj-oGZ"/>
</constraints>
<connections>
<outlet property="dataSource" destination="BYZ-38-t0r" id="e4g-y8-rgS"/>
<outlet property="delegate" destination="BYZ-38-t0r" id="txx-qB-tmn"/>
</connections>
</pickerView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Color Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q2s-bO-zy8">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Normal Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="I4F-1D-Czt">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Displacement Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uci-PY-aOB">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="5Ee-cu-NZx">
<constraints>
<constraint firstAttribute="width" constant="300" id="zHK-PA-cxQ"/>
</constraints>
<connections>
<action selector="sliderChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="x6e-A1-PtP"/>
</connections>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Mipmap Bias" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ep7-AF-66o">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Displacement" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2eJ-wE-QUZ">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="lg4-UF-DUA">
<constraints>
<constraint firstAttribute="width" constant="300" id="SAY-uf-0VR"/>
</constraints>
<connections>
<action selector="sliderChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="T6h-NW-Qz3"/>
</connections>
</slider>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="P8z-O2-OLV" firstAttribute="leading" secondItem="esT-7h-XLG" secondAttribute="trailing" constant="8" id="0zt-WU-LC3"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="404-z0-Fv7"/>
<constraint firstItem="pci-qy-cH2" firstAttribute="centerY" secondItem="uci-PY-aOB" secondAttribute="centerY" id="51c-EC-nM4"/>
<constraint firstAttribute="trailing" secondItem="pci-qy-cH2" secondAttribute="trailing" constant="8" id="5JD-9Q-LoS"/>
<constraint firstItem="MhN-MJ-gcY" firstAttribute="top" secondItem="pci-qy-cH2" secondAttribute="bottom" constant="8" id="5We-Fg-mqK"/>
<constraint firstItem="8kP-4Y-wzA" firstAttribute="leading" secondItem="FvR-NK-6s0" secondAttribute="trailing" constant="8" id="5rd-n5-Uxl"/>
<constraint firstItem="5Ee-cu-NZx" firstAttribute="trailing" secondItem="lg4-UF-DUA" secondAttribute="trailing" id="7wp-4z-St6"/>
<constraint firstItem="8kP-4Y-wzA" firstAttribute="top" secondItem="7yA-a6-Sq7" secondAttribute="bottom" constant="8" id="81h-8V-det"/>
<constraint firstItem="lKi-xk-48C" firstAttribute="leading" secondItem="Q2s-bO-zy8" secondAttribute="trailing" constant="8" id="9Hf-nv-kO7"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="leading" secondItem="dlx-hC-oDg" secondAttribute="trailing" constant="8" id="B0o-kO-368"/>
<constraint firstAttribute="trailing" secondItem="MhN-MJ-gcY" secondAttribute="trailing" constant="8" id="B5N-TG-DvY"/>
<constraint firstAttribute="trailing" secondItem="lKi-xk-48C" secondAttribute="trailing" constant="8" id="Dsf-kk-VQH"/>
<constraint firstItem="8kP-4Y-wzA" firstAttribute="trailing" secondItem="7yA-a6-Sq7" secondAttribute="trailing" id="HIl-Xg-PwW"/>
<constraint firstItem="ioY-T2-PEM" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="25" id="Kg5-1N-BpG"/>
<constraint firstItem="P8z-O2-OLV" firstAttribute="centerY" secondItem="esT-7h-XLG" secondAttribute="centerY" id="Oxf-2f-wTD"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="top" secondItem="QQ6-5o-gla" secondAttribute="bottom" constant="8" id="PJS-Lq-bIL"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="lKi-xk-48C" secondAttribute="bottom" constant="25" id="PnT-0o-uNH"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="top" secondItem="sDC-ZC-b6I" secondAttribute="bottom" constant="8" id="QC2-TN-FjW"/>
<constraint firstItem="Ze8-2s-lED" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="20" id="SZK-UA-BiA"/>
<constraint firstItem="MhN-MJ-gcY" firstAttribute="leading" secondItem="I4F-1D-Czt" secondAttribute="trailing" constant="8" id="T1r-ZQ-Jxi"/>
<constraint firstItem="MhN-MJ-gcY" firstAttribute="centerY" secondItem="I4F-1D-Czt" secondAttribute="centerY" id="Tdj-kw-7IN"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="dlx-hC-oDg" secondAttribute="bottom" constant="25" id="U0T-iQ-NLt"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="fw1-9C-P6U" secondAttribute="bottom" constant="20" id="Uw7-fz-We7"/>
<constraint firstItem="sDC-ZC-b6I" firstAttribute="leading" secondItem="kuw-3r-nzl" secondAttribute="trailing" constant="8" id="W06-wv-gqs"/>
<constraint firstItem="QQ6-5o-gla" firstAttribute="centerY" secondItem="N12-GK-yLY" secondAttribute="centerY" id="bqu-uw-PqG"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="centerY" secondItem="dlx-hC-oDg" secondAttribute="centerY" id="cV6-GZ-8IP"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="leading" secondItem="ioY-T2-PEM" secondAttribute="trailing" constant="8" id="cqL-gl-vn2"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="5xP-bY-PgM" secondAttribute="bottom" constant="25" id="cqZ-ZJ-qwf"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="leading" secondItem="5xP-bY-PgM" secondAttribute="trailing" constant="8" id="dhX-z5-kgA"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="5Ee-cu-NZx" secondAttribute="bottom" constant="25" id="erc-MZ-6N2"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="centerY" secondItem="Iw4-VH-Zwm" secondAttribute="centerY" id="fEO-gM-cmZ"/>
<constraint firstItem="lg4-UF-DUA" firstAttribute="leading" secondItem="2eJ-wE-QUZ" secondAttribute="trailing" constant="8" id="gne-Dp-lLU"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="gqA-q9-SK3"/>
<constraint firstItem="lKi-xk-48C" firstAttribute="centerY" secondItem="Q2s-bO-zy8" secondAttribute="centerY" id="hdJ-mn-wba"/>
<constraint firstItem="pci-qy-cH2" firstAttribute="leading" secondItem="uci-PY-aOB" secondAttribute="trailing" constant="8" id="huu-H0-Tby"/>
<constraint firstItem="5Ee-cu-NZx" firstAttribute="centerY" secondItem="ep7-AF-66o" secondAttribute="centerY" id="iXa-Hm-SyL"/>
<constraint firstItem="Ze8-2s-lED" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="20" id="kTX-YC-JKR"/>
<constraint firstItem="dlx-hC-oDg" firstAttribute="leading" secondItem="fw1-9C-P6U" secondAttribute="trailing" constant="57" id="kk2-dV-2jk"/>
<constraint firstItem="lKi-xk-48C" firstAttribute="top" secondItem="MhN-MJ-gcY" secondAttribute="bottom" constant="8" id="m49-1U-Jcw"/>
<constraint firstItem="8kP-4Y-wzA" firstAttribute="centerY" secondItem="FvR-NK-6s0" secondAttribute="centerY" id="n3L-qM-7Pr"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="centerY" secondItem="5xP-bY-PgM" secondAttribute="centerY" id="nP1-Bt-GuV"/>
<constraint firstItem="lKi-xk-48C" firstAttribute="top" secondItem="MhN-MJ-gcY" secondAttribute="bottom" constant="8" id="nrc-E0-3gd"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="trailing" secondItem="sDC-ZC-b6I" secondAttribute="trailing" id="pkW-Gf-A1P"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="top" secondItem="P8z-O2-OLV" secondAttribute="bottom" constant="8" id="pwK-2F-IIf"/>
<constraint firstItem="P8z-O2-OLV" firstAttribute="top" secondItem="8kP-4Y-wzA" secondAttribute="bottom" constant="8" id="q11-mD-QDz"/>
<constraint firstItem="QQ6-5o-gla" firstAttribute="leading" secondItem="N12-GK-yLY" secondAttribute="trailing" constant="8" id="qBz-A8-IZc"/>
<constraint firstItem="P8z-O2-OLV" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="rha-qA-vsj"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="ro3-hx-iLk"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="leading" secondItem="Iw4-VH-Zwm" secondAttribute="trailing" constant="8" id="ry7-bQ-bRa"/>
<constraint firstItem="MhN-MJ-gcY" firstAttribute="top" secondItem="pci-qy-cH2" secondAttribute="bottom" constant="8" id="sR8-Lw-q9X"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="trailing" secondItem="QQ6-5o-gla" secondAttribute="trailing" id="syp-eW-H7w"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="tsW-3r-293"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="centerY" secondItem="ioY-T2-PEM" secondAttribute="centerY" id="wE0-Cg-4Qf"/>
<constraint firstItem="sDC-ZC-b6I" firstAttribute="centerY" secondItem="kuw-3r-nzl" secondAttribute="centerY" id="wTg-7H-KXF"/>
<constraint firstItem="lg4-UF-DUA" firstAttribute="centerY" secondItem="2eJ-wE-QUZ" secondAttribute="centerY" id="x0b-B2-XkG"/>
<constraint firstItem="ep7-AF-66o" firstAttribute="leading" secondItem="eYp-5M-Rgk" secondAttribute="trailing" constant="52" id="xFx-Kb-IBp"/>
<constraint firstItem="5Ee-cu-NZx" firstAttribute="leading" secondItem="ep7-AF-66o" secondAttribute="trailing" constant="8" id="xye-mn-VX2"/>
<constraint firstItem="5Ee-cu-NZx" firstAttribute="top" secondItem="lg4-UF-DUA" secondAttribute="bottom" constant="8" id="zVK-yu-Uuz"/>
</constraints>
</view>
<connections>
<outlet property="backfaceCullingSwitch" destination="5Ns-3P-r13" id="n8X-2V-BRl"/>
<outlet property="backpatchCullingSwitch" destination="P8z-O2-OLV" id="VIe-Lv-hsC"/>
<outlet property="colorModePickerView" destination="lKi-xk-48C" id="u5F-aY-10I"/>
<outlet property="displacementModePickerView" destination="pci-qy-cH2" id="jaV-1A-n0X"/>
<outlet property="displacementSlider" destination="lg4-UF-DUA" id="BWG-lH-Qfm"/>
<outlet property="frameTimeLabel" destination="Ze8-2s-lED" id="vLj-Id-oiv"/>
<outlet property="mipmapBiasSlider" destination="5Ee-cu-NZx" id="WGF-bb-PaA"/>
<outlet property="normalModePickerView" destination="MhN-MJ-gcY" id="LJw-CH-3Im"/>
<outlet property="patchClipCullingSwitch" destination="fw1-9C-P6U" id="P2G-3F-eJh"/>
<outlet property="refLvlLabel" destination="N12-GK-yLY" id="lXc-6r-pZY"/>
<outlet property="refinementStepper" destination="QQ6-5o-gla" id="URK-fS-krY"/>
<outlet property="screenspaceTessellationSwitch" destination="7yA-a6-Sq7" id="RpM-ER-4Oy"/>
<outlet property="singleCreaseSwitch" destination="sDC-ZC-b6I" id="Arw-OY-Z4A"/>
<outlet property="tesLvLlabel" destination="dlx-hC-oDg" id="haB-Hi-A9B"/>
<outlet property="tessellationStepper" destination="eYp-5M-Rgk" id="IFG-H5-rJS"/>
<outlet property="wireframeSwitch" destination="8kP-4Y-wzA" id="y3a-yu-4cs"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="463.83601756954607" y="406.640625"/>
</scene>
</scenes>
<color key="tintColor" cocoaTouchSystemColor="darkTextColor"/>
</document>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>mtlPtexViewer</string>
<key>CFBundleIdentifier</key>
<string>com.osd.mtlPtexViewer</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>mtlPtexViewer</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
<string>metal</string>
</array>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,57 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <UIKit/UIKit.h>
#import <MetalKit/MetalKit.h>
#import "../mtlPtexViewer.h"
@interface ViewController : UIViewController<
MTKViewDelegate,
UIPickerViewDelegate,
UIPickerViewDataSource,
OSDRendererDelegate
>
@property (weak, nonatomic) IBOutlet UILabel *refLvlLabel;
@property (weak, nonatomic) IBOutlet UILabel *tesLvLlabel;
@property (weak, nonatomic) IBOutlet UILabel *frameTimeLabel;
@property (weak, nonatomic) IBOutlet UIPickerView *colorModePickerView;
@property (weak, nonatomic) IBOutlet UIPickerView *normalModePickerView;
@property (weak, nonatomic) IBOutlet UIPickerView *displacementModePickerView;
@property (weak, nonatomic) IBOutlet UIStepper *tessellationStepper;
@property (weak, nonatomic) IBOutlet UIStepper *refinementStepper;
@property (weak, nonatomic) IBOutlet UISwitch *wireframeSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *backpatchCullingSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *backfaceCullingSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *patchClipCullingSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *singleCreaseSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *screenspaceTessellationSwitch;
@property (weak, nonatomic) IBOutlet UISlider *displacementSlider;
@property (weak, nonatomic) IBOutlet UISlider *mipmapBiasSlider;
- (IBAction)stepperChanged:(UIStepper *)sender;
- (IBAction)switchChanged:(UISwitch *)sender;
- (IBAction)sliderChanged:(UISlider*)sender;
@end

View File

@ -0,0 +1,297 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "ViewController.h"
#define FRAME_HISTORY 30
@interface ViewController ()
{
dispatch_semaphore_t _frameSemaphore;
CGPoint _startTouch;
bool _isTouching;
OSDRenderer* _osdRenderer;
MTKView* _view;
id<MTLDevice> _device;
id<MTLCommandQueue> _commandQueue;
double _frameTimes[FRAME_HISTORY];
uint64_t _currentFrame;
UIPanGestureRecognizer *_zoomGesture;
}
@end
@implementation ViewController
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
_osdRenderer.camera->aspectRatio = size.width / size.height;
}
-(void)drawInMTKView:(MTKView *)view {
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
auto commandBuffer = [_commandQueue commandBuffer];
[_osdRenderer drawFrame:commandBuffer];
__weak auto blockSemaphore = _frameSemaphore;
unsigned frameIndex = _currentFrame % FRAME_HISTORY;
const auto beginTime = CACurrentMediaTime();
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
dispatch_semaphore_signal(blockSemaphore);
_frameTimes[frameIndex] = CACurrentMediaTime() - beginTime;
}];
[commandBuffer presentDrawable:_view.currentDrawable];
[commandBuffer commit];
_currentFrame++;
double frameAverage = 0;
for(auto& x : _frameTimes)
frameAverage += x;
frameAverage /= 30.0;
_frameTimeLabel.text = [NSString stringWithFormat:@"%0.2f ms", frameAverage * 1000.0];
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (void)viewDidLoad {
[super viewDidLoad];
_view = (MTKView*)self.view;
_frameSemaphore = dispatch_semaphore_create(3);
_device = MTLCreateSystemDefaultDevice();
_commandQueue = [_device newCommandQueue];
_view.device = _device;
_view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
_view.sampleCount = 2;
_view.frame = CGRectMake(0, 0, 1920, 1080);
_view.contentScaleFactor = 1;
_view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
_view.delegate = self;
_zoomGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_zoomView)];
_zoomGesture.minimumNumberOfTouches = 2;
_zoomGesture.maximumNumberOfTouches = 2;
_zoomGesture.cancelsTouchesInView = true;
[_view addGestureRecognizer:_zoomGesture];
[self _applyOptions];
}
-(void)_applyOptions {
_osdRenderer.useSingleCrease = _singleCreaseSwitch.isOn;
_osdRenderer.usePatchBackfaceCulling = _backpatchCullingSwitch.isOn;
_osdRenderer.usePrimitiveBackfaceCulling = _backfaceCullingSwitch.isOn;
_osdRenderer.useScreenspaceTessellation = sender.isOn;
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
_osdRenderer.usePatchClipCulling = _patchClipCullingSwitch.isOn;
_osdRenderer.useAdaptive = true;
_osdRenderer.freeze = true;
_osdRenderer.animateVertices = false;
_osdRenderer.kernelType = kMetal;
_osdRenderer.refinementLevel = _refinementStepper.value;
_osdRenderer.tessellationLevel = _tessellationStepper.value;
_osdRenderer.colorMode = (ColorMode)[_colorModePickerView selectedRowInComponent:0];
_osdRenderer.normalMode = (NormalMode)[_normalModePickerView selectedRowInComponent:0];
_osdRenderer.displacementMode = (DisplacementMode)[_displacementModePickerView selectedRowInComponent:0];
_osdRenderer.mipmapBias = _mipmapBiasSlider.value;
_osdRenderer.displacementScale = _displacementSlider.value;
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
[_tesLvLlabel sizeToFit];
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
[_refLvlLabel sizeToFit];
}
-(void)_zoomView {
static float lastY = 0;
if(_zoomGesture.state == UIGestureRecognizerStateBegan) {
lastY = [_zoomGesture translationInView:_view].y;
} else if(_zoomGesture.state == UIGestureRecognizerStateChanged) {
const auto currentY = [_zoomGesture translationInView:_view].y;
const auto deltaY = (currentY - lastY) / 100.0;
lastY = currentY;
_osdRenderer.camera->dollyDistance += deltaY;
}
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
_isTouching = true;
_startTouch = [touches.anyObject locationInView:self.view];
[super touchesBegan:touches withEvent:event];
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
_isTouching = false;
[super touchesEnded:touches withEvent:event];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if(_isTouching)
{
for(UITouch* touch in touches)
{
CGPoint location = [touch locationInView:self.view];
_startTouch = [touch previousLocationInView:self.view];
double deltaX = location.x - _startTouch.x;
double deltaY = location.y - _startTouch.y;
_osdRenderer.camera->rotationX += deltaX / 5.0;
_osdRenderer.camera->rotationY += deltaY / 5.0;
}
}
[super touchesMoved:touches withEvent:event];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
return _device;
}
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
return _commandQueue;
}
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
return _view.currentRenderPassDescriptor;
}
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
}
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
descriptor.colorAttachments[0].pixelFormat = _view.colorPixelFormat;
descriptor.depthAttachmentPixelFormat = _view.depthStencilPixelFormat;
descriptor.sampleCount = _view.sampleCount;
}
- (IBAction)stepperChanged:(UIStepper *)sender {
if(sender == _tessellationStepper) {
_osdRenderer.tessellationLevel = sender.value;
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
[_tesLvLlabel sizeToFit];
} else if (sender == _refinementStepper) {
_osdRenderer.refinementLevel = sender.value;
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
[_refLvlLabel sizeToFit];
}
}
- (IBAction)switchChanged:(UISwitch *)sender {
if(sender == _wireframeSwitch) {
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
} else if(sender == _backpatchCullingSwitch) {
_osdRenderer.usePatchBackfaceCulling = sender.isOn;
} else if(sender == _backfaceCullingSwitch) {
_osdRenderer.usePrimitiveBackfaceCulling = sender.isOn;
} else if(sender == _patchClipCullingSwitch) {
_osdRenderer.usePatchClipCulling = sender.isOn;
} else if(sender == _singleCreaseSwitch) {
_osdRenderer.useSingleCrease = sender.isOn;
} else if(sender == _screenspaceTessellationSwitch) {
_osdRenderer.useScreenspaceTessellation = sender.isOn;
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
}
}
-(void)sliderChanged:(UISlider *)sender {
if(sender == _displacementSlider) {
_osdRenderer.displacementScale = sender.value;
} else if(sender == _mipmapBiasSlider) {
_osdRenderer.mipmapBias = sender.value;
}
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if(pickerView == _colorModePickerView) {
return 8;
} else if(pickerView == _normalModePickerView) {
return 5;
} else if(pickerView == _displacementModePickerView) {
return 4;
}
return 0;
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(pickerView == _colorModePickerView) {
switch(row) {
case kColorModePtexNearest: return @"Ptex Nearest";
case kColorModeNormal: return @"Normal";
case kColorModeNone: return @"None";
case kColorModePatchType: return @"Patch Type";
case kColorModePatchCoord: return @"Patch Coord";
case kColorModePtexBilinear: return @"Ptex Bilinear";
case kColorModePtexHWBilinear: return @"Ptex HW Bilinear";
case kColorModePtexBiQuadratic: return @"Ptex BiQuadratic";
}
} else if(pickerView == _normalModePickerView) {
switch(row) {
case kNormalModeSurface: return @"Surface";
case kNormalModeBiQuadratic: return @"BiQuadratic";
case kNormalModeScreenspace: return @"Screenspace";
case kNormalModeBiQuadraticWG: return @"BiQuadratic WG";
case kNormalModeHWScreenspace: return @"HW Screenspace";
}
} else if(pickerView == _displacementModePickerView) {
switch (row) {
case kDisplacementModeBilinear: return @"Bilinear";
case KDisplacementModeNone: return @"None";
case kDisplacementModeHWBilinear: return @"HW Bilinear";
case kDisplacementModeBiQuadratic: return @"BiQuadratic";
}
}
return @"";
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if(pickerView == _colorModePickerView) {
_osdRenderer.colorMode = (ColorMode)row;
} else if(pickerView == _normalModePickerView) {
_osdRenderer.normalMode = (NormalMode)row;
} else if(pickerView == _displacementModePickerView) {
_osdRenderer.displacementMode = (DisplacementMode)row;
}
}
@end

View File

@ -0,0 +1,8 @@
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@ -0,0 +1,122 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../../regression/common/shape_utils.h"
#include "../../regression/shapes/all.h"
struct ShapeDesc {
ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme,
bool iIsLeftHanded = false) :
name(iname), data(idata), scheme(ischeme), isLeftHanded(iIsLeftHanded) { }
std::string name,
data;
Scheme scheme;
bool isLeftHanded;
};
static std::vector<ShapeDesc> g_defaultShapes;
//------------------------------------------------------------------------------
static void initShapes() {
// g_defaultShapes.push_back(ShapeDesc("temple", Viewer::shapes::temple, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_fan", catmark_fan, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_flap", catmark_flap, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_flap2", catmark_flap2, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/));
g_defaultShapes.push_back(ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark));
// g_defaultShapes.push_back(ShapeDesc("catmark_pole8", catmark_pole8, kCatmark));
// g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark));
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark));
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases1", catmark_tent_creases1, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_tent", catmark_tent, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_torus", catmark_torus, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark));
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit0", catmark_square_hedit0, kCatmark ) );
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit1", catmark_square_hedit1, kCatmark ) );
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit2", catmark_square_hedit2, kCatmark ) );
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit3", catmark_square_hedit3, kCatmark ) );
g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
//
// g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
//
// g_defaultShapes.push_back(ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_pole8", loop_pole8, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
// g_defaultShapes.push_back(ShapeDesc("loop_pole360", loop_pole360, kLoop));
}

View File

@ -0,0 +1,107 @@
#pragma once
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
typedef enum {
kCPU = 0,
kMetal,
} KernelType;
typedef enum {
kDisplacementModeHWBilinear = 0,
kDisplacementModeBilinear,
kDisplacementModeBiQuadratic,
kDisplacementModeNone
} DisplacementMode;
typedef enum {
kNormalModeHWScreenspace = 0,
kNormalModeScreenspace,
kNormalModeBiQuadratic,
kNormalModeBiQuadraticWG,
kNormalModeSurface
} NormalMode;
typedef enum {
kDisplayStyleWire = 0,
kDisplayStyleShaded,
kDisplayStyleWireOnShaded,
} DisplayStyle;
typedef enum {
kColorModePtexNearest = 0,
kColorModePtexBilinear,
kColorModePtexHWBilinear,
kColorModePtexBiQuadratic,
kColorModePatchType,
kColorModePatchCoord,
kColorModeNormal,
kColorModeNone
} ColorMode;
typedef struct {
float rotationX;
float rotationY;
float dollyDistance;
float aspectRatio;
} Camera;
@class OSDRenderer;
@protocol OSDRendererDelegate <NSObject>
-(id<MTLDevice>)deviceFor:(OSDRenderer*)renderer;
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer*)renderer;
-(MTLRenderPassDescriptor*)renderPassDescriptorFor:(OSDRenderer*)renderer;
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor*)descriptor for:(OSDRenderer*)renderer;
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor*)descriptor for:(OSDRenderer*)renderer;
@end
@interface OSDRenderer : NSObject
-(instancetype)initWithDelegate:(id<OSDRendererDelegate>)delegate;
-(id<MTLRenderCommandEncoder>)drawFrame:(id<MTLCommandBuffer>)commandBuffer;
@property (readonly, nonatomic) id<OSDRendererDelegate> delegate;
@property (nonatomic) unsigned refinementLevel;
@property (nonatomic) float tessellationLevel;
@property (readonly, nonatomic) NSArray<NSString*>* loadedModels;
@property (nonatomic) NSString* currentModel;
@property (readonly, nonatomic) Camera* camera;
@property (nonatomic) bool useSeamlessMipmap;
@property (nonatomic) bool useFractionalTessellation;
@property (nonatomic) bool useScreenspaceTessellation;
@property (nonatomic) bool usePatchIndexBuffer;
@property (nonatomic) bool usePatchBackfaceCulling;
@property (nonatomic) bool usePatchClipCulling;
@property (nonatomic) bool useSingleCrease;
@property (nonatomic) bool useInfinitelySharpPatch;
@property (nonatomic) bool useStageIn;
@property (nonatomic) bool usePrimitiveBackfaceCulling;
@property (nonatomic) bool useAdaptive;
@property (nonatomic) bool freeze;
@property (nonatomic) bool animateVertices;
@property (nonatomic) bool displayControlMeshEdges;
@property (nonatomic) bool displayControlMeshVertices;
@property (nonatomic) bool displaySpecular;
@property (nonatomic) bool displayOcclusion;
@property (nonatomic) float mipmapBias;
@property (nonatomic) float displacementScale;
@property (nonatomic) NSString* ptexColorFilename;
@property (nonatomic) NSString* ptexDisplacementFilename;
@property (nonatomic) NSString* ptexOcclusionFilename;
@property (nonatomic) NSString* ptexSpecularFilename;
@property (nonatomic) ColorMode colorMode;
@property (nonatomic) NormalMode normalMode;
@property (nonatomic) DisplacementMode displacementMode;
@property (nonatomic) DisplayStyle displayStyle;
@property (nonatomic) KernelType kernelType;
@end

View File

@ -0,0 +1,697 @@
#line 0 "examples/mtlPtexViewer/mtlPtexViewer.metal"
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include <metal_stdlib>
using namespace metal;
struct Config {
float displacementScale;
float mipmapBias;
};
struct PerFrameConstants {
float4x4 ModelViewMatrix;
float4x4 ProjectionMatrix;
float4x4 ModelViewProjectionMatrix;
float4x4 ModelViewInverseMatrix;
float TessLevel;
};
// ---------------------------------------------------------------------------
const constant float4 patchColors[] = {
float4(1.0f, 1.0f, 1.0f, 1.0f), // regular
float4(0.0f, 1.0f, 1.0f, 1.0f), // regular pattern 0
float4(0.0f, 0.5f, 1.0f, 1.0f), // regular pattern 1
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(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.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.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.50f, 0.6f, 1.0f), // single crease pattern 4
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.2f, 0.75f, 1.0f), // boundary pattern 1
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.8f, 0.75f, 1.0f), // boundary pattern 4
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 1
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 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, 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
};
float4
getAdaptivePatchColor(int3 patchParam, float sharpness)
{
int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
int patchType = 0;
#if OSD_PATCH_ENABLE_SINGLE_CREASE
if (sharpness > 0) {
pattern = 1;
}
#endif
if (edgeCount == 1) {
patchType = 2; // BOUNDARY
}
if (edgeCount == 2) {
patchType = 3; // CORNER
}
// XXX: it looks like edgeCount != 0 for some gregory boundary patches.
// there might be a bug somewhere...
#if OSD_PATCH_GREGORY
patchType = 4;
#elif OSD_PATCH_GREGORY_BOUNDARY
patchType = 5;
#elif OSD_PATCH_GREGORY_BASIS
patchType = 6;
#endif
return patchColors[6*patchType + pattern];
}
#if DISPLACEMENT_HW_BILINEAR \
|| DISPLACEMENT_BILINEAR \
|| DISPLACEMENT_BIQUADRATIC \
|| NORMAL_HW_SCREENSPACE \
|| NORMAL_SCREENSPACE \
|| NORMAL_BIQUADRATIC \
|| NORMAL_BIQUADRATIC_WG
#define USE_DISPLACEMENT_RESOURCES 1
#endif
#if DISPLACEMENT_HW_BILINEAR \
|| DISPLACEMENT_BILINEAR \
|| DISPLACEMENT_BIQUADRATIC
#define USE_DISPLACEMENT 1
#undef OSD_DISPLACEMENT_CALLBACK
#define OSD_DISPLACEMENT_CALLBACK \
float3 displacement(float3 position, float3 normal, float4 patchCoord, float mipmapBias, float displacementScale
#if USE_DISPLACEMENT_RESOURCES
,texture2d_array<float, access::sample> textureDisplace_Data
,device ushort* textureDisplace_Packing
#endif
)
{
#if DISPLACEMENT_HW_BILINEAR
float disp = PtexLookupFast(patchCoord, mipmapBias,
textureDisplace_Data,
textureDisplace_Packing).x;
#elif DISPLACEMENT_BILINEAR
float disp = PtexMipmapLookup(patchCoord, mipmapBias,
textureDisplace_Data,
textureDisplace_Packing).x;
#elif DISPLACEMENT_BIQUADRATIC
float disp = PtexMipmapLookupQuadratic(patchCoord, mipmapBias,
textureDisplace_Data,
textureDisplace_Packing).x;
#else
float disp(0);
#endif
return position + disp*normal * displacementScale;
}
#endif
float4 GeneratePatchCoord(float2 uv, int3 patchParam) // for non-adaptive
{
return OsdInterpolatePatchCoord(uv, patchParam);
}
#if NORMAL_HW_SCREENSPACE || NORMAL_SCREENSPACE
float3
perturbNormalFromDisplacement(float3 position, float3 normal, float4 patchCoord, float mipmapBias
,texture2d_array<float, access::sample> textureDisplace_Data
,device ushort* textureDisplace_Packing
,float displacementScale)
{
// by Morten S. Mikkelsen
// http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf
// slightly modified for ptex guttering
float3 vSigmaS = dfdx(position);
float3 vSigmaT = dfdy(position);
float3 vN = normal;
float3 vR1 = cross(vSigmaT, vN);
float3 vR2 = cross(vN, vSigmaS);
float fDet = dot(vSigmaS, vR1);
#if 0
// not work well with ptex
float dBs = dfdx(disp);
float dBt = dfdy(disp);
#else
float2 texDx = dfdx(patchCoord.xy);
float2 texDy = dfdy(patchCoord.xy);
// limit forward differencing to the width of ptex gutter
const float resolution = 128.0;
float d = min(1.0f, (0.5/resolution)/max(length(texDx), length(texDy)));
float4 STll = patchCoord;
float4 STlr = patchCoord + d * float4(texDx.x, texDx.y, 0, 0);
float4 STul = patchCoord + d * float4(texDy.x, texDy.y, 0, 0);
#if NORMAL_HW_SCREENSPACE
float Hll = PtexLookupFast(STll, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
float Hlr = PtexLookupFast(STlr, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
float Hul = PtexLookupFast(STul, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
#elif NORMAL_SCREENSPACE
float Hll = PtexMipmapLookup(STll, mipmapBias, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
float Hlr = PtexMipmapLookup(STlr, mipmapBias, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
float Hul = PtexMipmapLookup(STul, mipmapBias, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
#endif
float dBs = (Hlr - Hll)/d;
float dBt = (Hul - Hll)/d;
#endif
float3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
return normalize(abs(fDet) * vN - vSurfGrad);
}
#endif // NORMAL_SCREENSPACE
// ---------------------------------------------------------------------------
// Vertex Shader
// ---------------------------------------------------------------------------
struct FragmentInput
{
float4 positionOut [[position]];
float3 position;
float3 normal;
float3 tangent;
float3 bitangent;
float4 patchCoord;
#if COLOR_PATCHTYPE
float4 patchColor;
#endif
#if OSD_COMPUTE_NORMAL_DERIVATIVES
float3 Nu;
float3 Nv;
#endif
};
#if OSD_IS_ADAPTIVE
#if USE_STAGE_IN
#if OSD_PATCH_REGULAR
struct ControlPoint
{
float3 P [[attribute(0)]];
#if OSD_PATCH_ENABLE_SINGLE_CREASE
float3 P1 [[attribute(1)]];
float3 P2 [[attribute(2)]];
#if !USE_PTVS_SHARPNESS
float2 vSegments [[attribute(3)]];
#endif
#endif
};
struct PatchInput
{
patch_control_point<ControlPoint> cv;
#if !USE_PTVS_FACTORS
float4 tessOuterLo [[attribute(5)]];
float4 tessOuterHi [[attribute(6)]];
#endif
int3 patchParam [[attribute(10)]];
};
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
struct ControlPoint
{
float3 P [[attribute(0)]];
float3 Ep [[attribute(1)]];
float3 Em [[attribute(2)]];
float3 Fp [[attribute(3)]];
float3 Fm [[attribute(4)]];
};
struct PatchInput
{
patch_control_point<ControlPoint> cv;
int3 patchParam [[attribute(10)]];
};
#elif OSD_PATCH_GREGORY_BASIS
struct ControlPoint
{
float3 position [[attribute(0)]];
};
struct PatchInput
{
patch_control_point<ControlPoint> cv;
int3 patchParam [[attribute(10)]];
};
#endif
#endif
kernel void compute_main(
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
unsigned thread_position_in_grid [[thread_position_in_grid]],
unsigned thread_position_in_threadgroup [[thread_position_in_threadgroup]],
unsigned threadgroup_position_in_grid [[threadgroup_position_in_grid]],
OsdPatchParamBufferSet osdBuffers,
device MTLQuadTessellationFactorsHalf* quadTessellationFactors [[buffer(QUAD_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)]]
#endif
)
{
threadgroup int3 patchParam[PATCHES_PER_THREADGROUP];
threadgroup PatchVertexType patchVertices[PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH];
const auto real_threadgroup = thread_position_in_grid / REAL_THREADGROUP_DIVISOR;
const auto subthreadgroup_in_threadgroup = thread_position_in_threadgroup / REAL_THREADGROUP_DIVISOR;
const auto real_thread_in_threadgroup = thread_position_in_threadgroup & (REAL_THREADGROUP_DIVISOR - 1);
#if NEEDS_BARRIER
const auto validThread = thread_position_in_grid * CONTROL_POINTS_PER_THREAD < osdBuffers.kernelExecutionLimit;
#else
const auto validThread = true;
if(thread_position_in_grid * CONTROL_POINTS_PER_THREAD >= osdBuffers.kernelExecutionLimit)
return;
#endif
if(validThread)
{
patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer);
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 v = osdBuffers.vertexBuffer[vertexId];
threadgroup auto& patchVertex = patchVertices[thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset];
OsdComputePerVertex(float4(v.position,1), patchVertex, vertexId, frameConsts.ModelViewProjectionMatrix, osdBuffers);
//User per vertex goes here, modifying 'patchVertex'
}
}
#if NEEDS_BARRIER
threadgroup_barrier(mem_flags::mem_threadgroup);
#endif
if(validThread)
{
#if PATCHES_PER_THREADGROUP > 1
auto patch = patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_THREAD * CONTROL_POINTS_PER_PATCH;
#else
//Small optimization for the '1 patch per threadgroup' case
auto patch = patchVertices;
#endif
if(!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix))
{
#if !OSD_USE_PATCH_INDEX_BUFFER
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[0] = 0.0h;
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[1] = 0.0h;
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[2] = 0.0h;
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[3] = 0.0h;
quadTessellationFactors[real_threadgroup].insideTessellationFactor[0] = 0.0h;
quadTessellationFactors[real_threadgroup].insideTessellationFactor[1] = 0.0h;
#endif
patchParam[subthreadgroup_in_threadgroup].z = -1;
#if !NEEDS_BARRIER
return;
#endif
}
}
#if NEEDS_BARRIER
threadgroup_barrier(mem_flags::mem_threadgroup);
#endif
if(validThread && patchParam[subthreadgroup_in_threadgroup].z != -1)
{
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
{
OsdComputePerPatchVertex(
patchParam[subthreadgroup_in_threadgroup],
real_thread_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset,
real_threadgroup,
thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset,
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
osdBuffers
);
}
}
#if NEEDS_BARRIER
threadgroup_barrier(mem_flags::mem_device_and_threadgroup);
#endif
if(validThread && real_thread_in_threadgroup == 0)
{
#if OSD_USE_PATCH_INDEX_BUFFER
const auto patchId = atomic_fetch_add_explicit((device atomic_uint*)&drawIndirectCommands->patchCount, 1, memory_order_relaxed);
patchIndex[patchId] = real_threadgroup;
#else
const auto patchId = real_threadgroup;
#endif
OsdComputePerPatchFactors(
patchParam[subthreadgroup_in_threadgroup],
frameConsts.TessLevel,
real_threadgroup,
frameConsts.ProjectionMatrix,
frameConsts.ModelViewMatrix,
osdBuffers,
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
quadTessellationFactors[patchId]
);
}
}
[[patch(quad, VERTEX_CONTROL_POINTS_PER_PATCH)]]
vertex FragmentInput vertex_main(
const constant Config& config [[buffer(CONFIG_BUFFER_INDEX)]],
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
#if USE_STAGE_IN
const PatchInput patchInput [[stage_in]],
#else
const OsdVertexBufferSet patchInput,
#endif
float2 position_in_patch [[position_in_patch]],
uint patch_id [[patch_id]]
#if USE_DISPLACEMENT_RESOURCES
,texture2d_array<float, access::sample> textureDisplace_Data [[texture(DISPLACEMENT_TEXTURE_INDEX)]]
,device ushort* textureDisplace_Packing [[buffer(DISPLACEMENT_BUFFER_INDEX)]]
#endif
)
{
FragmentInput out;
#if USE_STAGE_IN
int3 patchParam = patchInput.patchParam;
#else
int3 patchParam = patchInput.patchParamBuffer[patch_id];
#endif
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) /
exp2((float)refinementLevel - 1);
auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput);
#if USE_DISPLACEMENT
float3 position = displacement(patchVertex.position,
patchVertex.normal,
patchVertex.patchCoord,
config.mipmapBias,
config.displacementScale
#if USE_DISPLACEMENT_RESOURCES
,textureDisplace_Data, textureDisplace_Packing
#endif
);
#else
float3 position = patchVertex.position;
#endif
out.positionOut = mul(frameConsts.ModelViewProjectionMatrix, float4(position, 1));
out.position = mul(frameConsts.ModelViewMatrix, float4(position,1)).xyz;
out.normal = mul(frameConsts.ModelViewMatrix,float4(patchVertex.normal, 0)).xyz;
out.tangent = mul(frameConsts.ModelViewMatrix,float4(patchVertex.tangent,0)).xyz;
out.bitangent = mul(frameConsts.ModelViewMatrix,float4(patchVertex.bitangent,0)).xyz;
out.patchCoord = patchVertex.patchCoord;
#if COLOR_PATCHTYPE
out.patchColor = getAdaptivePatchColor(patchParam, OsdGetPatchSharpness(patchParam));
#endif
#if OSD_COMPUTE_NORMAL_DERIVATIVES
out.Nu = mul(frameConsts.ModelViewMatrix, float4(patchVertex.Nu, 0)).xyz;
out.Nv = mul(frameConsts.ModelViewMatrix, float4(patchVertex.Nv, 0)).xyz;
#endif
return out;
}
#endif
const constant float VIEWPORT_SCALE = 1024.0; // XXXdyu
// ---------------------------------------------------------------------------
// Lighting
// ---------------------------------------------------------------------------
#define NUM_LIGHTS 1
struct LightSource {
float4 position;
float4 ambient;
float4 diffuse;
float4 specular;
};
float4
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);
float3 n = Neye;
for (int i = 0; i < NUM_LIGHTS; ++i) {
float4 Plight = lightSource[i].position;
float3 l = (Plight.w == 0.0)
? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
float3 h = normalize(l + float3(0,0,1)); // directional viewer
float d = max(0.0, dot(n, l));
float s = pow(max(0.0, dot(n, h)), 64.0f);
color += (1.0 - occ) * ((lightSource[i].ambient +
d * lightSource[i].diffuse) * texColor +
s * lightSource[i].specular);
}
color.a = 1.0;
return color;
}
// ---------------------------------------------------------------------------
// Pixel Shader
// ---------------------------------------------------------------------------
float4
edgeColor(float4 Cfill, float4 edgeDistance)
{
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
#ifdef PRIM_TRI
float d =
min(edgeDistance[0], min(edgeDistance[1], edgeDistance[2]));
#endif
#ifdef PRIM_QUAD
float d =
min(min(edgeDistance[0], edgeDistance[1]),
min(edgeDistance[2], edgeDistance[3]));
#endif
float4 Cedge = float4(1.0, 1.0, 0.0, 1.0);
float p = exp2(-2 * d * d);
#if defined(GEOMETRY_OUT_WIRE)
if (p < 0.25) discard;
#endif
Cfill.rgb = lerp(Cfill.rgb, Cedge.rgb, p);
#endif
return Cfill;
}
// ---------------------------------------------------------------------------
// Pixel Shader
// ---------------------------------------------------------------------------
#if COLOR_PTEX_NEAREST || \
COLOR_PTEX_HW_BILINEAR || \
COLOR_PTEX_BILINEAR || \
COLOR_PTEX_BIQUADRATIC
#define USE_IMAGE_RESOURCES 1
#endif
#if USE_PTEX_OCCLUSION
#define USE_OCCLUSION_RESOURCES 1
#endif
#if USE_PTEX_SPECULAR
#define USE_SPECULAR_RESOURCES 1
#endif
fragment float4 fragment_main(
FragmentInput input [[stage_in]]
#if USE_DISPLACEMENT_RESOURCES
,texture2d_array<float, access::sample> textureDisplace_Data [[texture(DISPLACEMENT_TEXTURE_INDEX)]]
,device ushort* textureDisplace_Packing [[buffer(DISPLACEMENT_BUFFER_INDEX)]]
#endif
#if USE_IMAGE_RESOURCES
,texture2d_array<float, access::sample> textureImage_Data [[texture(IMAGE_TEXTURE_INDEX)]]
,device ushort* textureImage_Packing [[buffer(IMAGE_BUFFER_INDEX)]]
#endif
#if USE_OCCLUSION_RESOURCES
,texture2d_array<float, access::sample> textureOcclusion_Data [[texture(OCCLUSION_TEXTURE_INDEX)]]
,device ushort* textureOcclusion_Packing [[buffer(OCCLUSION_BUFFER_INDEX)]]
#endif
#if USE_SPECULAR_RESOURCES
,texture2d_array<float, acess::read> textureSpecular_Data [[texture(SPECULAR_TEXTURE_INDEX)]]
,device ushort* textureSpecular_Packing [[buffer(SPECULAR_BUFFER_INDEX)]]
#endif
,const constant LightSource (&lightSource [[buffer(0)]]) [NUM_LIGHTS]
,const constant Config& config [[buffer(1)]]
,const constant float4& shade [[buffer(2)]]
)
{
const auto displacementScale = config.displacementScale;
const auto mipmapBias = config.mipmapBias;
float4 outColor;
// ------------ normal ---------------
#if NORMAL_HW_SCREENSPACE || NORMAL_SCREENSPACE
float3 normal = perturbNormalFromDisplacement(input.position.xyz,
input.normal,
input.patchCoord,
config.mipmapBias,
textureDisplace_Data,
textureDisplace_Packing,
config.displacementScale);
#elif NORMAL_BIQUADRATIC || NORMAL_BIQUADRATIC_WG
float4 du, dv;
float4 disp = PtexMipmapLookupQuadratic(du, dv, input.patchCoord,
config.mipmapBias,
textureDisplace_Data,
textureDisplace_Packing);
disp *= displacementScale;
du *= displacementScale;
dv *= displacementScale;
float3 n = normalize(cross(input.tangent, input.bitangent));
float3 tangent = input.tangent + n * du.x;
float3 bitangent = input.bitangent + n * dv.x;
#if NORMAL_BIQUADRATIC_WG
tangent += input.Nu * disp.x;
bitangent += input.Nv * disp.x;
#endif
float3 normal = normalize(cross(tangent, bitangent));
#else
float3 normal = input.normal;
#endif
// ------------ color ---------------
#if COLOR_PTEX_NEAREST
float4 texColor = PtexLookupNearest(input.patchCoord,
textureImage_Data,
textureImage_Packing);
#elif COLOR_PTEX_HW_BILINEAR
float4 texColor = PtexLookupFast(input.patchCoord,
textureImage_Data,
textureImage_Packing);
#elif COLOR_PTEX_BILINEAR
float4 texColor = PtexMipmapLookup(input.patchCoord, mipmapBias,
textureImage_Data,
textureImage_Packing);
#elif COLOR_PTEX_BIQUADRATIC
float4 texColor = PtexMipmapLookupQuadratic(input.patchCoord, mipmapBias,
textureImage_Data,
textureImage_Packing);
#elif COLOR_PATCHTYPE
float4 texColor = lighting(float4(input.patchColor), input.position.xyz, normal, 0, lightSource);
outColor = texColor;
return outColor;
#elif COLOR_PATCHCOORD
float4 texColor = lighting(input.patchCoord, input.position.xyz, normal, 0, lightSource);
outColor = texColor;
return outColor;
#elif COLOR_NORMAL
float4 texColor = float4(normal.x, normal.y, normal.z, 1);
outColor = texColor;
return outColor;
#else // COLOR_NONE
float4 texColor = float4(0.5, 0.5, 0.5, 1);
#endif
// ------------ occlusion ---------------
#if USE_PTEX_OCCLUSION
float occ = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
textureOcclusion_Data,
textureOcclusion_Packing).x;
#else
float occ = 0.0;
#endif
// ------------ specular ---------------
#if USE_PTEX_SPECULAR
float specular = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
textureSpecular_Data,
textureSpecular_Packing).x;
#else
float specular = 1.0;
#endif
// ------------ lighting ---------------
float4 Cf = lighting(texColor, input.position.xyz, normal, occ, lightSource);
// ------------ wireframe ---------------
outColor = max(Cf, shade);
return outColor;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
#
# Copyright 2013 Pixar
#
# Licensed under the Apache License, Version 2.0 (the "Apache License")
# with the following modification; you may not use this file except in
# compliance with the Apache License and the following modification to it:
# Section 6. Trademarks. is deleted and replaced with:
#
# 6. Trademarks. This License does not grant permission to use the trade
# names, trademarks, service marks, or product names of the Licensor
# and its affiliates, except as required to comply with Section 4(c) of
# the License and to reproduce the content of the NOTICE file.
#
# You may obtain a copy of the Apache License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Apache License with the above modification is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
# *** mtlViewer ***
if(IOS)
set(BUNDLE_FILES
"iOS/Base.lproj/LaunchScreen.storyboard"
"iOS/Base.lproj/Main.storyboard"
)
set(PLATFORM_PLIST "iOS/Info.plist")
set(PLATFORM_FILES
"iOS/AppDelegate.h"
"iOS/AppDelegate.m"
"iOS/main.m"
"iOS/ViewController.h"
"iOS/ViewController.mm"
)
list(APPEND PLATFORM_LIBRARIES
"-framework UIKit"
)
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
else()
set(BUNDLE_FILES
"OSX/MainMenu.xib"
)
set(PLATFORM_PLIST "OSX/Info.plist")
set(PLATFORM_FILES
"OSX/AppDelegate.h"
"OSX/AppDelegate.m"
"OSX/main.m"
"OSX/ViewController.h"
"OSX/ViewController.mm"
)
list(APPEND PLATFORM_LIBRARIES
"-framework OpenGL"
"-framework AppKit"
)
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
endif()
include_directories(
"${OPENSUBDIV_INCLUDE_DIR}"
"${METAL_INCLUDE_DIR}"
)
list(APPEND PLATFORM_FILES
"mtlViewer.h"
"mtlViewer.mm"
)
list(APPEND PLATFORM_LIBRARIES
"osd_static_framework"
"${METAL_LIBRARY}"
"-framework MetalKit"
"-framework Foundation"
"-framework QuartzCore"
)
_stringify("mtlViewer.metal" INC_FILES)
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
_add_executable(mtlViewer "examples/mtlViewer"
MACOSX_BUNDLE
"${PLATFORM_FILES}"
"${INC_FILES}"
"${BUNDLE_FILES}"
$<TARGET_OBJECTS:regression_common_obj>
$<TARGET_OBJECTS:regression_far_utils_obj>
$<TARGET_OBJECTS:examples_common_obj>
)
set_target_properties (mtlViewer PROPERTIES
LINKER_LANGUAGE CXX
RESOURCE "${BUNDLE_FILES}"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_LIST_DIR}/${PLATFORM_PLIST}"
)
if(IOS)
set_target_properties(mtlViewer PROPERTIES
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
)
endif()
set_property (TARGET mtlViewer PROPERTY CXX_STANDARD 14)
target_link_libraries(mtlViewer
${PLATFORM_LIBRARIES}
)
install(TARGETS mtlViewer DESTINATION "${CMAKE_BINDIR_BASE}")

View File

@ -0,0 +1,32 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@end

View File

@ -0,0 +1,44 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "AppDelegate.h"
#import <MetalKit/MetalKit.h>
@implementation AppDelegate
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return true;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
@end

View File

@ -0,0 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Apple. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
</dict>
</plist>

View File

@ -0,0 +1,686 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16C20" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject">
<connections>
<outlet property="delegate" destination="aZQ-9t-9YL" id="ke3-sq-jK1"/>
</connections>
</customObject>
<customObject id="aZQ-9t-9YL" customClass="AppDelegate"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Test" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Test" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About NewApplication" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide NewApplication" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit NewApplication" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="File" id="bib-Uj-vzu">
<items>
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
<connections>
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
<connections>
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="tXI-mr-wws">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
<items>
<menuItem title="Clear Menu" id="vNY-rz-j42">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
<connections>
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
<connections>
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
</connections>
</menuItem>
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
<connections>
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="KaW-ft-85H">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
<connections>
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<items>
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
<connections>
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
<connections>
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
<connections>
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
<connections>
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
<connections>
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
<connections>
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
<menuItem title="Find" id="4EN-yA-p0u">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Find" id="1b7-l0-nxx">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
<connections>
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
<connections>
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
<connections>
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
<connections>
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
<connections>
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
<connections>
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="9ic-FL-obx">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
<items>
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
</connections>
</menuItem>
<menuItem title="Smart Links" id="cwL-P1-jid">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
</connections>
</menuItem>
<menuItem title="Data Detectors" id="tRr-pd-1PS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="2oI-Rn-ZJC">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
<items>
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="xrE-MZ-jX0">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
<items>
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
<items>
<menuItem title="Font" id="Gi5-1S-RQB">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
<connections>
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
<connections>
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
<menuItem title="Kern" id="jBQ-r6-VK2">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
<items>
<menuItem title="Use Default" id="GUa-eO-cwY">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
</connections>
</menuItem>
<menuItem title="Use None" id="cDB-IK-hbR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="46P-cB-AYj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="ogc-rX-tC1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="o6e-r0-MWq">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
<items>
<menuItem title="Use Default" id="agt-UL-0e3">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
</connections>
</menuItem>
<menuItem title="Use None" id="J7y-lM-qPV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
</connections>
</menuItem>
<menuItem title="Use All" id="xQD-1f-W4t">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="OaQ-X3-Vso">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
<items>
<menuItem title="Use Default" id="3Om-Ey-2VK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="Rqc-34-cIF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="I0S-gh-46l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
</connections>
</menuItem>
<menuItem title="Raise" id="2h7-ER-AoG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
</connections>
</menuItem>
<menuItem title="Lower" id="1tx-W0-xDw">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
<connections>
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="Fal-I4-PZk">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="d9c-me-L2H">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
<connections>
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
<connections>
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
</connections>
</menuItem>
<menuItem title="Justify" id="J5U-5w-g23">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
<connections>
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
<menuItem title="Writing Direction" id="H1b-Si-o9J">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
<items>
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="YGs-j5-SAR">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
</connections>
</menuItem>
<menuItem id="Lbh-J2-qVU">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
</connections>
</menuItem>
<menuItem id="jFq-tB-4Kx">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="Nop-cj-93Q">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
</connections>
</menuItem>
<menuItem id="BgM-ve-c93">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
</connections>
</menuItem>
<menuItem id="RB4-Sm-HuC">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
<menuItem title="Show Ruler" id="vLm-3I-IUL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="NewApplication Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hasShadow="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="1920" height="1080"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="se5-gp-TjO" customClass="OSDView">
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<connections>
<outlet property="menu" destination="AYu-sK-qS6" id="0eg-gK-PK4"/>
</connections>
</view>
<point key="canvasLocation" x="172" y="11"/>
</window>
<viewController id="tdF-Vh-f4K" customClass="ViewController">
<connections>
<outlet property="view" destination="se5-gp-TjO" id="fc1-e3-wEk"/>
</connections>
</viewController>
</objects>
</document>

View File

@ -0,0 +1,44 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <AppKit/AppKit.h>
#import <MetalKit/MetalKit.h>
#import "../mtlViewer.h"
#import "../../common/mtlHud.h"
@class ViewController;
@interface OSDView : MTKView {
@public
MTLhud hud;
}
@property (nonatomic) ViewController* controller;
@end
@interface ViewController : NSViewController<MTKViewDelegate, OSDRendererDelegate>
@property (weak) IBOutlet OSDView *view;
@property (nonatomic) OSDRenderer* osdRenderer;
@end

View File

@ -0,0 +1,447 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "ViewController.h"
#import <far/patchDescriptor.h>
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
enum {
kHUD_CB_DISPLAY_CONTROL_MESH_EDGES,
kHUD_CB_DISPLAY_CONTROL_MESH_VERTS,
kHUD_CB_ANIMATE_VERTICES,
kHUD_CB_DISPLAY_PATCH_COLOR, //Unused
kHUD_CB_DISPLAY_PATCH_CVs, //Unused
kHUD_CB_VIEW_LOD,
kHUD_CB_FRACTIONAL_SPACING,
kHUD_CB_PATCH_CULL,
kHUD_CB_BACK_CULL,
kHUD_CB_PATCH_INDIRECT_CULL,
kHUD_CB_FREEZE,
kHUD_CB_SINGLE_CREASE_PATCH,
kHUD_CB_INFINITE_SHARP_PATCH,
kHUD_CB_ADAPTIVE,
kHUD_CB_DISPLAY_PATCH_COUNTS
};
@implementation OSDView {
bool _mouseDown;
NSPoint _lastMouse;
}
-(void)mouseDown:(NSEvent *)event {
if(event.buttonNumber == 0) {
_lastMouse = [event locationInWindow];
_mouseDown = !hud.MouseClick(_lastMouse.x, (self.bounds.size.height - _lastMouse.y));
}
[super mouseDown:event];
}
-(void)mouseUp:(NSEvent *)event {
if(event.buttonNumber == 0) {
_mouseDown = false;
_lastMouse = [event locationInWindow];
hud.MouseRelease();
}
[super mouseUp:event];
}
-(void)mouseDragged:(NSEvent *)event {
auto mouse = [NSEvent mouseLocation];
hud.MouseMotion(mouse.x, mouse.y);
if(_mouseDown) {
CGPoint delta;
delta.x = mouse.x - _lastMouse.x;
delta.y = mouse.y - _lastMouse.y;
_lastMouse = mouse;
_controller.osdRenderer.camera->rotationX += delta.x / 2.0;
_controller.osdRenderer.camera->rotationY -= delta.y / 2.0;
}
[super mouseDragged:event];
}
-(void)keyDown:(NSEvent *)event {
const auto key = [event.charactersIgnoringModifiers characterAtIndex:0];
if(key == '=') {
_controller.osdRenderer.tessellationLevel = std::min(_controller.osdRenderer.tessellationLevel + 1, 16.0f);
} else if (key == '-') {
_controller.osdRenderer.tessellationLevel = std::max(_controller.osdRenderer.tessellationLevel - 1, 0.0f);
} else if(!hud.KeyDown(key))
[super keyDown:event];
}
-(void)scrollWheel:(NSEvent *)event {
_controller.osdRenderer.camera->dollyDistance += event.deltaY / 100.0;
}
-(BOOL)acceptsFirstResponder {
return true;
}
@end
#define FRAME_HISTORY 30
@implementation ViewController {
id<MTLDevice> _device;
id<MTLCommandQueue> _commandQueue;
dispatch_semaphore_t _frameSemaphore;
OSDRenderer* _osdRenderer;
unsigned _currentFrame;
double _frameBeginTimestamp[FRAME_HISTORY];
NSMagnificationGestureRecognizer* _magnificationGesture;
int _showPatchCounts;
}
-(void)viewDidLoad {
_device = MTLCreateSystemDefaultDevice();
_commandQueue = [_device newCommandQueue];
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
_osdRenderer.displayControlMeshEdges = false;
_frameSemaphore = dispatch_semaphore_create(3);
self.view.device = _device;
self.view.delegate = self;
self.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
self.view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
self.view.controller = self;
self.view.sampleCount = 1;
self.view->hud.UIScale = 1.0;
_osdRenderer.camera->aspectRatio = self.view.bounds.size.width / self.view.bounds.size.height;
_currentFrame = 0;
auto renderPipelineDescriptor = [MTLRenderPipelineDescriptor new];
renderPipelineDescriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
renderPipelineDescriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
renderPipelineDescriptor.sampleCount = self.view.sampleCount;
auto depthStencilDescriptor = [MTLDepthStencilDescriptor new];
depthStencilDescriptor.depthWriteEnabled = false;
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
auto& hud = self.view->hud;
hud.Init(_device, renderPipelineDescriptor, depthStencilDescriptor, self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
auto callbackCheckbox = [=](bool value, int ID) {
switch(ID) {
case kHUD_CB_FREEZE:
self.osdRenderer.freeze = value;
break;
case kHUD_CB_VIEW_LOD:
self.osdRenderer.useScreenspaceTessellation = value;
break;
case kHUD_CB_PATCH_CULL:
self.osdRenderer.usePatchClipCulling = value;
break;
case kHUD_CB_ANIMATE_VERTICES:
self.osdRenderer.animateVertices = value;
break;
case kHUD_CB_FRACTIONAL_SPACING:
self.osdRenderer.useFractionalTessellation = value;
break;
case kHUD_CB_SINGLE_CREASE_PATCH:
self.osdRenderer.useSingleCrease = value;
break;
case kHUD_CB_DISPLAY_CONTROL_MESH_EDGES:
self.osdRenderer.displayControlMeshEdges = value;
break;
case kHUD_CB_DISPLAY_CONTROL_MESH_VERTS:
self.osdRenderer.displayControlMeshVertices = value;
break;
case kHUD_CB_BACK_CULL:
self.osdRenderer.usePatchBackfaceCulling = value;
self.osdRenderer.usePrimitiveBackfaceCulling = value;
break;
case kHUD_CB_PATCH_INDIRECT_CULL:
self.osdRenderer.usePatchIndexBuffer = value;
break;
case kHUD_CB_ADAPTIVE:
self.osdRenderer.useAdaptive = value;
break;
case kHUD_CB_INFINITE_SHARP_PATCH:
self.osdRenderer.useInfinitelySharpPatch = value;
break;
case kHUD_CB_DISPLAY_PATCH_COUNTS:
_showPatchCounts = value;
break;
default:
assert("Unknown checkbox ID" && 0);
}
};
auto callbackKernel = [=](int kernelType) {
switch((KernelType)kernelType) {
case kCPU:
case kMetal:
self.osdRenderer.kernelType = (KernelType)(kernelType);
break;
default:
assert("Unknown kernelType" && 0);
}
};
auto callbackDisplayStyle = [=](int displayStyle) {
switch((DisplayStyle)displayStyle) {
case kDisplayStyleWire:
case kDisplayStyleShaded:
case kDisplayStyleWireOnShaded:
self.osdRenderer.displayStyle = (DisplayStyle)displayStyle;
break;
default:
assert("Unknown displayStyle" && 0);
}
};
auto callbackShadingMode = [=](int shadingMode) {
switch((ShadingMode)shadingMode) {
case kShadingNormal:
case kShadingMaterial:
case kShadingPatchType:
case kShadingPatchCoord:
self.osdRenderer.shadingMode = (ShadingMode)shadingMode;
break;
default:
assert("Unknown shadingMode" && 0);
}
};
auto callbackEndCap = [=](int endCap) {
switch((EndCap)endCap) {
case kEndCapNone:
case kEndCapBSplineBasis:
case kEndCapGregoryBasis:
case kEndCapLegacyGregory:
self.osdRenderer.endCapMode = (EndCap)endCap;
break;
default:
assert("Unknown endCap" && 0);
}
};
auto callbackLevel = [=](int level) {
self.osdRenderer.refinementLevel = level;
};
auto callbackModel = [=](int modelIndex) {
assert(modelIndex >= 0);
assert((NSUInteger)modelIndex < self.osdRenderer.loadedModels.count);
self.osdRenderer.currentModel = self.osdRenderer.loadedModels[modelIndex];
};
int y = 10;
hud.AddCheckBox("Control edges (H)",
_osdRenderer.displayControlMeshEdges,
10, y, callbackCheckbox,
kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, 'h');
y += 20;
hud.AddCheckBox("Control vertices (J)",
_osdRenderer.displayControlMeshVertices,
10, y, callbackCheckbox,
kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, 'j');
y += 20;
hud.AddCheckBox("Animate vertices (M)", _osdRenderer.animateVertices,
10, y, callbackCheckbox, kHUD_CB_ANIMATE_VERTICES, 'm');
y += 20;
hud.AddCheckBox("Screen space LOD (V)", _osdRenderer.useScreenspaceTessellation,
10, y, callbackCheckbox, kHUD_CB_VIEW_LOD, 'v');
y += 20;
hud.AddCheckBox("Fractional spacing (T)", _osdRenderer.useFractionalTessellation,
10, y, callbackCheckbox, kHUD_CB_FRACTIONAL_SPACING, 't');
y += 20;
hud.AddCheckBox("Frustum Patch Culling (B)", _osdRenderer.usePatchClipCulling,
10, y, callbackCheckbox, kHUD_CB_PATCH_CULL, 'b');
y += 20;
hud.AddCheckBox("Backface Culling (L)", _osdRenderer.usePatchBackfaceCulling,
10, y, callbackCheckbox, kHUD_CB_BACK_CULL, 'l');
y += 20;
hud.AddCheckBox("Patch Index Culling (O)", _osdRenderer.usePatchIndexBuffer,
10, y, callbackCheckbox, kHUD_CB_PATCH_INDIRECT_CULL, 'o');
y += 20;
hud.AddCheckBox("Freeze (spc)", _osdRenderer.freeze,
10, y, callbackCheckbox, kHUD_CB_FREEZE, ' ');
y += 20;
int displaystyle_pulldown = hud.AddPullDown("DisplayStyle (W)", 200, 10, 250,
callbackDisplayStyle, 'w');
hud.AddPullDownButton(displaystyle_pulldown, "Wire", kDisplayStyleWire,
_osdRenderer.displayStyle == kDisplayStyleWire);
hud.AddPullDownButton(displaystyle_pulldown, "Shaded", kDisplayStyleShaded,
_osdRenderer.displayStyle == kDisplayStyleShaded);
hud.AddPullDownButton(displaystyle_pulldown, "Wire+Shaded", kDisplayStyleWireOnShaded,
_osdRenderer.displayStyle == kDisplayStyleWireOnShaded);
int shading_pulldown = hud.AddPullDown("Shading (C)", 200, 70, 250,
callbackShadingMode, 'c');
hud.AddPullDownButton(shading_pulldown, "Material",
kShadingMaterial,
_osdRenderer.shadingMode == kShadingMaterial);
hud.AddPullDownButton(shading_pulldown, "Patch Type",
kShadingPatchType,
_osdRenderer.shadingMode == kShadingPatchType);
hud.AddPullDownButton(shading_pulldown, "Patch Coord",
kShadingPatchCoord,
_osdRenderer.shadingMode == kShadingPatchCoord);
hud.AddPullDownButton(shading_pulldown, "Normal",
kShadingNormal,
_osdRenderer.shadingMode == kShadingNormal);
int compute_pulldown = hud.AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k');
hud.AddPullDownButton(compute_pulldown, "CPU", kCPU, _osdRenderer.kernelType == kCPU);
hud.AddPullDownButton(compute_pulldown, "Metal", kMetal, _osdRenderer.kernelType == kMetal);
{
hud.AddCheckBox("Adaptive (`)", _osdRenderer.useAdaptive,
10, 190, callbackCheckbox, kHUD_CB_ADAPTIVE, '`');
hud.AddCheckBox("Single Crease Patch (S)", _osdRenderer.useSingleCrease,
10, 210, callbackCheckbox, kHUD_CB_SINGLE_CREASE_PATCH, 's');
hud.AddCheckBox("Inf Sharp Patch (I)", _osdRenderer.useInfinitelySharpPatch,
10, 230, callbackCheckbox, kHUD_CB_INFINITE_SHARP_PATCH, 'i');
int endcap_pulldown = hud.AddPullDown(
"End cap (E)", 10, 250, 200, callbackEndCap, 'e');
hud.AddPullDownButton(endcap_pulldown,"None",
kEndCapNone,
_osdRenderer.endCapMode == kEndCapNone);
hud.AddPullDownButton(endcap_pulldown, "BSpline",
kEndCapBSplineBasis,
_osdRenderer.endCapMode == kEndCapBSplineBasis);
hud.AddPullDownButton(endcap_pulldown, "GregoryBasis",
kEndCapGregoryBasis,
_osdRenderer.endCapMode == kEndCapGregoryBasis);
hud.AddPullDownButton(endcap_pulldown, "LegacyGregory",
kEndCapLegacyGregory,
_osdRenderer.endCapMode == kEndCapLegacyGregory);
}
for (int i = 1; i < 11; ++i) {
char level[16];
sprintf(level, "Lv. %d", i);
hud.AddRadioButton(3, level, i==2, 10, 310+i*20, callbackLevel, i, '0'+(i%10));
}
int shapes_pulldown = hud.AddPullDown("Shape (N)", -300, 10, 300, callbackModel, 'n');
for (int i = 0; i < (int)_osdRenderer.loadedModels.count; ++i) {
hud.AddPullDownButton(shapes_pulldown, _osdRenderer.loadedModels[i].UTF8String,i);
}
hud.AddCheckBox("Show patch counts (,)", _showPatchCounts, -280, -20, callbackCheckbox, kHUD_CB_DISPLAY_PATCH_COUNTS, ',');
hud.Rebuild(self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
}
-(void)drawInMTKView:(MTKView *)view {
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
auto commandBuffer = [_commandQueue commandBuffer];
double avg = 0;
for(int i = 0; i < FRAME_HISTORY; i++)
avg += _frameBeginTimestamp[i];
avg /= FRAME_HISTORY;
auto renderEncoder = [_osdRenderer drawFrame:commandBuffer];
auto& hud = self.view->hud;
if(hud.IsVisible()) {
if(_showPatchCounts) {
int x = -280;
int y = -180;
hud.DrawString(x, y, "NonPatch : %d",
_osdRenderer.patchCounts[Far::PatchDescriptor::QUADS]); y += 20;
hud.DrawString(x, y, "Regular : %d",
_osdRenderer.patchCounts[Far::PatchDescriptor::REGULAR]); y+= 20;
hud.DrawString(x, y, "Gregory : %d",
_osdRenderer.patchCounts[Far::PatchDescriptor::GREGORY]); y+= 20;
hud.DrawString(x, y, "Boundary Gregory : %d",
_osdRenderer.patchCounts[Far::PatchDescriptor::GREGORY_BOUNDARY]); y+= 20;
hud.DrawString(x, y, "Gregory Basis : %d",
_osdRenderer.patchCounts[Far::PatchDescriptor::GREGORY_BASIS]); y+= 20;
}
hud.DrawString(10, -120, "Tess level : %f", _osdRenderer.tessellationLevel);
hud.DrawString(10, -20, "FPS = %3.1f", 1.0 / avg);
//Disable Culling & Force Fill mode when drawing the UI
[renderEncoder setTriangleFillMode:MTLTriangleFillModeFill];
[renderEncoder setCullMode:MTLCullModeNone];
self.view->hud.Flush(renderEncoder);
}
[renderEncoder endEncoding];
__weak auto blockSemaphore = _frameSemaphore;
unsigned frameId = _currentFrame % FRAME_HISTORY;
auto frameBeginTime = CACurrentMediaTime();
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
dispatch_semaphore_signal(blockSemaphore);
_frameBeginTimestamp[frameId] = CACurrentMediaTime() - frameBeginTime;
}];
[commandBuffer presentDrawable:view.currentDrawable];
[commandBuffer commit];
_currentFrame++;
}
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
_osdRenderer.camera->aspectRatio = size.width / size.height;
self.view->hud.Rebuild(self.view.bounds.size.width, self.view.bounds.size.height, size.width, size.height);
}
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
}
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
descriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
descriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
descriptor.sampleCount = self.view.sampleCount;
}
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
return _commandQueue;
}
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
return _device;
}
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
return self.view.currentRenderPassDescriptor;
}
@end

View File

@ -0,0 +1,29 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {
return NSApplicationMain(argc, argv);
}

View File

@ -0,0 +1,33 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@ -0,0 +1,61 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end

View File

@ -0,0 +1,73 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11147" systemVersion="16A201u" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11119"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="1024" height="1366"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,227 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11147" systemVersion="16A201u" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11119"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="MTKView">
<rect key="frame" x="0.0" y="0.0" width="1366" height="1024"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Information Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ze8-2s-lED">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oQb-3T-gg6" userLabel="modelPickerView">
<constraints>
<constraint firstAttribute="width" constant="195" id="Qn1-yQ-7c6"/>
<constraint firstAttribute="height" constant="102" id="xJP-UH-SIl"/>
</constraints>
<connections>
<outlet property="dataSource" destination="BYZ-38-t0r" id="jd1-qJ-49i"/>
<outlet property="delegate" destination="BYZ-38-t0r" id="OdV-ot-p6a"/>
</connections>
</pickerView>
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minimumValue="1" maximumValue="5" translatesAutoresizingMaskIntoConstraints="NO" id="QQ6-5o-gla">
<connections>
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="uHZ-dB-XZV"/>
</connections>
</stepper>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Ref Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N12-GK-yLY">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="16" translatesAutoresizingMaskIntoConstraints="NO" id="eYp-5M-Rgk">
<connections>
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="mBg-38-OPM"/>
</connections>
</stepper>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="jQK-WK-vfP">
<segments>
<segment title="BSpline"/>
<segment title="Legacy Gregory"/>
<segment title="Gregory Basis"/>
</segments>
<connections>
<action selector="endcapChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="vBH-MZ-zYA"/>
</connections>
</segmentedControl>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="8kP-4Y-wzA">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="UsH-Nw-M31"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Wireframe" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FvR-NK-6s0" userLabel="Wireframe">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backpatch Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="esT-7h-XLG">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="P8z-O2-OLV">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="w7T-KH-L3E"/>
</connections>
</switch>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="5Ns-3P-r13">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ym1-Xw-wU6"/>
</connections>
</switch>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="fw1-9C-P6U">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="8kp-Rh-Yua"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backface Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iw4-VH-Zwm">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Patch Clip Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5xP-bY-PgM">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Crease" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kuw-3r-nzl">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7yA-a6-Sq7">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="Yg5-z5-avS"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Control Mesh" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cRi-2K-jkK">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Screenspace Tessellation" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ioY-T2-PEM">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Tes Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlx-hC-oDg">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sDC-ZC-b6I">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ebT-0s-gYR"/>
</connections>
</switch>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Ta2-7B-7Ck">
<connections>
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="PcJ-3J-UKL"/>
</connections>
</switch>
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-iT-gpT">
<constraints>
<constraint firstAttribute="height" constant="57" id="8qk-aN-q1z"/>
<constraint firstAttribute="width" constant="194" id="aSF-hS-BWT"/>
</constraints>
<connections>
<outlet property="dataSource" destination="BYZ-38-t0r" id="4w5-fv-wIj"/>
<outlet property="delegate" destination="BYZ-38-t0r" id="73C-8g-Biy"/>
</connections>
</pickerView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="P8z-O2-OLV" firstAttribute="leading" secondItem="esT-7h-XLG" secondAttribute="trailing" constant="8" id="0zt-WU-LC3"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="2nS-t9-ncz"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="404-z0-Fv7"/>
<constraint firstItem="8kP-4Y-wzA" firstAttribute="leading" secondItem="FvR-NK-6s0" secondAttribute="trailing" constant="8" id="5rd-n5-Uxl"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="oQb-3T-gg6" secondAttribute="bottom" constant="20" id="6dr-og-11f"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="trailing" secondItem="jQK-WK-vfP" secondAttribute="trailing" id="AnK-qT-Bca"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="leading" secondItem="dlx-hC-oDg" secondAttribute="trailing" constant="8" id="B0o-kO-368"/>
<constraint firstItem="QQ6-5o-gla" firstAttribute="leading" secondItem="N12-GK-yLY" secondAttribute="trailing" constant="8" id="DrB-sY-inQ"/>
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="top" secondItem="sDC-ZC-b6I" secondAttribute="bottom" constant="8" id="EK0-Q5-QyW"/>
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="leading" secondItem="cRi-2K-jkK" secondAttribute="trailing" constant="8" id="En4-Ve-B3K"/>
<constraint firstItem="8Ky-iT-gpT" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="HnT-dY-hLh"/>
<constraint firstItem="oQb-3T-gg6" firstAttribute="leading" secondItem="fw1-9C-P6U" secondAttribute="trailing" constant="24" id="JmG-em-jfy"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="top" secondItem="Ta2-7B-7Ck" secondAttribute="bottom" constant="8" id="O1O-AY-rOc"/>
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="centerY" secondItem="cRi-2K-jkK" secondAttribute="centerY" id="OGy-au-4ty"/>
<constraint firstItem="sDC-ZC-b6I" firstAttribute="trailing" secondItem="jQK-WK-vfP" secondAttribute="trailing" id="OLn-EQ-Ol5"/>
<constraint firstItem="P8z-O2-OLV" firstAttribute="centerY" secondItem="esT-7h-XLG" secondAttribute="centerY" id="Oxf-2f-wTD"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="top" secondItem="QQ6-5o-gla" secondAttribute="bottom" constant="4" id="PJS-Lq-bIL"/>
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="trailing" secondItem="jQK-WK-vfP" secondAttribute="trailing" id="PVt-1f-oef"/>
<constraint firstItem="Ze8-2s-lED" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="20" id="SZK-UA-BiA"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="fw1-9C-P6U" secondAttribute="bottom" constant="20" id="Uw7-fz-We7"/>
<constraint firstItem="sDC-ZC-b6I" firstAttribute="leading" secondItem="kuw-3r-nzl" secondAttribute="trailing" constant="8" id="W06-wv-gqs"/>
<constraint firstItem="oQb-3T-gg6" firstAttribute="top" secondItem="8Ky-iT-gpT" secondAttribute="bottom" constant="8" id="b0I-kW-GRc"/>
<constraint firstItem="QQ6-5o-gla" firstAttribute="centerY" secondItem="N12-GK-yLY" secondAttribute="centerY" id="bqu-uw-PqG"/>
<constraint firstItem="eYp-5M-Rgk" firstAttribute="centerY" secondItem="dlx-hC-oDg" secondAttribute="centerY" id="cV6-GZ-8IP"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="leading" secondItem="ioY-T2-PEM" secondAttribute="trailing" constant="8" id="cqL-gl-vn2"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="leading" secondItem="5xP-bY-PgM" secondAttribute="trailing" constant="8" id="dhX-z5-kgA"/>
<constraint firstItem="jQK-WK-vfP" firstAttribute="top" secondItem="7yA-a6-Sq7" secondAttribute="bottom" constant="8" id="egb-qP-Lva"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="centerY" secondItem="Iw4-VH-Zwm" secondAttribute="centerY" id="fEO-gM-cmZ"/>
<constraint firstItem="QQ6-5o-gla" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="ggj-9I-tbQ"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="gqA-q9-SK3"/>
<constraint firstItem="Ze8-2s-lED" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="20" id="kTX-YC-JKR"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="jQK-WK-vfP" secondAttribute="bottom" constant="20" id="kuT-qk-ibg"/>
<constraint firstItem="8kP-4Y-wzA" firstAttribute="centerY" secondItem="FvR-NK-6s0" secondAttribute="centerY" id="n3L-qM-7Pr"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="centerY" secondItem="5xP-bY-PgM" secondAttribute="centerY" id="nP1-Bt-GuV"/>
<constraint firstItem="oQb-3T-gg6" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="pIi-zk-crx"/>
<constraint firstItem="5xP-bY-PgM" firstAttribute="leading" secondItem="jQK-WK-vfP" secondAttribute="trailing" constant="20" id="pvx-Go-b8B"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="top" secondItem="P8z-O2-OLV" secondAttribute="bottom" constant="8" id="pwK-2F-IIf"/>
<constraint firstItem="P8z-O2-OLV" firstAttribute="top" secondItem="8kP-4Y-wzA" secondAttribute="bottom" constant="8" id="q11-mD-QDz"/>
<constraint firstItem="oQb-3T-gg6" firstAttribute="top" secondItem="eYp-5M-Rgk" secondAttribute="bottom" constant="8" id="qfG-FK-QD4"/>
<constraint firstItem="P8z-O2-OLV" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="rha-qA-vsj"/>
<constraint firstItem="8Ky-iT-gpT" firstAttribute="top" secondItem="eYp-5M-Rgk" secondAttribute="bottom" constant="8" id="rjU-ER-xAm"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="ro3-hx-iLk"/>
<constraint firstItem="5Ns-3P-r13" firstAttribute="leading" secondItem="Iw4-VH-Zwm" secondAttribute="trailing" constant="8" id="ry7-bQ-bRa"/>
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="tsW-3r-293"/>
<constraint firstItem="7yA-a6-Sq7" firstAttribute="centerY" secondItem="ioY-T2-PEM" secondAttribute="centerY" id="wE0-Cg-4Qf"/>
<constraint firstItem="sDC-ZC-b6I" firstAttribute="centerY" secondItem="kuw-3r-nzl" secondAttribute="centerY" id="wTg-7H-KXF"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="qfG-FK-QD4"/>
</mask>
</variation>
</view>
<connections>
<outlet property="backfaceCullingSwitch" destination="5Ns-3P-r13" id="n8X-2V-BRl"/>
<outlet property="backpatchCullingSwitch" destination="P8z-O2-OLV" id="VIe-Lv-hsC"/>
<outlet property="controlMeshSwitch" destination="Ta2-7B-7Ck" id="hVP-58-sGA"/>
<outlet property="endcapSegmentedControl" destination="jQK-WK-vfP" id="MIt-kE-Kwg"/>
<outlet property="frameTimeLabel" destination="Ze8-2s-lED" id="vLj-Id-oiv"/>
<outlet property="modelPickerView" destination="oQb-3T-gg6" id="YLl-SI-Azc"/>
<outlet property="patchClipCullingSwitch" destination="fw1-9C-P6U" id="P2G-3F-eJh"/>
<outlet property="refLvlLabel" destination="N12-GK-yLY" id="lXc-6r-pZY"/>
<outlet property="refinementStepper" destination="QQ6-5o-gla" id="URK-fS-krY"/>
<outlet property="screenspaceTessellationSwitch" destination="7yA-a6-Sq7" id="RpM-ER-4Oy"/>
<outlet property="shadingModePickerView" destination="8Ky-iT-gpT" id="PAS-0I-Vju"/>
<outlet property="singleCreaseSwitch" destination="sDC-ZC-b6I" id="Arw-OY-Z4A"/>
<outlet property="tesLvLlabel" destination="dlx-hC-oDg" id="haB-Hi-A9B"/>
<outlet property="tessellationStepper" destination="eYp-5M-Rgk" id="IFG-H5-rJS"/>
<outlet property="wireframeSwitch" destination="8kP-4Y-wzA" id="y3a-yu-4cs"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="476.57393850658855" y="533.7890625"/>
</scene>
</scenes>
<color key="tintColor" cocoaTouchSystemColor="darkTextColor"/>
</document>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>mtlViewer</string>
<key>CFBundleIdentifier</key>
<string>com.osd.mtlViewer</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>mtlViewer</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
<string>metal</string>
</array>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,33 @@
#import <UIKit/UIKit.h>
#import <MetalKit/MetalKit.h>
#import "../mtlViewer.h"
@interface ViewController : UIViewController<
MTKViewDelegate,
UIPickerViewDelegate,
UIPickerViewDataSource,
OSDRendererDelegate
>
@property (weak, nonatomic) IBOutlet UILabel *refLvlLabel;
@property (weak, nonatomic) IBOutlet UILabel *tesLvLlabel;
@property (weak, nonatomic) IBOutlet UILabel *frameTimeLabel;
@property (weak, nonatomic) IBOutlet UIPickerView *modelPickerView;
@property (weak, nonatomic) IBOutlet UIPickerView *shadingModePickerView;
@property (weak, nonatomic) IBOutlet UIStepper *tessellationStepper;
@property (weak, nonatomic) IBOutlet UIStepper *refinementStepper;
@property (weak, nonatomic) IBOutlet UISwitch *wireframeSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *backpatchCullingSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *backfaceCullingSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *patchClipCullingSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *singleCreaseSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *controlMeshSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *screenspaceTessellationSwitch;
@property (weak, nonatomic) IBOutlet UISegmentedControl *endcapSegmentedControl;
- (IBAction)stepperChanged:(UIStepper *)sender;
- (IBAction)switchChanged:(UISwitch *)sender;
- (IBAction)endcapChanged:(UISegmentedControl *)sender;
@end

View File

@ -0,0 +1,249 @@
#import "ViewController.h"
#define FRAME_HISTORY 30
@interface ViewController ()
{
dispatch_semaphore_t _frameSemaphore;
CGPoint _startTouch;
bool _isTouching;
OSDRenderer* _osdRenderer;
MTKView* _view;
id<MTLDevice> _device;
id<MTLCommandQueue> _commandQueue;
double _frameTimes[FRAME_HISTORY];
uint64_t _currentFrame;
UIPanGestureRecognizer *_zoomGesture;
}
@end
@implementation ViewController
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
_osdRenderer.camera->aspectRatio = size.width / size.height;
}
-(void)drawInMTKView:(MTKView *)view {
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
auto commandBuffer = [_commandQueue commandBuffer];
[[_osdRenderer drawFrame:commandBuffer] endEncoding];
__weak auto blockSemaphore = _frameSemaphore;
unsigned frameIndex = _currentFrame % FRAME_HISTORY;
const auto beginTime = CACurrentMediaTime();
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
dispatch_semaphore_signal(blockSemaphore);
_frameTimes[frameIndex] = CACurrentMediaTime() - beginTime;
}];
[commandBuffer presentDrawable:_view.currentDrawable];
[commandBuffer commit];
_currentFrame++;
double frameAverage = 0;
for(auto& x : _frameTimes)
frameAverage += x;
frameAverage /= 30.0;
_frameTimeLabel.text = [NSString stringWithFormat:@"%0.2f ms", frameAverage * 1000.0];
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (void)viewDidLoad {
[super viewDidLoad];
_view = (MTKView*)self.view;
_frameSemaphore = dispatch_semaphore_create(3);
_device = MTLCreateSystemDefaultDevice();
_commandQueue = [_device newCommandQueue];
_view.device = _device;
_view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
_view.sampleCount = 2;
_view.frame = CGRectMake(0, 0, 1920, 1080);
_view.contentScaleFactor = 1;
_view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
_view.delegate = self;
_zoomGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_zoomView)];
_zoomGesture.minimumNumberOfTouches = 2;
_zoomGesture.maximumNumberOfTouches = 2;
_zoomGesture.cancelsTouchesInView = true;
[_view addGestureRecognizer:_zoomGesture];
[self _applyOptions];
}
-(void)_applyOptions {
_osdRenderer.useSingleCrease = _singleCreaseSwitch.isOn;
_osdRenderer.usePatchBackfaceCulling = _backpatchCullingSwitch.isOn;
_osdRenderer.usePrimitiveBackfaceCulling = _backfaceCullingSwitch.isOn;
_osdRenderer.useScreenspaceTessellation = _screenspaceTessellationSwitch.isOn;
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
_osdRenderer.displayControlMeshVertices = _controlMeshSwitch.isOn;
_osdRenderer.displayControlMeshEdges = _controlMeshSwitch.isOn;
_osdRenderer.usePatchClipCulling = _patchClipCullingSwitch.isOn;
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
_osdRenderer.useAdaptive = true;
_osdRenderer.freeze = true;
_osdRenderer.animateVertices = false;
_osdRenderer.kernelType = kMetal;
_osdRenderer.refinementLevel = _refinementStepper.value;
_osdRenderer.tessellationLevel = _tessellationStepper.value;
_osdRenderer.endCapMode = (EndCap)(1 + _endcapSegmentedControl.selectedSegmentIndex);
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
[_tesLvLlabel sizeToFit];
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
[_refLvlLabel sizeToFit];
}
-(void)_zoomView {
static float lastY = 0;
if(_zoomGesture.state == UIGestureRecognizerStateBegan) {
lastY = [_zoomGesture translationInView:_view].y;
} else if(_zoomGesture.state == UIGestureRecognizerStateChanged) {
const auto currentY = [_zoomGesture translationInView:_view].y;
const auto deltaY = (currentY - lastY) / 100.0;
lastY = currentY;
_osdRenderer.camera->dollyDistance += deltaY;
}
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
_isTouching = true;
_startTouch = [touches.anyObject locationInView:self.view];
[super touchesBegan:touches withEvent:event];
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
_isTouching = false;
[super touchesEnded:touches withEvent:event];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if(_isTouching)
{
for(UITouch* touch in touches)
{
CGPoint location = [touch locationInView:self.view];
_startTouch = [touch previousLocationInView:self.view];
double deltaX = location.x - _startTouch.x;
double deltaY = location.y - _startTouch.y;
_osdRenderer.camera->rotationX += deltaX / 5.0;
_osdRenderer.camera->rotationY += deltaY / 5.0;
}
}
[super touchesMoved:touches withEvent:event];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
return _device;
}
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
return _commandQueue;
}
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
return _view.currentRenderPassDescriptor;
}
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
}
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
descriptor.colorAttachments[0].pixelFormat = _view.colorPixelFormat;
descriptor.depthAttachmentPixelFormat = _view.depthStencilPixelFormat;
descriptor.sampleCount = _view.sampleCount;
}
- (IBAction)stepperChanged:(UIStepper *)sender {
if(sender == _tessellationStepper) {
_osdRenderer.tessellationLevel = sender.value;
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
[_tesLvLlabel sizeToFit];
} else if (sender == _refinementStepper) {
_osdRenderer.refinementLevel = sender.value;
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
[_refLvlLabel sizeToFit];
}
}
- (IBAction)switchChanged:(UISwitch *)sender {
if(sender == _wireframeSwitch) {
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
} else if(sender == _backpatchCullingSwitch) {
_osdRenderer.usePatchBackfaceCulling = sender.isOn;
} else if(sender == _backfaceCullingSwitch) {
_osdRenderer.usePrimitiveBackfaceCulling = sender.isOn;
} else if(sender == _patchClipCullingSwitch) {
_osdRenderer.usePatchClipCulling = sender.isOn;
} else if(sender == _singleCreaseSwitch) {
_osdRenderer.useSingleCrease = sender.isOn;
} else if(sender == _controlMeshSwitch) {
_osdRenderer.displayControlMeshEdges = sender.isOn;
_osdRenderer.displayControlMeshVertices = sender.isOn;
} else if(sender == _screenspaceTessellationSwitch) {
_osdRenderer.useScreenspaceTessellation = sender.isOn;
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
}
}
- (IBAction)endcapChanged:(UISegmentedControl *)sender {
_osdRenderer.endCapMode = (EndCap)(1 + sender.selectedSegmentIndex);
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if(pickerView == _modelPickerView) {
return _osdRenderer.loadedModels.count;
} else if(pickerView == _shadingModePickerView) {
return 4;
}
return 0;
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(pickerView == _modelPickerView) {
return _osdRenderer.loadedModels[row];
} else if(pickerView == _shadingModePickerView) {
switch((ShadingMode)row) {
case kShadingMaterial: return @"Material";
case kShadingNormal: return @"Normal";
case kShadingPatchCoord: return @"Patch Coord";
case kShadingPatchType: return @"Patch Type";
}
}
return @"";
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if(pickerView == _modelPickerView) {
_osdRenderer.currentModel = _osdRenderer.loadedModels[row];
} else if(pickerView == _shadingModePickerView) {
_osdRenderer.shadingMode = (ShadingMode)row;
}
}
@end

View File

@ -0,0 +1,8 @@
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@ -0,0 +1,122 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../../regression/common/shape_utils.h"
#include "../../regression/shapes/all.h"
struct ShapeDesc {
ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme,
bool iIsLeftHanded = false) :
name(iname), data(idata), scheme(ischeme), isLeftHanded(iIsLeftHanded) { }
std::string name,
data;
Scheme scheme;
bool isLeftHanded;
};
static std::vector<ShapeDesc> g_defaultShapes;
//------------------------------------------------------------------------------
static void initShapes() {
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube", catmark_cube, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_flap", catmark_flap, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_flap2", catmark_flap2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test8", catmark_gregory_test8, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/ ) );
g_defaultShapes.push_back( ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pole8", catmark_pole8, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pole64", catmark_pole64, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases1", catmark_tent_creases1 , kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_tent", catmark_tent, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_torus", catmark_torus, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark ) );
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit0", catmark_square_hedit0, kCatmark ) );
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit1", catmark_square_hedit1, kCatmark ) );
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit2", catmark_square_hedit2, kCatmark ) );
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit3", catmark_square_hedit3, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_bishop", catmark_bishop, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_helmet", catmark_helmet, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pawn", catmark_pawn, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_rook", catmark_rook, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("bilinear_cube", bilinear_cube, kBilinear ) );
g_defaultShapes.push_back( ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_cube", loop_cube, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_pole8", loop_pole8, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_pole64", loop_pole64, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_pole360", loop_pole360, kLoop ) );
}

View File

@ -0,0 +1,110 @@
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#pragma once
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
typedef enum {
kEndCapNone = 0,
kEndCapBSplineBasis,
kEndCapLegacyGregory,
kEndCapGregoryBasis,
} EndCap;
typedef enum {
kCPU = 0,
kMetal,
} KernelType;
typedef enum {
kDisplayStyleWire = 0,
kDisplayStyleShaded,
kDisplayStyleWireOnShaded,
} DisplayStyle;
typedef enum {
kShadingMaterial = 0,
kShadingPatchType,
kShadingNormal,
kShadingPatchCoord
} ShadingMode;
typedef struct {
float rotationX;
float rotationY;
float dollyDistance;
float aspectRatio;
} Camera;
@class OSDRenderer;
@protocol OSDRendererDelegate <NSObject>
-(id<MTLDevice>)deviceFor:(OSDRenderer*)renderer;
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer*)renderer;
-(MTLRenderPassDescriptor*)renderPassDescriptorFor:(OSDRenderer*)renderer;
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor*)descriptor for:(OSDRenderer*)renderer;
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor*)descriptor for:(OSDRenderer*)renderer;
@end
@interface OSDRenderer : NSObject
-(instancetype)initWithDelegate:(id<OSDRendererDelegate>)delegate;
-(id<MTLRenderCommandEncoder>)drawFrame:(id<MTLCommandBuffer>)commandBuffer;
@property (readonly, nonatomic) id<OSDRendererDelegate> delegate;
@property (nonatomic) unsigned refinementLevel;
@property (nonatomic) float tessellationLevel;
@property (readonly, nonatomic) NSArray<NSString*>* loadedModels;
@property (nonatomic) NSString* currentModel;
@property (readonly, nonatomic) Camera* camera;
@property (readonly, nonatomic) int* patchCounts;
@property (nonatomic) bool useFractionalTessellation;
@property (nonatomic) bool useScreenspaceTessellation;
@property (nonatomic) bool usePatchIndexBuffer;
@property (nonatomic) bool usePatchBackfaceCulling;
@property (nonatomic) bool usePatchClipCulling;
@property (nonatomic) bool useSingleCrease;
@property (nonatomic) bool useInfinitelySharpPatch;
@property (nonatomic) bool useStageIn;
@property (nonatomic) bool usePrimitiveBackfaceCulling;
@property (nonatomic) bool useAdaptive;
@property (nonatomic) bool freeze;
@property (nonatomic) bool animateVertices;
@property (nonatomic) bool displayControlMeshEdges;
@property (nonatomic) bool displayControlMeshVertices;
@property (nonatomic) DisplayStyle displayStyle;
@property (nonatomic) ShadingMode shadingMode;
@property (nonatomic) EndCap endCapMode;
@property (nonatomic) KernelType kernelType;
@end

View File

@ -0,0 +1,685 @@
#line 0 "examples/mtlViewer/mtlViewer.metal"
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include <metal_stdlib>
using namespace metal;
#define SHADING_TYPE_MATERIAL 0
#define SHADING_TYPE_PATCH 1
#define SHADING_TYPE_NORMAL 2
#define SHADING_TYPE_PATCH_COORD 3
struct PerFrameConstants {
float4x4 ModelViewMatrix;
float4x4 ProjectionMatrix;
float4x4 ModelViewProjectionMatrix;
float4x4 ModelViewInverseMatrix;
float TessLevel;
};
struct OutputVertex {
float4 positionOut [[position]];
float3 position;
float3 normal;
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD
float3 patchColor;
#endif
};
struct SolidColorVertex {
float4 positionOut [[position]];
half4 getColor() const {
return unpack_unorm4x8_to_half(_color);
}
void setColor(half4 color) {
_color = pack_half_to_unorm4x8(color);
}
private:
uint _color [[flat, user(color)]];
};
struct PackedInputVertex {
packed_float3 position;
};
struct Light {
float3 Position;
float3 ambient;
float3 diffuse;
float3 specular;
};
float3 lighting(float3 diffuseColor, const constant Light* lightData, float3 eyePos, float3 eyeN)
{
float3 color(0);
for(int i = 0; i < 2; i++)
{
const auto l = lightData[i].Position;
const auto h = normalize(l + float3(0,0,1));
const auto d = max(0.0, dot(eyeN, l));
const auto s = powr(max(0.0, dot(eyeN, h)), 500.0f);
color += lightData[i].ambient
+ d * lightData[i].diffuse * diffuseColor
+ s * lightData[i].specular;
}
return color;
}
const constant float4 patchColors[] = {
float4(1.0f, 1.0f, 1.0f, 1.0f), // regular
float4(0.0f, 1.0f, 1.0f, 1.0f), // regular pattern 0
float4(0.0f, 0.5f, 1.0f, 1.0f), // regular pattern 1
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(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.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.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.50f, 0.6f, 1.0f), // single crease pattern 4
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.2f, 0.75f, 1.0f), // boundary pattern 1
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.8f, 0.75f, 1.0f), // boundary pattern 4
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 1
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 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, 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
};
float4
getAdaptivePatchColor(int3 patchParam
#if OSD_PATCH_ENABLE_SINGLE_CREASE
, float2 vSegments
#else
#endif
)
{
int patchType = 0;
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
if (edgeCount == 1) {
patchType = 2; // BOUNDARY
}
if (edgeCount == 2) {
patchType = 3; // CORNER
}
#if OSD_PATCH_ENABLE_SINGLE_CREASE
// check this after boundary/corner since single crease patch also has edgeCount.
if (vSegments.y > 0) {
patchType = 1;
}
#elif OSD_PATCH_GREGORY
patchType = 4;
#elif OSD_PATCH_GREGORY_BOUNDARY
patchType = 5;
#elif OSD_PATCH_GREGORY_BASIS
patchType = 6;
#endif
int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
return patchColors[6*patchType + pattern];
}
#if OSD_IS_ADAPTIVE
#if USE_STAGE_IN
#if OSD_PATCH_REGULAR
struct ControlPoint
{
float3 P [[attribute(0)]];
#if OSD_PATCH_ENABLE_SINGLE_CREASE
float3 P1 [[attribute(1)]];
float3 P2 [[attribute(2)]];
#if !USE_PTVS_SHARPNESS
float2 vSegments [[attribute(3)]];
#endif
#endif
};
struct PatchInput
{
patch_control_point<ControlPoint> cv;
#if !USE_PTVS_FACTORS
float4 tessOuterLo [[attribute(5)]];
float4 tessOuterHi [[attribute(6)]];
#endif
int3 patchParam [[attribute(10)]];
};
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
struct ControlPoint
{
float3 P [[attribute(0)]];
float3 Ep [[attribute(1)]];
float3 Em [[attribute(2)]];
float3 Fp [[attribute(3)]];
float3 Fm [[attribute(4)]];
};
struct PatchInput
{
patch_control_point<ControlPoint> cv;
int3 patchParam [[attribute(10)]];
};
#elif OSD_PATCH_GREGORY_BASIS
struct ControlPoint
{
float3 position [[attribute(0)]];
};
struct PatchInput
{
patch_control_point<ControlPoint> cv;
int3 patchParam [[attribute(10)]];
};
#endif
#endif
//----------------------------------------------------------
// OSD Kernel
//----------------------------------------------------------
//The user of OSD should define this kernel which serves as the landing point for all patch computation
//This compute function should just be copied and pasted, modifying the section under "User Vertex Transform"
//Or the entire function may be moddified as needed (for example to add a patch index buffer)
kernel void compute_main(
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
unsigned thread_position_in_grid [[thread_position_in_grid]],
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* quadTessellationFactors [[buffer(QUAD_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)]]
#endif
)
{
//----------------------------------------------------------
// OSD Kernel Setup
//----------------------------------------------------------
//Contains the shared patchParam value used by all threads that act upon a single patch
//the .z (sharpness) field is set to -1 (NAN) if that patch should be culled to signal other threads to return.
threadgroup int3 patchParam[PATCHES_PER_THREADGROUP];
threadgroup PatchVertexType patchVertices[PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH];
const auto real_threadgroup = thread_position_in_grid / REAL_THREADGROUP_DIVISOR;
const auto subthreadgroup_in_threadgroup = thread_position_in_threadgroup / REAL_THREADGROUP_DIVISOR;
const auto real_thread_in_threadgroup = thread_position_in_threadgroup & (REAL_THREADGROUP_DIVISOR - 1);
#if NEEDS_BARRIER
const auto validThread = thread_position_in_grid * CONTROL_POINTS_PER_THREAD < osdBuffers.kernelExecutionLimit;
#else
const auto validThread = true;
if(thread_position_in_grid * CONTROL_POINTS_PER_THREAD >= osdBuffers.kernelExecutionLimit)
return;
#endif
//----------------------------------------------------------
// OSD Vertex Transform
//----------------------------------------------------------
if(validThread)
{
patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer);
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 v = osdBuffers.vertexBuffer[vertexId];
threadgroup auto& patchVertex = patchVertices[thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset];
//----------------------------------------------------------
// User Vertex Transform
//----------------------------------------------------------
OsdComputePerVertex(float4(v.position,1), patchVertex, vertexId, frameConsts.ModelViewProjectionMatrix, osdBuffers);
}
}
#if NEEDS_BARRIER
threadgroup_barrier(mem_flags::mem_threadgroup);
#endif
//----------------------------------------------------------
// OSD Patch Cull
//----------------------------------------------------------
if(validThread)
{
#if PATCHES_PER_THREADGROUP > 1
auto patch = patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_THREAD * CONTROL_POINTS_PER_PATCH;
#else
//Small optimization for the '1 patch per threadgroup' case
auto patch = patchVertices;
#endif
if(!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix))
{
#if !OSD_USE_PATCH_INDEX_BUFFER
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[0] = 0.0h;
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[1] = 0.0h;
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[2] = 0.0h;
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[3] = 0.0h;
quadTessellationFactors[real_threadgroup].insideTessellationFactor[0] = 0.0h;
quadTessellationFactors[real_threadgroup].insideTessellationFactor[1] = 0.0h;
#endif
patchParam[subthreadgroup_in_threadgroup].z = -1;
#if !NEEDS_BARRIER
return;
#endif
}
}
#if NEEDS_BARRIER
threadgroup_barrier(mem_flags::mem_threadgroup);
#endif
//----------------------------------------------------------
// OSD Patch Compute
//----------------------------------------------------------
if(validThread && patchParam[subthreadgroup_in_threadgroup].z != -1)
{
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
{
OsdComputePerPatchVertex(
patchParam[subthreadgroup_in_threadgroup],
real_thread_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset,
real_threadgroup,
thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset,
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
osdBuffers
);
}
}
#if NEEDS_BARRIER
threadgroup_barrier(mem_flags::mem_device_and_threadgroup);
#endif
//----------------------------------------------------------
// OSD Tessellation Factors
//----------------------------------------------------------
if(validThread && real_thread_in_threadgroup == 0)
{
#if OSD_USE_PATCH_INDEX_BUFFER
const auto patchId = atomic_fetch_add_explicit((device atomic_uint*)&drawIndirectCommands->patchCount, 1, memory_order_relaxed);
patchIndex[patchId] = real_threadgroup;
#else
const auto patchId = real_threadgroup;
#endif
OsdComputePerPatchFactors(
patchParam[subthreadgroup_in_threadgroup],
frameConsts.TessLevel,
real_threadgroup,
frameConsts.ProjectionMatrix,
frameConsts.ModelViewMatrix,
osdBuffers,
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
quadTessellationFactors[patchId]
);
}
}
[[patch(quad, VERTEX_CONTROL_POINTS_PER_PATCH)]]
vertex OutputVertex vertex_main(
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
#if USE_STAGE_IN
const PatchInput patchInput [[stage_in]],
#else
const OsdVertexBufferSet patchInput,
#endif
float2 position_in_patch [[position_in_patch]],
uint patch_id [[patch_id]]
)
{
OutputVertex out;
#if USE_STAGE_IN
int3 patchParam = patchInput.patchParam;
#else
int3 patchParam = patchInput.patchParamBuffer[patch_id];
#endif
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) /
exp2((float)refinementLevel - 1);
auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput);
out.position = (frameConsts.ModelViewMatrix * float4(patchVertex.position, 1.0f)).xyz;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(patchVertex.position, 1.0f);
out.normal = mul(frameConsts.ModelViewMatrix, patchVertex.normal);
#if SHADING_TYPE == SHADING_TYPE_PATCH
#if OSD_PATCH_ENABLE_SINGLE_CREASE
out.patchColor = getAdaptivePatchColor(patchParam, patchVertex.vSegments).xyz;
#else
out.patchColor = getAdaptivePatchColor(patchParam).xyz;
#endif
#elif SHADING_TYPE == SHADING_TYPE_NORMAL
#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD
out.patchColor = patchVertex.patchCoord.xyz;
#endif
return out;
}
#endif
#if OSD_PATCH_REGULAR
const constant unsigned BSplineControlLineIndices[] = {
0, 1, //Outer lines
1, 2,
2, 3,
3, 7,
7, 11,
11, 15,
15, 14,
14, 13,
13, 12,
12, 8,
8, 4,
4, 0,
//Inner lines
5, 6,
6, 10,
10, 9,
9, 5,
//TL edge lines
1, 5,
4, 5,
//TR edge lines
2, 6,
6, 7,
//BL edge lines
8, 9,
9, 13,
//BR edge lines
10, 14,
10, 11
};
vertex SolidColorVertex vertex_lines(
const device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
const device OsdPerPatchVertexBezier* osdPerPatchVertexBezier [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]],
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
uint vertex_id [[vertex_id]]
)
{
const auto idx_size = sizeof(BSplineControlLineIndices) / sizeof(BSplineControlLineIndices[0]);
const auto idx = vertex_id % idx_size;
const auto patch_id = vertex_id / idx_size;
const auto in = osdPerPatchVertexBezier[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + BSplineControlLineIndices[idx]];
SolidColorVertex out;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.P, 1.0);
out.positionOut.z -= 0.001;
if(idx > 22) {
out.setColor(half4(0,1,0,1));
}
else
{
out.setColor(half4(1,0,0,1));
}
return out;
}
#endif
#if OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_BOUNDARY || OSD_PATCH_GREGORY
const constant uint GregoryBasisControlLineIndices[] = {
//Outer Edge
0, 2,
2, 16,
16, 15,
15, 17,
17, 11,
11, 10,
10, 12,
12, 6,
6, 5,
5, 7,
7, 1,
1, 0,
//Outside-Inside Edges
1, 3,
2, 4,
16, 18,
17, 19,
11, 13,
12, 14,
6, 8,
7, 9,
//Inner Edge
3, 4,
4, 18,
18, 19,
19, 13,
13, 14,
14, 8,
8, 9,
9, 3,
};
vertex SolidColorVertex vertex_lines(
#if OSD_PATCH_GREGORY_BASIS
const device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
const device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]],
#else
const device PackedInputVertex* vertexBuffer [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]],
#endif
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
uint vertex_id [[vertex_id]]
)
{
const auto idx_size = sizeof(GregoryBasisControlLineIndices) / sizeof(GregoryBasisControlLineIndices[0]);
const auto idx = vertex_id % idx_size;
const auto patch_id = vertex_id / idx_size;
#if OSD_PATCH_GREGORY_BASIS
const auto in = vertexBuffer[indicesBuffer[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + GregoryBasisControlLineIndices[idx]]];
#else
const auto in = vertexBuffer[patch_id * 20 + GregoryBasisControlLineIndices[idx]];
#endif
SolidColorVertex out;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.position, 1.0);
out.positionOut.z -= 0.001;
if(idx > 22) {
out.setColor(half4(0,1,0,1));
}
else
{
out.setColor(half4(1,0,0,1));
}
return out;
}
#endif
#if OSD_PATCH_QUADS || OSD_PATCH_TRIANGLES
#if OSD_PATCH_QUADS
const constant uint triangleIdx[6] = {
0, 2, 1, 3, 2, 0
};
#endif
vertex OutputVertex vertex_main(
device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]],
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
uint vertex_id [[vertex_id]]
)
{
#if OSD_PATCH_QUADS
const auto quadId = vertex_id / 6;
#else
const auto primID = vertex_id / 3;
#endif
#if OSD_PATCH_QUADS
float3 p0 = vertexBuffer[indicesBuffer[quadId * 4 + 0]].position;
float3 p1 = vertexBuffer[indicesBuffer[quadId * 4 + 1]].position;
float3 p2 = vertexBuffer[indicesBuffer[quadId * 4 + 2]].position;
float3 position = vertexBuffer[indicesBuffer[quadId * 4 + triangleIdx[vertex_id % 6]]].position;
#else
float3 p0 = vertexBuffer[indicesBuffer[primID * 3 + 0]].position;
float3 p1 = vertexBuffer[indicesBuffer[primID * 3 + 1]].position;
float3 p2 = vertexBuffer[indicesBuffer[primID * 3 + 2]].position;
float3 position = vertexBuffer[indicesBuffer[vertex_id]].position;
#endif
float3 normal = normalize(cross(p2 - p1, p0 - p1));
OutputVertex out;
out.position = (frameConsts.ModelViewMatrix * float4(position, 1.0)).xyz;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0);
out.normal = (frameConsts.ModelViewMatrix * float4(normal,0.0)).xyz;
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD
out.patchColor = out.normal;
#endif
return out;
}
vertex SolidColorVertex vertex_lines(
device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]],
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
uint vertex_id [[vertex_id]]
)
{
#if OSD_PATCH_QUADS
const auto quadId = vertex_id / 6;
#else
const auto primID = vertex_id / 3;
#endif
#if OSD_PATCH_QUADS
float3 position = vertexBuffer[indicesBuffer[quadId * 4 + triangleIdx[vertex_id % 6]]].position;
#else
float3 position = vertexBuffer[indicesBuffer[vertex_id]].position;
#endif
SolidColorVertex out;
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0);
return out;
}
#endif
fragment half4 fragment_solidcolor(SolidColorVertex in [[stage_in]])
{
return in.getColor();
}
fragment float4 fragment_main(OutputVertex in [[stage_in]],
const constant Light* lightData [[buffer(0)]],
const constant PerFrameConstants& frameConsts [[buffer(1)]],
const constant float4& shade [[buffer(2)]])
{
float4 color;
#if SHADING_TYPE == SHADING_TYPE_MATERIAL
const float3 diffuseColor = float3(0.4f, 0.4f, 0.8f);
#elif SHADING_TYPE == SHADING_TYPE_PATCH
const float3 diffuseColor = in.patchColor;
#else
#endif
#if SHADING_TYPE == SHADING_TYPE_NORMAL
color.xyz = normalize(in.normal) * 0.5 + 0.5;
#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD
color.xy = in.patchColor.xy;
color.z = 0;
#else
color.xyz = lighting(diffuseColor, lightData, in.position, normalize(in.normal));
#endif
// color.xyz = pow(color.xyz, 2.2);
color.w = 1;
return max(color,shade);
}

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ if (NOT NO_LIB)
)
endif()
if(OPENGL_FOUND OR OPENCL_FOUND OR DXSDK_FOUND)
if(OPENGL_FOUND OR OPENCL_FOUND OR DXSDK_FOUND OR METAL_FOUND)
add_subdirectory(tools/stringify)
endif()
@ -96,6 +96,14 @@ if (NOT NO_LIB)
)
endif()
if( METAL_FOUND )
include_directories( "${METAL_INCLUDE_DIR}" )
list(APPEND PLATFORM_GPU_LIBRARIES
${METAL_LIBRARIES}
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
endif()
if ( OPENCL_FOUND )
include_directories( "${OPENCL_INCLUDE_DIRS}" )
list(APPEND PLATFORM_GPU_LIBRARIES
@ -142,6 +150,7 @@ if (NOT NO_LIB)
$<TARGET_OBJECTS:far_obj>
$<TARGET_OBJECTS:osd_cpu_obj>
)
set_target_properties(osd_static_cpu
PROPERTIES
OUTPUT_NAME osdCPU
@ -159,7 +168,7 @@ if (NOT NO_LIB)
# this macro uses FindCUDA.cmake to compile .cu kernel files
# the target then adds the other obj dependencies and include files
_add_possibly_cuda_library(osd_static_gpu "opensubdiv"
STATIC
STATIC
version.cpp
$<TARGET_OBJECTS:osd_gpu_obj>
${CUDA_KERNEL_FILES}
@ -244,6 +253,113 @@ if (NOT NO_LIB)
endif()
# Build frameworks ----------------------------------
if(APPLE)
get_directory_property(OSD_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/osd DEFINITION PUBLIC_HEADER_FILES)
get_directory_property(FAR_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/far DEFINITION PUBLIC_HEADER_FILES)
get_directory_property(SDC_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/sdc DEFINITION PUBLIC_HEADER_FILES)
get_directory_property(HBR_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/hbr DEFINITION PUBLIC_HEADER_FILES)
get_directory_property(VTR_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/vtr DEFINITION PUBLIC_HEADER_FILES)
foreach(file ${OSD_HEADER_FILES})
list(APPEND PUBLIC_HEADER_FILES "osd/${file}")
endforeach(file)
foreach(file ${FAR_HEADER_FILES})
list(APPEND PUBLIC_HEADER_FILES "far/${file}")
endforeach(file)
foreach(file ${SDC_HEADER_FILES})
list(APPEND PUBLIC_HEADER_FILES "sdc/${file}")
endforeach(file)
foreach(file ${HBR_HEADER_FILES})
list(APPEND PUBLIC_HEADER_FILES "hbr/${file}")
endforeach(file)
foreach(file ${VTR_HEADER_FILES})
list(APPEND PUBLIC_HEADER_FILES "vtr/${file}")
endforeach(file)
list(APPEND PUBLIC_HEADER_FILES "version.h")
#static framework
add_library(osd_static_framework
STATIC
version.cpp
$<TARGET_OBJECTS:sdc_obj>
$<TARGET_OBJECTS:vtr_obj>
$<TARGET_OBJECTS:far_obj>
$<TARGET_OBJECTS:osd_cpu_obj>
$<TARGET_OBJECTS:osd_gpu_obj>
)
set_target_properties(
osd_static_framework
PROPERTIES
FRAMEWORK true
INSTALL_NAME_DIR "@rpath/OpenSubdiv.framework/OpenSubdiv"
INSTALL_RPATH "@executable_path/Frameworks;@loader_path/Frameworks"
OUTPUT_NAME OpenSubdiv
CLEAN_DIRECT_OUTPUT true
)
target_link_libraries(osd_static_framework
${PLATFORM_CPU_LIBRARIES} ${PLATFORM_GPU_LIBRARIES}
)
install( TARGETS osd_static_framework
LIBRARY DESTINATION "${CMAKE_LIBDIR_BASE}"
FRAMEWORK DESTINATION "${CMAKE_LIBDIR_BASE}"
PUBLIC_HEADER DESTINATION "${CMAKE_INCDIR_BASE}"
ARCHIVE DESTINATION "${CMAKE_LIBDIR_BASE}")
#shared framework
add_library(osd_dynamic_framework
SHARED
version.cpp
$<TARGET_OBJECTS:sdc_obj>
$<TARGET_OBJECTS:vtr_obj>
$<TARGET_OBJECTS:far_obj>
$<TARGET_OBJECTS:osd_cpu_obj>
$<TARGET_OBJECTS:osd_gpu_obj>
)
set_target_properties(
osd_dynamic_framework
PROPERTIES
RPATH true
FRAMEWORK true
INSTALL_NAME_DIR "@rpath/OpenSubdiv.framework/OpenSubdiv"
INSTALL_RPATH "@executable_path/Frameworks;@loader_path/Frameworks"
OUTPUT_NAME OpenSubdiv
CLEAN_DIRECT_OUTPUT true
)
target_link_libraries(osd_dynamic_framework
${PLATFORM_CPU_LIBRARIES} ${PLATFORM_GPU_LIBRARIES}
)
install( TARGETS osd_dynamic_framework
FRAMEWORK DESTINATION "${CMAKE_LIBDIR_BASE}"
LIBRARY DESTINATION "${CMAKE_LIBDIR_BASE}"
PUBLIC_HEADER DESTINATION "${CMAKE_INCDIR_BASE}"
PRIVATE_HEADER DESTINATION "${CMAKE_INCDIR_BASE}"
)
foreach(file ${PUBLIC_HEADER_FILES})
add_custom_command(TARGET osd_dynamic_framework POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/opensubdiv/${file}" "$<TARGET_FILE_DIR:osd_dynamic_framework>/Headers/${file}"
)
endforeach(file)
add_custom_command(TARGET osd_dynamic_framework POST_BUILD
COMMAND ln -sf "Versions/Current/Headers" "$<TARGET_FILE_DIR:osd_dynamic_framework>/../../Headers"
)
endif()
endif()
#-------------------------------------------------------------------------------

View File

@ -117,7 +117,7 @@ set(GL_PUBLIC_HEADERS
glslPatchShaderSource.h
)
if( OPENGL_FOUND OR OPENGLES_FOUND )
if( (NOT NO_OPENGL) AND (OPENGL_FOUND OR OPENGLES_FOUND) )
list(APPEND GPU_SOURCE_FILES
cpuGLVertexBuffer.cpp
glLegacyGregoryPatchTable.cpp
@ -218,6 +218,55 @@ endif()
list(APPEND DOXY_HEADER_FILES ${DXSDK_PUBLIC_HEADERS})
#-------------------------------------------------------------------------------
# Metal code & dependencies
set(METAL_PUBLIC_HEADERS
mtlVertexBuffer.h
mtlComputeEvaluator.h
mtlLegacyGregoryPatchTable.h
mtlPatchTable.h
mtlVertexBuffer.h
mtlMesh.h
mtlPatchShaderSource.h
mtlCommon.h
)
if( METAL_FOUND )
set(METAL_SOURCE_FILES
mtlVertexBuffer.mm
mtlComputeEvaluator.mm
mtlLegacyGregoryPatchTable.mm
mtlPatchTable.mm
mtlVertexBuffer.mm
mtlPatchShaderSource.mm
)
set_source_files_properties(
${METAL_SOURCE_FILES}
PROPERTIES
COMPILE_FLAGS
"-fobjc-arc")
list(APPEND GPU_SOURCE_FILES ${METAL_SOURCE_FILES})
list(APPEND PUBLIC_HEADER_FILES ${METAL_PUBLIC_HEADERS})
list(APPEND KERNEL_FILES
mtlComputeKernel.metal
mtlPatchCommon.metal
mtlPatchBSpline.metal
mtlPatchGregory.metal
mtlPatchGregoryBasis.metal
)
list(APPEND PLATFORM_GPU_LIBRARIES
${METAL_LIBRARIES}
)
endif()
list(APPEND DOXY_HEADER_FILES ${METAL_PUBLIC_HEADERS})
#-------------------------------------------------------------------------------
# OpenCL code & dependencies
set(OPENCL_PUBLIC_HEADERS
@ -330,12 +379,10 @@ if( GPU_SOURCE_FILES )
${PUBLIC_HEADER_FILES}
${INC_FILES}
)
set_target_properties(osd_gpu_obj
PROPERTIES
FOLDER "opensubdiv"
)
endif()
_add_doxy_headers( "${DOXY_HEADER_FILES}" )
@ -350,7 +397,6 @@ install(
GROUP_READ
WORLD_READ )
if (ANDROID)
install(
FILES

View File

@ -0,0 +1,52 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_MTL_COMMON_H
#define OPENSUBDIV3_OSD_MTL_COMMON_H
#include "../version.h"
#include <cstddef>
@protocol MTLDevice;
@protocol MTLCommandQueue;
namespace OpenSubdiv
{
namespace OPENSUBDIV_VERSION
{
namespace Osd
{
class MTLContext
{
public:
id<MTLDevice> device = nullptr;
id<MTLCommandQueue> commandQueue = nullptr;
};
}
}
using namespace OPENSUBDIV_VERSION;
}
#endif //OPENSUBDIV3_OSD_MTL_COMMON_H

View File

@ -0,0 +1,867 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
#define OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
#include "../version.h"
#include "../osd/types.h"
#include "../osd/bufferDescriptor.h"
#include "../osd/mtlCommon.h"
@protocol MTLDevice;
@protocol MTLBuffer;
@protocol MTLLibrary;
@protocol MTLComputePipelineState;
namespace OpenSubdiv
{
namespace OPENSUBDIV_VERSION
{
namespace Far
{
class StencilTable;
class PatchTable;
class LimitStencilTable;
}
namespace Osd
{
class MTLStencilTable
{
public:
template<typename STENCIL_TABLE, typename DEVICE_CONTEXT>
static MTLStencilTable* Create(STENCIL_TABLE* stencilTable,
DEVICE_CONTEXT context)
{
return new MTLStencilTable(stencilTable, context);
}
MTLStencilTable(Far::StencilTable const* stencilTable, MTLContext* context);
MTLStencilTable(Far::LimitStencilTable const* stencilTable, MTLContext* context);
~MTLStencilTable();
id<MTLBuffer> GetSizesBuffer() const { return _sizesBuffer; }
id<MTLBuffer> GetOffsetsBuffer() const { return _offsetsBuffer; }
id<MTLBuffer> GetIndicesBuffer() const { return _indicesBuffer; }
id<MTLBuffer> GetWeightsBuffer() const { return _weightsBuffer; }
id<MTLBuffer> GetDuWeightsBuffer() const { return _duWeightsBuffer; }
id<MTLBuffer> GetDvWeightsBuffer() const { return _dvWeightsBuffer; }
int GetNumStencils() const { return _numStencils; }
private:
id<MTLBuffer> _sizesBuffer;
id<MTLBuffer> _offsetsBuffer;
id<MTLBuffer> _indicesBuffer;
id<MTLBuffer> _weightsBuffer;
id<MTLBuffer> _duWeightsBuffer;
id<MTLBuffer> _dvWeightsBuffer;
int _numStencils;
};
class MTLComputeEvaluator
{
public:
typedef bool Instantiatable;
static MTLComputeEvaluator * Create(BufferDescriptor const &srcDesc,
BufferDescriptor const &dstDesc,
BufferDescriptor const &duDesc,
BufferDescriptor const &dvDesc,
MTLContext* context);
static MTLComputeEvaluator * Create(BufferDescriptor const &srcDesc,
BufferDescriptor const &dstDesc,
BufferDescriptor const &duDesc,
BufferDescriptor const &dvDesc,
BufferDescriptor const &duuDesc,
BufferDescriptor const &duvDesc,
BufferDescriptor const &dvvDesc,
MTLContext* context);
MTLComputeEvaluator();
~MTLComputeEvaluator();
/// ----------------------------------------------------------------------
///
/// Stencil evaluations with StencilTable
///
/// ----------------------------------------------------------------------
/// \brief Generic static compute function. This function has a same
/// signature as other device kernels have so that it can be called
/// transparently from OsdMesh template interface.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning an
/// MTLBuffer object of source data
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBO() method returning an
/// MTLBuffer object of destination data
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param stencilTable stencil table to be applied. The table must have
/// MTLBuffer interfaces.
///
/// @param instance cached compiled instance. Clients are supposed to
/// pre-compile an instance of this class and provide
/// to this function. If it's null the kernel still
/// compute by instantiating on-demand kernel although
/// it may cause a performance problem.
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
static bool EvalStencils(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
STENCIL_TABLE const *stencilTable,
MTLComputeEvaluator const *instance,
MTLContext* context)
{
if (instance)
{
return instance->EvalStencils(srcBuffer, srcDesc,
dstBuffer, dstDesc,
stencilTable,
context);
}
else
{
// Create an instace on demand (slow)
instance = Create(srcDesc, dstDesc,
BufferDescriptor(),
BufferDescriptor(),
context);
if (instance)
{
bool r = instance->EvalStencils(srcBuffer, srcDesc,
dstBuffer, dstDesc,
stencilTable,
context);
delete instance;
return r;
}
return false;
}
}
/// \brief Generic static compute function. This function has a same
/// signature as other device kernels have so that it can be called
/// transparently from OsdMesh template interface.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning an
/// MTLBuffer object of source data
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBO() method returning an
/// MTLBuffer object of destination data
///
/// @param dstDesc vertex buffer descriptor for the dstBuffer
///
/// @param duBuffer Output U-derivative buffer
/// must have BindVBO() method returning an
/// MTLBuffer object of destination data
///
/// @param duDesc vertex buffer descriptor for the duBuffer
///
/// @param dvBuffer Output V-derivative buffer
/// must have BindVBO() method returning an
/// MTLBuffer object of destination data
///
/// @param dvDesc vertex buffer descriptor for the dvBuffer
///
/// @param stencilTable stencil table to be applied. The table must have
/// SSBO interfaces.
///
/// @param instance cached compiled instance. Clients are supposed to
/// pre-compile an instance of this class and provide
/// to this function. If it's null the kernel still
/// compute by instantiating on-demand kernel although
/// it may cause a performance problem.
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
static bool EvalStencils(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
STENCIL_TABLE const *stencilTable,
MTLComputeEvaluator const *instance,
MTLContext* context) {
if (instance) {
return instance->EvalStencils(srcBuffer, srcDesc,
dstBuffer, dstDesc,
duBuffer, duDesc,
dvBuffer, dvDesc,
stencilTable,
context);
} else {
// Create a pipeline state on demand (slow)
instance = Create(srcDesc, dstDesc, duDesc, dvDesc, context);
if (instance) {
bool r = instance->EvalStencils(srcBuffer, srcDesc,
dstBuffer, dstDesc,
duBuffer, duDesc,
dvBuffer, dvDesc,
stencilTable,
context);
delete instance;
return r;
}
return false;
}
}
/// Dispatch the compute pipeline on GPU asynchronously.
/// returns false if the kernel hasn't been compiled yet.
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
bool EvalStencils(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
STENCIL_TABLE const *stencilTable,
MTLContext* context) const
{
return EvalStencils(srcBuffer->BindMTLBuffer(context), srcDesc,
dstBuffer->BindMTLBuffer(context), dstDesc,
0, BufferDescriptor(),
0, BufferDescriptor(),
stencilTable->GetSizesBuffer(),
stencilTable->GetOffsetsBuffer(),
stencilTable->GetIndicesBuffer(),
stencilTable->GetWeightsBuffer(),
0,
0,
/* start = */ 0,
/* end = */ stencilTable->GetNumStencils(),
context);
}
/// Dispatch the compute pipeline on GPU asynchronously.
/// returns false if the kernel hasn't been compiled yet.
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
bool EvalStencils(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
STENCIL_TABLE const *stencilTable,
MTLContext* context) const
{
return EvalStencils(srcBuffer->BindVBO(), srcDesc,
dstBuffer->BindVBO(), dstDesc,
duBuffer->BindVBO(), duDesc,
dvBuffer->BindVBO(), dvDesc,
stencilTable->GetSizesBuffer(),
stencilTable->GetOffsetsBuffer(),
stencilTable->GetIndicesBuffer(),
stencilTable->GetWeightsBuffer(),
stencilTable->GetDuWeightsBuffer(),
stencilTable->GetDvWeightsBuffer(),
/* start = */ 0,
/* end = */ stencilTable->GetNumStencils(),
context);
}
/// Dispatch the compute pipeline on GPU asynchronously.
/// returns false if the kernel hasn't been compiled yet.
bool EvalStencils(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
id<MTLBuffer> sizesBuffer,
id<MTLBuffer> offsetsBuffer,
id<MTLBuffer> indicesBuffer,
id<MTLBuffer> weightsBuffer,
id<MTLBuffer> duWeightsBuffer,
id<MTLBuffer> dvWeightsBuffer,
int start,
int end,
MTLContext* context) const;
/// ----------------------------------------------------------------------
///
/// Limit evaluations with PatchTable
///
/// ----------------------------------------------------------------------
///
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning an
/// MTLBuffer object of source data
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBO() method returning an
/// MTLBuffer object of destination data
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
/// must have BindVBO() method returning an
/// array of PatchCoord struct in VBO.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param instance cached compiled instance. Clients are supposed to
/// pre-compile an instance of this class and provide
/// to this function. If it's null the kernel still
/// compute by instantiating on-demand kernel although
/// it may cause a performance problem.
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
static bool EvalPatches(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
MTLComputeEvaluator const *instance,
MTLContext* context) {
if (instance) {
return instance->EvalPatches(srcBuffer, srcDesc,
dstBuffer, dstDesc,
numPatchCoords, patchCoords,
patchTable,
context);
} else {
// Create an instance on demand (slow)
instance = Create(srcDesc, dstDesc,
BufferDescriptor(),
BufferDescriptor(), context );
if (instance) {
bool r = instance->EvalPatches(srcBuffer, srcDesc,
dstBuffer, dstDesc,
numPatchCoords, patchCoords,
patchTable,
context);
delete instance;
return r;
}
return false;
}
}
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning an
/// MTLBuffer object of source data
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBO() method returning an
/// MTLBuffer object of destination data
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param duBuffer
///
/// @param duDesc
///
/// @param dvBuffer
///
/// @param dvDesc
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
/// must have BindVBO() method returning an
/// array of PatchCoord struct in VBO.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param instance cached compiled instance. Clients are supposed to
/// pre-compile an instance of this class and provide
/// to this function. If it's null the kernel still
/// compute by instantiating on-demand kernel although
/// it may cause a performance problem.
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
static bool EvalPatches(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
MTLComputeEvaluator* instance,
MTLContext* context) {
if (instance) {
return instance->EvalPatches(srcBuffer, srcDesc,
dstBuffer, dstDesc,
duBuffer, duDesc,
dvBuffer, dvDesc,
numPatchCoords, patchCoords,
patchTable,
context);
} else {
// Create an instance on demand (slow)
instance = Create(srcDesc, dstDesc, duDesc, dvDesc, context);
if (instance) {
bool r = instance->EvalPatches(srcBuffer, srcDesc,
dstBuffer, dstDesc,
duBuffer, duDesc,
dvBuffer, dvDesc,
numPatchCoords, patchCoords,
patchTable,
context);
delete instance;
return r;
}
return false;
}
}
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning a
/// const float pointer for read
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBOBuffer() method returning a
/// float pointer for write
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
/// must have BindVBO() method returning an
/// array of PatchCoord struct in VBO.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
bool EvalPatches(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
MTLContext* context) const {
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
dstBuffer->BindVBO(), dstDesc,
0, BufferDescriptor(),
0, BufferDescriptor(),
numPatchCoords,
patchCoords->BindVBO(),
patchTable->GetPatchArrays(),
patchTable->GetPatchIndexBuffer(),
patchTable->GetPatchParamBuffer(),
context);
}
/// \brief Generic limit eval function with derivatives. This function has
/// a same signature as other device kernels have so that it can be
/// called in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning a
/// const float pointer for read
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBO() method returning a
/// float pointer for write
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param duBuffer Output U-derivatives buffer
/// must have BindVBO() method returning a
/// float pointer for write
///
/// @param duDesc vertex buffer descriptor for the duBuffer
///
/// @param dvBuffer Output V-derivatives buffer
/// must have BindVBO() method returning a
/// float pointer for write
///
/// @param dvDesc vertex buffer descriptor for the dvBuffer
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
bool EvalPatches(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
MTLContext* context) const {
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
dstBuffer->BindVBO(), dstDesc,
duBuffer->BindVBO(), duDesc,
dvBuffer->BindVBO(), dvDesc,
numPatchCoords,
patchCoords->BindVBO(),
patchTable->GetPatchArrays(),
patchTable->GetPatchIndexBuffer(),
patchTable->GetPatchParamBuffer(),
context);
}
bool EvalPatches(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
int numPatchCoords,
id<MTLBuffer> patchCoordsBuffer,
const PatchArrayVector &patchArrays,
id<MTLBuffer> patchIndexBuffer,
id<MTLBuffer> patchParamsBuffer,
MTLContext* context) const;
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning a GL
/// buffer object of source data
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBO() method returning a GL
/// buffer object of destination data
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
/// must have BindVBO() method returning an
/// array of PatchCoord struct in VBO.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param instance cached compiled instance. Clients are supposed to
/// pre-compile an instance of this class and provide
/// to this function. If it's null the kernel still
/// compute by instantiating on-demand kernel although
/// it may cause a performance problem.
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
static bool EvalPatchesVarying(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
MTLComputeEvaluator const *instance,
MTLContext* deviceContext) {
if (instance) {
return instance->EvalPatchesVarying(
srcBuffer, srcDesc,
dstBuffer, dstDesc,
numPatchCoords, patchCoords,
patchTable,
deviceContext);
} else {
// Create an instance on demand (slow)
instance = Create(srcDesc, dstDesc,
BufferDescriptor(),
BufferDescriptor(),
deviceContext);
if (instance) {
bool r = instance->EvalPatchesVarying(
srcBuffer, srcDesc,
dstBuffer, dstDesc,
numPatchCoords, patchCoords,
patchTable,
deviceContext);
delete instance;
return r;
}
return false;
}
}
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning a
/// const float pointer for read
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBOBuffer() method returning a
/// float pointer for write
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
/// must have BindVBO() method returning an
/// array of PatchCoord struct in VBO.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
bool EvalPatchesVarying(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
MTLContext* deviceContext) const {
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
dstBuffer->BindVBO(), dstDesc,
0, BufferDescriptor(),
0, BufferDescriptor(),
numPatchCoords,
patchCoords->BindVBO(),
patchTable->GetVaryingPatchArrays(),
patchTable->GetVaryingPatchIndexBuffer(),
patchTable->GetPatchParamBuffer(),
deviceContext
);
}
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning a GL
/// buffer object of source data
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBO() method returning a GL
/// buffer object of destination data
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
/// must have BindVBO() method returning an
/// array of PatchCoord struct in VBO.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param fvarChannel face-varying channel
///
/// @param instance cached compiled instance. Clients are supposed to
/// pre-compile an instance of this class and provide
/// to this function. If it's null the kernel still
/// compute by instantiating on-demand kernel although
/// it may cause a performance problem.
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
static bool EvalPatchesFaceVarying(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
int fvarChannel,
MTLComputeEvaluator const *instance,
MTLContext* deviceContext) {
if (instance) {
return instance->EvalPatchesFaceVarying(
srcBuffer, srcDesc,
dstBuffer, dstDesc,
numPatchCoords, patchCoords,
patchTable, fvarChannel,
deviceContext);
} else {
// Create an instance on demand (slow)
instance = Create(srcDesc, dstDesc,
BufferDescriptor(),
BufferDescriptor(),
deviceContext);
if (instance) {
bool r = instance->EvalPatchesFaceVarying(
srcBuffer, srcDesc,
dstBuffer, dstDesc,
numPatchCoords, patchCoords,
patchTable, fvarChannel,
deviceContext);
delete instance;
return r;
}
return false;
}
}
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// in the same way.
///
/// @param srcBuffer Input primvar buffer.
/// must have BindVBO() method returning a
/// const float pointer for read
///
/// @param srcDesc vertex buffer descriptor for the input buffer
///
/// @param dstBuffer Output primvar buffer
/// must have BindVBOBuffer() method returning a
/// float pointer for write
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param numPatchCoords number of patchCoords.
///
/// @param patchCoords array of locations to be evaluated.
/// must have BindVBO() method returning an
/// array of PatchCoord struct in VBO.
///
/// @param patchTable MTLPatchTable or equivalent
///
/// @param fvarChannel face-varying channel
///
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
/// to obtain command buffers from.
///
template <typename SRC_BUFFER, typename DST_BUFFER,
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
bool EvalPatchesFaceVarying(
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
int numPatchCoords,
PATCHCOORD_BUFFER *patchCoords,
PATCH_TABLE *patchTable,
MTLContext* deviceContext,
int fvarChannel = 0
) const {
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
dstBuffer->BindVBO(), dstDesc,
0, BufferDescriptor(),
0, BufferDescriptor(),
numPatchCoords,
patchCoords->BindVBO(),
patchTable->GetFVarPatchArrays(fvarChannel),
patchTable->GetFVarPatchIndexBuffer(fvarChannel),
patchTable->GetFVarPatchParamBuffer(fvarChannel),
deviceContext);
}
/// Configure compute pipline state. Returns false if it fails to create the pipeline state.
bool Compile(BufferDescriptor const &srcDesc,
BufferDescriptor const &dstDesc,
BufferDescriptor const &duDesc,
BufferDescriptor const &dvDesc,
MTLContext* context);
/// Wait for the dispatched kernel to finish.
static void Synchronize(MTLContext* context);
private:
id<MTLLibrary> _computeLibrary;
id<MTLComputePipelineState> _evalStencils;
id<MTLComputePipelineState> _evalPatches;
id<MTLBuffer> _parameterBuffer;
int _workGroupSize;
};
} //end namespace Osd
} //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSubdiv
#endif // OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H

View File

@ -0,0 +1,473 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../osd/mtlComputeEvaluator.h"
#include "../osd/mtlPatchShaderSource.h"
#include <vector>
#include <Metal/Metal.h>
#include <simd/simd.h>
#include <sstream>
#include <string>
#include "../far/stencilTable.h"
#include "../far/error.h"
#define PARAMETER_BUFFER_INDEX 0
#define SIZES_BUFFER_INDEX 1
#define OFFSETS_BUFFER_INDEX 2
#define INDICES_BUFFER_INDEX 3
#define WEIGHTS_BUFFER_INDEX 4
#define DST_VERTEX_BUFFER_INDEX 5
#define SRC_VERTEX_BUFFER_INDEX 6
#define DU_WEIGHTS_BUFFER_INDEX 7
#define DV_WEIGHTS_BUFFER_INDEX 8
#define DU_DERIVATIVE_BUFFER_INDEX 9
#define DV_DERIVATIVE_BUFFER_INDEX 10
#define PATCH_ARRAYS_BUFFER_INDEX 11
#define PATCH_COORDS_BUFFER_INDEX 12
#define PATCH_INDICES_BUFFER_INDEX 13
#define PATCH_PARAMS_BUFFER_INDEX 14
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
namespace mtl
{
struct PatchCoord
{
int arrayIndex;
int patchIndex;
int vertIndex;
float s;
float t;
};
struct PatchParam
{
uint field0;
uint field1;
float sharpness;
};
struct KernelUniformArgs
{
int batchStart;
int batchEnd;
int srcOffset;
int dstOffset;
simd::int3 duDesc;
simd::int3 dvDesc;
};
} //end namespace mtl
static const char *KernelSource =
#include "mtlComputeKernel.gen.h"
;
template <typename T>
static id<MTLBuffer> createBuffer(const std::vector<T> &vec,
MTLContext* context)
{
const auto length = sizeof(T) * vec.size();
#if TARGET_OS_IOS || TARGET_OS_TV
return [context->device newBufferWithBytes:vec.data() length:length options:MTLResourceOptionCPUCacheModeDefault];
#elif TARGET_OS_OSX
@autoreleasepool {
auto cmdBuf = [context->commandQueue commandBuffer];
auto blitEncoder = [cmdBuf blitCommandEncoder];
auto stageBuffer = [context->device newBufferWithBytes:vec.data() length:length options:MTLResourceOptionCPUCacheModeDefault];
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
[blitEncoder endEncoding];
[cmdBuf commit];
[cmdBuf waitUntilCompleted];
#if !__has_feature(objc_arc)
[stageBuffer release];
#endif
return finalBuffer;
}
#endif
}
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
using namespace Osd;
MTLStencilTable::MTLStencilTable(Far::StencilTable const *stencilTable,
MTLContext* context)
{
assert(context != nil);
assert(context->device != nil && context->commandQueue != nil);
_numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0)
{
auto sizes = stencilTable->GetSizes();
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
_sizesBuffer.label = @"StencilTable Sizes";
_offsetsBuffer.label = @"StencilTable Offsets";
_indicesBuffer.label = @"StencilTable Indices";
_weightsBuffer.label = @"StencilTable Weights";
}
_duWeightsBuffer = nil;
_dvWeightsBuffer = nil;
}
MTLStencilTable::MTLStencilTable(Far::LimitStencilTable const *stencilTable,
MTLContext* context)
{
assert(context != nil);
assert(context->device != nil && context->commandQueue != nil);
_numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0)
{
auto sizes = stencilTable->GetSizes();
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
_duWeightsBuffer = createBuffer(stencilTable->GetDuWeights(), context);
_dvWeightsBuffer = createBuffer(stencilTable->GetDvWeights(), context);
_sizesBuffer.label = @"StencilTable Sizes";
_offsetsBuffer.label = @"StencilTable Offsets";
_indicesBuffer.label = @"StencilTable Indices";
_weightsBuffer.label = @"StencilTable Weights";
_duWeightsBuffer.label = @"StencilTable duWeights";
_dvWeightsBuffer.label = @"StencilTable dvWeights";
}
}
MTLStencilTable::~MTLStencilTable() {}
MTLComputeEvaluator *MTLComputeEvaluator::Create(
BufferDescriptor const &srcDesc, BufferDescriptor const &dstDesc,
BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc,
MTLContext* context)
{
assert(context != nil);
assert(context->device != nil && context->commandQueue != nil);
auto instance = new MTLComputeEvaluator();
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, context))
return instance;
delete instance;
return nullptr;
}
MTLComputeEvaluator *MTLComputeEvaluator::Create(
BufferDescriptor const &srcDesc, BufferDescriptor const &dstDesc,
BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc,
BufferDescriptor const &duuDesc, BufferDescriptor const &duvDesc, BufferDescriptor const &dvvDesc,
MTLContext* context)
{
assert(context != nil);
assert(context->device != nil && context->commandQueue != nil);
auto instance = new MTLComputeEvaluator();
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, context))
return instance;
delete instance;
return nullptr;
}
bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
BufferDescriptor const &dstDesc,
BufferDescriptor const &duDesc,
BufferDescriptor const &dvDesc,
MTLContext* context)
{
assert(context != nil);
assert(context->device != nil && context->commandQueue != nil);
using namespace Osd;
using namespace Far;
MTLCompileOptions *compileOptions = [[MTLCompileOptions alloc] init];
compileOptions.preprocessorMacros = nil;
bool useDeriv = duDesc.length > 0 || dvDesc.length > 0;
if(useDeriv)
{
printf("Using OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES");
}
#define DEFINE(x,y) @(#x) : @(y)
auto preprocessor = @{
DEFINE(LENGTH, srcDesc.length),
DEFINE(SRC_STRIDE, srcDesc.stride),
DEFINE(DST_STRIDE, dstDesc.stride),
DEFINE(WORK_GROUP_SIZE, _workGroupSize),
DEFINE(OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES, useDeriv),
DEFINE(PARAMETER_BUFFER_INDEX,PARAMETER_BUFFER_INDEX),
DEFINE(SIZES_BUFFER_INDEX,SIZES_BUFFER_INDEX),
DEFINE(OFFSETS_BUFFER_INDEX,OFFSETS_BUFFER_INDEX),
DEFINE(INDICES_BUFFER_INDEX,INDICES_BUFFER_INDEX),
DEFINE(WEIGHTS_BUFFER_INDEX,WEIGHTS_BUFFER_INDEX),
DEFINE(SRC_VERTEX_BUFFER_INDEX,SRC_VERTEX_BUFFER_INDEX),
DEFINE(DST_VERTEX_BUFFER_INDEX,DST_VERTEX_BUFFER_INDEX),
DEFINE(DU_WEIGHTS_BUFFER_INDEX,DU_WEIGHTS_BUFFER_INDEX),
DEFINE(DV_WEIGHTS_BUFFER_INDEX,DV_WEIGHTS_BUFFER_INDEX),
DEFINE(DU_DERIVATIVE_BUFFER_INDEX,DU_DERIVATIVE_BUFFER_INDEX),
DEFINE(DV_DERIVATIVE_BUFFER_INDEX,DV_DERIVATIVE_BUFFER_INDEX),
DEFINE(PATCH_ARRAYS_BUFFER_INDEX,PATCH_ARRAYS_BUFFER_INDEX),
DEFINE(PATCH_COORDS_BUFFER_INDEX,PATCH_COORDS_BUFFER_INDEX),
DEFINE(PATCH_INDICES_BUFFER_INDEX,PATCH_INDICES_BUFFER_INDEX),
DEFINE(PATCH_PARAMS_BUFFER_INDEX,PATCH_PARAMS_BUFFER_INDEX),
};
#undef DEFINE
compileOptions.preprocessorMacros = preprocessor;
std::stringstream sourceString;
sourceString << MTLPatchShaderSource::GetPatchBasisShaderSource();
sourceString << KernelSource;
NSError *err = nil;
_computeLibrary =
[context->device newLibraryWithSource:@(sourceString.str().c_str())
options:compileOptions
error:&err];
#if !__has_feature(objc_arc)
[compileOptions release];
#endif
if (!_computeLibrary)
{
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Shader: %s\n",
err ? err.localizedDescription.UTF8String : "");
return false;
}
auto evalStencilsFunction = [_computeLibrary newFunctionWithName:@"eval_stencils"];
_evalStencils =
[context->device newComputePipelineStateWithFunction:evalStencilsFunction
error:&err];
#if !__has_feature(objc_arc)
[evalStencilsFunction release];
#endif
if (!_evalStencils)
{
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_stencils: %s\n",
err ? err.localizedDescription.UTF8String : "");
return false;
}
auto evalPatchesFunction = [_computeLibrary newFunctionWithName:@"eval_patches"];
_evalPatches =
[context->device newComputePipelineStateWithFunction:evalPatchesFunction
error:&err];
#if !__has_feature(objc_arc)
[evalPatchesFunction release];
#endif
if (!_evalPatches)
{
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_patches: %s\n",
err ? err.localizedDescription.UTF8String : "");
return false;
}
_parameterBuffer =
[context->device newBufferWithLength:sizeof(mtl::KernelUniformArgs)
options:MTLResourceOptionCPUCacheModeDefault];
return true;
}
MTLComputeEvaluator::MTLComputeEvaluator() : _workGroupSize(32) {}
MTLComputeEvaluator::~MTLComputeEvaluator()
{
#if !__has_feature(objc_arc)
[_computeLibrary release];
[_evalStencils release];
[_evalPatches release];
[_parameterBuffer release];
#endif
}
void MTLComputeEvaluator::Synchronize(MTLContext* context) { }
bool MTLComputeEvaluator::EvalStencils(
id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
id<MTLBuffer> sizesBuffer,
id<MTLBuffer> offsetsBuffer,
id<MTLBuffer> indicesBuffer,
id<MTLBuffer> weightsBuffer,
id<MTLBuffer> duWeightsBuffer,
id<MTLBuffer> dvWeightsBuffer, int start, int end,
MTLContext* context) const
{
if(_evalStencils == nil)
return false;
auto count = end - start;
if (count <= 0)
return true;
assert(context != nullptr);
auto device = context->device;
auto commandQueue = context->commandQueue;
assert(device != nil && commandQueue != nil);
mtl::KernelUniformArgs args;
args.batchStart = start;
args.batchEnd = end;
args.srcOffset = srcDesc.offset;
args.dstOffset = dstDesc.offset;
args.duDesc = (simd::int3){duDesc.offset, duDesc.length, duDesc.stride};
args.dvDesc = (simd::int3){dvDesc.offset, dvDesc.length, dvDesc.stride};
memcpy(_parameterBuffer.contents, &args, sizeof(args));
auto commandBuffer = [commandQueue commandBuffer];
auto computeEncoder = [commandBuffer computeCommandEncoder];
[computeEncoder setBuffer:_parameterBuffer offset:0 atIndex:PARAMETER_BUFFER_INDEX];
[computeEncoder setBuffer:sizesBuffer offset:0 atIndex:SIZES_BUFFER_INDEX];
[computeEncoder setBuffer:weightsBuffer offset:0 atIndex:WEIGHTS_BUFFER_INDEX];
[computeEncoder setBuffer:offsetsBuffer offset:0 atIndex:OFFSETS_BUFFER_INDEX];
[computeEncoder setBuffer:indicesBuffer offset:0 atIndex:INDICES_BUFFER_INDEX];
[computeEncoder setBuffer:srcBuffer offset:0 atIndex:SRC_VERTEX_BUFFER_INDEX];
[computeEncoder setBuffer:dstBuffer offset:0 atIndex:DST_VERTEX_BUFFER_INDEX];
if(duWeightsBuffer && dvWeightsBuffer)
{
[computeEncoder setBuffer:duWeightsBuffer offset:0 atIndex:DU_WEIGHTS_BUFFER_INDEX];
[computeEncoder setBuffer:dvWeightsBuffer offset:0 atIndex:DV_WEIGHTS_BUFFER_INDEX];
}
[computeEncoder setBuffer:duBuffer offset:0 atIndex:DU_DERIVATIVE_BUFFER_INDEX];
[computeEncoder setBuffer:dvBuffer offset:0 atIndex:DV_DERIVATIVE_BUFFER_INDEX];
[computeEncoder setComputePipelineState:_evalStencils];
auto threadgroups = MTLSizeMake((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
auto threadsPerGroup = MTLSizeMake(_workGroupSize, 1, 1);
[computeEncoder dispatchThreadgroups:threadgroups
threadsPerThreadgroup:threadsPerGroup];
[computeEncoder endEncoding];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
return true;
}
bool
MTLComputeEvaluator::EvalPatches(
id<MTLBuffer> srcBuffer, const BufferDescriptor &srcDesc,
id<MTLBuffer> dstBuffer, const BufferDescriptor &dstDesc,
id<MTLBuffer> duBuffer, const BufferDescriptor &duDesc,
id<MTLBuffer> dvBuffer, const BufferDescriptor &dvDesc,
int numPatchCoords,
id<MTLBuffer> patchCoordsBuffer,
const PatchArrayVector &patchArrays,
id<MTLBuffer> patchIndexBuffer,
id<MTLBuffer> patchParamsBuffer,
MTLContext* context) const
{
if(_evalPatches == nil)
return false;
assert(context != nullptr);
auto device = context->device;
auto commandQueue = context->commandQueue;
assert(device != nil && commandQueue != nil);
auto commandBuffer = [commandQueue commandBuffer];
auto computeCommandEncoder = [commandBuffer computeCommandEncoder];
mtl::KernelUniformArgs args;
args.batchStart = 0;
args.batchEnd = numPatchCoords;
args.srcOffset = srcDesc.offset;
args.dstOffset = dstDesc.offset;
args.duDesc = (simd::int3){duDesc.offset, duDesc.length, duDesc.stride};
args.dvDesc = (simd::int3){dvDesc.offset, dvDesc.length, dvDesc.stride};
[computeCommandEncoder setBytes:&args length:sizeof(mtl::KernelUniformArgs) atIndex:PARAMETER_BUFFER_INDEX];
[computeCommandEncoder setBuffer:srcBuffer offset:0 atIndex:SRC_VERTEX_BUFFER_INDEX];
[computeCommandEncoder setBuffer:dstBuffer offset:0 atIndex:DST_VERTEX_BUFFER_INDEX];
[computeCommandEncoder setBuffer:duBuffer offset:0 atIndex:DU_DERIVATIVE_BUFFER_INDEX];
[computeCommandEncoder setBuffer:dvBuffer offset:0 atIndex:DV_DERIVATIVE_BUFFER_INDEX];
[computeCommandEncoder setBuffer:patchCoordsBuffer offset:0 atIndex:PATCH_COORDS_BUFFER_INDEX];
[computeCommandEncoder setBuffer:patchIndexBuffer offset:0 atIndex:PATCH_INDICES_BUFFER_INDEX];
[computeCommandEncoder setBuffer:patchParamsBuffer offset:0 atIndex:PATCH_PARAMS_BUFFER_INDEX];
assert(patchArrays.size() == 2);
[computeCommandEncoder setBytes:&patchArrays[0] length:sizeof(patchArrays[0]) * 2 atIndex:PATCH_ARRAYS_BUFFER_INDEX];
[computeCommandEncoder setComputePipelineState:_evalPatches];
auto threadgroups =
MTLSizeMake((numPatchCoords + _workGroupSize - 1) / _workGroupSize, 1, 1);
auto threadsPerGroup = MTLSizeMake(_workGroupSize, 1, 1);
[computeCommandEncoder dispatchThreadgroups:threadgroups
threadsPerThreadgroup:threadsPerGroup];
[computeCommandEncoder endEncoding];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
return true;
}
} //end namespace Osd
} //end namespace OPENSUBDIV_VERSION
} //end namespace OpenSubdiv

View File

@ -0,0 +1,292 @@
#line 0 "osd/mtlComputeKernel.metal"
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include <metal_stdlib>
#ifndef OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES
#define OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES 0
#endif
using namespace metal;
struct PatchCoord
{
int arrayIndex;
int patchIndex;
int vertIndex;
float s;
float t;
};
struct PatchParam
{
uint field0;
uint field1;
float sharpness;
};
struct KernelUniformArgs
{
int batchStart;
int batchEnd;
int srcOffset;
int dstOffset;
int3 duDesc;
int3 dvDesc;
};
struct Vertex {
float vertexData[LENGTH];
};
void clear(thread Vertex& v) {
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] = 0;
}
}
Vertex readVertex(int index, device const float* vertexBuffer, KernelUniformArgs args) {
Vertex v;
int vertexIndex = args.srcOffset + index * SRC_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] = vertexBuffer[vertexIndex + i];
}
return v;
}
void writeVertex(int index, Vertex v, device float* vertexBuffer, KernelUniformArgs args) {
int vertexIndex = args.dstOffset + index * DST_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
vertexBuffer[vertexIndex + i] = v.vertexData[i];
}
}
void writeVertexSeparate(int index, Vertex v, device float* dstVertexBuffer, KernelUniformArgs args) {
int vertexIndex = args.dstOffset + index * DST_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
}
}
void addWithWeight(thread Vertex& v, const Vertex src, float weight) {
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] += weight * src.vertexData[i];
}
}
void writeDu(int index, Vertex du, device float* duDerivativeBuffer, KernelUniformArgs args)
{
int duIndex = args.duDesc.x + index * args.duDesc.z;
for(int i = 0; i < LENGTH; i++)
{
duDerivativeBuffer[duIndex + i] = du.vertexData[i];
}
}
void writeDv(int index, Vertex dv, device float* dvDerivativeBuffer, KernelUniformArgs args)
{
int dvIndex = args.dvDesc.x + index * args.dvDesc.z;
for(int i = 0; i < LENGTH; i++)
{
dvDerivativeBuffer[dvIndex + i] = dv.vertexData[i];
}
}
// ---------------------------------------------------------------------------
kernel void eval_stencils(
uint thread_position_in_grid [[thread_position_in_grid]],
const device int* sizes [[buffer(SIZES_BUFFER_INDEX)]],
const device int* offsets [[buffer(OFFSETS_BUFFER_INDEX)]],
const device int* indices [[buffer(INDICES_BUFFER_INDEX)]],
const device float* weights [[buffer(WEIGHTS_BUFFER_INDEX)]],
const device float* srcVertices [[buffer(SRC_VERTEX_BUFFER_INDEX)]],
device float* dstVertexBuffer [[buffer(DST_VERTEX_BUFFER_INDEX)]],
const device float* duWeights [[buffer(DU_WEIGHTS_BUFFER_INDEX)]],
const device float* dvWeights [[buffer(DV_WEIGHTS_BUFFER_INDEX)]],
device float* duDerivativeBuffer [[buffer(DU_DERIVATIVE_BUFFER_INDEX)]],
device float* dvDerivativeBuffer [[buffer(DV_DERIVATIVE_BUFFER_INDEX)]],
const constant KernelUniformArgs& args [[buffer(PARAMETER_BUFFER_INDEX)]]
)
{
auto current = thread_position_in_grid + args.batchStart;
if(current >= args.batchEnd)
return;
Vertex dst;
clear(dst);
auto offset = offsets[current];
auto size = sizes[current];
for(auto stencil = 0; stencil < size; stencil++)
{
auto vindex = offset + stencil;
addWithWeight(dst, readVertex(indices[vindex], srcVertices, args), weights[vindex]);
}
writeVertex(current, dst, dstVertexBuffer, args);
#if OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES
Vertex du, dv;
clear(du);
clear(dv);
for(auto i = 0; i < size; i++)
{
auto src = readVertex(indices[offset + i], srcVertices, args);
addWithWeight(du, src, duWeights[offset + i]);
addWithWeight(dv, src, dvWeights[offset + i]);
}
writeDu(current, du, duDerivativeBuffer, args);
writeDv(current, dv, dvDerivativeBuffer, args);
#endif
}
// ---------------------------------------------------------------------------
// PERFORMANCE: stride could be constant, but not as significant as length
//struct PatchArray {
// int patchType;
// int numPatches;
// int indexBase; // an offset within the index buffer
// int primitiveIdBase; // an offset within the patch param buffer
//};
// # of patcharrays is 1 or 2.
uint getDepth(uint patchBits) {
return (patchBits & 0xf);
}
float getParamFraction(uint patchBits) {
uint nonQuadRoot = (patchBits >> 4) & 0x1;
uint depth = getDepth(patchBits);
if (nonQuadRoot == 1) {
return 1.0f / float( 1 << (depth-1) );
} else {
return 1.0f / float( 1 << depth );
}
}
float2 normalizePatchCoord(uint patchBits, float2 uv) {
float frac = getParamFraction(patchBits);
uint iu = (patchBits >> 22) & 0x3ff;
uint iv = (patchBits >> 12) & 0x3ff;
// top left corner
float pu = float(iu*frac);
float pv = float(iv*frac);
// normalize u,v coordinates
return float2((uv.x - pu) / frac, (uv.y - pv) / frac);
}
bool isRegular(uint patchBits) {
return (((patchBits >> 5) & 0x1u) != 0);
}
int getNumControlVertices(int patchType) {
switch(patchType) {
case 3: return 4;
case 6: return 16;
case 9: return 20;
default: return 0;
}
}
// ---------------------------------------------------------------------------
kernel void eval_patches(
uint thread_position_in_grid [[thread_position_in_grid]],
const constant uint4* patchArrays [[buffer(PATCH_ARRAYS_BUFFER_INDEX)]],
const device PatchCoord* patchCoords [[buffer(PATCH_COORDS_BUFFER_INDEX)]],
const device int* patchIndices [[buffer(PATCH_INDICES_BUFFER_INDEX)]],
const device PatchParam* patchParams [[buffer(PATCH_PARAMS_BUFFER_INDEX)]],
const device float* srcVertexBuffer [[buffer(SRC_VERTEX_BUFFER_INDEX)]],
device float* dstVertexBuffer [[buffer(DST_VERTEX_BUFFER_INDEX)]],
device float* duDerivativeBuffer [[buffer(DU_DERIVATIVE_BUFFER_INDEX)]],
device float* dvDerivativeBuffer [[buffer(DV_DERIVATIVE_BUFFER_INDEX)]],
const constant KernelUniformArgs& args [[buffer(PARAMETER_BUFFER_INDEX)]]
)
{
auto current = thread_position_in_grid;
auto patchCoord = patchCoords[current];
auto patchIndex = patchIndices[patchCoord.patchIndex];
auto patchArray = patchArrays[patchCoord.arrayIndex];
auto patchBits = patchParams[patchIndex].field1;
auto patchType = select(isRegular(patchBits), 6, patchArray.x);
auto numControlVertices = getNumControlVertices(patchType);
auto uv = normalizePatchCoord(patchBits, float2(patchCoord.s, patchCoord.t));
auto dScale = float(1 << getDepth(patchBits));
auto boundry = int((patchBits >> 8) & 0xFU);
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
if(patchType == 3) {
OsdGetBilinearPatchWeights(uv.x, uv.y, dScale, wP, wDs, wDt, wDss, wDst, wDtt);
} else if(patchType == 6) {
OsdGetBSplinePatchWeights(uv.x, uv.y, dScale, boundry, wP, wDs, wDt, wDss, wDst, wDtt);
} else if(patchType == 9) {
OsdGetGregoryPatchWeights(uv.x, uv.y, dScale, wP, wDs, wDt, wDss, wDst, wDtt);
}
Vertex dst, du, dv;
clear(dst);
clear(du);
clear(dv);
auto indexBase = patchArray.z + numControlVertices * (patchCoord.patchIndex - patchArray.w);
for(auto cv = 0; cv < numControlVertices; cv++)
{
auto index = patchIndices[indexBase + cv];
auto src = readVertex(index, srcVertexBuffer, args);
addWithWeight(dst, src, wP[cv]);
addWithWeight(du, src, wDs[cv]);
addWithWeight(dv, src, wDt[cv]);
}
writeVertex(current, dst, dstVertexBuffer, args);
#if OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES
if(args.duDesc.y > 0)
writeDu(current, du, duDerivativeBuffer, args);
if(args.dvDesc.y > 0)
writeDv(current, dv, dvDerivativeBuffer, args);
#endif
}

View File

@ -0,0 +1,90 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
#define OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
#include "../version.h"
#include "../far/patchTable.h"
#include "../osd/nonCopyable.h"
#include "../osd/mtlCommon.h"
@protocol MTLDevice;
@protocol MTLBuffer;
namespace OpenSubdiv
{
namespace OPENSUBDIV_VERSION
{
namespace Osd
{
class MTLLegacyGregoryPatchTable
: private NonCopyable<MTLLegacyGregoryPatchTable>
{
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
{
return _vertexBuffer;
}
id<MTLBuffer> GetVertexValenceBuffer() const
{
return _vertexValenceBuffer;
}
id<MTLBuffer> GetQuadOffsetsBuffer() const
{
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
#endif // OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H

View File

@ -0,0 +1,100 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../osd/mtlLegacyGregoryPatchTable.h"
#include <Metal/Metal.h>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
static id<MTLBuffer> createBuffer(const void* data, const size_t length,
MTLContext* context)
{
@autoreleasepool {
auto cmdBuf = [context->commandQueue commandBuffer];
auto blitEncoder = [cmdBuf blitCommandEncoder];
auto stageBuffer = [context->device newBufferWithBytes:data length:length options:MTLResourceOptionCPUCacheModeDefault];
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
[blitEncoder endEncoding];
[cmdBuf commit];
[cmdBuf waitUntilCompleted];
#if !__has_feature(objc_arc)
[stageBuffer release];
#endif
return finalBuffer;
}
}
MTLLegacyGregoryPatchTable::~MTLLegacyGregoryPatchTable()
{
}
MTLLegacyGregoryPatchTable* MTLLegacyGregoryPatchTable::Create(const Far::PatchTable *farPatchTable,
MTLContext* context)
{
auto pt = new MTLLegacyGregoryPatchTable();
auto& vertexValenceTable = farPatchTable->GetVertexValenceTable();
auto& quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
if(!vertexValenceTable.empty())
{
pt->_vertexValenceBuffer = createBuffer(vertexValenceTable.data(), vertexValenceTable.size() * sizeof(vertexValenceTable[0]), context);
}
if(!quadOffsetsTable.empty())
{
pt->_quadOffsetsBuffer = createBuffer(quadOffsetsTable.data(), quadOffsetsTable.size() * sizeof(quadOffsetsTable[0]), context);
}
pt->_quadOffsetsBase[0] = 0;
pt->_quadOffsetsBase[1] = 0;
for(auto i = 0; i < farPatchTable->GetNumPatchArrays(); i++)
{
if(farPatchTable->GetPatchArrayDescriptor(i).GetType() == Far::PatchDescriptor::GREGORY)
{
pt->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
break;
}
}
return pt;
}
void MTLLegacyGregoryPatchTable::UpdateVertexBuffer(id<MTLBuffer> vbo, int numVertices, int numVertexElements, MTLContext* context)
{
_vertexBuffer = vbo;
}
} //end namespace Osd
} //end namespace OPENSUBDIV_VERSION
} //end namespace OpenSubdiv

46
opensubdiv/osd/mtlMesh.h Normal file
View File

@ -0,0 +1,46 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_MTL_MESH_H
#define OPENSUBDIV3_OSD_MTL_MESH_H
#include "../version.h"
#include "../osd/mesh.h"
#include "../osd/mtlPatchTable.h"
namespace OpenSubdiv
{
namespace OPENSUBDIV_VERSION
{
namespace Osd
{
typedef MeshInterface<MTLPatchTable> MTLMeshInterface;
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif // OPENSUBDIV3_OSD_MTL_MESH_H

View File

@ -0,0 +1 @@
#import "../osd/mtlMesh.h"

View File

@ -0,0 +1,238 @@
#line 0 "osd/mtlPatchBSpline.metal"
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
//----------------------------------------------------------
// Patches.BSpline.Hull
//----------------------------------------------------------
void OsdComputePerVertex(
float4 vertexPosition,
threadgroup HullVertex& hullVertex,
int vertexId,
float4x4 ModelViewProjectionMatrix,
OsdPatchParamBufferSet osdBuffers
)
{
hullVertex.position = vertexPosition;
#if OSD_ENABLE_PATCH_CULL
float4 clipPos = mul(ModelViewProjectionMatrix, vertexPosition);
short3 clip0 = short3(clipPos.x < clipPos.w,
clipPos.y < clipPos.w,
clipPos.z < clipPos.w);
short3 clip1 = short3(clipPos.x > -clipPos.w,
clipPos.y > -clipPos.w,
clipPos.z > -clipPos.w);
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
#endif
}
//----------------------------------------------------------
// Patches.BSpline.Factors
//----------------------------------------------------------
void OsdComputePerPatchBSplineFactors(
int3 patchParam,
float tessLevel,
float4x4 projectionMatrix,
float4x4 modelViewMatrix,
device OsdPerPatchVertexBezier* patch
#if !USE_PTVS_FACTORS
,device OsdPerPatchTessFactors& patchFactors
#endif
,device MTLQuadTessellationFactorsHalf& quadFactors
)
{
float4 tessLevelOuter = float4(0,0,0,0);
float2 tessLevelInner = float2(0,0);
float4 tessOuterLo = float4(0,0,0,0);
float4 tessOuterHi = float4(0,0,0,0);
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
OsdGetTessLevelsAdaptiveLimitPoints(
tessLevel,
projectionMatrix,
modelViewMatrix,
patch,
patchParam,
tessLevelOuter,
tessLevelInner,
tessOuterLo,
tessOuterHi
);
#else
OsdGetTessLevelsUniform(
tessLevel,
patchParam,
tessLevelOuter,
tessLevelInner,
tessOuterLo,
tessOuterHi
);
#endif
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
#if !USE_PTVS_FACTORS
patchFactors.tessOuterLo = tessOuterLo;
patchFactors.tessOuterHi = tessOuterHi;
#endif
}
void OsdComputePerPatchFactors(
int3 patchParam,
float tessLevel,
unsigned patchID,
float4x4 projectionMatrix,
float4x4 modelViewMatrix,
OsdPatchParamBufferSet osdBuffer,
threadgroup PatchVertexType* patchVertices,
device MTLQuadTessellationFactorsHalf& quadFactors
)
{
OsdComputePerPatchBSplineFactors(
patchParam,
tessLevel,
projectionMatrix,
modelViewMatrix,
osdBuffer.perPatchVertexBuffer + patchID * CONTROL_POINTS_PER_PATCH,
#if !USE_PTVS_FACTORS
osdBuffer.patchTessBuffer[patchID],
#endif
quadFactors
);
}
//----------------------------------------------------------
// Patches.BSpline.Vertex
//----------------------------------------------------------
void OsdComputePerPatchVertex(
int3 patchParam,
unsigned ID,
unsigned PrimitiveID,
unsigned ControlID,
threadgroup PatchVertexType* patchVertices,
OsdPatchParamBufferSet osdBuffers
)
{
OsdComputePerPatchVertexBSpline(patchParam, ID, patchVertices, osdBuffers.perPatchVertexBuffer[ControlID]);
}
//----------------------------------------------------------
// Patches.BSpline.Domain
//----------------------------------------------------------
template<typename PerPatchVertexBezier>
OsdPatchVertex ds_regular_patches(
const float TessLevel,
#if !USE_PTVS_FACTORS
float4 tessOuterHi,
float4 tessOuterLo,
#endif
PerPatchVertexBezier cv,
int3 patchParam,
float2 domainCoord)
{
OsdPatchVertex output;
float3 P, dPu, dPv;
float3 N, dNu, dNv;
float2 vSegments;
#if !USE_PTVS_FACTORS
float2 UV = OsdGetTessParameterization(domainCoord,
tessOuterLo,
tessOuterHi);
#else
auto transitionMask = OsdGetPatchTransitionMask(patchParam);
float4 tessLevelMin = float4(1)
+ float4(((transitionMask & 8) >> 3),
((transitionMask & 1) >> 0),
((transitionMask & 2) >> 1),
((transitionMask & 4) >> 2));
float2 UV = OsdGetTessParameterization(domainCoord,
tessLevelMin,
float4(0));
#endif
OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv, vSegments);
output.normal = N;
output.tangent = dPu;
output.bitangent = dPv;
#if OSD_COMPUTE_NORMAL_DERIVATIVES
output.Nu = dNu;
output.Nv = dNv;
#endif
#if OSD_PATCH_ENABLE_SINGLE_CREASE
output.vSegments = vSegments;
#endif
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
output.position = P;
return output;
}
#if USE_STAGE_IN
template<typename PerPatchVertexBezier>
#endif
OsdPatchVertex OsdComputePatch(
float tessLevel,
float2 domainCoord,
unsigned patchID,
#if USE_STAGE_IN
PerPatchVertexBezier osdPatch
#else
OsdVertexBufferSet osdBuffers
#endif
)
{
return ds_regular_patches(
tessLevel,
#if !USE_PTVS_FACTORS
#if USE_STAGE_IN
osdPatch.tessOuterHi,
osdPatch.tessOuterLo,
#else
osdBuffers.patchTessBuffer[patchID].tessOuterHi,
osdBuffers.patchTessBuffer[patchID].tessOuterLo,
#endif
#endif
#if USE_STAGE_IN
osdPatch.cv,
osdPatch.patchParam,
#else
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
osdBuffers.patchParamBuffer[patchID],
#endif
domainCoord
);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
#line 0 "osd/mtlPatchGregory.metal"
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
//----------------------------------------------------------
// Patches.Gregory.Hull
//----------------------------------------------------------
void OsdComputePerVertex(
float4 position,
threadgroup OsdPerVertexGregory& hullVertex,
int vertexId,
float4x4 modelViewProjectionMatrix,
OsdPatchParamBufferSet osdBuffers
)
{
OsdComputePerVertexGregory(vertexId, position.xyz, hullVertex, osdBuffers);
#if OSD_ENABLE_PATCH_CULL
float4 clipPos = mul(modelViewProjectionMatrix, position);
short3 clip0 = short3(clipPos.x < clipPos.w,
clipPos.y < clipPos.w,
clipPos.z < clipPos.w);
short3 clip1 = short3(clipPos.x > -clipPos.w,
clipPos.y > -clipPos.w,
clipPos.z > -clipPos.w);
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
#endif
}
//----------------------------------------------------------
// Patches.Gregory.Factors
//----------------------------------------------------------
void OsdComputePerPatchFactors(
int3 patchParam,
float tessLevel,
unsigned patchID,
float4x4 projectionMatrix,
float4x4 modelViewMatrix,
OsdPatchParamBufferSet osdBuffer,
threadgroup PatchVertexType* patchVertices,
device MTLQuadTessellationFactorsHalf& quadFactors
)
{
float4 tessLevelOuter = float4(0,0,0,0);
float2 tessLevelInner = float2(0,0);
OsdGetTessLevels(
tessLevel,
projectionMatrix,
modelViewMatrix,
patchVertices[0].P,
patchVertices[3].P,
patchVertices[2].P,
patchVertices[1].P,
patchParam,
tessLevelOuter,
tessLevelInner
);
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
}
//----------------------------------------------------------
// Patches.Gregory.Vertex
//----------------------------------------------------------
void OsdComputePerPatchVertex(
int3 patchParam,
unsigned ID,
unsigned PrimitiveID,
unsigned ControlID,
threadgroup PatchVertexType* patchVertices,
OsdPatchParamBufferSet osdBuffers
)
{
OsdComputePerPatchVertexGregory(
patchParam,
ID,
PrimitiveID,
patchVertices,
osdBuffers.perPatchVertexBuffer[ControlID],
osdBuffers);
}
//----------------------------------------------------------
// Patches.Gregory.Domain
//----------------------------------------------------------
template<typename PerPatchVertexGregory>
OsdPatchVertex ds_gregory_patches(
PerPatchVertexGregory patch,
int3 patchParam,
float2 UV
)
{
OsdPatchVertex output;
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 cv[20];
cv[0] = patch[0].P;
cv[1] = patch[0].Ep;
cv[2] = patch[0].Em;
cv[3] = patch[0].Fp;
cv[4] = patch[0].Fm;
cv[5] = patch[1].P;
cv[6] = patch[1].Ep;
cv[7] = patch[1].Em;
cv[8] = patch[1].Fp;
cv[9] = patch[1].Fm;
cv[10] = patch[2].P;
cv[11] = patch[2].Ep;
cv[12] = patch[2].Em;
cv[13] = patch[2].Fp;
cv[14] = patch[2].Fm;
cv[15] = patch[3].P;
cv[16] = patch[3].Ep;
cv[17] = patch[3].Em;
cv[18] = patch[3].Fp;
cv[19] = patch[3].Fm;
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
// all code below here is client code
output.position = P;
output.normal = N;
output.tangent = dPu;
output.bitangent = dPv;
#if OSD_COMPUTE_NORMAL_DERIVATIVES
output.Nu = dNu;
output.Nv = dNv;
#endif
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
return output;
}
#if USE_STAGE_IN
template<typename PerPatchVertexGregoryBasis>
#endif
OsdPatchVertex OsdComputePatch(
float tessLevel,
float2 domainCoord,
unsigned patchID,
#if USE_STAGE_IN
PerPatchVertexGregoryBasis osdPatch
#else
OsdVertexBufferSet osdBuffers
#endif
)
{
return ds_gregory_patches(
#if USE_STAGE_IN
osdPatch.cv,
osdPatch.patchParam,
#else
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
osdBuffers.patchParamBuffer[patchID],
#endif
domainCoord);
}

View File

@ -0,0 +1,199 @@
#line 0 "osd/mtlPatchGregoryBasis.metal"
//
// Copyright 2015 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
//----------------------------------------------------------
// Patches.GregoryBasis.Hull
//----------------------------------------------------------
void OsdComputePerVertex(
float4 position,
threadgroup HullVertex& hullVertex,
int vertexId,
float4x4 modelViewProjectionMatrix,
OsdPatchParamBufferSet osdBuffers
)
{
hullVertex.position = position;
#if OSD_ENABLE_PATCH_CULL
float4 clipPos = mul(modelViewProjectionMatrix, position);
short3 clip0 = short3(clipPos.x < clipPos.w,
clipPos.y < clipPos.w,
clipPos.z < clipPos.w);
short3 clip1 = short3(clipPos.x > -clipPos.w,
clipPos.y > -clipPos.w,
clipPos.z > -clipPos.w);
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
#endif
}
//----------------------------------------------------------
// Patches.GregoryBasis.Factors
//----------------------------------------------------------
void OsdComputePerPatchFactors(
int3 patchParam,
float tessLevel,
unsigned patchID,
float4x4 projectionMatrix,
float4x4 modelViewMatrix,
OsdPatchParamBufferSet osdBuffer,
threadgroup PatchVertexType* patchVertices,
device MTLQuadTessellationFactorsHalf& quadFactors
)
{
float4 tessLevelOuter = float4(0,0,0,0);
float2 tessLevelInner = float2(0,0);
OsdGetTessLevels(
tessLevel,
projectionMatrix,
modelViewMatrix,
patchVertices[0].position.xyz,
patchVertices[3].position.xyz,
patchVertices[2].position.xyz,
patchVertices[1].position.xyz,
patchParam,
tessLevelOuter,
tessLevelInner
);
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
}
//----------------------------------------------------------
// Patches.GregoryBasis.Vertex
//----------------------------------------------------------
void OsdComputePerPatchVertex(
int3 patchParam,
unsigned ID,
unsigned PrimitiveID,
unsigned ControlID,
threadgroup PatchVertexType* patchVertices,
OsdPatchParamBufferSet osdBuffers
)
{
//Does nothing, all transforms are in the PTVS
}
//----------------------------------------------------------
// Patches.GregoryBasis.Domain
//----------------------------------------------------------
#define USE_128BIT_GREGORY_BASIS_INDICES_READ 1
#if USE_STAGE_IN
template<typename PerPatchVertexGregoryBasis>
#endif
OsdPatchVertex ds_gregory_basis_patches(
#if USE_STAGE_IN
PerPatchVertexGregoryBasis patch,
#else
const device OsdInputVertexType* patch,
const device unsigned* patchIndices,
#endif
int3 patchParam,
float2 UV
)
{
OsdPatchVertex output;
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);
#if USE_STAGE_IN
float3 cv[20];
for(int i = 0; i < 20; i++)
cv[i] = patch[i].position;
#else
#if USE_128BIT_GREGORY_BASIS_INDICES_READ
float3 cv[20];
for(int i = 0; i < 5; i++) {
int4 indices = ((device int4*)patchIndices)[i];
int n = i * 4;
cv[n + 0] = (patch + indices[0])->position;
cv[n + 1] = (patch + indices[1])->position;
cv[n + 2] = (patch + indices[2])->position;
cv[n + 3] = (patch + indices[3])->position;
}
#else
float3 cv[20];
for (int i = 0; i < 20; ++i) {
cv[i] = patch[patchIndices[i]].position;
}
#endif
#endif
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
output.position = P;
output.normal = N;
output.tangent = dPu;
output.bitangent = dPv;
#if OSD_COMPUTE_NORMAL_DERIVATIVES
output.Nu = dNu;
output.Nv = dNv;
#endif
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
return output;
}
#if USE_STAGE_IN
template<typename PerPatchVertexGregoryBasis>
#endif
OsdPatchVertex OsdComputePatch(
float tessLevel,
float2 domainCoord,
unsigned patchID,
#if USE_STAGE_IN
PerPatchVertexGregoryBasis osdPatch
#else
OsdVertexBufferSet osdBuffers
#endif
)
{
return ds_gregory_basis_patches(
#if USE_STAGE_IN
osdPatch.cv,
osdPatch.patchParam,
#else
osdBuffers.vertexBuffer,
osdBuffers.indexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
osdBuffers.patchParamBuffer[patchID],
#endif
domainCoord
);
}

View File

@ -0,0 +1,54 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#pragma once
#import <string>
#import "../version.h"
#import "../far/patchDescriptor.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
class MTLPatchShaderSource {
public:
static std::string GetCommonShaderSource();
static std::string GetPatchBasisShaderSource();
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type);
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type);
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type);
};
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv

View File

@ -0,0 +1,136 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../osd/mtlPatchShaderSource.h"
#include "../far/error.h"
#include <sstream>
#include <string>
#include <TargetConditionals.h>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
static std::string commonShaderSource(
#include "mtlPatchCommon.gen.h"
);
static std::string patchBasisShaderSource(
#include "patchBasisCommon.gen.h"
);
static std::string bsplineShaderSource(
#include "mtlPatchBSpline.gen.h"
);
static std::string gregoryShaderSource(
#include "mtlPatchGregory.gen.h"
);
static std::string gregoryBasisShaderSource(
#include "mtlPatchGregoryBasis.gen.h"
);
static std::string GetPatchTypeDefine(Far::PatchDescriptor::Type type) {
switch(type) {
case Far::PatchDescriptor::LINES: return "#define OSD_PATCH_LINES 1\n";
case Far::PatchDescriptor::TRIANGLES: return "#define OSD_PATCH_TRIANGLES 1\n";
case Far::PatchDescriptor::QUADS: return "#define OSD_PATCH_QUADS 1\n";
case Far::PatchDescriptor::REGULAR: return "#define OSD_PATCH_BSPLINE 1\n#define OSD_PATCH_REGULAR 1\n";
case Far::PatchDescriptor::GREGORY: return "#define OSD_PATCH_GREGORY 1\n";
case Far::PatchDescriptor::GREGORY_BOUNDARY: return "#define OSD_PATCH_GREGORY_BOUNDRY 1\n";
case Far::PatchDescriptor::GREGORY_BASIS: return "#define OSD_PATCH_GREGORY_BASIS 1\n";
default:
assert("Unknown Far::PatchDescriptor::Type" && 0);
return "";
}
}
static std::string GetPatchTypeSource(Far::PatchDescriptor::Type type) {
switch(type) {
case Far::PatchDescriptor::QUADS: return "";
case Far::PatchDescriptor::REGULAR: return bsplineShaderSource;
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
}
/*static*/
std::string
MTLPatchShaderSource::GetPatchBasisShaderSource() {
std::stringstream ss;
ss << "#define OSD_PATCH_BASIS_METAL 1\n";
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
ss << "define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES 1\n";
#endif
ss << patchBasisShaderSource;
return ss.str();
}
/*static*/
std::string
MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
std::stringstream ss;
ss << GetPatchTypeDefine(type);
ss << GetCommonShaderSource();
ss << GetPatchTypeSource(type);
return ss.str();
}
/*static*/
std::string
MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type) {
std::stringstream ss;
ss << GetPatchTypeDefine(type);
ss << GetCommonShaderSource();
ss << GetPatchTypeSource(type);
return ss.str();
}
/*static*/
std::string
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type) {
std::stringstream ss;
ss << GetPatchTypeDefine(type);
ss << GetCommonShaderSource();
ss << GetPatchTypeSource(type);
return ss.str();
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -0,0 +1,98 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
#define OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
#include "../version.h"
#include "../far/patchDescriptor.h"
#include "../osd/nonCopyable.h"
#include "../osd/types.h"
#include "../osd/mtlCommon.h"
@protocol MTLDevice;
@protocol MTLBuffer;
namespace OpenSubdiv
{
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)
{
return Create(farPatchTable, context);
}
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, MTLContext* context);
PatchArrayVector const &GetPatchArrays() const { return _patchArrays; }
id<MTLBuffer> GetPatchIndexBuffer() const { return _indexBuffer; }
id<MTLBuffer> GetPatchParamBuffer() const { return _patchParamBuffer; }
PatchArrayVector const &GetVaryingPatchArrays() const { return _varyingPatchArrays; }
id<MTLBuffer> GetVaryingPatchIndexBuffer() const { return _varyingPatchIndexBuffer; }
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]; }
protected:
bool allocate(Far::PatchTable const *farPatchTable, MTLContext* context);
PatchArrayVector _patchArrays;
id<MTLBuffer> _indexBuffer;
id<MTLBuffer> _patchParamBuffer;
PatchArrayVector _varyingPatchArrays;
id<MTLBuffer> _varyingPatchIndexBuffer;
std::vector<PatchArrayVector> _fvarPatchArrays;
std::vector<id<MTLBuffer>> _fvarIndexBuffers;
std::vector<id<MTLBuffer>> _fvarParamBuffers;
};
} // end namespace Osd
} //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSubdiv
#endif //end OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H

View File

@ -0,0 +1,141 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#import "../osd/mtlPatchTable.h"
#import <Metal/Metal.h>
#import "../far/patchTable.h"
#import "../osd/cpuPatchTable.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
MTLPatchTable::MTLPatchTable()
:
_indexBuffer(nil),
_patchParamBuffer(nil),
_varyingPatchIndexBuffer(nil)
{
}
MTLPatchTable::~MTLPatchTable()
{
}
static id<MTLBuffer> createBuffer(const void* data, const size_t length,
MTLContext* context)
{
if(length == 0)
return nil;
#if TARGET_OS_IOS || TARGET_OS_TV
return [context->device newBufferWithBytes:data length:length options:MTLResourceOptionCPUCacheModeDefault];
#elif TARGET_OS_OSX
@autoreleasepool {
auto cmdBuf = [context->commandQueue commandBuffer];
auto blitEncoder = [cmdBuf blitCommandEncoder];
auto stageBuffer = [context->device newBufferWithBytes:data length:length options:MTLResourceOptionCPUCacheModeDefault];
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
[blitEncoder endEncoding];
[cmdBuf commit];
[cmdBuf waitUntilCompleted];
#if !__has_feature(objc_arc)
[stageBuffer release];
#endif
return finalBuffer;
}
#endif
}
MTLPatchTable* MTLPatchTable::Create(const Far::PatchTable *farPatchTable, MTLContext* context)
{
auto patchTable = new MTLPatchTable();
if(patchTable->allocate(farPatchTable, context))
return patchTable;
delete patchTable;
assert(0 && "MTLPatchTable Creation Failed");
return nullptr;
}
bool MTLPatchTable::allocate(Far::PatchTable const *farPatchTable, MTLContext* context)
{
CpuPatchTable cpuTable(farPatchTable);
auto numPatchArrays = cpuTable.GetNumPatchArrays();
auto indexSize = cpuTable.GetPatchIndexSize();
auto patchParamSize = cpuTable.GetPatchParamSize();
_patchArrays.assign(cpuTable.GetPatchArrayBuffer(), cpuTable.GetPatchArrayBuffer() + numPatchArrays);
_indexBuffer = createBuffer(cpuTable.GetPatchIndexBuffer(), indexSize * sizeof(unsigned), context);
if(_indexBuffer == nil)
return false;
_indexBuffer.label = @"OSD PatchIndexBuffer";
_patchParamBuffer = createBuffer(cpuTable.GetPatchParamBuffer(), patchParamSize * sizeof(PatchParam), context);
if(_patchParamBuffer == nil)
return false;
_patchParamBuffer.label = @"OSD PatchParamBuffer";
_varyingPatchArrays.assign(cpuTable.GetVaryingPatchArrayBuffer(), cpuTable.GetVaryingPatchArrayBuffer() + numPatchArrays);
_varyingPatchIndexBuffer = createBuffer(cpuTable.GetVaryingPatchIndexBuffer(), sizeof(int) * cpuTable.GetVaryingPatchIndexSize(), context);
if(_varyingPatchIndexBuffer == nil && cpuTable.GetVaryingPatchIndexSize() > 0)
return false;
auto numFVarChannels = cpuTable.GetNumFVarChannels();
_fvarPatchArrays.resize(numFVarChannels);
_fvarIndexBuffers.resize(numFVarChannels);
_fvarParamBuffers.resize(numFVarChannels);
for(auto fvc = 0; fvc < numFVarChannels; fvc++)
{
_fvarPatchArrays[fvc].assign(cpuTable.GetFVarPatchArrayBuffer(fvc), cpuTable.GetFVarPatchArrayBuffer(fvc) + numPatchArrays);
_fvarIndexBuffers[fvc] = createBuffer(cpuTable.GetFVarPatchIndexBuffer(fvc), cpuTable.GetFVarPatchIndexSize(fvc) * sizeof(int), context);
if(_fvarIndexBuffers[fvc] == nil)
return false;
_fvarParamBuffers[fvc] = createBuffer(cpuTable.GetFVarPatchParamBuffer(fvc), cpuTable.GetFVarPatchParamSize(fvc) * sizeof(PatchParam), context);
if(_fvarParamBuffers[fvc] == nil)
return false;
}
return true;
}
} //end namespace Osd
} //end namespace OPENSUBDIV_VERSION
} //end namespace OpenSubdiv

View File

@ -0,0 +1,84 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H
#define OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H
#include "../version.h"
#include "../osd/mtlCommon.h"
@protocol MTLDevice;
@protocol MTLBuffer;
namespace OpenSubdiv
{
namespace OPENSUBDIV_VERSION
{
namespace Osd
{
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
{
return _numElements;
}
int GetNumVertices() const
{
return _numVertices;
}
float* BindCpuBuffer();
id<MTLBuffer> BindMTLBuffer(MTLContext* context);
id<MTLBuffer> BindVBO(MTLContext* context)
{
return BindMTLBuffer(context);
}
protected:
CPUMTLVertexBuffer(int numElements, int numVertices);
bool allocate(MTLContext* context);
private:
int _numElements;
int _numVertices;
id<MTLBuffer> _buffer;
bool _dirty;
};
} //end namespace Osd
} //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSubdiv
#endif // OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H

View File

@ -0,0 +1,98 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../osd/mtlVertexBuffer.h"
#include <Metal/Metal.h>
#include <TargetConditionals.h>
namespace OpenSubdiv
{
namespace OPENSUBDIV_VERSION
{
namespace Osd
{
CPUMTLVertexBuffer::CPUMTLVertexBuffer(int numElements, int numVertices)
:
_numElements(numElements), _numVertices(numVertices),
_buffer(nullptr), _dirty(true)
{
}
bool CPUMTLVertexBuffer::allocate(MTLContext* context)
{
#if TARGET_OS_IOS || TARGET_OS_TV
_buffer = [context->device newBufferWithLength: _numElements * _numVertices * sizeof(float) options:MTLResourceOptionCPUCacheModeDefault];
#elif TARGET_OS_OSX
_buffer = [context->device newBufferWithLength: _numElements * _numVertices * sizeof(float) options:MTLResourceStorageModeManaged];
#endif
if(_buffer == nil)
return false;
_dirty = true;
_buffer.label = @"OSD VertexBuffer";
return true;
}
CPUMTLVertexBuffer* CPUMTLVertexBuffer::Create(int numElements, int numVertices, MTLContext* context)
{
auto instance = new CPUMTLVertexBuffer(numElements, numVertices);
if(!instance->allocate(context))
{
delete instance;
return nullptr;
}
return instance;
}
void CPUMTLVertexBuffer::UpdateData(const float* src, int startVertex, int numVertices, MTLContext* context)
{
_dirty = true;
memcpy(((float*)_buffer.contents) + startVertex * _numElements, src, _numElements * numVertices * sizeof(float));
}
float* CPUMTLVertexBuffer::BindCpuBuffer()
{
_dirty = true;
return (float*)_buffer.contents;
}
id<MTLBuffer> CPUMTLVertexBuffer::BindMTLBuffer(MTLContext* context)
{
#if TARGET_OS_OSX
if(_dirty)
[_buffer didModifyRange:NSMakeRange(0, _buffer.length)];
_dirty = false;
#endif
return _buffer;
}
} //end namepsace Osd
} //end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} //end namespace OpenSubdiv

View File

@ -33,6 +33,7 @@
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_OUT out
#define OSD_INOUT inout
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
elementType[](a0,a1,a2,a3,a4,a5,a6,a7)
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
@ -46,6 +47,7 @@
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_OUT out
#define OSD_INOUT inout
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
@ -59,6 +61,7 @@
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_OUT
#define OSD_INOUT
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
@ -72,6 +75,21 @@
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_OUT
#define OSD_INOUT
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11}
#elif defined(OSD_PATCH_BASIS_METAL)
#define OSD_FUNCTION_STORAGE_CLASS
#define OSD_DATA_STORAGE_CLASS
#define OSD_OPTIONAL(a) true
#define OSD_OPTIONAL_INIT(a,b) b
#define OSD_OUT
#define OSD_INOUT
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) thread elementType* identifier
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
@ -85,6 +103,7 @@
#define OSD_OPTIONAL_INIT(a,b) (a ? b : 0)
#define OSD_OUT
#define OSD_INOUT
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
{a0,a1,a2,a3,a4,a5,a6,a7}
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
@ -95,7 +114,7 @@
OSD_FUNCTION_STORAGE_CLASS
void
OsdGetBezierWeights(
float t, OSD_OUT float wP[4], OSD_OUT float wDP[4], OSD_OUT float wDP2[4]) {
float t, OSD_TYPE_ARRAY(OSD_OUT float, wP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP2, 4)) {
// The four uniform cubic Bezier basis functions (in terms of t and its
// complement tC) evaluated at t:
@ -128,7 +147,7 @@ OsdGetBezierWeights(
OSD_FUNCTION_STORAGE_CLASS
void
OsdGetBSplineWeights(
float t, OSD_OUT float wP[4], OSD_OUT float wDP[4], OSD_OUT float wDP2[4]) {
float t, OSD_TYPE_ARRAY(OSD_OUT float, wP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP2, 4)) {
// The four uniform cubic B-Spline basis functions evaluated at t:
const float one6th = 1.0f / 6.0f;
@ -160,7 +179,7 @@ OsdGetBSplineWeights(
OSD_FUNCTION_STORAGE_CLASS
void
OsdGetBoxSplineWeights(float v, float w, OSD_OUT float wP[12]) {
OsdGetBoxSplineWeights(float v, float w, OSD_TYPE_ARRAY(OSD_OUT float, wP, 12)) {
float u = 1.0f - v - w;
@ -215,8 +234,8 @@ OSD_FUNCTION_STORAGE_CLASS
void
OsdGetBilinearPatchWeights(
float s, float t, float dScale,
OSD_OUT float wP[4], OSD_OUT float wDs[4], OSD_OUT float wDt[4],
OSD_OUT float wDss[4], OSD_OUT float wDst[4], OSD_OUT float wDtt[4]) {
OSD_TYPE_ARRAY(OSD_OUT float, wP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 4),
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 4)) {
float sC = 1.0f - s,
tC = 1.0f - t;
@ -259,7 +278,7 @@ OsdGetBilinearPatchWeights(
OSD_FUNCTION_STORAGE_CLASS
void OsdAdjustBoundaryWeights(
int boundary,
OSD_INOUT float sWeights[4], OSD_INOUT float tWeights[4]) {
OSD_TYPE_ARRAY(OSD_INOUT float, sWeights, 4), OSD_TYPE_ARRAY(OSD_INOUT float, tWeights, 4)) {
if ((boundary & 1) != 0) {
tWeights[2] -= tWeights[0];
@ -285,11 +304,11 @@ void OsdAdjustBoundaryWeights(
OSD_FUNCTION_STORAGE_CLASS
void OsdComputeTensorProductPatchWeights(float dScale, int boundary,
float sWeights[4], float tWeights[4],
float dsWeights[4], float dtWeights[4],
float dssWeights[4], float dttWeights[4],
OSD_OUT float wP[16], OSD_OUT float wDs[16], OSD_OUT float wDt[16],
OSD_OUT float wDss[16], OSD_OUT float wDst[16], OSD_OUT float wDtt[16]) {
OSD_TYPE_ARRAY(float, sWeights, 4), OSD_TYPE_ARRAY(float, tWeights, 4),
OSD_TYPE_ARRAY(float, dsWeights, 4), OSD_TYPE_ARRAY(float, dtWeights, 4),
OSD_TYPE_ARRAY(float, dssWeights, 4), OSD_TYPE_ARRAY(float, dttWeights, 4),
OSD_TYPE_ARRAY(OSD_OUT float, wP, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 16),
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 16)) {
if (OSD_OPTIONAL(wP)) {
// Compute the tensor product weight of the (s,t) basis function
@ -338,8 +357,8 @@ void OsdComputeTensorProductPatchWeights(float dScale, int boundary,
OSD_FUNCTION_STORAGE_CLASS
void OsdGetBezierPatchWeights(
float s, float t, float dScale,
OSD_OUT float wP[16], OSD_OUT float wDS[16], OSD_OUT float wDT[16],
OSD_OUT float wDSS[16], OSD_OUT float wDST[16], OSD_OUT float wDTT[16]) {
OSD_TYPE_ARRAY(OSD_OUT float, wP, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDS, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDT, 16),
OSD_TYPE_ARRAY(OSD_OUT float, wDSS, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDST, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDTT, 16)) {
float sWeights[4], tWeights[4], dsWeights[4], dtWeights[4], dssWeights[4], dttWeights[4];
@ -352,8 +371,8 @@ void OsdGetBezierPatchWeights(
OSD_FUNCTION_STORAGE_CLASS
void OsdGetBSplinePatchWeights(
float s, float t, float dScale, int boundary,
OSD_OUT float wP[16], OSD_OUT float wDs[16], OSD_OUT float wDt[16],
OSD_OUT float wDss[16], OSD_OUT float wDst[16], OSD_OUT float wDtt[16]) {
OSD_TYPE_ARRAY(OSD_OUT float, wP, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 16),
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 16)) {
float sWeights[4], tWeights[4], dsWeights[4], dtWeights[4], dssWeights[4], dttWeights[4];
@ -366,8 +385,8 @@ void OsdGetBSplinePatchWeights(
OSD_FUNCTION_STORAGE_CLASS
void OsdGetGregoryPatchWeights(
float s, float t, float dScale,
OSD_OUT float wP[20], OSD_OUT float wDs[20], OSD_OUT float wDt[20],
OSD_OUT float wDss[20], OSD_OUT float wDst[20], OSD_OUT float wDtt[20]) {
OSD_TYPE_ARRAY(OSD_OUT float, wP, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 20),
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 20)) {
//
// P3 e3- e2+ P2

View File

@ -22,8 +22,15 @@
# language governing permissions and limitations under the Apache License.
#
_add_executable(stringify "opensubdiv/tools"
main.cpp
)
if(CMAKE_CROSSCOMPILING)
set(STRINGIFY_LOCATION "STRINGIFY-NOTFOUND" CACHE FILEPATH "Point it to the stringify binary from a native build")
add_executable(stringify IMPORTED GLOBAL)
set_property(TARGET stringify PROPERTY IMPORTED_LOCATION ${STRINGIFY_LOCATION})
endif()
install(TARGETS stringify DESTINATION ${CMAKE_BINDIR_BASE})
if(NOT CMAKE_CROSSCOMPILING)
_add_executable(stringify "opensubdiv/tools"
main.cpp
)
install(TARGETS stringify DESTINATION ${CMAKE_BINDIR_BASE})
endif()