Branimir Karadžić 9 лет назад
Родитель
Сommit
1aad048a56
3 измененных файлов с 7326 добавлено и 0 удалено
  1. 21 0
      3rdparty/mtlpp/LICENSE
  2. 2706 0
      3rdparty/mtlpp/mtlpp.hpp
  3. 4599 0
      3rdparty/mtlpp/mtlpp.mm

+ 21 - 0
3rdparty/mtlpp/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Nikolay Aleksiev
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 2706 - 0
3rdparty/mtlpp/mtlpp.hpp

@@ -0,0 +1,2706 @@
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+#pragma once
+
+//////////////////////////////////////
+// FILE: defines.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+#include <stdint.h>
+#include <assert.h>
+#include <functional>
+
+#ifndef __has_feature
+#   define __has_feature(x) 0
+#endif
+
+#ifndef MTLPP_CONFIG_RVALUE_REFERENCES
+#   define MTLPP_CONFIG_RVALUE_REFERENCES __has_feature(cxx_rvalue_references)
+#endif
+
+#ifndef MTLPP_CONFIG_VALIDATE
+#   define MTLPP_CONFIG_VALIDATE 1
+#endif
+
+#ifndef MTLPP_CONFIG_USE_AVAILABILITY
+#   define MTLPP_CONFIG_USE_AVAILABILITY 0
+#endif
+
+#if MTLPP_CONFIG_USE_AVAILABILITY
+#   if __has_feature(attribute_availability_with_version_underscores) || (__has_feature(attribute_availability_with_message) && __clang__ && __clang_major__ >= 7)
+#       include <CoreFoundation/CFAvailability.h>
+#       define MTLPP_AVAILABLE(mac, ios)                            CF_AVAILABLE(mac, ios)
+#       define MTLPP_AVAILABLE_MAC(mac)                             CF_AVAILABLE_MAC(mac)
+#       define MTLPP_AVAILABLE_IOS(ios)                             CF_AVAILABLE_IOS(ios)
+#       define MTLPP_AVAILABLE_TVOS(tvos)
+#       define MTLPP_DEPRECATED(macIntro, macDep, iosIntro, iosDep) CF_DEPRECATED(macIntro, macDep, iosIntro, iosDep)
+#       define MTLPP_DEPRECATED_MAC(macIntro, macDep)               CF_DEPRECATED_MAC(macIntro, macDep)
+#       define MTLPP_DEPRECATED_IOS(iosIntro, iosDep)               CF_DEPRECATED_IOS(iosIntro, iosDep)
+#   endif
+#endif
+
+#ifndef MTLPP_AVAILABLE
+#   define MTLPP_AVAILABLE(mac, ios)
+#   define MTLPP_AVAILABLE_MAC(mac)
+#   define MTLPP_AVAILABLE_IOS(ios)
+#   define MTLPP_AVAILABLE_TVOS(tvos)
+#   define MTLPP_DEPRECATED(macIntro, macDep, iosIntro, iosDep)
+#   define MTLPP_DEPRECATED_MAC(macIntro, macDep)
+#   define MTLPP_DEPRECATED_IOS(iosIntro, iosDep)
+#endif
+
+#ifndef __DARWIN_ALIAS_STARTING_MAC___MAC_10_11
+#   define __DARWIN_ALIAS_STARTING_MAC___MAC_10_11(x)
+#endif
+#ifndef __DARWIN_ALIAS_STARTING_MAC___MAC_10_12
+#   define __DARWIN_ALIAS_STARTING_MAC___MAC_10_12(x)
+#endif
+#ifndef __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_8_0
+#   define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_8_0(x)
+#endif
+#ifndef __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_9_0
+#   define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_9_0(x)
+#endif
+#ifndef __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_10_0
+#   define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_10_0(x)
+#endif
+
+#define MTLPP_IS_AVAILABLE_MAC(mac)  (0 __DARWIN_ALIAS_STARTING_MAC___MAC_##mac( || 1 ))
+#define MTLPP_IS_AVAILABLE_IOS(ios)  (0 __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_##ios( || 1 ))
+#define MTLPP_IS_AVAILABLE(mac, ios) (MTLPP_IS_AVAILABLE_MAC(mac) || MTLPP_IS_AVAILABLE_IOS(ios))
+
+
+//////////////////////////////////////
+// FILE: ns.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+
+namespace ns
+{
+    struct Handle
+    {
+        const void* ptr;
+    };
+
+    class Object
+    {
+    public:
+        inline const void* GetPtr() const { return m_ptr; }
+
+        inline operator bool() const { return m_ptr != nullptr; }
+
+    protected:
+        Object();
+        Object(const Handle& handle);
+        Object(const Object& rhs);
+#if MTLPP_CONFIG_RVALUE_REFERENCES
+        Object(Object&& rhs);
+#endif
+        virtual ~Object();
+
+        Object& operator=(const Object& rhs);
+#if MTLPP_CONFIG_RVALUE_REFERENCES
+        Object& operator=(Object&& rhs);
+#endif
+
+        inline void Validate() const
+        {
+#if MTLPP_CONFIG_VALIDATE
+            assert(m_ptr);
+#endif
+        }
+
+        const void* m_ptr = nullptr;
+    };
+
+    struct Range
+    {
+        inline Range(uint32_t location, uint32_t length) :
+            Location(location),
+            Length(length)
+        { }
+
+        uint32_t Location;
+        uint32_t Length;
+    };
+
+    class ArrayBase : public Object
+    {
+    public:
+        ArrayBase() { }
+        ArrayBase(const Handle& handle) : Object(handle) { }
+
+        const uint32_t GetSize() const;
+
+    protected:
+        void* GetItem(uint32_t index) const;
+    };
+
+    template<typename T>
+    class Array : public ArrayBase
+    {
+    public:
+        Array() { }
+        Array(const Handle& handle) : ArrayBase(handle) { }
+
+        const T operator[](uint32_t index) const
+        {
+            return Handle{ GetItem(index) };
+        }
+
+        T operator[](uint32_t index)
+        {
+            return Handle{ GetItem(index) };
+        }
+    };
+
+    class DictionaryBase : public Object
+    {
+    public:
+        DictionaryBase() { }
+        DictionaryBase(const Handle& handle) : Object(handle) { }
+
+    protected:
+
+    };
+
+    template<typename KeyT, typename ValueT>
+    class Dictionary : public DictionaryBase
+    {
+    public:
+        Dictionary() { }
+        Dictionary(const Handle& handle) : DictionaryBase(handle) { }
+    };
+
+    class String : public Object
+    {
+    public:
+        String() { }
+        String(const Handle& handle) : Object(handle) { }
+        String(const char* cstr);
+
+        const char* GetCStr() const;
+        uint32_t    GetLength() const;
+    };
+
+    class Error : public Object
+    {
+    public:
+        Error();
+        Error(const Handle& handle) : Object(handle) { }
+
+        String   GetDomain() const;
+        uint32_t GetCode() const;
+        //@property (readonly, copy) NSDictionary *userInfo;
+        String   GetLocalizedDescription() const;
+        String   GetLocalizedFailureReason() const;
+        String   GetLocalizedRecoverySuggestion() const;
+        String   GetLocalizedRecoveryOptions() const;
+        //@property (nullable, readonly, strong) id recoveryAttempter;
+        String   GetHelpAnchor() const;
+    };
+}
+
+//////////////////////////////////////
+// FILE: command_encoder.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+
+namespace mtlpp
+{
+    class Device;
+
+    class CommandEncoder : public ns::Object
+    {
+    public:
+        CommandEncoder() { }
+        CommandEncoder(const ns::Handle& handle) : ns::Object(handle) { }
+
+        Device     GetDevice() const;
+        ns::String GetLabel() const;
+
+        void SetLabel(const ns::String& label);
+
+        void EndEncoding();
+        void InsertDebugSignpost(const ns::String& string);
+        void PushDebugGroup(const ns::String& string);
+        void PopDebugGroup();
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: pixel_format.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+
+namespace mtlpp
+{
+    enum class PixelFormat
+    {
+        Invalid                                            = 0,
+
+        A8Unorm                                            = 1,
+
+        R8Unorm                                            = 10,
+        R8Unorm_sRGB          MTLPP_AVAILABLE_IOS(8_0)     = 11,
+
+        R8Snorm                                            = 12,
+        R8Uint                                             = 13,
+        R8Sint                                             = 14,
+
+        R16Unorm                                           = 20,
+        R16Snorm                                           = 22,
+        R16Uint                                            = 23,
+        R16Sint                                            = 24,
+        R16Float                                           = 25,
+
+        RG8Unorm                                           = 30,
+        RG8Unorm_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 31,
+        RG8Snorm                                           = 32,
+        RG8Uint                                            = 33,
+        RG8Sint                                            = 34,
+
+        B5G6R5Unorm           MTLPP_AVAILABLE_IOS(8_0)     = 40,
+        A1BGR5Unorm           MTLPP_AVAILABLE_IOS(8_0)     = 41,
+        ABGR4Unorm            MTLPP_AVAILABLE_IOS(8_0)     = 42,
+        BGR5A1Unorm           MTLPP_AVAILABLE_IOS(8_0)     = 43,
+
+        R32Uint                                            = 53,
+        R32Sint                                            = 54,
+        R32Float                                           = 55,
+
+        RG16Unorm                                          = 60,
+        RG16Snorm                                          = 62,
+        RG16Uint                                           = 63,
+        RG16Sint                                           = 64,
+        RG16Float                                          = 65,
+
+        RGBA8Unorm                                         = 70,
+        RGBA8Unorm_sRGB                                    = 71,
+        RGBA8Snorm                                         = 72,
+        RGBA8Uint                                          = 73,
+        RGBA8Sint                                          = 74,
+
+        BGRA8Unorm                                         = 80,
+        BGRA8Unorm_sRGB                                    = 81,
+
+        RGB10A2Unorm                                       = 90,
+        RGB10A2Uint                                        = 91,
+
+        RG11B10Float                                       = 92,
+        RGB9E5Float                                        = 93,
+
+        BGR10_XR              MTLPP_AVAILABLE_IOS(10_0)    = 554,
+        BGR10_XR_sRGB         MTLPP_AVAILABLE_IOS(10_0)    = 555,
+
+
+        RG32Uint                                           = 103,
+        RG32Sint                                           = 104,
+        RG32Float                                          = 105,
+
+        RGBA16Unorm                                        = 110,
+        RGBA16Snorm                                        = 112,
+        RGBA16Uint                                         = 113,
+        RGBA16Sint                                         = 114,
+        RGBA16Float                                        = 115,
+
+        BGRA10_XR             MTLPP_AVAILABLE_IOS(10_0)    = 552,
+        BGRA10_XR_sRGB        MTLPP_AVAILABLE_IOS(10_0)    = 553,
+
+        RGBA32Uint                                         = 123,
+        RGBA32Sint                                         = 124,
+        RGBA32Float                                        = 125,
+
+        BC1_RGBA              MTLPP_AVAILABLE_MAC(10_11)   = 130,
+        BC1_RGBA_sRGB         MTLPP_AVAILABLE_MAC(10_11)   = 131,
+        BC2_RGBA              MTLPP_AVAILABLE_MAC(10_11)   = 132,
+        BC2_RGBA_sRGB         MTLPP_AVAILABLE_MAC(10_11)   = 133,
+        BC3_RGBA              MTLPP_AVAILABLE_MAC(10_11)   = 134,
+        BC3_RGBA_sRGB         MTLPP_AVAILABLE_MAC(10_11)   = 135,
+
+        BC4_RUnorm            MTLPP_AVAILABLE_MAC(10_11)   = 140,
+        BC4_RSnorm            MTLPP_AVAILABLE_MAC(10_11)   = 141,
+        BC5_RGUnorm           MTLPP_AVAILABLE_MAC(10_11)   = 142,
+        BC5_RGSnorm           MTLPP_AVAILABLE_MAC(10_11)   = 143,
+
+        BC6H_RGBFloat         MTLPP_AVAILABLE_MAC(10_11)   = 150,
+        BC6H_RGBUfloat        MTLPP_AVAILABLE_MAC(10_11)   = 151,
+        BC7_RGBAUnorm         MTLPP_AVAILABLE_MAC(10_11)   = 152,
+        BC7_RGBAUnorm_sRGB    MTLPP_AVAILABLE_MAC(10_11)   = 153,
+
+        PVRTC_RGB_2BPP        MTLPP_AVAILABLE_IOS(8_0)     = 160,
+        PVRTC_RGB_2BPP_sRGB   MTLPP_AVAILABLE_IOS(8_0)     = 161,
+        PVRTC_RGB_4BPP        MTLPP_AVAILABLE_IOS(8_0)     = 162,
+        PVRTC_RGB_4BPP_sRGB   MTLPP_AVAILABLE_IOS(8_0)     = 163,
+        PVRTC_RGBA_2BPP       MTLPP_AVAILABLE_IOS(8_0)     = 164,
+        PVRTC_RGBA_2BPP_sRGB  MTLPP_AVAILABLE_IOS(8_0)     = 165,
+        PVRTC_RGBA_4BPP       MTLPP_AVAILABLE_IOS(8_0)     = 166,
+        PVRTC_RGBA_4BPP_sRGB  MTLPP_AVAILABLE_IOS(8_0)     = 167,
+
+        EAC_R11Unorm          MTLPP_AVAILABLE_IOS(8_0)     = 170,
+        EAC_R11Snorm          MTLPP_AVAILABLE_IOS(8_0)     = 172,
+        EAC_RG11Unorm         MTLPP_AVAILABLE_IOS(8_0)     = 174,
+        EAC_RG11Snorm         MTLPP_AVAILABLE_IOS(8_0)     = 176,
+        EAC_RGBA8             MTLPP_AVAILABLE_IOS(8_0)     = 178,
+        EAC_RGBA8_sRGB        MTLPP_AVAILABLE_IOS(8_0)     = 179,
+
+        ETC2_RGB8             MTLPP_AVAILABLE_IOS(8_0)     = 180,
+        ETC2_RGB8_sRGB        MTLPP_AVAILABLE_IOS(8_0)     = 181,
+        ETC2_RGB8A1           MTLPP_AVAILABLE_IOS(8_0)     = 182,
+        ETC2_RGB8A1_sRGB      MTLPP_AVAILABLE_IOS(8_0)     = 183,
+
+        ASTC_4x4_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 186,
+        ASTC_5x4_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 187,
+        ASTC_5x5_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 188,
+        ASTC_6x5_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 189,
+        ASTC_6x6_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 190,
+        ASTC_8x5_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 192,
+        ASTC_8x6_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 193,
+        ASTC_8x8_sRGB         MTLPP_AVAILABLE_IOS(8_0)     = 194,
+        ASTC_10x5_sRGB        MTLPP_AVAILABLE_IOS(8_0)     = 195,
+        ASTC_10x6_sRGB        MTLPP_AVAILABLE_IOS(8_0)     = 196,
+        ASTC_10x8_sRGB        MTLPP_AVAILABLE_IOS(8_0)     = 197,
+        ASTC_10x10_sRGB       MTLPP_AVAILABLE_IOS(8_0)     = 198,
+        ASTC_12x10_sRGB       MTLPP_AVAILABLE_IOS(8_0)     = 199,
+        ASTC_12x12_sRGB       MTLPP_AVAILABLE_IOS(8_0)     = 200,
+
+        ASTC_4x4_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 204,
+        ASTC_5x4_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 205,
+        ASTC_5x5_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 206,
+        ASTC_6x5_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 207,
+        ASTC_6x6_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 208,
+        ASTC_8x5_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 210,
+        ASTC_8x6_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 211,
+        ASTC_8x8_LDR          MTLPP_AVAILABLE_IOS(8_0)     = 212,
+        ASTC_10x5_LDR         MTLPP_AVAILABLE_IOS(8_0)     = 213,
+        ASTC_10x6_LDR         MTLPP_AVAILABLE_IOS(8_0)     = 214,
+        ASTC_10x8_LDR         MTLPP_AVAILABLE_IOS(8_0)     = 215,
+        ASTC_10x10_LDR        MTLPP_AVAILABLE_IOS(8_0)     = 216,
+        ASTC_12x10_LDR        MTLPP_AVAILABLE_IOS(8_0)     = 217,
+        ASTC_12x12_LDR        MTLPP_AVAILABLE_IOS(8_0)     = 218,
+
+        GBGR422                                            = 240,
+
+        BGRG422                                            = 241,
+
+        Depth16Unorm          MTLPP_AVAILABLE_MAC(10_12)   = 250,
+        Depth32Float                                       = 252,
+
+        Stencil8                                           = 253,
+
+        Depth24Unorm_Stencil8 MTLPP_AVAILABLE_MAC(10_11)   = 255,
+        Depth32Float_Stencil8 MTLPP_AVAILABLE(10_11, 9_0)  = 260,
+
+        X32_Stencil8          MTLPP_AVAILABLE(10_12, 10_0) = 261,
+        X24_Stencil8          MTLPP_AVAILABLE_MAC(10_12)   = 262,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+
+//////////////////////////////////////
+// FILE: resource.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+
+namespace mtlpp
+{
+    class Heap;
+
+    static const uint32_t ResourceCpuCacheModeShift        = 0;
+    static const uint32_t ResourceStorageModeShift         = 4;
+    static const uint32_t ResourceHazardTrackingModeShift  = 8;
+
+    enum class PurgeableState
+    {
+        KeepCurrent = 1,
+        NonVolatile = 2,
+        Volatile    = 3,
+        Empty       = 4,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class CpuCacheMode
+    {
+        DefaultCache  = 0,
+        WriteCombined = 1,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class StorageMode
+    {
+        Shared                                = 0,
+        Managed    MTLPP_AVAILABLE(10_11, NA) = 1,
+        Private                               = 2,
+        Memoryless MTLPP_AVAILABLE(NA, 10_0)  = 3,
+    }
+    MTLPP_AVAILABLE(10_11, 9_0);
+
+    enum class ResourceOptions
+    {
+        CpuCacheModeDefaultCache                                = uint32_t(CpuCacheMode::DefaultCache)  << ResourceCpuCacheModeShift,
+        CpuCacheModeWriteCombined                               = uint32_t(CpuCacheMode::WriteCombined) << ResourceCpuCacheModeShift,
+
+        StorageModeShared           MTLPP_AVAILABLE(10_11, 9_0) = uint32_t(StorageMode::Shared)     << ResourceStorageModeShift,
+        StorageModeManaged          MTLPP_AVAILABLE(10_11, NA)  = uint32_t(StorageMode::Managed)    << ResourceStorageModeShift,
+        StorageModePrivate          MTLPP_AVAILABLE(10_11, 9_0) = uint32_t(StorageMode::Private)    << ResourceStorageModeShift,
+        StorageModeMemoryless       MTLPP_AVAILABLE(NA, 10_0)   = uint32_t(StorageMode::Memoryless) << ResourceStorageModeShift,
+
+        HazardTrackingModeUntracked MTLPP_AVAILABLE(NA, 10_0)   = 0x1 << ResourceHazardTrackingModeShift,
+
+        OptionCPUCacheModeDefault                               = CpuCacheModeDefaultCache,
+        OptionCPUCacheModeWriteCombined                         = CpuCacheModeWriteCombined,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class Resource : public ns::Object
+    {
+    public:
+        Resource() { }
+        Resource(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String   GetLabel() const;
+        CpuCacheMode GetCpuCacheMode() const;
+        StorageMode  GetStorageMode() const MTLPP_AVAILABLE(10_11, 9_0);
+        Heap         GetHeap() const MTLPP_AVAILABLE(NA, 10_0);
+        bool         IsAliasable() const MTLPP_AVAILABLE(NA, 10_0);
+
+        void SetLabel(const ns::String& label);
+
+        PurgeableState SetPurgeableState(PurgeableState state);
+        void MakeAliasable() const MTLPP_AVAILABLE(NA, 10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: buffer.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "pixel_format.hpp"
+// #include "resource.hpp"
+
+namespace mtlpp
+{
+    class Texture;
+    class TextureDescriptor;
+
+    class Buffer : public Resource
+    {
+    public:
+        Buffer() { }
+        Buffer(const ns::Handle& handle) : Resource(handle) { }
+
+        uint32_t GetLength() const;
+        void*    GetContents();
+        void     DidModify(const ns::Range& range) MTLPP_AVAILABLE_MAC(10_11);
+        Texture  NewTexture(const TextureDescriptor& descriptor, uint32_t offset, uint32_t bytesPerRow) MTLPP_AVAILABLE_IOS(8_0);
+        void     AddDebugMarker(const ns::String& marker, const ns::Range& range) MTLPP_AVAILABLE(10_12, 10_0);
+        void     RemoveAllDebugMarkers() MTLPP_AVAILABLE(10_12, 10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: types.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+
+namespace mtlpp
+{
+    struct Origin
+    {
+        inline Origin(uint32_t x, uint32_t y, uint32_t z) :
+            X(x),
+            Y(y),
+            Z(z)
+        { }
+
+        uint32_t X;
+        uint32_t Y;
+        uint32_t Z;
+    };
+
+    struct Size
+    {
+        inline Size(uint32_t width, uint32_t height, uint32_t depth) :
+            Width(width),
+            Height(height),
+            Depth(depth)
+        { }
+
+        uint32_t Width;
+        uint32_t Height;
+        uint32_t Depth;
+    };
+
+    struct Region
+    {
+        inline Region(uint32_t x, uint32_t width) :
+            Origin(x, 0, 0),
+            Size(width, 1, 1)
+        { }
+
+        inline Region(uint32_t x, uint32_t y, uint32_t width, uint32_t height) :
+            Origin(x, y, 0),
+            Size(width, height, 1)
+        { }
+
+        inline Region(uint32_t x, uint32_t y, uint32_t z, uint32_t width, uint32_t height, uint32_t depth) :
+            Origin(x, y, z),
+            Size(width, height, depth)
+        { }
+
+        Origin Origin;
+        Size   Size;
+    };
+}
+
+//////////////////////////////////////
+// FILE: texture.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "resource.hpp"
+// #include "buffer.hpp"
+// #include "types.hpp"
+
+namespace mtlpp
+{
+    enum class TextureType
+    {
+        Texture1D                                       = 0,
+        Texture1DArray                                  = 1,
+        Texture2D                                       = 2,
+        Texture2DArray                                  = 3,
+        Texture2DMultisample                            = 4,
+        TextureCube                                     = 5,
+        TextureCubeArray     MTLPP_AVAILABLE_MAC(10_11) = 6,
+        Texture3D                                       = 7,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class TextureUsage
+    {
+        Unknown         = 0x0000,
+        ShaderRead      = 0x0001,
+        ShaderWrite     = 0x0002,
+        RenderTarget    = 0x0004,
+        PixelFormatView = 0x0010,
+    }
+    MTLPP_AVAILABLE(10_11, 9_0);
+
+
+    class TextureDescriptor : public ns::Object
+    {
+    public:
+        TextureDescriptor();
+        TextureDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        static TextureDescriptor Texture2DDescriptor(PixelFormat pixelFormat, uint32_t width, uint32_t height, bool mipmapped);
+        static TextureDescriptor TextureCubeDescriptor(PixelFormat pixelFormat, uint32_t size, bool mipmapped);
+
+        TextureType     GetTextureType() const;
+        PixelFormat     GetPixelFormat() const;
+        uint32_t        GetWidth() const;
+        uint32_t        GetHeight() const;
+        uint32_t        GetDepth() const;
+        uint32_t        GetMipmapLevelCount() const;
+        uint32_t        GetSampleCount() const;
+        uint32_t        GetArrayLength() const;
+        ResourceOptions GetResourceOptions() const;
+        CpuCacheMode    GetCpuCacheMode() const MTLPP_AVAILABLE(10_11, 9_0);
+        StorageMode     GetStorageMode() const MTLPP_AVAILABLE(10_11, 9_0);
+        TextureUsage    GetUsage() const MTLPP_AVAILABLE(10_11, 9_0);
+
+        void SetTextureType(TextureType textureType);
+        void SetPixelFormat(PixelFormat pixelFormat);
+        void SetWidth(uint32_t width);
+        void SetHeight(uint32_t height);
+        void SetDepth(uint32_t depth);
+        void SetMipmapLevelCount(uint32_t mipmapLevelCount);
+        void SetSampleCount(uint32_t sampleCount);
+        void SetArrayLength(uint32_t arrayLength);
+        void SetResourceOptions(ResourceOptions resourceOptions);
+        void SetCpuCacheMode(CpuCacheMode cpuCacheMode) MTLPP_AVAILABLE(10_11, 9_0);
+        void SetStorageMode(StorageMode storageMode) MTLPP_AVAILABLE(10_11, 9_0);
+        void SetUsage(TextureUsage usage) MTLPP_AVAILABLE(10_11, 9_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class Texture : public Resource
+    {
+    public:
+        Texture() { }
+        Texture(const ns::Handle& handle) : Resource(handle) { }
+
+        Resource     GetRootResource() const MTLPP_DEPRECATED(10_11, 10_12, 8_0, 10_0);
+        Texture      GetParentTexture() const MTLPP_AVAILABLE(10_11, 9_0);
+        uint32_t     GetParentRelativeLevel() const MTLPP_AVAILABLE(10_11, 9_0);
+        uint32_t     GetParentRelativeSlice() const MTLPP_AVAILABLE(10_11, 9_0);
+        Buffer       GetBuffer() const MTLPP_AVAILABLE(10_12, 9_0);
+        uint32_t     GetBufferOffset() const MTLPP_AVAILABLE(10_12, 9_0);
+        uint32_t     GetBufferBytesPerRow() const MTLPP_AVAILABLE(10_12, 9_0);
+        //IOSurfaceRef GetIOSurface() const;
+        uint32_t     GetIOSurfacePlane() const MTLPP_AVAILABLE_MAC(10_11);
+        TextureType  GetTextureType() const;
+        PixelFormat  GetPixelFormat() const;
+        uint32_t     GetWidth() const;
+        uint32_t     GetHeight() const;
+        uint32_t     GetDepth() const;
+        uint32_t     GetMipmapLevelCount() const;
+        uint32_t     GetSampleCount() const;
+        uint32_t     GetArrayLength() const;
+        TextureUsage GetUsage() const;
+        bool         IsFrameBufferOnly() const;
+
+        void GetBytes(void* pixelBytes, uint32_t bytesPerRow, uint32_t bytesPerImage, const Region& fromRegion, uint32_t mipmapLevel, uint32_t slice);
+        void Replace(const Region& region, uint32_t mipmapLevel, uint32_t slice, void* pixelBytes, uint32_t bytesPerRow, uint32_t bytesPerImage);
+        void GetBytes(void* pixelBytes, uint32_t bytesPerRow, const Region& fromRegion, uint32_t mipmapLevel);
+        void Replace(const Region& region, uint32_t mipmapLevel, void* pixelBytes, uint32_t bytesPerRow);
+        Texture NewTextureView(PixelFormat pixelFormat);
+        Texture NewTextureView(PixelFormat pixelFormat, TextureType textureType, const ns::Range& mipmapLevelRange, const ns::Range& sliceRange);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: argument.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "texture.hpp"
+
+namespace mtlpp
+{
+    class StructType;
+    class ArrayType;
+
+    enum class DataType
+    {
+        None     = 0,
+
+        Struct   = 1,
+        Array    = 2,
+
+        Float    = 3,
+        Float2   = 4,
+        Float3   = 5,
+        Float4   = 6,
+
+        Float2x2 = 7,
+        Float2x3 = 8,
+        Float2x4 = 9,
+
+        Float3x2 = 10,
+        Float3x3 = 11,
+        Float3x4 = 12,
+
+        Float4x2 = 13,
+        Float4x3 = 14,
+        Float4x4 = 15,
+
+        Half     = 16,
+        Half2    = 17,
+        Half3    = 18,
+        Half4    = 19,
+
+        Half2x2  = 20,
+        Half2x3  = 21,
+        Half2x4  = 22,
+
+        Half3x2  = 23,
+        Half3x3  = 24,
+        Half3x4  = 25,
+
+        Half4x2  = 26,
+        Half4x3  = 27,
+        Half4x4  = 28,
+
+        Int      = 29,
+        Int2     = 30,
+        Int3     = 31,
+        Int4     = 32,
+
+        UInt     = 33,
+        UInt2    = 34,
+        UInt3    = 35,
+        UInt4    = 36,
+
+        Short    = 37,
+        Short2   = 38,
+        Short3   = 39,
+        Short4   = 40,
+
+        UShort   = 41,
+        UShort2  = 42,
+        UShort3  = 43,
+        UShort4  = 44,
+
+        Char     = 45,
+        Char2    = 46,
+        Char3    = 47,
+        Char4    = 48,
+
+        UChar    = 49,
+        UChar2   = 50,
+        UChar3   = 51,
+        UChar4   = 52,
+
+        Bool     = 53,
+        Bool2    = 54,
+        Bool3    = 55,
+        Bool4    = 56,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class ArgumentType
+    {
+        Buffer            = 0,
+        ThreadgroupMemory = 1,
+        Texture           = 2,
+        Sampler           = 3,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class ArgumentAccess
+    {
+        ReadOnly  = 0,
+        ReadWrite = 1,
+        WriteOnly = 2,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class StructMember : public ns::Object
+    {
+    public:
+        StructMember();
+        StructMember(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String GetName() const;
+        uint32_t   GetOffset() const;
+        DataType   GetDataType() const;
+
+        StructType GetStructType() const;
+        ArrayType  GetArrayType() const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class StructType : public ns::Object
+    {
+    public:
+        StructType();
+        StructType(const ns::Handle& handle) : ns::Object(handle) { }
+
+        const ns::Array<StructMember> GetMembers() const;
+        StructMember                  GetMember(const ns::String& name) const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class ArrayType : public ns::Object
+    {
+    public:
+        ArrayType();
+        ArrayType(const ns::Handle& handle) : ns::Object(handle) { }
+
+        uint32_t   GetArrayLength() const;
+        DataType   GetElementType() const;
+        uint32_t   GetStride() const;
+        StructType GetElementStructType() const;
+        ArrayType  GetElementArrayType() const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class Argument : public ns::Object
+    {
+    public:
+        Argument();
+        Argument(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String     GetName() const;
+        ArgumentType   GetType() const;
+        ArgumentAccess GetAccess() const;
+        uint32_t       GetIndex() const;
+
+        bool           IsActive() const;
+
+        uint32_t       GetBufferAlignment() const;
+        uint32_t       GetBufferDataSize() const;
+        DataType       GetBufferDataType() const;
+        StructType     GetBufferStructType() const;
+
+        uint32_t       GetThreadgroupMemoryAlignment() const;
+        uint32_t       GetThreadgroupMemoryDataSize() const;
+
+        TextureType    GetTextureType() const;
+        DataType       GetTextureDataType() const;
+
+        bool           IsDepthTexture() const MTLPP_AVAILABLE(10_12, 10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+
+//////////////////////////////////////
+// FILE: library.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+// #include "argument.hpp"
+
+namespace mtlpp
+{
+    class Device;
+    class FunctionConstantValues;
+
+    enum class PatchType
+    {
+        None     = 0,
+        Triangle = 1,
+        Quad     = 2,
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    class VertexAttribute : public ns::Object
+    {
+    public:
+        VertexAttribute();
+        VertexAttribute(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String   GetName() const;
+        uint32_t     GetAttributeIndex() const;
+        DataType     GetAttributeType() const MTLPP_AVAILABLE(10_11, 8_3);
+        bool         IsActive() const;
+        bool         IsPatchData() const MTLPP_AVAILABLE(10_12, 10_0);
+        bool         IsPatchControlPointData() const MTLPP_AVAILABLE(10_12, 10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class Attribute : public ns::Object
+    {
+    public:
+        Attribute();
+        Attribute(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String   GetName() const;
+        uint32_t     GetAttributeIndex() const;
+        DataType     GetAttributeType() const MTLPP_AVAILABLE(10_11, 8_3);
+        bool         IsActive() const;
+        bool         IsPatchData() const MTLPP_AVAILABLE(10_12, 10_0);
+        bool         IsPatchControlPointData() const MTLPP_AVAILABLE(10_12, 10_0);
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    enum class FunctionType
+    {
+        TypeVertex   = 1,
+        TypeFragment = 2,
+        TypeKernel   = 3,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class FunctionConstant : public ns::Object
+    {
+    public:
+        FunctionConstant();
+        FunctionConstant(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String GetName() const;
+        DataType   GetType() const;
+        uint32_t   GetIndex() const;
+        bool       IsRequired() const;
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    class Function : public ns::Object
+    {
+    public:
+        Function(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String                                   GetLabel() const MTLPP_AVAILABLE(10_12, 10_0);
+        Device                                       GetDevice() const;
+        FunctionType                                 GetFunctionType() const;
+        PatchType                                    GetPatchType() const MTLPP_AVAILABLE(10_12, 10_0);
+        int32_t                                      GetPatchControlPointCount() const MTLPP_AVAILABLE(10_12, 10_0);
+        const ns::Array<VertexAttribute>             GetVertexAttributes() const;
+        const ns::Array<Attribute>                   GetStageInputAttributes() const MTLPP_AVAILABLE(10_12, 10_0);
+        ns::String                                   GetName() const;
+        ns::Dictionary<ns::String, FunctionConstant> GetFunctionConstants() const MTLPP_AVAILABLE(10_12, 10_0);
+
+        void SetLabel(const ns::String& label) MTLPP_AVAILABLE(10_12, 10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class LanguageVersion
+    {
+        Version1_0 MTLPP_AVAILABLE(NA, 9_0)     = (1 << 16),
+        Version1_1 MTLPP_AVAILABLE(10_11, 9_0)  = (1 << 16) + 1,
+        Version1_2 MTLPP_AVAILABLE(10_12, 10_0) = (1 << 16) + 2,
+    }
+    MTLPP_AVAILABLE(10_11, 9_0);
+
+    class CompileOptions : public ns::Object
+    {
+    public:
+        CompileOptions();
+        CompileOptions(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::Dictionary<ns::String, ns::String> GetPreprocessorMacros() const;
+        bool                                   IsFastMathEnabled() const;
+        LanguageVersion                        GetLanguageVersion() const MTLPP_AVAILABLE(10_11, 9_0);
+
+        void SetFastMathEnabled(bool fastMathEnabled);
+        void SetFastMathEnabled(LanguageVersion languageVersion);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class LibraryError
+    {
+        Unsupported                                   = 1,
+        Internal                                      = 2,
+        CompileFailure                                = 3,
+        CompileWarning                                = 4,
+        FunctionNotFound MTLPP_AVAILABLE(10_12, 10_0) = 5,
+        FileNotFound     MTLPP_AVAILABLE(10_12, 10_0) = 6,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class RenderPipelineError
+    {
+        Internal     = 1,
+        Unsupported  = 2,
+        InvalidInput = 3,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class Library : public ns::Object
+    {
+    public:
+        Library() { }
+        Library(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String            GetLabel() const;
+        Device                GetDevice() const;
+        ns::Array<ns::String> GetFunctionNames() const;
+
+        void SetLabel(const ns::String& label);
+
+        Function NewFunction(const ns::String& functionName);
+        Function NewFunction(const ns::String& functionName, const FunctionConstantValues& constantValues, ns::Error* error) MTLPP_AVAILABLE(10_12, 10_0);
+        void NewFunction(const ns::String& functionName, const FunctionConstantValues& constantValues, std::function<void(const Function&, const ns::Error&)> completionHandler) MTLPP_AVAILABLE(10_12, 10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: device.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "types.hpp"
+// #include "pixel_format.hpp"
+// #include "resource.hpp"
+// #include "library.hpp"
+
+namespace mtlpp
+{
+    class CommandQueue;
+    class Device;
+    class Buffer;
+    class DepthStencilState;
+    class Function;
+    class Library;
+    class Texture;
+    class SamplerState;
+    class RenderPipelineState;
+    class ComputePipelineState;
+    class Heap;
+    class Fence;
+
+    class SamplerDescriptor;
+    class RenderPipelineColorAttachmentDescriptor;
+    class DepthStencilDescriptor;
+    class TextureDescriptor;
+    class CompileOptions;
+    class RenderPipelineDescriptor;
+    class RenderPassDescriptor;
+    class RenderPipelineReflection;
+    class ComputePipelineDescriptor;
+    class ComputePipelineReflection;
+    class CommandQueueDescriptor;
+    class HeapDescriptor;
+
+    enum class FeatureSet
+    {
+        iOS_GPUFamily1_v1         MTLPP_AVAILABLE_IOS(8_0)   = 0,
+        iOS_GPUFamily2_v1         MTLPP_AVAILABLE_IOS(8_0)   = 1,
+
+        iOS_GPUFamily1_v2         MTLPP_AVAILABLE_IOS(8_0)   = 2,
+        iOS_GPUFamily2_v2         MTLPP_AVAILABLE_IOS(8_0)   = 3,
+        iOS_GPUFamily3_v1         MTLPP_AVAILABLE_IOS(9_0)   = 4,
+
+        iOS_GPUFamily1_v3         MTLPP_AVAILABLE_IOS(10_0)  = 5,
+        iOS_GPUFamily2_v3         MTLPP_AVAILABLE_IOS(10_0)  = 6,
+        iOS_GPUFamily3_v2         MTLPP_AVAILABLE_IOS(10_0)  = 7,
+
+        OSX_GPUFamily1_v1         MTLPP_AVAILABLE_MAC(8_0)   = 10000,
+
+        OSX_GPUFamily1_v2         MTLPP_AVAILABLE_MAC(10_12) = 10001,
+        OSX_ReadWriteTextureTier2 MTLPP_AVAILABLE_MAC(10_12) = 10002,
+
+        tvOS_GPUFamily1_v1        MTLPP_AVAILABLE_TVOS(9_0)  = 30000,
+
+        tvOS_GPUFamily1_v2        MTLPP_AVAILABLE_TVOS(10_0) = 30001,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class PipelineOption
+    {
+        None           = 0,
+        ArgumentInfo   = 1 << 0,
+        BufferTypeInfo = 1 << 1,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    struct SizeAndAlign
+    {
+        uint32_t Size;
+        uint32_t Align;
+    };
+
+    class Device : public ns::Object
+    {
+    public:
+        Device() { }
+        Device(const ns::Handle& handle) : ns::Object(handle) { }
+
+        static Device CreateSystemDefaultDevice() MTLPP_AVAILABLE(10_11, 8_0);
+        static ns::Array<Device> CopyAllDevices() MTLPP_AVAILABLE(10_11, NA);
+
+        ns::String GetName() const;
+        Size       GetMaxThreadsPerThreadgroup() const MTLPP_AVAILABLE(10_11, 9_0);
+        bool       IsLowPower() const MTLPP_AVAILABLE_MAC(10_11);
+        bool       IsHeadless() const MTLPP_AVAILABLE_MAC(10_11);
+        uint64_t   GetRecommendedMaxWorkingSetSize() const MTLPP_AVAILABLE_MAC(10_12);
+        bool       IsDepth24Stencil8PixelFormatSupported() const MTLPP_AVAILABLE_MAC(10_11);
+
+        CommandQueue NewCommandQueue();
+        CommandQueue NewCommandQueue(uint32_t maxCommandBufferCount);
+        SizeAndAlign HeapTextureSizeAndAlign(const TextureDescriptor& desc) MTLPP_AVAILABLE(NA, 10_0);
+        SizeAndAlign HeapBufferSizeAndAlign(uint32_t length, ResourceOptions options) MTLPP_AVAILABLE(NA, 10_0);
+        Heap NewHeap(const HeapDescriptor& descriptor) MTLPP_AVAILABLE(NA, 10_0);
+        Buffer NewBuffer(uint32_t length, ResourceOptions options);
+        Buffer NewBuffer(const void* pointer, uint32_t length, ResourceOptions options);
+        Buffer NewBuffer(void* pointer, uint32_t length, ResourceOptions options, std::function<void (void* pointer, uint32_t length)> deallocator);
+        DepthStencilState NewDepthStencilState(const DepthStencilDescriptor& descriptor);
+        Texture NewTexture(const TextureDescriptor& descriptor);
+        //- (id <MTLTexture>)newTextureWithDescriptor:(MTLTextureDescriptor *)descriptor iosurface:(IOSurfaceRef)iosurface plane:(NSUInteger)plane NS_AVAILABLE_MAC(10_11);
+        SamplerState NewSamplerState(const SamplerDescriptor& descriptor);
+        Library NewDefaultLibrary();
+        //- (nullable id <MTLLibrary>)newDefaultLibraryWithBundle:(NSBundle *)bundle error:(__autoreleasing NSError **)error NS_AVAILABLE(10_12, 10_0);
+        Library NewLibrary(const ns::String& filepath, ns::Error* error);
+        Library NewLibrary(const char* source, const CompileOptions& options, ns::Error* error);
+        void NewLibrary(const char* source, const CompileOptions& options, std::function<void(const Library&, const ns::Error&)> completionHandler);
+        RenderPipelineState NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, ns::Error* error);
+        RenderPipelineState NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, PipelineOption options, RenderPipelineReflection* outReflection, ns::Error* error);
+        void NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, std::function<void(const RenderPipelineState&, const ns::Error&)> completionHandler);
+        void NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, PipelineOption options, std::function<void(const RenderPipelineState&, const RenderPipelineReflection&, const ns::Error&)> completionHandler);
+        ComputePipelineState NewComputePipelineState(const Function& computeFunction, ns::Error* error);
+        ComputePipelineState NewComputePipelineState(const Function& computeFunction, PipelineOption options, ComputePipelineReflection& outReflection, ns::Error* error);
+        void NewComputePipelineState(const Function& computeFunction, std::function<void(const ComputePipelineState&, const ns::Error&)> completionHandler);
+        void NewComputePipelineState(const Function& computeFunction, PipelineOption options, std::function<void(const ComputePipelineState&, const ComputePipelineReflection&, const ns::Error&)> completionHandler);
+        ComputePipelineState NewComputePipelineState(const ComputePipelineDescriptor& descriptor, PipelineOption options, ComputePipelineReflection* outReflection, ns::Error* error);
+        void NewComputePipelineState(const ComputePipelineDescriptor& descriptor, PipelineOption options, std::function<void(const ComputePipelineState&, const ComputePipelineReflection&, const ns::Error&)> completionHandler) MTLPP_AVAILABLE(10_11, 9_0);
+        Fence NewFence() MTLPP_AVAILABLE(NA, 10_0);
+        bool SupportsFeatureSet(FeatureSet featureSet) const;
+        bool SupportsTextureSampleCount(uint32_t sampleCount) const MTLPP_AVAILABLE(10_11, 9_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: fence.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+// #include "device.hpp"
+
+
+namespace mtlpp
+{
+    class Fence : public ns::Object
+    {
+    public:
+        Fence(const ns::Handle& handle) : ns::Object(handle) { }
+
+        Texture    GetDevice() const;
+        ns::String GetLabel() const;
+
+        void SetLabel(const ns::String& label);
+    }
+    MTLPP_AVAILABLE(NA, 10_0);
+}
+
+//////////////////////////////////////
+// FILE: blit_command_encoder.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "command_encoder.hpp"
+// #include "buffer.hpp"
+// #include "texture.hpp"
+// #include "fence.hpp"
+
+namespace mtlpp
+{
+    enum class BlitOption
+    {
+        None                                             = 0,
+        DepthFromDepthStencil                            = 1 << 0,
+        StencilFromDepthStencil                          = 1 << 1,
+        RowLinearPVRTC          MTLPP_AVAILABLE_IOS(9_0) = 1 << 2,
+    }
+    MTLPP_AVAILABLE(10_11, 9_0);
+
+    class BlitCommandEncoder : public ns::Object
+    {
+    public:
+        BlitCommandEncoder() { }
+        BlitCommandEncoder(const ns::Handle& handle) : ns::Object(handle) { }
+
+        void Synchronize(const Resource& resource) MTLPP_AVAILABLE_MAC(10_11);
+        void Synchronize(const Texture& texture, uint32_t slice, uint32_t level) MTLPP_AVAILABLE_MAC(10_11);
+        void Copy(const Texture& sourceTexture, uint32_t sourceSlice, uint32_t sourceLevel, const Origin& sourceOrigin, const Size& sourceSize, const Texture& destinationTexture, uint32_t destinationSlice, uint32_t destinationLevel, const Origin& destinationOrigin);
+        void Copy(const Buffer& sourceBuffer, uint32_t sourceOffset, uint32_t sourceBytesPerRow, uint32_t sourceBytesPerImage, const Size& sourceSize, const Texture& destinationTexture, uint32_t destinationSlice, uint32_t destinationLevel, const Origin& destinationOrigin);
+        void Copy(const Buffer& sourceBuffer, uint32_t sourceOffset, uint32_t sourceBytesPerRow, uint32_t sourceBytesPerImage, const Size& sourceSize, const Texture& destinationTexture, uint32_t destinationSlice, uint32_t destinationLevel, const Origin& destinationOrigin, BlitOption options);
+        void Copy(const Texture& sourceTexture, uint32_t sourceSlice, uint32_t sourceLevel, const Origin& sourceOrigin, const Size& sourceSize, const Buffer& destinationBuffer, uint32_t destinationOffset, uint32_t destinationBytesPerRow, uint32_t destinationBytesPerImage);
+        void Copy(const Texture& sourceTexture, uint32_t sourceSlice, uint32_t sourceLevel, const Origin& sourceOrigin, const Size& sourceSize, const Buffer& destinationBuffer, uint32_t destinationOffset, uint32_t destinationBytesPerRow, uint32_t destinationBytesPerImage, BlitOption options);
+        void Copy(const Buffer& sourceBuffer, uint32_t soruceOffset, const Buffer& destinationBuffer, uint32_t destinationOffset, uint32_t size);
+        void GenerateMipmaps(const Texture& texture);
+        void Fill(const Buffer& buffer, const ns::Range& range, uint8_t value);
+        void UpdateFence(const Fence& fence) MTLPP_AVAILABLE_IOS(10_0);
+        void WaitForFence(const Fence& fence) MTLPP_AVAILABLE_IOS(10_0);
+    };
+}
+
+//////////////////////////////////////
+// FILE: command_buffer.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+
+namespace mtlpp
+{
+    class Device;
+    class CommandQueue;
+    class BlitCommandEncoder;
+    class RenderCommandEncoder;
+    class ParallelRenderCommandEncoder;
+    class ComputeCommandEncoder;
+    class CommandQueue;
+    class Drawable;
+    class RenderPassDescriptor;
+
+    enum class CommandBufferStatus
+    {
+        NotEnqueued = 0,
+        Enqueued    = 1,
+        Committed   = 2,
+        Scheduled   = 3,
+        Completed   = 4,
+        Error       = 5,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class CommandBufferError
+    {
+        None                                      = 0,
+        Internal                                  = 1,
+        Timeout                                   = 2,
+        PageFault                                 = 3,
+        Blacklisted                               = 4,
+        NotPermitted                              = 7,
+        OutOfMemory                               = 8,
+        InvalidResource                           = 9,
+        Memoryless      MTLPP_AVAILABLE_IOS(10_0) = 10,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class CommandBuffer : public ns::Object
+    {
+    public:
+        CommandBuffer() { }
+        CommandBuffer(const ns::Handle& handle) : ns::Object(handle) { }
+
+        Device              GetDevice() const;
+        CommandQueue        GetCommandQueue() const;
+        bool                GetRetainedReferences() const;
+        ns::String          GetLabel() const;
+        CommandBufferStatus GetStatus() const;
+        ns::Error           GetError() const;
+
+        void SetLabel(const ns::String& label);
+
+        void Enqueue();
+        void Commit();
+        void AddScheduledHandler(std::function<void(const CommandBuffer&)> handler);
+        void AddCompletedHandler(std::function<void(const CommandBuffer&)> handler);
+        void Present(const Drawable& drawable);
+        void Present(const Drawable& drawable, double presentationTime);
+        void WaitUntilScheduled();
+        void WaitUntilCompleted();
+        BlitCommandEncoder BlitCommandEncoder();
+        RenderCommandEncoder RenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor);
+        ComputeCommandEncoder ComputeCommandEncoder();
+        ParallelRenderCommandEncoder ParallelRenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: compute_command_encoder.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+// #include "command_encoder.hpp"
+// #include "texture.hpp"
+// #include "command_buffer.hpp"
+// #include "fence.hpp"
+
+namespace mtlpp
+{
+    class ComputeCommandEncoder : public CommandEncoder
+    {
+    public:
+        ComputeCommandEncoder() { }
+        ComputeCommandEncoder(const ns::Handle& handle) : CommandEncoder(handle) { }
+
+        void SetComputePipelineState(const ComputePipelineState& state);
+        void SetBytes(const void* data, uint32_t length, uint32_t index);
+        void SetBuffer(const Buffer& buffer, uint32_t offset, uint32_t index);
+        void SetBufferOffset(uint32_t offset, uint32_t index) MTLPP_AVAILABLE(10_11, 8_3);
+        void SetBuffers(const Buffer* buffers, const uint32_t* offsets, const ns::Range& range);
+        void SetTexture(const Texture& texture, uint32_t index);
+        void SetTextures(const Texture* textures, const ns::Range& range);
+        void SetSamplerState(const SamplerState& sampler, uint32_t index);
+        void SetSamplerStates(const SamplerState* samplers, const ns::Range& range);
+        void SetSamplerState(const SamplerState& sampler, float lodMinClamp, float lodMaxClamp, uint32_t index);
+        void SetSamplerStates(const SamplerState* samplers, const float* lodMinClamps, const float* lodMaxClamps, const ns::Range& range);
+        void SetThreadgroupMemory(uint32_t length, uint32_t index);
+        void SetStageInRegion(const Region& region) MTLPP_AVAILABLE(10_12, 10_0);
+        void DispatchThreadgroups(const Size& threadgroupsPerGrid, const Size& threadsPerThreadgroup);
+        void DispatchThreadgroupsWithIndirectBuffer(const Buffer& indirectBuffer, uint32_t indirectBufferOffset, const Size& threadsPerThreadgroup);
+        void UpdateFence(const Fence& fence) MTLPP_AVAILABLE_IOS(10_0);
+        void WaitForFence(const Fence& fence) MTLPP_AVAILABLE_IOS(10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: command_queue.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+
+namespace mtlpp
+{
+    class Device;
+    class CommandBuffer;
+
+    class CommandQueue : public ns::Object
+    {
+    public:
+        CommandQueue() { }
+        CommandQueue(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String GetLabel() const;
+        Device     GetDevice() const;
+
+        void SetLabel(const ns::String& label);
+
+        class CommandBuffer CommandBufferWithUnretainedReferences();
+        class CommandBuffer CommandBuffer();
+        void                InsertDebugCaptureBoundary();
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: depth_stencil.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+// #include "device.hpp"
+
+namespace mtlpp
+{
+    enum class CompareFunction
+    {
+        Never        = 0,
+        Less         = 1,
+        Equal        = 2,
+        LessEqual    = 3,
+        Greater      = 4,
+        NotEqual     = 5,
+        GreaterEqual = 6,
+        Always       = 7,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class StencilOperation
+    {
+        Keep           = 0,
+        Zero           = 1,
+        Replace        = 2,
+        IncrementClamp = 3,
+        DecrementClamp = 4,
+        Invert         = 5,
+        IncrementWrap  = 6,
+        DecrementWrap  = 7,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class StencilDescriptor : public ns::Object
+    {
+    public:
+        StencilDescriptor();
+        StencilDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        CompareFunction  GetStencilCompareFunction() const;
+        StencilOperation GetStencilFailureOperation() const;
+        StencilOperation GetDepthFailureOperation() const;
+        StencilOperation GetDepthStencilPassOperation() const;
+        uint32_t         GetReadMask() const;
+        uint32_t         GetWriteMask() const;
+
+        void SetStencilCompareFunction(CompareFunction stencilCompareFunction);
+        void SetStencilFailureOperation(StencilOperation stencilFailureOperation);
+        void SetDepthFailureOperation(StencilOperation depthFailureOperation);
+        void SetDepthStencilPassOperation(StencilOperation depthStencilPassOperation);
+        void SetReadMask(uint32_t readMask);
+        void SetWriteMask(uint32_t writeMask);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class DepthStencilDescriptor : public ns::Object
+    {
+    public:
+        DepthStencilDescriptor();
+        DepthStencilDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        CompareFunction   GetDepthCompareFunction() const;
+        bool              IsDepthWriteEnabled() const;
+        StencilDescriptor GetFrontFaceStencil() const;
+        StencilDescriptor GetBackFaceStencil() const;
+        ns::String        GetLabel() const;
+
+        void SetDepthCompareFunction(CompareFunction depthCompareFunction) const;
+        void SetDepthWriteEnabled(bool depthWriteEnabled) const;
+        void SetFrontFaceStencil(const StencilDescriptor& frontFaceStencil) const;
+        void SetBackFaceStencil(const StencilDescriptor& backFaceStencil) const;
+        void SetLabel(const ns::String& label) const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class DepthStencilState : public ns::Object
+    {
+    public:
+        DepthStencilState() { }
+        DepthStencilState(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String GetLabel() const;
+        Device     GetDevice() const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: drawable.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+
+namespace mtlpp
+{
+    class Drawable : public ns::Object
+    {
+    public:
+        Drawable() { }
+        Drawable(const ns::Handle& handle) : ns::Object(handle) { }
+
+        void Present();
+        void Present(double presentationTime);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+
+//////////////////////////////////////
+// FILE: render_pass.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+
+namespace mtlpp
+{
+    class Texture;
+    class Buffer;
+
+    enum class LoadAction
+    {
+        DontCare = 0,
+        Load     = 1,
+        Clear    = 2,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class StoreAction
+    {
+        DontCare                                               = 0,
+        Store                                                  = 1,
+        MultisampleResolve                                     = 2,
+        StoreAndMultisampleResolve MTLPP_AVAILABLE(10_12,10_0) = 3,
+        Unknown                    MTLPP_AVAILABLE(10_12,10_0) = 4,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class MultisampleDepthResolveFilter
+    {
+        Sample0 = 0,
+        Min     = 1,
+        Max     = 2,
+    }
+    MTLPP_AVAILABLE_IOS(9_0);
+
+    struct ClearColor
+    {
+        ClearColor(double red, double green, double blue, double alpha) :
+            Red(red),
+            Green(green),
+            Blue(blue),
+            Alpha(alpha) { }
+
+        double Red;
+        double Green;
+        double Blue;
+        double Alpha;
+    };
+
+    class RenderPassAttachmentDescriptor : public ns::Object
+    {
+    public:
+        RenderPassAttachmentDescriptor();
+        RenderPassAttachmentDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        Texture     GetTexture() const;
+        uint32_t    GetLevel() const;
+        uint32_t    GetSlice() const;
+        uint32_t    GetDepthPlane() const;
+        Texture     GetResolveTexture() const;
+        uint32_t    GetResolveLevel() const;
+        uint32_t    GetResolveSlice() const;
+        uint32_t    GetResolveDepthPlane() const;
+        LoadAction  GetLoadAction() const;
+        StoreAction GetStoreAction() const;
+
+        void SetTexture(const Texture& texture);
+        void SetLevel(uint32_t level);
+        void SetSlice(uint32_t slice);
+        void SetDepthPlane(uint32_t depthPlane);
+        void SetResolveTexture(const Texture& texture);
+        void SetResolveLevel(uint32_t resolveLevel);
+        void SetResolveSlice(uint32_t resolveSlice);
+        void SetResolveDepthPlane(uint32_t resolveDepthPlane);
+        void SetLoadAction(LoadAction loadAction);
+        void SetStoreAction(StoreAction storeAction);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class RenderPassColorAttachmentDescriptor : public RenderPassAttachmentDescriptor
+    {
+    public:
+        RenderPassColorAttachmentDescriptor();
+        RenderPassColorAttachmentDescriptor(const ns::Handle& handle) : RenderPassAttachmentDescriptor(handle) { }
+
+        ClearColor GetClearColor() const;
+
+        void SetClearColor(const ClearColor& clearColor);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class RenderPassDepthAttachmentDescriptor : public RenderPassAttachmentDescriptor
+    {
+    public:
+        RenderPassDepthAttachmentDescriptor();
+        RenderPassDepthAttachmentDescriptor(const ns::Handle& handle) : RenderPassAttachmentDescriptor(handle) { }
+
+        double                        GetClearDepth() const;
+        MultisampleDepthResolveFilter GetDepthResolveFilter() const MTLPP_AVAILABLE_IOS(9_0);
+
+        void SetClearDepth(double clearDepth);
+        void SetDepthResolveFilter(MultisampleDepthResolveFilter depthResolveFilter) MTLPP_AVAILABLE_IOS(9_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class RenderPassStencilAttachmentDescriptor : public RenderPassAttachmentDescriptor
+    {
+    public:
+        RenderPassStencilAttachmentDescriptor();
+        RenderPassStencilAttachmentDescriptor(const ns::Handle& handle) : RenderPassAttachmentDescriptor(handle) { }
+
+        uint32_t GetClearStencil() const;
+
+        void SetClearStencil(uint32_t clearStencil);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class RenderPassDescriptor : public ns::Object
+    {
+    public:
+        RenderPassDescriptor();
+        RenderPassDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::Array<RenderPassColorAttachmentDescriptor> GetColorAttachments() const;
+        RenderPassDepthAttachmentDescriptor   GetDepthAttachment() const;
+        RenderPassStencilAttachmentDescriptor GetStencilAttachment() const;
+        Buffer                                GetVisibilityResultBuffer() const;
+        uint32_t                              GetRenderTargetArrayLength() const MTLPP_AVAILABLE_MAC(10_11);
+
+        void SetDepthAttachment(const RenderPassDepthAttachmentDescriptor& depthAttachment);
+        void SetStencilAttachment(const RenderPassStencilAttachmentDescriptor& stencilAttachment);
+        void SetVisibilityResultBuffer(const Buffer& visibilityResultBuffer);
+        void SetRenderTargetArrayLength(uint32_t renderTargetArrayLength) MTLPP_AVAILABLE_MAC(10_11);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: stage_input_output_descriptor.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "device.hpp"
+
+namespace mtlpp
+{
+    enum class AttributeFormat
+    {
+        Invalid               = 0,
+
+        UChar2                = 1,
+        UChar3                = 2,
+        UChar4                = 3,
+
+        Char2                 = 4,
+        Char3                 = 5,
+        Char4                 = 6,
+
+        UChar2Normalized      = 7,
+        UChar3Normalized      = 8,
+        UChar4Normalized      = 9,
+
+        Char2Normalized       = 10,
+        Char3Normalized       = 11,
+        Char4Normalized       = 12,
+
+        UShort2               = 13,
+        UShort3               = 14,
+        UShort4               = 15,
+
+        Short2                = 16,
+        Short3                = 17,
+        Short4                = 18,
+
+        UShort2Normalized     = 19,
+        UShort3Normalized     = 20,
+        UShort4Normalized     = 21,
+
+        Short2Normalized      = 22,
+        Short3Normalized      = 23,
+        Short4Normalized      = 24,
+
+        Half2                 = 25,
+        Half3                 = 26,
+        Half4                 = 27,
+
+        Float                 = 28,
+        Float2                = 29,
+        Float3                = 30,
+        Float4                = 31,
+
+        Int                   = 32,
+        Int2                  = 33,
+        Int3                  = 34,
+        Int4                  = 35,
+
+        UInt                  = 36,
+        UInt2                 = 37,
+        UInt3                 = 38,
+        UInt4                 = 39,
+
+        Int1010102Normalized  = 40,
+        UInt1010102Normalized = 41,
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    enum class IndexType
+    {
+        UInt16 = 0,
+        UInt32 = 1,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+
+    enum class StepFunction
+    {
+        Constant                                                  = 0,
+
+        PerVertex                                                 = 1,
+        PerInstance                                               = 2,
+        PerPatch                     MTLPP_AVAILABLE(10_12, 10_0) = 3,
+        PerPatchControlPoint         MTLPP_AVAILABLE(10_12, 10_0) = 4,
+
+        ThreadPositionInGridX                                     = 5,
+        ThreadPositionInGridY                                     = 6,
+        ThreadPositionInGridXIndexed                              = 7,
+        ThreadPositionInGridYIndexed                              = 8,
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    class BufferLayoutDescriptor : public ns::Object
+    {
+    public:
+        BufferLayoutDescriptor();
+        BufferLayoutDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        uint32_t     GetStride() const;
+        StepFunction GetStepFunction() const;
+        uint32_t     GetStepRate() const;
+
+        void SetStride(uint32_t stride);
+        void SetStepFunction(StepFunction stepFunction);
+        void SetStepRate(uint32_t stepRate);
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    class AttributeDescriptor : public ns::Object
+    {
+    public:
+        AttributeDescriptor();
+        AttributeDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        AttributeFormat GetFormat() const;
+        uint32_t        GetOffset() const;
+        uint32_t        GetBufferIndex() const;
+
+        void SetFormat(AttributeFormat format);
+        void SetOffset(uint32_t offset);
+        void SetBufferIndex(uint32_t bufferIndex);
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    class StageInputOutputDescriptor : public ns::Object
+    {
+    public:
+        StageInputOutputDescriptor();
+        StageInputOutputDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+
+        ns::Array<BufferLayoutDescriptor> GetLayouts() const;
+        ns::Array<AttributeDescriptor>    GetAttributes() const;
+        IndexType                         GetIndexType() const;
+        uint32_t                          GetIndexBufferIndex() const;
+
+        void SetIndexType(IndexType indexType);
+        void SetIndexBufferIndex(uint32_t indexBufferIndex);
+
+        void Reset();
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+}
+
+//////////////////////////////////////
+// FILE: compute_pipeline.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "device.hpp"
+// #include "argument.hpp"
+// #include "stage_input_output_descriptor.hpp"
+
+namespace mtlpp
+{
+    class ComputePipelineReflection : public ns::Object
+    {
+    public:
+        ComputePipelineReflection();
+        ComputePipelineReflection(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::Array<Argument> GetArguments() const;
+    }
+    MTLPP_AVAILABLE(10_11, 9_0);
+
+    class ComputePipelineDescriptor : public ns::Object
+    {
+    public:
+        ComputePipelineDescriptor();
+        ComputePipelineDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String                 GetLabel() const;
+        Function                   GetComputeFunction() const;
+        bool                       GetThreadGroupSizeIsMultipleOfThreadExecutionWidth() const;
+        StageInputOutputDescriptor GetStageInputDescriptor() const MTLPP_AVAILABLE(10_12, 10_0);
+
+        void SetLabel(const ns::String& label);
+        void SetComputeFunction(const Function& function);
+        void SetThreadGroupSizeIsMultipleOfThreadExecutionWidth(bool value);
+        void SetStageInputDescriptor(const StageInputOutputDescriptor& stageInputDescriptor) const MTLPP_AVAILABLE(10_12, 10_0);
+
+        void Reset();
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class ComputePipelineState : public ns::Object
+    {
+    public:
+        ComputePipelineState() { }
+        ComputePipelineState(const ns::Handle& handle) : ns::Object(handle) { }
+
+        Device   GetDevice() const;
+        uint32_t GetMaxTotalThreadsPerThreadgroup() const;
+        uint32_t GetThreadExecutionWidth() const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: render_command_encoder.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "command_encoder.hpp"
+// #include "command_buffer.hpp"
+// #include "render_pass.hpp"
+// #include "fence.hpp"
+// #include "stage_input_output_descriptor.hpp"
+
+namespace mtlpp
+{
+    enum class PrimitiveType
+    {
+        Point         = 0,
+        Line          = 1,
+        LineStrip     = 2,
+        Triangle      = 3,
+        TriangleStrip = 4,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class VisibilityResultMode
+    {
+        Disabled                             = 0,
+        Boolean                              = 1,
+        Counting MTLPP_AVAILABLE(10_11, 9_0) = 2,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    struct ScissorRect
+    {
+        uint32_t X;
+        uint32_t Y;
+        uint32_t Width;
+        uint32_t Height;
+    };
+
+    struct Viewport
+    {
+        double OriginX;
+        double OriginY;
+        double Width;
+        double Height;
+        double ZNear;
+        double ZFar;
+    };
+
+    enum class CullMode
+    {
+        None  = 0,
+        Front = 1,
+        Back  = 2,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class Winding
+    {
+        Clockwise        = 0,
+        CounterClockwise = 1,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class DepthClipMode
+    {
+        Clip  = 0,
+        Clamp = 1,
+    }
+    MTLPP_AVAILABLE(10_11, 9_0);
+
+    enum class TriangleFillMode
+    {
+        Fill  = 0,
+        Lines = 1,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    struct DrawPrimitivesIndirectArguments
+    {
+        uint32_t VertexCount;
+        uint32_t InstanceCount;
+        uint32_t VertexStart;
+        uint32_t BaseInstance;
+    };
+
+    struct DrawIndexedPrimitivesIndirectArguments
+    {
+        uint32_t IndexCount;
+        uint32_t InstanceCount;
+        uint32_t IndexStart;
+        int32_t  BaseVertex;
+        uint32_t BaseInstance;
+    };
+
+    struct DrawPatchIndirectArguments
+    {
+        uint32_t PatchCount;
+        uint32_t InstanceCount;
+        uint32_t PatchStart;
+        uint32_t BaseInstance;
+    };
+
+    struct QuadTessellationFactorsHalf
+    {
+        uint16_t EdgeTessellationFactor[4];
+        uint16_t InsideTessellationFactor[2];
+    };
+
+    struct riangleTessellationFactorsHalf
+    {
+        uint16_t EdgeTessellationFactor[3];
+        uint16_t InsideTessellationFactor;
+    };
+
+    enum class RenderStages
+    {
+        Vertex   = (1 << 0),
+        Fragment = (1 << 1),
+    }
+    MTLPP_AVAILABLE_IOS(10_0);
+
+
+    class RenderCommandEncoder : public CommandEncoder
+    {
+    public:
+        RenderCommandEncoder() { }
+        RenderCommandEncoder(const ns::Handle& handle) : CommandEncoder(handle) { }
+
+        void SetRenderPipelineState(const RenderPipelineState& pipelineState);
+        void SetVertexData(const void* bytes, uint32_t length, uint32_t index) MTLPP_AVAILABLE(10_11, 8_3);
+        void SetVertexBuffer(const Buffer& buffer, uint32_t offset, uint32_t index);
+        void SetVertexBufferOffset(uint32_t offset, uint32_t index) MTLPP_AVAILABLE(10_11, 8_3);
+        void SetVertexBuffers(const Buffer* buffers, const uint32_t* offsets, const ns::Range& range);
+        void SetVertexTexture(const Texture& texture, uint32_t index);
+        void SetVertexTextures(const Texture* textures, const ns::Range& range);
+        void SetVertexSamplerState(const SamplerState& sampler, uint32_t index);
+        void SetVertexSamplerStates(const SamplerState* samplers, const ns::Range& range);
+        void SetVertexSamplerState(const SamplerState& sampler, float lodMinClamp, float lodMaxClamp, uint32_t index);
+        void SetVertexSamplerStates(const SamplerState* samplers, const float* lodMinClamps, const float* lodMaxClamps, const ns::Range& range);
+        void SetViewport(const Viewport& viewport);
+        void SetFrontFacingWinding(Winding frontFacingWinding);
+        void SetCullMode(CullMode cullMode);
+        void SetDepthClipMode(DepthClipMode depthClipMode) MTLPP_AVAILABLE(10_11, NA);
+        void SetDepthBias(float depthBias, float slopeScale, float clamp);
+        void SetScissorRect(const ScissorRect& rect);
+        void SetTriangleFillMode(TriangleFillMode fillMode);
+        void SetFragmentData(const void* bytes, uint32_t length, uint32_t index);
+        void SetFragmentBuffer(const Buffer& buffer, uint32_t offset, uint32_t index);
+        void SetFragmentBufferOffset(uint32_t offset, uint32_t index) MTLPP_AVAILABLE(10_11, 8_3);
+        void SetFragmentBuffers(const Buffer* buffers, const uint32_t* offsets, const ns::Range& range);
+        void SetFragmentTexture(const Texture& texture, uint32_t index);
+        void SetFragmentTextures(const Texture* textures, const ns::Range& range);
+        void SetFragmentSamplerState(const SamplerState& sampler, uint32_t index);
+        void SetFragmentSamplerStates(const SamplerState* samplers, const ns::Range& range);
+        void SetFragmentSamplerState(const SamplerState& sampler, float lodMinClamp, float lodMaxClamp, uint32_t index);
+        void SetFragmentSamplerStates(const SamplerState* samplers, const float* lodMinClamps, const float* lodMaxClamps, const ns::Range& range);
+        void SetBlendColor(float red, float green, float blue, float alpha);
+        void SetDepthStencilState(const DepthStencilState& depthStencilState);
+        void SetStencilReferenceValue(uint32_t referenceValue);
+        void SetStencilReferenceValue(uint32_t frontReferenceValue, uint32_t backReferenceValue);
+        void SetVisibilityResultMode(VisibilityResultMode mode, uint32_t offset);
+        void SetColorStoreAction(StoreAction storeAction, uint32_t colorAttachmentIndex) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetDepthStoreAction(StoreAction storeAction) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetStencilStoreAction(StoreAction storeAction) MTLPP_AVAILABLE(10_12, 10_0);
+        void Draw(PrimitiveType primitiveType, uint32_t vertexStart, uint32_t vertexCount);
+        void Draw(PrimitiveType primitiveType, uint32_t vertexStart, uint32_t vertexCount, uint32_t instanceCount) MTLPP_AVAILABLE(10_11, 9_0);
+        void Draw(PrimitiveType primitiveType, uint32_t vertexStart, uint32_t vertexCount, uint32_t instanceCount, uint32_t baseInstance) MTLPP_AVAILABLE(10_11, 9_0);
+        void Draw(PrimitiveType primitiveType, Buffer indirectBuffer, uint32_t indirectBufferOffset);
+        void DrawIndexed(PrimitiveType primitiveType, uint32_t indexCount, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset);
+        void DrawIndexed(PrimitiveType primitiveType, uint32_t indexCount, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset, uint32_t instanceCount) MTLPP_AVAILABLE(10_11, 9_0);
+        void DrawIndexed(PrimitiveType primitiveType, uint32_t indexCount, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset, uint32_t instanceCount, uint32_t baseVertex, uint32_t baseInstance) MTLPP_AVAILABLE(10_11, 9_0);
+        void DrawIndexed(PrimitiveType primitiveType, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset, const Buffer& indirectBuffer, uint32_t indirectBufferOffset);
+        void TextureBarrier() MTLPP_AVAILABLE_MAC(10_11);
+        void UpdateFence(const Fence& fence, RenderStages afterStages) MTLPP_AVAILABLE_IOS(10_0);
+        void WaitForFence(const Fence& fence, RenderStages beforeStages) MTLPP_AVAILABLE_IOS(10_0);
+        void SetTessellationFactorBuffer(const Buffer& buffer, uint32_t offset, uint32_t instanceStride) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetTessellationFactorScale(float scale) MTLPP_AVAILABLE(10_12, 10_0);
+        void DrawPatches(uint32_t numberOfPatchControlPoints, uint32_t patchStart, uint32_t patchCount, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, uint32_t instanceCount, uint32_t baseInstance) MTLPP_AVAILABLE(10_12, 10_0);
+        void DrawPatches(uint32_t numberOfPatchControlPoints, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, const Buffer& indirectBuffer, uint32_t indirectBufferOffset) MTLPP_AVAILABLE(10_12, NA);
+        void DrawIndexedPatches(uint32_t numberOfPatchControlPoints, uint32_t patchStart, uint32_t patchCount, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, const Buffer& controlPointIndexBuffer, uint32_t controlPointIndexBufferOffset, uint32_t instanceCount, uint32_t baseInstance) MTLPP_AVAILABLE(10_12, 10_0);
+        void DrawIndexedPatches(uint32_t numberOfPatchControlPoints, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, const Buffer& controlPointIndexBuffer, uint32_t controlPointIndexBufferOffset, const Buffer& indirectBuffer, uint32_t indirectBufferOffset) MTLPP_AVAILABLE(10_12, NA);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+
+//////////////////////////////////////
+// FILE: function_constant_values.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+// #include "argument.hpp"
+
+namespace mtlpp
+{
+    class FunctionConstantValues : public ns::Object
+    {
+    public:
+        FunctionConstantValues();
+        FunctionConstantValues(const ns::Handle& handle) : ns::Object(handle) { }
+
+        void SetConstantValue(const void* value, DataType type, uint32_t index);
+        void SetConstantValue(const void* value, DataType type, const ns::String& name);
+        void SetConstantValues(const void* value, DataType type, const ns::Range& range);
+
+        void Reset();
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+}
+
+//////////////////////////////////////
+// FILE: render_pipeline.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "device.hpp"
+// #include "render_command_encoder.hpp"
+// #include "render_pass.hpp"
+// #include "pixel_format.hpp"
+// #include "argument.hpp"
+// #include "function_constant_values.hpp"
+
+namespace mtlpp
+{
+    class VertexDescriptor;
+
+    enum class BlendFactor
+    {
+        Zero                                                = 0,
+        One                                                 = 1,
+        SourceColor                                         = 2,
+        OneMinusSourceColor                                 = 3,
+        SourceAlpha                                         = 4,
+        OneMinusSourceAlpha                                 = 5,
+        DestinationColor                                    = 6,
+        OneMinusDestinationColor                            = 7,
+        DestinationAlpha                                    = 8,
+        OneMinusDestinationAlpha                            = 9,
+        SourceAlphaSaturated                                = 10,
+        BlendColor                                          = 11,
+        OneMinusBlendColor                                  = 12,
+        BlendAlpha                                          = 13,
+        OneMinusBlendAlpha                                  = 14,
+        Source1Color             MTLPP_AVAILABLE_MAC(10_12) = 15,
+        OneMinusSource1Color     MTLPP_AVAILABLE_MAC(10_12) = 16,
+        Source1Alpha             MTLPP_AVAILABLE_MAC(10_12) = 17,
+        OneMinusSource1Alpha     MTLPP_AVAILABLE_MAC(10_12) = 18,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class BlendOperation
+    {
+        Add             = 0,
+        Subtract        = 1,
+        ReverseSubtract = 2,
+        Min             = 3,
+        Max             = 4,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class ColorWriteMask
+    {
+        None  = 0,
+        Red   = 0x1 << 3,
+        Green = 0x1 << 2,
+        Blue  = 0x1 << 1,
+        Alpha = 0x1 << 0,
+        All   = 0xf
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class PrimitiveTopologyClass
+    {
+        Unspecified = 0,
+        Point       = 1,
+        Line        = 2,
+        Triangle    = 3,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class TessellationPartitionMode
+    {
+        ModePow2           = 0,
+        ModeInteger        = 1,
+        ModeFractionalOdd  = 2,
+        ModeFractionalEven = 3,
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    enum class TessellationFactorStepFunction
+    {
+        Constant               = 0,
+        PerPatch               = 1,
+        PerInstance            = 2,
+        PerPatchAndPerInstance = 3,
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    enum class TessellationFactorFormat
+    {
+        Half = 0,
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    enum class TessellationControlPointIndexType
+    {
+        None   = 0,
+        UInt16 = 1,
+        UInt32 = 2,
+    }
+    MTLPP_AVAILABLE(10_12, 10_0);
+
+    class RenderPipelineColorAttachmentDescriptor : public ns::Object
+    {
+    public:
+        RenderPipelineColorAttachmentDescriptor();
+        RenderPipelineColorAttachmentDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        PixelFormat     GetPixelFormat() const;
+        bool            IsBlendingEnabled() const;
+        BlendFactor     GetSourceRgbBlendFactor() const;
+        BlendFactor     GetDestinationRgbBlendFactor() const;
+        BlendOperation  GetRgbBlendOperation() const;
+        BlendFactor     GetSourceAlphaBlendFactor() const;
+        BlendFactor     GetDestinationAlphaBlendFactor() const;
+        BlendOperation  GetAlphaBlendOperation() const;
+        ColorWriteMask  GetWriteMask() const;
+
+        void SetPixelFormat(PixelFormat pixelFormat);
+        void SetBlendingEnabled(bool blendingEnabled);
+        void SetSourceRgbBlendFactor(BlendFactor sourceRgbBlendFactor);
+        void SetDestinationRgbBlendFactor(BlendFactor destinationRgbBlendFactor);
+        void SetRgbBlendOperation(BlendOperation rgbBlendOperation);
+        void SetSourceAlphaBlendFactor(BlendFactor sourceAlphaBlendFactor);
+        void SetDestinationAlphaBlendFactor(BlendFactor destinationAlphaBlendFactor);
+        void SetAlphaBlendOperation(BlendOperation alphaBlendOperation);
+        void SetWriteMask(ColorWriteMask writeMask);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class RenderPipelineReflection : public ns::Object
+    {
+    public:
+        RenderPipelineReflection();
+        RenderPipelineReflection(const ns::Handle& handle) : ns::Object(handle) { }
+
+        const ns::Array<Argument> GetVertexArguments() const;
+        const ns::Array<Argument> GetFragmentArguments() const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class RenderPipelineDescriptor : public ns::Object
+    {
+    public:
+        RenderPipelineDescriptor();
+        RenderPipelineDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String                                         GetLabel() const;
+        Function                                           GetVertexFunction() const;
+        Function                                           GetFragmentFunction() const;
+        VertexDescriptor                                   GetVertexDescriptor() const;
+        uint32_t                                           GetSampleCount() const;
+        bool                                               IsAlphaToCoverageEnabled() const;
+        bool                                               IsAlphaToOneEnabled() const;
+        bool                                               IsRasterizationEnabled() const;
+        ns::Array<RenderPipelineColorAttachmentDescriptor> GetColorAttachments() const;
+        PixelFormat                                        GetDepthAttachmentPixelFormat() const;
+        PixelFormat                                        GetStencilAttachmentPixelFormat() const;
+        PrimitiveTopologyClass                             GetInputPrimitiveTopology() const MTLPP_AVAILABLE_MAC(10_11);
+        TessellationPartitionMode                          GetTessellationPartitionMode() const MTLPP_AVAILABLE(10_12, 10_0);
+        uint32_t                                           GetMaxTessellationFactor() const MTLPP_AVAILABLE(10_12, 10_0);
+        bool                                               IsTessellationFactorScaleEnabled() const MTLPP_AVAILABLE(10_12, 10_0);
+        TessellationFactorFormat                           GetTessellationFactorFormat() const MTLPP_AVAILABLE(10_12, 10_0);
+        TessellationControlPointIndexType                  GetTessellationControlPointIndexType() const MTLPP_AVAILABLE(10_12, 10_0);
+        TessellationFactorStepFunction                     GetTessellationFactorStepFunction() const MTLPP_AVAILABLE(10_12, 10_0);
+        Winding                                            GetTessellationOutputWindingOrder() const MTLPP_AVAILABLE(10_12, 10_0);
+
+
+        void SetLabel(const ns::String& label);
+        void SetVertexFunction(const Function& vertexFunction);
+        void SetFragmentFunction(const Function& fragmentFunction);
+        void SetVertexDescriptor(const VertexDescriptor& vertexDescriptor);
+        void SetSampleCount(uint32_t sampleCount);
+        void SetAlphaToCoverageEnabled(bool alphaToCoverageEnabled);
+        void SetAlphaToOneEnabled(bool alphaToOneEnabled);
+        void SetRasterizationEnabled(bool rasterizationEnabled);
+        void SetDepthAttachmentPixelFormat(PixelFormat depthAttachmentPixelFormat);
+        void SetStencilAttachmentPixelFormat(PixelFormat stencilAttachmentPixelFormat);
+        void SetInputPrimitiveTopology(PrimitiveTopologyClass inputPrimitiveTopology) MTLPP_AVAILABLE_MAC(10_11);
+        void SetTessellationPartitionMode(TessellationPartitionMode tessellationPartitionMode) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetMaxTessellationFactor(uint32_t maxTessellationFactor) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetTessellationFactorScaleEnabled(bool tessellationFactorScaleEnabled) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetTessellationFactorFormat(TessellationFactorFormat tessellationFactorFormat) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetTessellationControlPointIndexType(TessellationControlPointIndexType tessellationControlPointIndexType) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetTessellationFactorStepFunction(TessellationFactorStepFunction tessellationFactorStepFunction) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetTessellationOutputWindingOrder(Winding tessellationOutputWindingOrder) MTLPP_AVAILABLE(10_12, 10_0);
+
+        void Reset();
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class RenderPipelineState : public ns::Object
+    {
+    public:
+        RenderPipelineState() { }
+        RenderPipelineState(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String GetLabel() const;
+        Device     GetDevice() const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: vertex_descriptor.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+
+namespace mtlpp
+{
+    enum class VertexFormat
+    {
+        Invalid               = 0,
+
+        UChar2                = 1,
+        UChar3                = 2,
+        UChar4                = 3,
+
+        Char2                 = 4,
+        Char3                 = 5,
+        Char4                 = 6,
+
+        UChar2Normalized      = 7,
+        UChar3Normalized      = 8,
+        UChar4Normalized      = 9,
+
+        Char2Normalized       = 10,
+        Char3Normalized       = 11,
+        Char4Normalized       = 12,
+
+        UShort2               = 13,
+        UShort3               = 14,
+        UShort4               = 15,
+
+        Short2                = 16,
+        Short3                = 17,
+        Short4                = 18,
+
+        UShort2Normalized     = 19,
+        UShort3Normalized     = 20,
+        UShort4Normalized     = 21,
+
+        Short2Normalized      = 22,
+        Short3Normalized      = 23,
+        Short4Normalized      = 24,
+
+        Half2                 = 25,
+        Half3                 = 26,
+        Half4                 = 27,
+
+        Float                 = 28,
+        Float2                = 29,
+        Float3                = 30,
+        Float4                = 31,
+
+        Int                   = 32,
+        Int2                  = 33,
+        Int3                  = 34,
+        Int4                  = 35,
+
+        UInt                  = 36,
+        UInt2                 = 37,
+        UInt3                 = 38,
+        UInt4                 = 39,
+
+        Int1010102Normalized  = 40,
+        UInt1010102Normalized = 41,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class VertexStepFunction
+    {
+        Constant                                          = 0,
+        PerVertex                                         = 1,
+        PerInstance                                       = 2,
+        PerPatch             MTLPP_AVAILABLE(10_12, 10_0) = 3,
+        PerPatchControlPoint MTLPP_AVAILABLE(10_12, 10_0) = 4,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class VertexBufferLayoutDescriptor : public ns::Object
+    {
+    public:
+        VertexBufferLayoutDescriptor();
+        VertexBufferLayoutDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        uint32_t           GetStride() const;
+        VertexStepFunction GetStepFunction() const;
+        uint32_t           GetStepRate() const;
+
+        void SetStride(uint32_t stride);
+        void SetStepFunction(VertexStepFunction stepFunction);
+        void SetStepRate(uint32_t stepRate);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class VertexAttributeDescriptor : public ns::Object
+    {
+    public:
+        VertexAttributeDescriptor();
+        VertexAttributeDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        VertexFormat GetFormat() const;
+        uint32_t     GetOffset() const;
+        uint32_t     GetBufferIndex() const;
+
+        void SetFormat(VertexFormat format);
+        void SetOffset(uint32_t offset);
+        void SetBufferIndex(uint32_t bufferIndex);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class VertexDescriptor : public ns::Object
+    {
+    public:
+        VertexDescriptor();
+        VertexDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::Array<VertexBufferLayoutDescriptor> GetLayouts() const;
+        ns::Array<VertexAttributeDescriptor>    GetAttributes() const;
+
+        void Reset();
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+//////////////////////////////////////
+// FILE: parallel_render_command_encoder.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+// #include "render_pass.hpp"
+// #include "command_encoder.hpp"
+
+namespace mtlpp
+{
+    class RenderCommandEncoder;
+
+    class ParallelRenderCommandEncoder : public ns::Object
+    {
+    public:
+        ParallelRenderCommandEncoder() { }
+        ParallelRenderCommandEncoder(const ns::Handle& handle) : ns::Object(handle) { }
+
+        RenderCommandEncoder GetRenderCommandEncoder();
+
+        void SetColorStoreAction(StoreAction storeAction, uint32_t colorAttachmentIndex) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetDepthStoreAction(StoreAction storeAction) MTLPP_AVAILABLE(10_12, 10_0);
+        void SetStencilStoreAction(StoreAction storeAction) MTLPP_AVAILABLE(10_12, 10_0);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+
+//////////////////////////////////////
+// FILE: sampler.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "depth_stencil.hpp"
+// #include "device.hpp"
+
+namespace mtlpp
+{
+    enum class SamplerMinMagFilter
+    {
+        Nearest = 0,
+        Linear  = 1,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class SamplerMipFilter
+    {
+        NotMipmapped = 0,
+        Nearest      = 1,
+        Linear       = 2,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class SamplerAddressMode
+    {
+        ClampToEdge                                   = 0,
+        MirrorClampToEdge  MTLPP_AVAILABLE_MAC(10_11) = 1,
+        Repeat                                        = 2,
+        MirrorRepeat                                  = 3,
+        ClampToZero                                   = 4,
+        ClampToBorderColor MTLPP_AVAILABLE_MAC(10_12) = 5,
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    enum class SamplerBorderColor
+    {
+        TransparentBlack = 0,  // {0,0,0,0}
+        OpaqueBlack = 1,       // {0,0,0,1}
+        OpaqueWhite = 2,       // {1,1,1,1}
+    };
+
+    class SamplerDescriptor : public ns::Object
+    {
+    public:
+        SamplerDescriptor();
+        SamplerDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        SamplerMinMagFilter GetMinFilter() const;
+        SamplerMinMagFilter GetMagFilter() const;
+        SamplerMipFilter    GetMipFilter() const;
+        uint32_t            GetMaxAnisotropy() const;
+        SamplerAddressMode  GetSAddressMode() const;
+        SamplerAddressMode  GetTAddressMode() const;
+        SamplerAddressMode  GetRAddressMode() const;
+        SamplerBorderColor  GetBorderColor() const MTLPP_AVAILABLE_MAC(10_12);
+        bool                IsNormalizedCoordinates() const;
+        float               GetLodMinClamp() const;
+        float               GetLodMaxClamp() const;
+        CompareFunction     GetCompareFunction() const MTLPP_AVAILABLE(10_11, 9_0);
+        ns::String          GetLabel() const;
+
+        void SetMinFilter(SamplerMinMagFilter minFilter);
+        void SetMagFilter(SamplerMinMagFilter magFilter);
+        void SetMipFilter(SamplerMipFilter mipFilter);
+        void SetMaxAnisotropy(uint32_t maxAnisotropy);
+        void SetSAddressMode(SamplerAddressMode sAddressMode);
+        void SetTAddressMode(SamplerAddressMode tAddressMode);
+        void SetRAddressMode(SamplerAddressMode rAddressMode);
+        void SetBorderColor(SamplerBorderColor borderColor) MTLPP_AVAILABLE_MAC(10_12);
+        void SetNormalizedCoordinates(bool normalizedCoordinates);
+        void SetLodMinClamp(float lodMinClamp);
+        void SetLodMaxClamp(float lodMaxClamp);
+        void SetCompareFunction(CompareFunction compareFunction) MTLPP_AVAILABLE(10_11, 9_0);
+        void SetLabel(const ns::String& label);
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+
+    class SamplerState : public ns::Object
+    {
+    public:
+        SamplerState() { }
+        SamplerState(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String GetLabel() const;
+        Device     GetDevice() const;
+    }
+    MTLPP_AVAILABLE(10_11, 8_0);
+}
+
+
+//////////////////////////////////////
+// FILE: heap.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "ns.hpp"
+// #include "device.hpp"
+// #include "resource.hpp"
+// #include "buffer.hpp"
+// #include "texture.hpp"
+// #include "types.hpp"
+
+namespace mtlpp
+{
+    class HeapDescriptor : public ns::Object
+    {
+    public:
+        HeapDescriptor(const ns::Handle& handle) : ns::Object(handle) { }
+
+        uint32_t     GetSize() const;
+        StorageMode  GetStorageMode() const;
+        CpuCacheMode GetCpuCacheMode() const;
+
+        void SetSize(uint32_t size) const;
+        void SetStorageMode(StorageMode storageMode) const;
+        void SetCpuCacheMode(CpuCacheMode cpuCacheMode) const;
+    }
+    MTLPP_AVAILABLE(NA, 10_0);
+
+    class Heap : public ns::Object
+    {
+    public:
+        Heap(const ns::Handle& handle) : ns::Object(handle) { }
+
+        ns::String   GetLabel() const;
+        Device       GetDevice() const;
+        StorageMode  GetStorageMode() const;
+        CpuCacheMode GetCpuCacheMode() const;
+        uint32_t     GetSize() const;
+        uint32_t     GetUsedSize() const;
+
+        void SetLabel(const ns::String& label);
+
+        uint32_t MaxAvailableSizeWithAlignment(uint32_t alignment);
+        Buffer NewBuffer(uint32_t length, ResourceOptions options);
+        Texture NewTexture(const TextureDescriptor& desc);
+        PurgeableState SetPurgeableState(PurgeableState state);
+    }
+    MTLPP_AVAILABLE(NA, 10_0);
+}
+
+//////////////////////////////////////
+// FILE: mtlpp.hpp
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #pragma once
+
+// #include "defines.hpp"
+// #include "blit_command_encoder.hpp"
+// #include "buffer.hpp"
+// #include "command_buffer.hpp"
+// #include "compute_command_encoder.hpp"
+// #include "command_queue.hpp"
+// #include "device.hpp"
+// #include "depth_stencil.hpp"
+// #include "drawable.hpp"
+// #include "render_pass.hpp"
+// #include "compute_pipeline.hpp"
+// #include "library.hpp"
+// #include "pixel_format.hpp"
+// #include "render_pipeline.hpp"
+// #include "vertex_descriptor.hpp"
+// #include "parallel_render_command_encoder.hpp"
+// #include "render_command_encoder.hpp"
+// #include "sampler.hpp"
+// #include "texture.hpp"
+// #include "heap.hpp"
+

+ 4599 - 0
3rdparty/mtlpp/mtlpp.mm

@@ -0,0 +1,4599 @@
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+#include "mtlpp.hpp"
+
+//////////////////////////////////////
+// FILE: argument.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "argument.hpp"
+#include <Metal/MTLArgument.h>
+
+namespace mtlpp
+{
+    StructMember::StructMember() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLStructMember alloc] init] })
+    {
+    }
+
+    ns::String StructMember::GetName() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLStructMember*)m_ptr name] };
+    }
+
+    uint32_t StructMember::GetOffset() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLStructMember*)m_ptr offset]);
+    }
+
+    DataType StructMember::GetDataType() const
+    {
+        Validate();
+        return DataType([(__bridge MTLStructMember*)m_ptr dataType]);
+    }
+
+    StructType StructMember::GetStructType() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLStructMember*)m_ptr structType] };
+    }
+
+    ArrayType StructMember::GetArrayType() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLStructMember*)m_ptr arrayType] };
+    }
+
+    StructType::StructType() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLStructType alloc] init] })
+    {
+    }
+
+    const ns::Array<StructMember> StructType::GetMembers() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLStructType*)m_ptr members] };
+    }
+
+    StructMember StructType::GetMember(const ns::String& name) const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLStructType*)m_ptr memberByName:(__bridge NSString*)name.GetPtr()] };
+    }
+
+    ArrayType::ArrayType() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLArrayType alloc] init] })
+    {
+    }
+
+    uint32_t ArrayType::GetArrayLength() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLArrayType*)m_ptr arrayLength]);
+    }
+
+    DataType ArrayType::GetElementType() const
+    {
+        Validate();
+        return DataType([(__bridge MTLArrayType*)m_ptr elementType]);
+    }
+
+    uint32_t ArrayType::GetStride() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLArrayType*)m_ptr stride]);
+    }
+
+    StructType ArrayType::GetElementStructType() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLArrayType*)m_ptr elementStructType] };
+    }
+
+    ArrayType ArrayType::GetElementArrayType() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLArrayType*)m_ptr elementArrayType] };
+    }
+
+    Argument::Argument() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLArgument alloc] init] })
+    {
+    }
+
+    ns::String Argument::GetName() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLArgument*)m_ptr name] };
+    }
+
+    ArgumentType Argument::GetType() const
+    {
+        Validate();
+        return ArgumentType([(__bridge MTLArgument*)m_ptr type]);
+    }
+
+    ArgumentAccess Argument::GetAccess() const
+    {
+        Validate();
+        return ArgumentAccess([(__bridge MTLArgument*)m_ptr access]);
+    }
+
+    uint32_t Argument::GetIndex() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLArgument*)m_ptr index]);
+    }
+
+    bool Argument::IsActive() const
+    {
+        Validate();
+        return [(__bridge MTLArgument*)m_ptr isActive];
+    }
+
+    uint32_t Argument::GetBufferAlignment() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLArgument*)m_ptr bufferAlignment]);
+    }
+
+    uint32_t Argument::GetBufferDataSize() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLArgument*)m_ptr bufferDataSize]);
+    }
+
+    DataType Argument::GetBufferDataType() const
+    {
+        Validate();
+        return DataType([(__bridge MTLArgument*)m_ptr bufferDataType]);
+    }
+
+    StructType Argument::GetBufferStructType() const
+    {
+        Validate();
+        return StructType(ns::Handle { (__bridge void*)[(__bridge MTLArgument*)m_ptr bufferStructType] });
+    }
+
+    uint32_t Argument::GetThreadgroupMemoryAlignment() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLArgument*)m_ptr threadgroupMemoryAlignment]);
+    }
+
+    uint32_t Argument::GetThreadgroupMemoryDataSize() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLArgument*)m_ptr threadgroupMemoryDataSize]);
+    }
+
+    TextureType Argument::GetTextureType() const
+    {
+        Validate();
+        return TextureType([(__bridge MTLArgument*)m_ptr textureType]);
+    }
+
+    DataType Argument::GetTextureDataType() const
+    {
+        Validate();
+        return DataType([(__bridge MTLArgument*)m_ptr textureDataType]);
+    }
+
+    bool Argument::IsDepthTexture() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLArgument*)m_ptr isDepthTexture];
+#else
+        return false;
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: blit_command_encoder.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "blit_command_encoder.hpp"
+#include <Metal/MTLBlitCommandEncoder.h>
+
+namespace mtlpp
+{
+    void BlitCommandEncoder::Synchronize(const Resource& resource)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            synchronizeResource:(__bridge id<MTLResource>)resource.GetPtr()];
+#endif
+    }
+
+    void BlitCommandEncoder::Synchronize(const Texture& texture, uint32_t slice, uint32_t level)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            synchronizeTexture:(__bridge id<MTLTexture>)texture.GetPtr()
+            slice:slice
+            level:level];
+#endif
+    }
+
+    void BlitCommandEncoder::Copy(const Texture& sourceTexture, uint32_t sourceSlice, uint32_t sourceLevel, const Origin& sourceOrigin, const Size& sourceSize, const Texture& destinationTexture, uint32_t destinationSlice, uint32_t destinationLevel, const Origin& destinationOrigin)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            copyFromTexture:(__bridge id<MTLTexture>)sourceTexture.GetPtr()
+            sourceSlice:sourceSlice
+            sourceLevel:sourceLevel
+            sourceOrigin:MTLOriginMake(sourceOrigin.X, sourceOrigin.Y, sourceOrigin.Z)
+            sourceSize:MTLSizeMake(sourceSize.Width, sourceSize.Height, sourceSize.Depth)
+            toTexture:(__bridge id<MTLTexture>)destinationTexture.GetPtr()
+            destinationSlice:destinationSlice
+            destinationLevel:destinationLevel
+            destinationOrigin:MTLOriginMake(destinationOrigin.X, destinationOrigin.Y, destinationOrigin.Z)];
+    }
+
+    void BlitCommandEncoder::Copy(const Buffer& sourceBuffer, uint32_t sourceOffset, uint32_t sourceBytesPerRow, uint32_t sourceBytesPerImage, const Size& sourceSize, const Texture& destinationTexture, uint32_t destinationSlice, uint32_t destinationLevel, const Origin& destinationOrigin)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            copyFromBuffer:(__bridge id<MTLBuffer>)sourceBuffer.GetPtr()
+            sourceOffset:sourceOffset
+            sourceBytesPerRow:sourceBytesPerRow
+            sourceBytesPerImage:sourceBytesPerImage
+            sourceSize:MTLSizeMake(sourceSize.Width, sourceSize.Height, sourceSize.Depth)
+            toTexture:(__bridge id<MTLTexture>)destinationTexture.GetPtr()
+            destinationSlice:destinationSlice
+            destinationLevel:destinationLevel
+            destinationOrigin:MTLOriginMake(destinationOrigin.X, destinationOrigin.Y, destinationOrigin.Z)];
+    }
+
+    void BlitCommandEncoder::Copy(const Buffer& sourceBuffer, uint32_t sourceOffset, uint32_t sourceBytesPerRow, uint32_t sourceBytesPerImage, const Size& sourceSize, const Texture& destinationTexture, uint32_t destinationSlice, uint32_t destinationLevel, const Origin& destinationOrigin, BlitOption options)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            copyFromBuffer:(__bridge id<MTLBuffer>)sourceBuffer.GetPtr()
+            sourceOffset:sourceOffset
+            sourceBytesPerRow:sourceBytesPerRow
+            sourceBytesPerImage:sourceBytesPerImage
+            sourceSize:MTLSizeMake(sourceSize.Width, sourceSize.Height, sourceSize.Depth)
+            toTexture:(__bridge id<MTLTexture>)destinationTexture.GetPtr()
+            destinationSlice:destinationSlice
+            destinationLevel:destinationLevel
+            destinationOrigin:MTLOriginMake(destinationOrigin.X, destinationOrigin.Y, destinationOrigin.Z)
+            options:MTLBlitOption(options)];
+    }
+
+    void BlitCommandEncoder::Copy(const Texture& sourceTexture, uint32_t sourceSlice, uint32_t sourceLevel, const Origin& sourceOrigin, const Size& sourceSize, const Buffer& destinationBuffer, uint32_t destinationOffset, uint32_t destinationBytesPerRow, uint32_t destinationBytesPerImage)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            copyFromTexture:(__bridge id<MTLTexture>)sourceTexture.GetPtr()
+            sourceSlice:sourceSlice
+            sourceLevel:sourceLevel
+            sourceOrigin:MTLOriginMake(sourceOrigin.X, sourceOrigin.Y, sourceOrigin.Z)
+            sourceSize:MTLSizeMake(sourceSize.Width, sourceSize.Height, sourceSize.Depth)
+            toBuffer:(__bridge id<MTLBuffer>)destinationBuffer.GetPtr()
+            destinationOffset:destinationOffset
+            destinationBytesPerRow:destinationBytesPerRow
+            destinationBytesPerImage:destinationBytesPerImage];
+    }
+
+    void BlitCommandEncoder::Copy(const Texture& sourceTexture, uint32_t sourceSlice, uint32_t sourceLevel, const Origin& sourceOrigin, const Size& sourceSize, const Buffer& destinationBuffer, uint32_t destinationOffset, uint32_t destinationBytesPerRow, uint32_t destinationBytesPerImage, BlitOption options)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            copyFromTexture:(__bridge id<MTLTexture>)sourceTexture.GetPtr()
+            sourceSlice:sourceSlice
+            sourceLevel:sourceLevel
+            sourceOrigin:MTLOriginMake(sourceOrigin.X, sourceOrigin.Y, sourceOrigin.Z)
+            sourceSize:MTLSizeMake(sourceSize.Width, sourceSize.Height, sourceSize.Depth)
+            toBuffer:(__bridge id<MTLBuffer>)destinationBuffer.GetPtr()
+            destinationOffset:destinationOffset
+            destinationBytesPerRow:destinationBytesPerRow
+            destinationBytesPerImage:destinationBytesPerImage
+            options:MTLBlitOption(options)];
+    }
+
+    void BlitCommandEncoder::Copy(const Buffer& sourceBuffer, uint32_t sourceOffset, const Buffer& destinationBuffer, uint32_t destinationOffset, uint32_t size)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            copyFromBuffer:(__bridge id<MTLBuffer>)sourceBuffer.GetPtr()
+            sourceOffset:sourceOffset
+            toBuffer:(__bridge id<MTLBuffer>)destinationBuffer.GetPtr()
+            destinationOffset:destinationOffset
+            size:size];
+    }
+
+    void BlitCommandEncoder::GenerateMipmaps(const Texture& texture)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            generateMipmapsForTexture:(__bridge id<MTLTexture>)texture.GetPtr()];
+    }
+
+    void BlitCommandEncoder::Fill(const Buffer& buffer, const ns::Range& range, uint8_t value)
+    {
+        Validate();
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            fillBuffer:(__bridge id<MTLBuffer>)buffer.GetPtr()
+            range:NSMakeRange(range.Location, range.Length)
+            value:value];
+    }
+
+    void BlitCommandEncoder::UpdateFence(const Fence& fence)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            updateFence:(__bridge id<MTLFence>)fence.GetPtr()];
+#endif
+    }
+
+    void BlitCommandEncoder::WaitForFence(const Fence& fence)
+    {
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLBlitCommandEncoder>)m_ptr
+            waitForFence:(__bridge id<MTLFence>)fence.GetPtr()];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: buffer.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "buffer.hpp"
+// #include "texture.hpp"
+#include <Metal/MTLBuffer.h>
+
+namespace mtlpp
+{
+    uint32_t Buffer::GetLength() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLBuffer>)m_ptr length]);
+    }
+
+    void* Buffer::GetContents()
+    {
+        Validate();
+        return [(__bridge id<MTLBuffer>)m_ptr contents];
+    }
+
+    void Buffer::DidModify(const ns::Range& range)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        [(__bridge id<MTLBuffer>)m_ptr didModifyRange:NSMakeRange(range.Location, range.Length)];
+#endif
+    }
+
+    Texture Buffer::NewTexture(const TextureDescriptor& descriptor, uint32_t offset, uint32_t bytesPerRow)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(8_0)
+        MTLTextureDescriptor* mtlTextureDescriptor = (__bridge MTLTextureDescriptor*)descriptor.GetPtr();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLBuffer>)m_ptr newTextureWithDescriptor:mtlTextureDescriptor offset:offset bytesPerRow:bytesPerRow] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    void Buffer::AddDebugMarker(const ns::String& marker, const ns::Range& range)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLBuffer>)m_ptr addDebugMarker:(__bridge NSString*)marker.GetPtr() range:NSMakeRange(range.Location, range.Length)];
+#endif
+    }
+
+    void Buffer::RemoveAllDebugMarkers()
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLBuffer>)m_ptr removeAllDebugMarkers];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: command_buffer.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "command_buffer.hpp"
+// #include "command_queue.hpp"
+// #include "drawable.hpp"
+// #include "blit_command_encoder.hpp"
+// #include "render_command_encoder.hpp"
+// #include "compute_command_encoder.hpp"
+// #include "parallel_render_command_encoder.hpp"
+// #include "render_pass.hpp"
+
+#include <Metal/MTLCommandBuffer.h>
+
+namespace mtlpp
+{
+    Device CommandBuffer::GetDevice() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr device] };
+    }
+
+    CommandQueue CommandBuffer::GetCommandQueue() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr commandQueue] };
+    }
+
+    bool CommandBuffer::GetRetainedReferences() const
+    {
+        Validate();
+        return [(__bridge id<MTLCommandBuffer>)m_ptr retainedReferences];
+    }
+
+    ns::String CommandBuffer::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr label] };
+    }
+
+    CommandBufferStatus CommandBuffer::GetStatus() const
+    {
+        Validate();
+        return CommandBufferStatus([(__bridge id<MTLCommandBuffer>)m_ptr status]);
+    }
+
+    ns::Error CommandBuffer::GetError() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr error] };
+    }
+
+    void CommandBuffer::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    void CommandBuffer::Enqueue()
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr enqueue];
+    }
+
+    void CommandBuffer::Commit()
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr commit];
+    }
+
+    void CommandBuffer::AddScheduledHandler(std::function<void(const CommandBuffer&)> handler)
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr addScheduledHandler:^(id <MTLCommandBuffer> mtlCommandBuffer){
+            CommandBuffer commandBuffer(ns::Handle{ (__bridge void*)mtlCommandBuffer });
+            handler(commandBuffer);
+        }];
+    }
+
+    void CommandBuffer::AddCompletedHandler(std::function<void(const CommandBuffer&)> handler)
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr addCompletedHandler:^(id <MTLCommandBuffer> mtlCommandBuffer){
+            CommandBuffer commandBuffer(ns::Handle{ (__bridge void*)mtlCommandBuffer });
+            handler(commandBuffer);
+        }];
+    }
+
+    void CommandBuffer::Present(const Drawable& drawable)
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr presentDrawable:(__bridge id<MTLDrawable>)drawable.GetPtr()];
+    }
+
+    void CommandBuffer::Present(const Drawable& drawable, double presentationTime)
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr presentDrawable:(__bridge id<MTLDrawable>)drawable.GetPtr() atTime:presentationTime];
+    }
+
+    void CommandBuffer::WaitUntilScheduled()
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr waitUntilScheduled];
+    }
+
+    void CommandBuffer::WaitUntilCompleted()
+    {
+        Validate();
+        [(__bridge id<MTLCommandBuffer>)m_ptr waitUntilCompleted];
+    }
+
+    BlitCommandEncoder CommandBuffer::BlitCommandEncoder()
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr blitCommandEncoder] };
+    }
+
+    RenderCommandEncoder CommandBuffer::RenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor)
+    {
+        Validate();
+        MTLRenderPassDescriptor* mtlRenderPassDescriptor = (__bridge MTLRenderPassDescriptor*)renderPassDescriptor.GetPtr();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr renderCommandEncoderWithDescriptor:mtlRenderPassDescriptor] };
+    }
+
+    ComputeCommandEncoder CommandBuffer::ComputeCommandEncoder()
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr computeCommandEncoder] };
+    }
+
+    ParallelRenderCommandEncoder CommandBuffer::ParallelRenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor)
+    {
+        Validate();
+        MTLRenderPassDescriptor* mtlRenderPassDescriptor = (__bridge MTLRenderPassDescriptor*)renderPassDescriptor.GetPtr();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandBuffer>)m_ptr parallelRenderCommandEncoderWithDescriptor:mtlRenderPassDescriptor] };
+    }
+}
+
+//////////////////////////////////////
+// FILE: command_encoder.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "command_encoder.hpp"
+// #include "device.hpp"
+#include <Metal/MTLCommandEncoder.h>
+
+namespace mtlpp
+{
+    Device CommandEncoder::GetDevice() const
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLCommandEncoder>)m_ptr device] };
+    }
+
+    ns::String CommandEncoder::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandEncoder>)m_ptr label] };
+    }
+
+    void CommandEncoder::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge id<MTLCommandEncoder>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    void CommandEncoder::EndEncoding()
+    {
+        Validate();
+        [(__bridge id<MTLCommandEncoder>)m_ptr endEncoding];
+    }
+
+    void CommandEncoder::InsertDebugSignpost(const ns::String& string)
+    {
+        Validate();
+        [(__bridge id<MTLCommandEncoder>)m_ptr insertDebugSignpost:(__bridge NSString*)string.GetPtr()];
+    }
+
+    void CommandEncoder::PushDebugGroup(const ns::String& string)
+    {
+        Validate();
+        [(__bridge id<MTLCommandEncoder>)m_ptr pushDebugGroup:(__bridge NSString*)string.GetPtr()];
+    }
+
+    void CommandEncoder::PopDebugGroup()
+    {
+        Validate();
+        [(__bridge id<MTLCommandEncoder>)m_ptr popDebugGroup];
+    }
+}
+
+//////////////////////////////////////
+// FILE: command_queue.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "command_queue.hpp"
+// #include "command_buffer.hpp"
+// #include "device.hpp"
+#include <Metal/MTLCommandQueue.h>
+
+namespace mtlpp
+{
+    ns::String CommandQueue::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLCommandQueue>)m_ptr label] };
+    }
+
+    Device CommandQueue::GetDevice() const
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLCommandQueue>)m_ptr device] };
+    }
+
+    void CommandQueue::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge id<MTLCommandQueue>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    CommandBuffer CommandQueue::CommandBufferWithUnretainedReferences()
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLCommandQueue>)m_ptr commandBufferWithUnretainedReferences] };
+    }
+
+    CommandBuffer CommandQueue::CommandBuffer()
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLCommandQueue>)m_ptr commandBuffer] };
+    }
+
+    void CommandQueue::InsertDebugCaptureBoundary()
+    {
+        Validate();
+        [(__bridge id<MTLCommandQueue>)m_ptr insertDebugCaptureBoundary];
+    }
+}
+
+//////////////////////////////////////
+// FILE: compute_command_encoder.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "compute_command_encoder.hpp"
+// #include "buffer.hpp"
+// #include "compute_pipeline.hpp"
+// #include "sampler.hpp"
+#include <Metal/MTLComputeCommandEncoder.h>
+
+namespace mtlpp
+{
+    void ComputeCommandEncoder::SetComputePipelineState(const ComputePipelineState& state)
+    {
+        Validate();
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setComputePipelineState:(__bridge id<MTLComputePipelineState>)state.GetPtr()];
+    }
+
+    void ComputeCommandEncoder::SetBytes(const void* data, uint32_t length, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setBytes:data length:length atIndex:index];
+    }
+
+    void ComputeCommandEncoder::SetBuffer(const Buffer& buffer, uint32_t offset, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setBuffer:(__bridge id<MTLBuffer>)buffer.GetPtr() offset:offset atIndex:index];
+    }
+
+    void ComputeCommandEncoder::SetBufferOffset(uint32_t offset, uint32_t index)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 8_3)
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setBufferOffset:offset atIndex:index];
+#endif
+    }
+
+    void ComputeCommandEncoder::SetBuffers(const Buffer* buffers, const uint32_t* offsets, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxBuffers = 32;
+        assert(range.Length <= maxBuffers);
+
+        id<MTLBuffer> mtlBuffers[maxBuffers];
+        NSUInteger    nsOffsets[maxBuffers];
+        for (uint32_t i=0; i<range.Length; i++)
+        {
+            mtlBuffers[i] = (__bridge id<MTLBuffer>)buffers[i].GetPtr();
+            nsOffsets[i] = offsets[i];
+        }
+
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setBuffers:mtlBuffers
+                                                         offsets:nsOffsets
+                                                       withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void ComputeCommandEncoder::SetTexture(const Texture& texture, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setTexture:(__bridge id<MTLTexture>)texture.GetPtr() atIndex:index];
+    }
+
+    void ComputeCommandEncoder::SetTextures(const Texture* textures, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxTextures = 32;
+        assert(range.Length <= maxTextures);
+
+        id<MTLTexture> mtlTextures[maxTextures];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlTextures[i] = (__bridge id<MTLTexture>)textures[i].GetPtr();
+
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setTextures:mtlTextures
+                                                        withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void ComputeCommandEncoder::SetSamplerState(const SamplerState& sampler, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setSamplerState:(__bridge id<MTLSamplerState>)sampler.GetPtr() atIndex:index];
+    }
+
+    void ComputeCommandEncoder::SetSamplerStates(const SamplerState* samplers, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxStates = 32;
+        assert(range.Length <= maxStates);
+
+        id<MTLSamplerState> mtlStates[maxStates];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlStates[i] = (__bridge id<MTLSamplerState>)samplers[i].GetPtr();
+
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setSamplerStates:mtlStates
+                                                             withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void ComputeCommandEncoder::SetSamplerState(const SamplerState& sampler, float lodMinClamp, float lodMaxClamp, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setSamplerState:(__bridge id<MTLSamplerState>)sampler.GetPtr()
+                                                          lodMinClamp:lodMinClamp
+                                                          lodMaxClamp:lodMaxClamp
+                                                              atIndex:index];
+    }
+
+    void ComputeCommandEncoder::SetSamplerStates(const SamplerState* samplers, const float* lodMinClamps, const float* lodMaxClamps, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxStates = 32;
+        assert(range.Length <= maxStates);
+
+        id<MTLSamplerState> mtlStates[maxStates];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlStates[i] = (__bridge id<MTLSamplerState>)samplers[i].GetPtr();
+
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setSamplerStates:mtlStates
+                                                          lodMinClamps:lodMinClamps
+                                                          lodMaxClamps:lodMaxClamps
+                                                             withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void ComputeCommandEncoder::SetThreadgroupMemory(uint32_t length, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setThreadgroupMemoryLength:length atIndex:index];
+    }
+
+    void ComputeCommandEncoder::SetStageInRegion(const Region& region)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr setStageInRegion:MTLRegionMake3D(region.Origin.X, region.Origin.Y, region.Origin.Z, region.Size.Width, region.Size.Height, region.Size.Depth)];
+#endif
+    }
+
+    void ComputeCommandEncoder::DispatchThreadgroups(const Size& threadgroupsPerGrid, const Size& threadsPerThreadgroup)
+    {
+        Validate();
+        MTLSize mtlThreadgroupsPerGrid = MTLSizeMake(threadgroupsPerGrid.Width, threadgroupsPerGrid.Height, threadgroupsPerGrid.Depth);
+        MTLSize mtlThreadsPerThreadgroup = MTLSizeMake(threadsPerThreadgroup.Width, threadsPerThreadgroup.Height, threadsPerThreadgroup.Depth);
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr dispatchThreadgroups:mtlThreadgroupsPerGrid threadsPerThreadgroup:mtlThreadsPerThreadgroup];
+    }
+
+    void ComputeCommandEncoder::DispatchThreadgroupsWithIndirectBuffer(const Buffer& indirectBuffer, uint32_t indirectBufferOffset, const Size& threadsPerThreadgroup)
+    {
+        Validate();
+        MTLSize mtlThreadsPerThreadgroup = MTLSizeMake(threadsPerThreadgroup.Width, threadsPerThreadgroup.Height, threadsPerThreadgroup.Depth);
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr dispatchThreadgroupsWithIndirectBuffer:(__bridge id<MTLBuffer>)indirectBuffer.GetPtr()
+                                                                        indirectBufferOffset:indirectBufferOffset
+                                                                       threadsPerThreadgroup:mtlThreadsPerThreadgroup];
+    }
+
+    void ComputeCommandEncoder::UpdateFence(const Fence& fence)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr updateFence:(__bridge id<MTLFence>)fence.GetPtr()];
+#endif
+    }
+
+    void ComputeCommandEncoder::WaitForFence(const Fence& fence)
+    {
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLComputeCommandEncoder>)m_ptr waitForFence:(__bridge id<MTLFence>)fence.GetPtr()];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: compute_pipeline.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "compute_pipeline.hpp"
+#include <Metal/MTLComputePipeline.h>
+
+namespace mtlpp
+{
+    ComputePipelineReflection::ComputePipelineReflection() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLComputePipelineReflection alloc] init] })
+    {
+    }
+
+    ComputePipelineDescriptor::ComputePipelineDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLComputePipelineDescriptor alloc] init] })
+    {
+    }
+
+    ns::String ComputePipelineDescriptor::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLComputePipelineDescriptor*)m_ptr label] };
+    }
+
+    Function ComputePipelineDescriptor::GetComputeFunction() const
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge MTLComputePipelineDescriptor*)m_ptr computeFunction] };
+    }
+
+    bool ComputePipelineDescriptor::GetThreadGroupSizeIsMultipleOfThreadExecutionWidth() const
+    {
+        Validate();
+        return [(__bridge MTLComputePipelineDescriptor*)m_ptr threadGroupSizeIsMultipleOfThreadExecutionWidth];
+    }
+
+    StageInputOutputDescriptor ComputePipelineDescriptor::GetStageInputDescriptor() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle { (__bridge void*)[(__bridge MTLComputePipelineDescriptor*)m_ptr stageInputDescriptor] };
+#else
+        return ns::Handle { nullptr };
+#endif
+    }
+
+    void ComputePipelineDescriptor::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge MTLComputePipelineDescriptor*)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    void ComputePipelineDescriptor::SetComputeFunction(const Function& function)
+    {
+        Validate();
+        [(__bridge MTLComputePipelineDescriptor*)m_ptr setComputeFunction:(__bridge id<MTLFunction>)function.GetPtr()];
+    }
+
+    void ComputePipelineDescriptor::SetThreadGroupSizeIsMultipleOfThreadExecutionWidth(bool value)
+    {
+        Validate();
+        [(__bridge MTLComputePipelineDescriptor*)m_ptr setThreadGroupSizeIsMultipleOfThreadExecutionWidth:value];
+    }
+
+    void ComputePipelineDescriptor::SetStageInputDescriptor(const StageInputOutputDescriptor& stageInputDescriptor) const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLComputePipelineDescriptor*)m_ptr setStageInputDescriptor:(__bridge MTLStageInputOutputDescriptor*)stageInputDescriptor.GetPtr()];
+#endif
+    }
+
+    Device ComputePipelineState::GetDevice() const
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLComputePipelineState>)m_ptr device] };
+    }
+
+    uint32_t ComputePipelineState::GetMaxTotalThreadsPerThreadgroup() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLComputePipelineState>)m_ptr maxTotalThreadsPerThreadgroup]);
+    }
+
+    uint32_t ComputePipelineState::GetThreadExecutionWidth() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLComputePipelineState>)m_ptr threadExecutionWidth]);
+    }
+}
+
+//////////////////////////////////////
+// FILE: depth_stencil.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "depth_stencil.hpp"
+#include <Metal/MTLDepthStencil.h>
+
+namespace mtlpp
+{
+    StencilDescriptor::StencilDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLStencilDescriptor alloc] init] })
+    {
+    }
+
+    CompareFunction StencilDescriptor::GetStencilCompareFunction() const
+    {
+        Validate();
+        return CompareFunction([(__bridge MTLStencilDescriptor*)m_ptr stencilCompareFunction]);
+    }
+
+    StencilOperation StencilDescriptor::GetStencilFailureOperation() const
+    {
+        Validate();
+        return StencilOperation([(__bridge MTLStencilDescriptor*)m_ptr stencilFailureOperation]);
+    }
+
+    StencilOperation StencilDescriptor::GetDepthFailureOperation() const
+    {
+        Validate();
+        return StencilOperation([(__bridge MTLStencilDescriptor*)m_ptr depthFailureOperation]);
+    }
+
+    StencilOperation StencilDescriptor::GetDepthStencilPassOperation() const
+    {
+        Validate();
+        return StencilOperation([(__bridge MTLStencilDescriptor*)m_ptr depthStencilPassOperation]);
+    }
+
+    uint32_t StencilDescriptor::GetReadMask() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLStencilDescriptor*)m_ptr readMask]);
+    }
+
+    uint32_t StencilDescriptor::GetWriteMask() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLStencilDescriptor*)m_ptr writeMask]);
+    }
+
+    void StencilDescriptor::SetStencilCompareFunction(CompareFunction stencilCompareFunction)
+    {
+        Validate();
+        [(__bridge MTLStencilDescriptor*)m_ptr setStencilCompareFunction:MTLCompareFunction(stencilCompareFunction)];
+    }
+
+    void StencilDescriptor::SetStencilFailureOperation(StencilOperation stencilFailureOperation)
+    {
+        Validate();
+        [(__bridge MTLStencilDescriptor*)m_ptr setStencilFailureOperation:MTLStencilOperation(stencilFailureOperation)];
+    }
+
+    void StencilDescriptor::SetDepthFailureOperation(StencilOperation depthFailureOperation)
+    {
+        Validate();
+        [(__bridge MTLStencilDescriptor*)m_ptr setDepthFailureOperation:MTLStencilOperation(depthFailureOperation)];
+    }
+
+    void StencilDescriptor::SetDepthStencilPassOperation(StencilOperation depthStencilPassOperation)
+    {
+        Validate();
+        [(__bridge MTLStencilDescriptor*)m_ptr setDepthStencilPassOperation:MTLStencilOperation(depthStencilPassOperation)];
+    }
+
+    void StencilDescriptor::SetReadMask(uint32_t readMask)
+    {
+        Validate();
+        [(__bridge MTLStencilDescriptor*)m_ptr setReadMask:readMask];
+    }
+
+    void StencilDescriptor::SetWriteMask(uint32_t writeMask)
+    {
+        Validate();
+        [(__bridge MTLStencilDescriptor*)m_ptr setWriteMask:writeMask];
+    }
+
+    DepthStencilDescriptor::DepthStencilDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLDepthStencilDescriptor alloc] init] })
+    {
+    }
+
+    CompareFunction DepthStencilDescriptor::GetDepthCompareFunction() const
+    {
+        Validate();
+        return CompareFunction([(__bridge MTLDepthStencilDescriptor*)m_ptr depthCompareFunction]);
+    }
+
+    bool DepthStencilDescriptor::IsDepthWriteEnabled() const
+    {
+        Validate();
+        return [(__bridge MTLDepthStencilDescriptor*)m_ptr isDepthWriteEnabled];
+    }
+
+    StencilDescriptor DepthStencilDescriptor::GetFrontFaceStencil() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLDepthStencilDescriptor*)m_ptr frontFaceStencil] };
+    }
+
+    StencilDescriptor DepthStencilDescriptor::GetBackFaceStencil() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLDepthStencilDescriptor*)m_ptr backFaceStencil] };
+    }
+
+    ns::String DepthStencilDescriptor::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLDepthStencilDescriptor*)m_ptr label] };
+    }
+
+    void DepthStencilDescriptor::SetDepthCompareFunction(CompareFunction depthCompareFunction) const
+    {
+        Validate();
+        [(__bridge MTLDepthStencilDescriptor*)m_ptr setDepthCompareFunction:MTLCompareFunction(depthCompareFunction)];
+    }
+
+    void DepthStencilDescriptor::SetDepthWriteEnabled(bool depthWriteEnabled) const
+    {
+        Validate();
+        [(__bridge MTLDepthStencilDescriptor*)m_ptr setDepthWriteEnabled:depthWriteEnabled];
+    }
+
+    void DepthStencilDescriptor::SetFrontFaceStencil(const StencilDescriptor& frontFaceStencil) const
+    {
+        Validate();
+        [(__bridge MTLDepthStencilDescriptor*)m_ptr setFrontFaceStencil:(__bridge MTLStencilDescriptor*)frontFaceStencil.GetPtr()];
+    }
+
+    void DepthStencilDescriptor::SetBackFaceStencil(const StencilDescriptor& backFaceStencil) const
+    {
+        Validate();
+        [(__bridge MTLDepthStencilDescriptor*)m_ptr setBackFaceStencil:(__bridge MTLStencilDescriptor*)backFaceStencil.GetPtr()];
+    }
+
+    void DepthStencilDescriptor::SetLabel(const ns::String& label) const
+    {
+        Validate();
+        [(__bridge MTLDepthStencilDescriptor*)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    ns::String DepthStencilState::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDepthStencilState>)m_ptr label] };
+    }
+
+    Device DepthStencilState::GetDevice() const
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLDepthStencilState>)m_ptr device] };
+    }
+}
+
+//////////////////////////////////////
+// FILE: device.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "device.hpp"
+// #include "buffer.hpp"
+// #include "command_queue.hpp"
+// #include "compute_pipeline.hpp"
+// #include "depth_stencil.hpp"
+// #include "render_pipeline.hpp"
+// #include "sampler.hpp"
+// #include "texture.hpp"
+// #include "heap.hpp"
+#include <Metal/MTLDevice.h>
+
+namespace mtlpp
+{
+    CompileOptions::CompileOptions() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLCompileOptions alloc] init] })
+    {
+    }
+
+    Device Device::CreateSystemDefaultDevice()
+    {
+        return ns::Handle{ (__bridge void*)MTLCreateSystemDefaultDevice() };
+    }
+
+    ns::Array<Device> Device::CopyAllDevices()
+    {
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        return ns::Handle{ (__bridge void*)MTLCopyAllDevices() };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    ns::String Device::GetName() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr name] };
+    }
+
+    Size Device::GetMaxThreadsPerThreadgroup() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        MTLSize mtlSize = [(__bridge id<MTLDevice>)m_ptr maxThreadsPerThreadgroup];
+        return Size(uint32_t(mtlSize.width), uint32_t(mtlSize.height), uint32_t(mtlSize.depth));
+#else
+        return Size(0, 0, 0);
+#endif
+    }
+
+    bool Device::IsLowPower() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        return [(__bridge id<MTLDevice>)m_ptr isLowPower];
+#else
+        return false;
+#endif
+    }
+
+    bool Device::IsHeadless() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        return [(__bridge id<MTLDevice>)m_ptr isHeadless];
+#else
+        return false;
+#endif
+    }
+
+    uint64_t Device::GetRecommendedMaxWorkingSetSize() const
+    {
+#if MTLPP_IS_AVAILABLE_MAC(10_12)
+        return [(__bridge id<MTLDevice>)m_ptr recommendedMaxWorkingSetSize];
+#else
+        return 0;
+#endif
+    }
+
+    bool Device::IsDepth24Stencil8PixelFormatSupported() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        return [(__bridge id<MTLDevice>)m_ptr isDepth24Stencil8PixelFormatSupported];
+#else
+        return true;
+#endif
+    }
+
+    CommandQueue Device::NewCommandQueue()
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newCommandQueue] };
+    }
+
+    CommandQueue Device::NewCommandQueue(uint32_t maxCommandBufferCount)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newCommandQueueWithMaxCommandBufferCount:maxCommandBufferCount] };
+    }
+
+    SizeAndAlign Device::HeapTextureSizeAndAlign(const TextureDescriptor& desc)
+    {
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        MTLSizeAndAlign mtlSizeAndAlign = [(__bridge id<MTLDevice>)m_ptr heapTextureSizeAndAlignWithDescriptor:(__bridge MTLTextureDescriptor*)desc.GetPtr()];
+        return SizeAndAlign{ uint32_t(mtlSizeAndAlign.size), uint32_t(mtlSizeAndAlign.align) };
+#else
+        return SizeAndAlign{0, 0};
+#endif
+    }
+
+    SizeAndAlign Device::HeapBufferSizeAndAlign(uint32_t length, ResourceOptions options)
+    {
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        MTLSizeAndAlign mtlSizeAndAlign = [(__bridge id<MTLDevice>)m_ptr heapBufferSizeAndAlignWithLength:length options:MTLResourceOptions(options)];
+        return SizeAndAlign{ uint32_t(mtlSizeAndAlign.size), uint32_t(mtlSizeAndAlign.align) };
+#else
+        return SizeAndAlign{0, 0};
+#endif
+    }
+
+    Heap Device::NewHeap(const HeapDescriptor& descriptor)
+    {
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newHeapWithDescriptor:(__bridge MTLHeapDescriptor*)descriptor.GetPtr()] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    Buffer Device::NewBuffer(uint32_t length, ResourceOptions options)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newBufferWithLength:length options:MTLResourceOptions(options)] };
+    }
+
+    Buffer Device::NewBuffer(const void* pointer, uint32_t length, ResourceOptions options)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newBufferWithBytes:pointer length:length options:MTLResourceOptions(options)] };
+    }
+
+
+    Buffer Device::NewBuffer(void* pointer, uint32_t length, ResourceOptions options, std::function<void (void* pointer, uint32_t length)> deallocator)
+    {
+        Validate();
+        return ns::Handle{
+            (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newBufferWithBytesNoCopy:pointer
+                                                                             length:length
+                                                                            options:MTLResourceOptions(options)
+                                                                        deallocator:^(void* pointer, NSUInteger length) { deallocator(pointer, uint32_t(length)); }]
+        };
+    }
+
+    DepthStencilState Device::NewDepthStencilState(const DepthStencilDescriptor& descriptor)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newDepthStencilStateWithDescriptor:(__bridge MTLDepthStencilDescriptor*)descriptor.GetPtr()] };
+    }
+
+    Texture Device::NewTexture(const TextureDescriptor& descriptor)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newTextureWithDescriptor:(__bridge MTLTextureDescriptor*)descriptor.GetPtr()] };
+    }
+
+    //- (id <MTLTexture>)newTextureWithDescriptor:(MTLTextureDescriptor *)descriptor iosurface:(IOSurfaceRef)iosurface plane:(NSUInteger)plane NS_AVAILABLE_MAC(10_11);
+    SamplerState Device::NewSamplerState(const SamplerDescriptor& descriptor)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newSamplerStateWithDescriptor:(__bridge MTLSamplerDescriptor*)descriptor.GetPtr()] };
+    }
+
+    Library Device::NewDefaultLibrary()
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newDefaultLibrary] };
+    }
+
+    Library Device::NewLibrary(const ns::String& filepath, ns::Error* error)
+    {
+        Validate();
+        NSError* nsError = error ? (__bridge NSError*)error->GetPtr() : nullptr;
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newLibraryWithFile:(__bridge NSString*)filepath.GetPtr() error:&nsError] };
+    }
+
+    Library Device::NewLibrary(const char* source, const CompileOptions& options, ns::Error* error)
+    {
+        Validate();
+        NSString* nsSource = [NSString stringWithUTF8String:source];
+        NSError* nsError = error ? (__bridge NSError*)error->GetPtr() : nullptr;
+        return ns::Handle{
+            (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newLibraryWithSource:nsSource
+                                                                        options:(__bridge MTLCompileOptions*)options.GetPtr()
+                                                                          error:&nsError]
+        };
+    }
+
+    void Device::NewLibrary(const char* source, const CompileOptions& options, std::function<void(const Library&, const ns::Error&)> completionHandler)
+    {
+        Validate();
+        NSString* nsSource = [NSString stringWithUTF8String:source];
+        [(__bridge id<MTLDevice>)m_ptr newLibraryWithSource:nsSource
+                                                    options:(__bridge MTLCompileOptions*)options.GetPtr()
+                                          completionHandler:^(id <MTLLibrary> library, NSError * error) {
+                                                completionHandler(
+                                                    ns::Handle{ (__bridge void*)library },
+                                                    ns::Handle{ (__bridge void*)error });
+                                          }];
+    }
+
+    RenderPipelineState Device::NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, ns::Error* error)
+    {
+        Validate();
+        NSError* nsError = error ? (__bridge NSError*)error->GetPtr() : nullptr;
+        return ns::Handle{
+            (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newRenderPipelineStateWithDescriptor:(__bridge MTLRenderPipelineDescriptor*)descriptor.GetPtr()
+                                                                                          error:&nsError]
+        };
+    }
+
+    RenderPipelineState Device::NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, PipelineOption options, RenderPipelineReflection* outReflection, ns::Error* error)
+    {
+        Validate();
+        NSError* nsError = error ? (__bridge NSError*)error->GetPtr() : nullptr;
+        MTLRenderPipelineReflection* mtlReflection = outReflection ? (__bridge MTLRenderPipelineReflection*)outReflection->GetPtr() : nullptr;
+        return ns::Handle{
+            (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newRenderPipelineStateWithDescriptor:(__bridge MTLRenderPipelineDescriptor*)descriptor.GetPtr()
+                                                                                        options:MTLPipelineOption(options)
+                                                                                     reflection:&mtlReflection
+                                                                                          error:&nsError]
+        };
+    }
+
+    void Device::NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, std::function<void(const RenderPipelineState&, const ns::Error&)> completionHandler)
+    {
+        Validate();
+        [(__bridge id<MTLDevice>)m_ptr newRenderPipelineStateWithDescriptor:(__bridge MTLRenderPipelineDescriptor*)descriptor.GetPtr()
+                                                          completionHandler:^(id <MTLRenderPipelineState> renderPipelineState, NSError * error) {
+                                                              completionHandler(
+                                                                  ns::Handle{ (__bridge void*)renderPipelineState },
+                                                                  ns::Handle{ (__bridge void*)error }
+                                                              );
+                                                          }];
+    }
+
+    void Device::NewRenderPipelineState(const RenderPipelineDescriptor& descriptor, PipelineOption options, std::function<void(const RenderPipelineState&, const RenderPipelineReflection&, const ns::Error&)> completionHandler)
+    {
+        Validate();
+        [(__bridge id<MTLDevice>)m_ptr newRenderPipelineStateWithDescriptor:(__bridge MTLRenderPipelineDescriptor*)descriptor.GetPtr()
+                                                                    options:MTLPipelineOption(options)
+                                                          completionHandler:^(id <MTLRenderPipelineState> renderPipelineState, MTLRenderPipelineReflection * reflection, NSError * error) {
+                                                              completionHandler(
+                                                                  ns::Handle{ (__bridge void*)renderPipelineState },
+                                                                  ns::Handle{ (__bridge void*)reflection },
+                                                                  ns::Handle{ (__bridge void*)error }
+                                                              );
+                                                          }];
+    }
+
+    ComputePipelineState Device::NewComputePipelineState(const Function& computeFunction, ns::Error* error)
+    {
+        Validate();
+        NSError* nsError = error ? (__bridge NSError*)error->GetPtr() : nullptr;
+        return ns::Handle{
+            (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newComputePipelineStateWithFunction:(__bridge id<MTLFunction>)computeFunction.GetPtr()
+                                                                                         error:&nsError]
+        };
+    }
+
+    ComputePipelineState Device::NewComputePipelineState(const Function& computeFunction, PipelineOption options, ComputePipelineReflection& outReflection, ns::Error* error)
+    {
+        Validate();
+        return ns::Handle{ nullptr };
+    }
+
+    void Device::NewComputePipelineState(const Function& computeFunction, std::function<void(const ComputePipelineState&, const ns::Error&)> completionHandler)
+    {
+        Validate();
+        [(__bridge id<MTLDevice>)m_ptr newComputePipelineStateWithFunction:(__bridge id<MTLFunction>)computeFunction.GetPtr()
+                                                         completionHandler:^(id <MTLComputePipelineState> computePipelineState, NSError * error) {
+                                                             completionHandler(
+                                                                 ns::Handle{ (__bridge void*)computePipelineState },
+                                                                 ns::Handle{ (__bridge void*)error }
+                                                             );
+                                                         }];
+    }
+
+    void Device::NewComputePipelineState(const Function& computeFunction, PipelineOption options, std::function<void(const ComputePipelineState&, const ComputePipelineReflection&, const ns::Error&)> completionHandler)
+    {
+        Validate();
+        [(__bridge id<MTLDevice>)m_ptr newComputePipelineStateWithFunction:(__bridge id<MTLFunction>)computeFunction.GetPtr()
+                                                                   options:MTLPipelineOption(options)
+                                                         completionHandler:^(id <MTLComputePipelineState> computePipelineState, MTLComputePipelineReflection * reflection, NSError * error) {
+                                                             completionHandler(
+                                                                 ns::Handle{ (__bridge void*)computePipelineState },
+                                                                 ns::Handle{ (__bridge void*)reflection },
+                                                                 ns::Handle{ (__bridge void*)error }
+                                                             );
+                                                         }];
+    }
+
+    ComputePipelineState Device::NewComputePipelineState(const ComputePipelineDescriptor& descriptor, PipelineOption options, ComputePipelineReflection* outReflection, ns::Error* error)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        NSError* nsError = error ? (__bridge NSError*)error->GetPtr() : nullptr;
+        MTLComputePipelineReflection* mtlReflection = outReflection ? (__bridge MTLComputePipelineReflection*)outReflection->GetPtr() : nullptr;
+        return ns::Handle{
+            (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newComputePipelineStateWithDescriptor:(__bridge MTLComputePipelineDescriptor*)descriptor.GetPtr()
+                                                                                         options:MTLPipelineOption(options)
+                                                                                      reflection:&mtlReflection
+                                                                                           error:&nsError] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    void Device::NewComputePipelineState(const ComputePipelineDescriptor& descriptor, PipelineOption options, std::function<void(const ComputePipelineState&, const ComputePipelineReflection&, const ns::Error&)> completionHandler)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge id<MTLDevice>)m_ptr newComputePipelineStateWithDescriptor:(__bridge MTLComputePipelineDescriptor*)descriptor.GetPtr()
+                                                                     options:MTLPipelineOption(options)
+                                                         completionHandler:^(id <MTLComputePipelineState> computePipelineState, MTLComputePipelineReflection * reflection, NSError * error)
+                                                                    {
+                                                                        completionHandler(
+                                                                            ns::Handle{ (__bridge void*)computePipelineState },
+                                                                            ns::Handle{ (__bridge void*)reflection },
+                                                                            ns::Handle{ (__bridge void*)error });
+                                                                    }];
+#endif
+    }
+
+    Fence Device::NewFence()
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLDevice>)m_ptr newFence] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    bool Device::SupportsFeatureSet(FeatureSet featureSet) const
+    {
+        Validate();
+        return [(__bridge id<MTLDevice>)m_ptr supportsFeatureSet:MTLFeatureSet(featureSet)];
+    }
+
+    bool Device::SupportsTextureSampleCount(uint32_t sampleCount) const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return [(__bridge id<MTLDevice>)m_ptr supportsTextureSampleCount:sampleCount];
+#else
+        return true;
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: drawable.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "drawable.hpp"
+#include <Metal/MTLDrawable.h>
+
+namespace mtlpp
+{
+    void Drawable::Present()
+    {
+        Validate();
+        [(__bridge id<MTLDrawable>)m_ptr present];
+    }
+
+    void Drawable::Present(double presentationTime)
+    {
+        Validate();
+        [(__bridge id<MTLDrawable>)m_ptr presentAtTime:presentationTime];
+    }
+}
+
+//////////////////////////////////////
+// FILE: fence.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "fence.hpp"
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+#   include <Metal/MTLFence.h>
+#endif
+
+namespace mtlpp
+{
+    Texture Fence::GetDevice() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFence>)m_ptr device] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    ns::String Fence::GetLabel() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFence>)m_ptr label] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    void Fence::SetLabel(const ns::String& label)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLFence>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: function_constant_values.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "function_constant_values.hpp"
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+#   include <Metal/MTLFunctionConstantValues.h>
+#endif
+
+namespace mtlpp
+{
+    FunctionConstantValues::FunctionConstantValues() :
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLFunctionConstantValues alloc] init] })
+#else
+        ns::Object(ns::Handle{ nullptr })
+#endif
+    {
+    }
+
+    void FunctionConstantValues::SetConstantValue(const void* value, DataType type, uint32_t index)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLFunctionConstantValues*)m_ptr setConstantValue:value type:MTLDataType(type) atIndex:index];
+#endif
+    }
+
+    void FunctionConstantValues::SetConstantValue(const void* value, DataType type, const ns::String& name)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLFunctionConstantValues*)m_ptr setConstantValue:value type:MTLDataType(type) withName:(__bridge NSString*)name.GetPtr()];
+#endif
+    }
+
+    void FunctionConstantValues::SetConstantValues(const void* value, DataType type, const ns::Range& range)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLFunctionConstantValues*)m_ptr setConstantValues:value type:MTLDataType(type) withRange:NSMakeRange(range.Location, range.Length)];
+#endif
+    }
+
+    void FunctionConstantValues::Reset()
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLFunctionConstantValues*)m_ptr reset];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: heap.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "heap.hpp"
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+#   include <Metal/MTLHeap.h>
+#endif
+
+namespace mtlpp
+{
+    uint32_t HeapDescriptor::GetSize() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return uint32_t([(__bridge MTLHeapDescriptor*)m_ptr size]);
+#else
+        return 0;
+#endif
+
+    }
+
+    StorageMode HeapDescriptor::GetStorageMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return StorageMode([(__bridge MTLHeapDescriptor*)m_ptr storageMode]);
+#else
+        return StorageMode(0);
+#endif
+
+    }
+
+    CpuCacheMode HeapDescriptor::GetCpuCacheMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return CpuCacheMode([(__bridge MTLHeapDescriptor*)m_ptr cpuCacheMode]);
+#else
+        return CpuCacheMode(0);
+#endif
+
+    }
+
+    void HeapDescriptor::SetSize(uint32_t size) const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge MTLHeapDescriptor*)m_ptr setSize:size];
+#endif
+
+    }
+
+    void HeapDescriptor::SetStorageMode(StorageMode storageMode) const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge MTLHeapDescriptor*)m_ptr setStorageMode:MTLStorageMode(storageMode)];
+#endif
+
+    }
+
+    void HeapDescriptor::SetCpuCacheMode(CpuCacheMode cpuCacheMode) const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge MTLHeapDescriptor*)m_ptr setCpuCacheMode:MTLCPUCacheMode(cpuCacheMode)];
+#endif
+
+    }
+
+    ns::String Heap::GetLabel() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLHeap>)m_ptr label] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+
+    }
+
+    Device Heap::GetDevice() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLHeap>)m_ptr device] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+
+    }
+
+    StorageMode Heap::GetStorageMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return StorageMode([(__bridge id<MTLHeap>)m_ptr storageMode]);
+#else
+        return StorageMode(0);
+#endif
+
+    }
+
+    CpuCacheMode Heap::GetCpuCacheMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return CpuCacheMode([(__bridge id<MTLHeap>)m_ptr cpuCacheMode]);
+#else
+        return CpuCacheMode(0);
+#endif
+
+    }
+
+    uint32_t Heap::GetSize() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return uint32_t([(__bridge id<MTLHeap>)m_ptr size]);
+#else
+        return 0;
+#endif
+
+    }
+
+    uint32_t Heap::GetUsedSize() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return uint32_t([(__bridge id<MTLHeap>)m_ptr usedSize]);
+#else
+        return 0;
+#endif
+
+    }
+
+    void Heap::SetLabel(const ns::String& label)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLHeap>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+#endif
+
+    }
+
+    uint32_t Heap::MaxAvailableSizeWithAlignment(uint32_t alignment)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return uint32_t([(__bridge id<MTLHeap>)m_ptr maxAvailableSizeWithAlignment:alignment]);
+#else
+        return 0;
+#endif
+
+    }
+
+    Buffer Heap::NewBuffer(uint32_t length, ResourceOptions options)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLHeap>)m_ptr newBufferWithLength:length options:MTLResourceOptions(options)] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+
+    }
+
+    Texture Heap::NewTexture(const TextureDescriptor& desc)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLHeap>)m_ptr newTextureWithDescriptor:(__bridge MTLTextureDescriptor*)desc.GetPtr()] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+
+    }
+
+    PurgeableState Heap::SetPurgeableState(PurgeableState state)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return PurgeableState([(__bridge id<MTLHeap>)m_ptr setPurgeableState:MTLPurgeableState(state)]);
+#else
+        return PurgeableState(0);
+#endif
+
+    }
+}
+
+//////////////////////////////////////
+// FILE: library.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "library.hpp"
+// #include "device.hpp"
+// #include "function_constant_values.hpp"
+#include <Metal/MTLLibrary.h>
+
+namespace mtlpp
+{
+    VertexAttribute::VertexAttribute() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLVertexAttribute alloc] init] })
+    {
+    }
+
+    ns::String VertexAttribute::GetName() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLVertexAttribute*)m_ptr name] };
+    }
+
+    uint32_t VertexAttribute::GetAttributeIndex() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLVertexAttribute*)m_ptr attributeIndex]);
+    }
+
+    DataType VertexAttribute::GetAttributeType() const
+    {
+        Validate();
+        return DataType([(__bridge MTLVertexAttribute*)m_ptr attributeType]);
+    }
+
+    bool VertexAttribute::IsActive() const
+    {
+        Validate();
+        return [(__bridge MTLVertexAttribute*)m_ptr isActive];
+    }
+
+    bool VertexAttribute::IsPatchData() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLVertexAttribute*)m_ptr isActive];
+#else
+        return false;
+#endif
+    }
+
+    bool VertexAttribute::IsPatchControlPointData() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLVertexAttribute*)m_ptr isActive];
+#else
+        return false;
+#endif
+    }
+
+    Attribute::Attribute() :
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLAttribute alloc] init] })
+#else
+        ns::Object(ns::Handle{ nullptr })
+#endif
+    {
+    }
+
+    ns::String Attribute::GetName() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge MTLAttribute*)m_ptr name] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    uint32_t Attribute::GetAttributeIndex() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLAttribute*)m_ptr attributeIndex]);
+#else
+        return 0;
+#endif
+    }
+
+    DataType Attribute::GetAttributeType() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return DataType([(__bridge MTLAttribute*)m_ptr attributeType]);
+#else
+        return DataType(0);
+#endif
+    }
+
+    bool Attribute::IsActive() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLAttribute*)m_ptr isActive];
+#else
+        return false;
+#endif
+    }
+
+    bool Attribute::IsPatchData() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLAttribute*)m_ptr isActive];
+#else
+        return false;
+#endif
+    }
+
+    bool Attribute::IsPatchControlPointData() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLAttribute*)m_ptr isActive];
+#else
+        return false;
+#endif
+    }
+
+    FunctionConstant::FunctionConstant() :
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLFunctionConstant alloc] init] })
+#else
+        ns::Object(ns::Handle{ nullptr })
+#endif
+    {
+    }
+
+    ns::String FunctionConstant::GetName() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge MTLFunctionConstant*)m_ptr name] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    DataType FunctionConstant::GetType() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return DataType([(__bridge MTLFunctionConstant*)m_ptr type]);
+#else
+        return DataType(0);
+#endif
+    }
+
+    uint32_t FunctionConstant::GetIndex() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLFunctionConstant*)m_ptr index]);
+#else
+        return 0;
+#endif
+    }
+
+    bool FunctionConstant::IsRequired() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLFunctionConstant*)m_ptr required];
+#else
+        return false;
+#endif
+    }
+
+    ns::String Function::GetLabel() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFunction>)m_ptr label] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    Device Function::GetDevice() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFunction>)m_ptr device] };
+    }
+
+    FunctionType Function::GetFunctionType() const
+    {
+        Validate();
+        return FunctionType([(__bridge id<MTLFunction>)m_ptr functionType]);
+    }
+
+    PatchType Function::GetPatchType() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return PatchType([(__bridge id<MTLFunction>)m_ptr patchType]);
+#else
+        return PatchType(0);
+#endif
+    }
+
+    int32_t Function::GetPatchControlPointCount() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return int32_t([(__bridge id<MTLFunction>)m_ptr patchControlPointCount]);
+#else
+        return 0;
+#endif
+    }
+
+    const ns::Array<VertexAttribute> Function::GetVertexAttributes() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFunction>)m_ptr vertexAttributes] };
+    }
+
+    const ns::Array<Attribute> Function::GetStageInputAttributes() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFunction>)m_ptr stageInputAttributes] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    ns::String Function::GetName() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFunction>)m_ptr name] };
+    }
+
+    ns::Dictionary<ns::String, FunctionConstant> Function::GetFunctionConstants() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLFunction>)m_ptr functionConstantsDictionary] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    void Function::SetLabel(const ns::String& label)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLFunction>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+#endif
+    }
+
+    ns::Dictionary<ns::String, ns::String> CompileOptions::GetPreprocessorMacros() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLCompileOptions*)m_ptr preprocessorMacros] };
+    }
+
+    bool CompileOptions::IsFastMathEnabled() const
+    {
+        Validate();
+        return [(__bridge MTLCompileOptions*)m_ptr fastMathEnabled];
+    }
+
+    LanguageVersion CompileOptions::GetLanguageVersion() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return LanguageVersion([(__bridge MTLCompileOptions*)m_ptr languageVersion]);
+#else
+        return LanguageVersion::Version1_0;
+#endif
+    }
+
+    void CompileOptions::SetFastMathEnabled(bool fastMathEnabled)
+    {
+        Validate();
+        [(__bridge MTLCompileOptions*)m_ptr setFastMathEnabled:fastMathEnabled];
+    }
+
+    void CompileOptions::SetFastMathEnabled(LanguageVersion languageVersion)
+    {
+        Validate();
+        [(__bridge MTLCompileOptions*)m_ptr setFastMathEnabled:MTLLanguageVersion(languageVersion)];
+    }
+
+    ns::String Library::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLLibrary>)m_ptr label] };
+    }
+
+    void Library::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge id<MTLLibrary>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    ns::Array<ns::String> Library::GetFunctionNames() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLLibrary>)m_ptr functionNames] };
+    }
+
+    Function Library::NewFunction(const ns::String& functionName)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLLibrary>)m_ptr newFunctionWithName:(__bridge NSString*)functionName.GetPtr()] };
+    }
+
+    Function Library::NewFunction(const ns::String& functionName, const FunctionConstantValues& constantValues, ns::Error* error)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        NSError* nsError = error ? (__bridge NSError*)error->GetPtr() : nullptr;
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLLibrary>)m_ptr
+                                            newFunctionWithName:(__bridge NSString*)functionName.GetPtr()
+                                            constantValues:(__bridge MTLFunctionConstantValues*)constantValues.GetPtr()
+                                            error:&nsError] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    void Library::NewFunction(const ns::String& functionName, const FunctionConstantValues& constantValues, std::function<void(const Function&, const ns::Error&)> completionHandler)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLLibrary>)m_ptr
+             newFunctionWithName:(__bridge NSString*)functionName.GetPtr()
+             constantValues:(__bridge MTLFunctionConstantValues*)constantValues.GetPtr()
+             completionHandler:^(id <MTLFunction> mtlFunction, NSError* error){
+                 completionHandler(ns::Handle{ (__bridge void*)mtlFunction }, ns::Handle{ (__bridge void*)error });
+             }];
+#endif
+    }
+
+}
+
+//////////////////////////////////////
+// FILE: ns.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "ns.hpp"
+#include <CoreFoundation/CFBase.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSError.h>
+#include <Foundation/NSArray.h>
+#include <cstring>
+
+namespace ns
+{
+    Object::Object() :
+        m_ptr(nullptr)
+    {
+    }
+
+    Object::Object(const Handle& handle) :
+        m_ptr(handle.ptr)
+    {
+        if (m_ptr)
+            CFRetain(m_ptr);
+    }
+
+    Object::Object(const Object& rhs) :
+        m_ptr(rhs.m_ptr)
+    {
+        if (m_ptr)
+            CFRetain(m_ptr);
+    }
+
+#if MTLPP_CONFIG_RVALUE_REFERENCES
+    Object::Object(Object&& rhs) :
+        m_ptr(rhs.m_ptr)
+    {
+        rhs.m_ptr = nullptr;
+    }
+#endif
+
+    Object::~Object()
+    {
+        if (m_ptr)
+            CFRelease(m_ptr);
+    }
+
+    Object& Object::operator=(const Object& rhs)
+    {
+        if (rhs.m_ptr == m_ptr)
+            return *this;
+        if (rhs.m_ptr)
+            CFRetain(rhs.m_ptr);
+        if (m_ptr)
+            CFRelease(m_ptr);
+        m_ptr = rhs.m_ptr;
+        return *this;
+    }
+
+#if MTLPP_CONFIG_RVALUE_REFERENCES
+    Object& Object::operator=(Object&& rhs)
+    {
+        if (rhs.m_ptr == m_ptr)
+            return *this;
+        if (m_ptr)
+            CFRelease(m_ptr);
+        m_ptr = rhs.m_ptr;
+        rhs.m_ptr = nullptr;
+        return *this;
+    }
+#endif
+
+    const uint32_t ArrayBase::GetSize() const
+    {
+        Validate();
+        return uint32_t([(__bridge NSArray*)m_ptr count]);
+    }
+
+    void* ArrayBase::GetItem(uint32_t index) const
+    {
+        Validate();
+        return (__bridge void*)[(__bridge NSArray*)m_ptr objectAtIndexedSubscript:index];
+    }
+
+    String::String(const char* cstr) :
+        Object(Handle{ (__bridge void*)[NSString stringWithUTF8String:cstr] })
+    {
+    }
+
+    const char* String::GetCStr() const
+    {
+        Validate();
+        return [(__bridge NSString*)m_ptr cStringUsingEncoding:NSUTF8StringEncoding];
+    }
+
+    uint32_t String::GetLength() const
+    {
+        Validate();
+        return uint32_t([(__bridge NSString*)m_ptr length]);
+    }
+
+    Error::Error() :
+        Object(Handle{ (__bridge void*)[[NSError alloc] init] })
+    {
+
+    }
+
+    String Error::GetDomain() const
+    {
+        Validate();
+        return Handle{ (__bridge void*)[(__bridge NSError*)m_ptr domain] };
+    }
+
+    uint32_t Error::GetCode() const
+    {
+        Validate();
+        return uint32_t([(__bridge NSError*)m_ptr code]);
+    }
+
+    //@property (readonly, copy) NSDictionary *userInfo;
+
+    String Error::GetLocalizedDescription() const
+    {
+        Validate();
+        return Handle{ (__bridge void*)[(__bridge NSError*)m_ptr localizedDescription] };
+    }
+
+    String Error::GetLocalizedFailureReason() const
+    {
+        Validate();
+        return Handle{ (__bridge void*)[(__bridge NSError*)m_ptr localizedFailureReason] };
+    }
+
+    String Error::GetLocalizedRecoverySuggestion() const
+    {
+        Validate();
+        return Handle{ (__bridge void*)[(__bridge NSError*)m_ptr localizedRecoverySuggestion] };
+    }
+
+    String Error::GetLocalizedRecoveryOptions() const
+    {
+        Validate();
+        return Handle{ (__bridge void*)[(__bridge NSError*)m_ptr localizedRecoveryOptions] };
+    }
+
+    //@property (nullable, readonly, strong) id recoveryAttempter;
+
+    String Error::GetHelpAnchor() const
+    {
+        Validate();
+        return Handle{ (__bridge void*)[(__bridge NSError*)m_ptr helpAnchor] };
+    }
+}
+
+//////////////////////////////////////
+// FILE: parallel_render_command_encoder.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "parallel_render_command_encoder.hpp"
+// #include "render_command_encoder.hpp"
+#include <Metal/MTLParallelRenderCommandEncoder.h>
+
+namespace mtlpp
+{
+    RenderCommandEncoder ParallelRenderCommandEncoder::GetRenderCommandEncoder()
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLParallelRenderCommandEncoder>)m_ptr renderCommandEncoder] };
+    }
+
+    void ParallelRenderCommandEncoder::SetColorStoreAction(StoreAction storeAction, uint32_t colorAttachmentIndex)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLParallelRenderCommandEncoder>)m_ptr setColorStoreAction:MTLStoreAction(storeAction) atIndex:colorAttachmentIndex];
+#endif
+    }
+
+    void ParallelRenderCommandEncoder::SetDepthStoreAction(StoreAction storeAction)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLParallelRenderCommandEncoder>)m_ptr setDepthStoreAction:MTLStoreAction(storeAction)];
+#endif
+    }
+
+    void ParallelRenderCommandEncoder::SetStencilStoreAction(StoreAction storeAction)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLParallelRenderCommandEncoder>)m_ptr setStencilStoreAction:MTLStoreAction(storeAction)];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: render_command_encoder.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "render_command_encoder.hpp"
+// #include "buffer.hpp"
+// #include "depth_stencil.hpp"
+// #include "render_pipeline.hpp"
+// #include "sampler.hpp"
+// #include "texture.hpp"
+#include <Metal/MTLRenderCommandEncoder.h>
+#include <Metal/MTLBuffer.h>
+
+namespace mtlpp
+{
+    void RenderCommandEncoder::SetRenderPipelineState(const RenderPipelineState& pipelineState)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setRenderPipelineState:(__bridge id<MTLRenderPipelineState>)pipelineState.GetPtr()];
+    }
+
+    void RenderCommandEncoder::SetVertexData(const void* bytes, uint32_t length, uint32_t index)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 8_3)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexBytes:bytes length:length atIndex:index];
+#endif
+    }
+
+    void RenderCommandEncoder::SetVertexBuffer(const Buffer& buffer, uint32_t offset, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexBuffer:(__bridge id<MTLBuffer>)buffer.GetPtr()
+                                                              offset:offset
+                                                             atIndex:index];
+    }
+    void RenderCommandEncoder::SetVertexBufferOffset(uint32_t offset, uint32_t index)
+    {
+#if MTLPP_IS_AVAILABLE(10_11, 8_3)
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexBufferOffset:offset atIndex:index];
+#endif
+    }
+
+    void RenderCommandEncoder::SetVertexBuffers(const Buffer* buffers, const uint32_t* offsets, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxBuffers = 32;
+        assert(range.Length <= maxBuffers);
+
+        id<MTLBuffer> mtlBuffers[maxBuffers];
+        NSUInteger    nsOffsets[maxBuffers];
+        for (uint32_t i=0; i<range.Length; i++)
+        {
+            mtlBuffers[i] = (__bridge id<MTLBuffer>)buffers[i].GetPtr();
+            nsOffsets[i] = offsets[i];
+        }
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexBuffers:mtlBuffers offsets:nsOffsets withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetVertexTexture(const Texture& texture, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexTexture:(__bridge id<MTLTexture>)texture.GetPtr()
+                                                              atIndex:index];
+    }
+
+
+    void RenderCommandEncoder::SetVertexTextures(const Texture* textures, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxTextures = 32;
+        assert(range.Length <= maxTextures);
+
+        id<MTLTexture> mtlTextures[maxTextures];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlTextures[i] = (__bridge id<MTLTexture>)textures[i].GetPtr();
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexTextures:mtlTextures withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetVertexSamplerState(const SamplerState& sampler, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexSamplerState:(__bridge id<MTLSamplerState>)sampler.GetPtr()
+                                                                   atIndex:index];
+
+    }
+
+    void RenderCommandEncoder::SetVertexSamplerStates(const SamplerState* samplers, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxStates = 32;
+        assert(range.Length <= maxStates);
+
+        id<MTLSamplerState> mtlStates[maxStates];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlStates[i] = (__bridge id<MTLSamplerState>)samplers[i].GetPtr();
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexSamplerStates:mtlStates withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetVertexSamplerState(const SamplerState& sampler, float lodMinClamp, float lodMaxClamp, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexSamplerState:(__bridge id<MTLSamplerState>)sampler.GetPtr()
+                                                               lodMinClamp:lodMinClamp
+                                                               lodMaxClamp:lodMaxClamp
+                                                                   atIndex:index];
+    }
+
+    void RenderCommandEncoder::SetVertexSamplerStates(const SamplerState* samplers, const float* lodMinClamps, const float* lodMaxClamps, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxStates = 32;
+        assert(range.Length <= maxStates);
+
+        id<MTLSamplerState> mtlStates[maxStates];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlStates[i] = (__bridge id<MTLSamplerState>)samplers[i].GetPtr();
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVertexSamplerStates:mtlStates
+                                                               lodMinClamps:lodMinClamps
+                                                               lodMaxClamps:lodMaxClamps
+                                                                  withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetViewport(const Viewport& viewport)
+    {
+        Validate();
+        MTLViewport mtlViewport = { viewport.OriginX, viewport.OriginY, viewport.Width, viewport.Height, viewport.ZNear, viewport.ZFar };
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setViewport:mtlViewport];
+    }
+
+    void RenderCommandEncoder::SetFrontFacingWinding(Winding frontFacingWinding)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFrontFacingWinding:MTLWinding(frontFacingWinding)];
+    }
+
+    void RenderCommandEncoder::SetCullMode(CullMode cullMode)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setCullMode:MTLCullMode(cullMode)];
+    }
+
+    void RenderCommandEncoder::SetDepthClipMode(DepthClipMode depthClipMode)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setDepthClipMode:MTLDepthClipMode(depthClipMode)];
+#endif
+    }
+
+    void RenderCommandEncoder::SetDepthBias(float depthBias, float slopeScale, float clamp)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setDepthBias:depthBias slopeScale:slopeScale clamp:clamp];
+    }
+
+    void RenderCommandEncoder::SetScissorRect(const ScissorRect& rect)
+    {
+        Validate();
+        MTLScissorRect mtlRect { rect.X, rect.Y, rect.Width, rect.Height };
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setScissorRect:mtlRect];
+    }
+
+    void RenderCommandEncoder::SetTriangleFillMode(TriangleFillMode fillMode)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setTriangleFillMode:MTLTriangleFillMode(fillMode)];
+    }
+
+    void RenderCommandEncoder::SetFragmentData(const void* bytes, uint32_t length, uint32_t index)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 8_3)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentBytes:bytes
+                                                               length:length
+                                                              atIndex:index];
+#endif
+    }
+
+    void RenderCommandEncoder::SetFragmentBuffer(const Buffer& buffer, uint32_t offset, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentBuffer:(__bridge id<MTLBuffer>)buffer.GetPtr()
+                                                                offset:offset
+                                                               atIndex:index];
+    }
+
+    void RenderCommandEncoder::SetFragmentBufferOffset(uint32_t offset, uint32_t index)
+    {
+#if MTLPP_IS_AVAILABLE(10_11, 8_3)
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentBufferOffset:offset atIndex:index];
+#endif
+    }
+
+    void RenderCommandEncoder::SetFragmentBuffers(const Buffer* buffers, const uint32_t* offsets, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxBuffers = 32;
+        assert(range.Length <= maxBuffers);
+
+        id<MTLBuffer> mtlBuffers[maxBuffers];
+        NSUInteger    nsOffsets[maxBuffers];
+        for (uint32_t i=0; i<range.Length; i++)
+        {
+            mtlBuffers[i] = (__bridge id<MTLBuffer>)buffers[i].GetPtr();
+            nsOffsets[i] = offsets[i];
+        }
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentBuffers:mtlBuffers offsets:nsOffsets withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetFragmentTexture(const Texture& texture, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentTexture:(__bridge id<MTLTexture>)texture.GetPtr()
+                                                                atIndex:index];
+    }
+
+    void RenderCommandEncoder::SetFragmentTextures(const Texture* textures, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxTextures = 32;
+        assert(range.Length <= maxTextures);
+
+        id<MTLTexture> mtlTextures[maxTextures];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlTextures[i] = (__bridge id<MTLTexture>)textures[i].GetPtr();
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentTextures:mtlTextures withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetFragmentSamplerState(const SamplerState& sampler, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentSamplerState:(__bridge id<MTLSamplerState>)sampler.GetPtr()
+                                                                     atIndex:index];
+    }
+
+    void RenderCommandEncoder::SetFragmentSamplerStates(const SamplerState* samplers, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxStates = 32;
+        assert(range.Length <= maxStates);
+
+        id<MTLSamplerState> mtlStates[maxStates];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlStates[i] = (__bridge id<MTLSamplerState>)samplers[i].GetPtr();
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentSamplerStates:mtlStates withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetFragmentSamplerState(const SamplerState& sampler, float lodMinClamp, float lodMaxClamp, uint32_t index)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentSamplerState:(__bridge id<MTLSamplerState>)sampler.GetPtr()
+                                                                 lodMinClamp:lodMinClamp
+                                                                 lodMaxClamp:lodMaxClamp
+                                                                     atIndex:index];
+    }
+
+    void RenderCommandEncoder::SetFragmentSamplerStates(const SamplerState* samplers, const float* lodMinClamps, const float* lodMaxClamps, const ns::Range& range)
+    {
+        Validate();
+
+        const uint32_t maxStates = 32;
+        assert(range.Length <= maxStates);
+
+        id<MTLSamplerState> mtlStates[maxStates];
+        for (uint32_t i=0; i<range.Length; i++)
+            mtlStates[i] = (__bridge id<MTLSamplerState>)samplers[i].GetPtr();
+
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setFragmentSamplerStates:mtlStates
+                                                                 lodMinClamps:lodMinClamps
+                                                                 lodMaxClamps:lodMaxClamps
+                                                                    withRange:NSMakeRange(range.Location, range.Length)];
+    }
+
+    void RenderCommandEncoder::SetBlendColor(float red, float green, float blue, float alpha)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setBlendColorRed:red green:green blue:blue alpha:alpha];
+    }
+
+    void RenderCommandEncoder::SetDepthStencilState(const DepthStencilState& depthStencilState)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setDepthStencilState:(__bridge id<MTLDepthStencilState>)depthStencilState.GetPtr()];
+    }
+
+    void RenderCommandEncoder::SetStencilReferenceValue(uint32_t referenceValue)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setStencilReferenceValue:referenceValue];
+    }
+
+    void RenderCommandEncoder::SetStencilReferenceValue(uint32_t frontReferenceValue, uint32_t backReferenceValue)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setStencilFrontReferenceValue:frontReferenceValue backReferenceValue:backReferenceValue];
+    }
+
+    void RenderCommandEncoder::SetVisibilityResultMode(VisibilityResultMode mode, uint32_t offset)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setVisibilityResultMode:MTLVisibilityResultMode(mode) offset:offset];
+    }
+
+    void RenderCommandEncoder::SetColorStoreAction(StoreAction storeAction, uint32_t colorAttachmentIndex)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setColorStoreAction:MTLStoreAction(storeAction) atIndex:colorAttachmentIndex];
+#endif
+    }
+
+    void RenderCommandEncoder::SetDepthStoreAction(StoreAction storeAction)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setDepthStoreAction:MTLStoreAction(storeAction)];
+#endif
+    }
+
+    void RenderCommandEncoder::SetStencilStoreAction(StoreAction storeAction)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setStencilStoreAction:MTLStoreAction(storeAction)];
+#endif
+    }
+
+    void RenderCommandEncoder::Draw(PrimitiveType primitiveType, uint32_t vertexStart, uint32_t vertexCount)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawPrimitives:MTLPrimitiveType(primitiveType)
+                                                        vertexStart:vertexStart
+                                                        vertexCount:vertexCount];
+    }
+
+    void RenderCommandEncoder::Draw(PrimitiveType primitiveType, uint32_t vertexStart, uint32_t vertexCount, uint32_t instanceCount)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawPrimitives:MTLPrimitiveType(primitiveType)
+                                                        vertexStart:vertexStart
+                                                        vertexCount:vertexCount
+                                                      instanceCount:instanceCount];
+#endif
+    }
+
+    void RenderCommandEncoder::Draw(PrimitiveType primitiveType, uint32_t vertexStart, uint32_t vertexCount, uint32_t instanceCount, uint32_t baseInstance)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawPrimitives:MTLPrimitiveType(primitiveType)
+                                                        vertexStart:vertexStart
+                                                        vertexCount:vertexCount
+                                                      instanceCount:instanceCount
+                                                       baseInstance:baseInstance];
+#endif
+    }
+
+    void RenderCommandEncoder::Draw(PrimitiveType primitiveType, Buffer indirectBuffer, uint32_t indirectBufferOffset)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawPrimitives:MTLPrimitiveType(primitiveType)
+                                                     indirectBuffer:(__bridge id<MTLBuffer>)indirectBuffer.GetPtr()
+                                               indirectBufferOffset:indirectBufferOffset];
+    }
+
+    void RenderCommandEncoder::DrawIndexed(PrimitiveType primitiveType, uint32_t indexCount, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawIndexedPrimitives:MTLPrimitiveType(primitiveType)
+                                                                indexCount:indexCount
+                                                                 indexType:MTLIndexType(indexType)
+                                                               indexBuffer:(__bridge id<MTLBuffer>)indexBuffer.GetPtr()
+                                                         indexBufferOffset:indexBufferOffset];
+    }
+
+    void RenderCommandEncoder::DrawIndexed(PrimitiveType primitiveType, uint32_t indexCount, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset, uint32_t instanceCount)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawIndexedPrimitives:MTLPrimitiveType(primitiveType)
+                                                                indexCount:indexCount indexType:MTLIndexType(indexType)
+                                                               indexBuffer:(__bridge id<MTLBuffer>)indexBuffer.GetPtr()
+                                                         indexBufferOffset:indexBufferOffset instanceCount:instanceCount];
+#endif
+    }
+
+    void RenderCommandEncoder::DrawIndexed(PrimitiveType primitiveType, uint32_t indexCount, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset, uint32_t instanceCount, uint32_t baseVertex, uint32_t baseInstance)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawIndexedPrimitives:MTLPrimitiveType(primitiveType)
+                                                                indexCount:indexCount
+                                                                 indexType:MTLIndexType(indexType)
+                                                               indexBuffer:(__bridge id<MTLBuffer>)indexBuffer.GetPtr()
+                                                         indexBufferOffset:indexBufferOffset
+                                                             instanceCount:instanceCount
+                                                                baseVertex:baseVertex
+                                                              baseInstance:baseInstance];
+#endif
+    }
+
+    void RenderCommandEncoder::DrawIndexed(PrimitiveType primitiveType, IndexType indexType, const Buffer& indexBuffer, uint32_t indexBufferOffset, const Buffer& indirectBuffer, uint32_t indirectBufferOffset)
+    {
+        Validate();
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawIndexedPrimitives:MTLPrimitiveType(primitiveType)
+                                                                 indexType:MTLIndexType(indexType)
+                                                               indexBuffer:(__bridge id<MTLBuffer>)indexBuffer.GetPtr()
+                                                         indexBufferOffset:indexBufferOffset
+                                                            indirectBuffer:(__bridge id<MTLBuffer>)indirectBuffer.GetPtr()
+                                                      indirectBufferOffset:indirectBufferOffset];
+    }
+
+    void RenderCommandEncoder::TextureBarrier()
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr textureBarrier];
+#endif
+    }
+
+    void RenderCommandEncoder::UpdateFence(const Fence& fence, RenderStages afterStages)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr updateFence:(__bridge id<MTLFence>)fence.GetPtr() afterStages:MTLRenderStages(afterStages)];
+#endif
+    }
+
+    void RenderCommandEncoder::WaitForFence(const Fence& fence, RenderStages beforeStages)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr waitForFence:(__bridge id<MTLFence>)fence.GetPtr() beforeStages:MTLRenderStages(beforeStages)];
+#endif
+    }
+
+    void RenderCommandEncoder::SetTessellationFactorBuffer(const Buffer& buffer, uint32_t offset, uint32_t instanceStride)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setTessellationFactorBuffer:(__bridge id<MTLBuffer>)buffer.GetPtr() offset:offset instanceStride:instanceStride];
+#endif
+    }
+
+    void RenderCommandEncoder::SetTessellationFactorScale(float scale)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr setTessellationFactorScale:scale];
+#endif
+    }
+
+    void RenderCommandEncoder::DrawPatches(uint32_t numberOfPatchControlPoints, uint32_t patchStart, uint32_t patchCount, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, uint32_t instanceCount, uint32_t baseInstance)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawPatches:numberOfPatchControlPoints
+                                                      patchStart:patchStart
+                                                      patchCount:patchCount
+                                                patchIndexBuffer:(__bridge id<MTLBuffer>)patchIndexBuffer.GetPtr()
+                                          patchIndexBufferOffset:patchIndexBufferOffset
+                                                   instanceCount:instanceCount
+                                                    baseInstance:baseInstance];
+#endif
+    }
+
+    void RenderCommandEncoder::DrawPatches(uint32_t numberOfPatchControlPoints, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, const Buffer& indirectBuffer, uint32_t indirectBufferOffset)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_12)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawPatches:numberOfPatchControlPoints
+                                                patchIndexBuffer:(__bridge id<MTLBuffer>)patchIndexBuffer.GetPtr()
+                                          patchIndexBufferOffset:patchIndexBufferOffset
+                                                  indirectBuffer:(__bridge id<MTLBuffer>)indirectBuffer.GetPtr()
+                                            indirectBufferOffset:indirectBufferOffset];
+#endif
+    }
+
+    void RenderCommandEncoder::DrawIndexedPatches(uint32_t numberOfPatchControlPoints, uint32_t patchStart, uint32_t patchCount, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, const Buffer& controlPointIndexBuffer, uint32_t controlPointIndexBufferOffset, uint32_t instanceCount, uint32_t baseInstance)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawIndexedPatches:numberOfPatchControlPoints
+                                                             patchStart:patchStart
+                                                             patchCount:patchCount
+                                                       patchIndexBuffer:(__bridge id<MTLBuffer>)patchIndexBuffer.GetPtr()
+                                                 patchIndexBufferOffset:patchIndexBufferOffset
+                                                controlPointIndexBuffer:(__bridge id<MTLBuffer>)controlPointIndexBuffer.GetPtr()
+                                          controlPointIndexBufferOffset:controlPointIndexBufferOffset
+                                                          instanceCount:instanceCount
+                                                           baseInstance:baseInstance];
+#endif
+    }
+
+    void RenderCommandEncoder::DrawIndexedPatches(uint32_t numberOfPatchControlPoints, const Buffer& patchIndexBuffer, uint32_t patchIndexBufferOffset, const Buffer& controlPointIndexBuffer, uint32_t controlPointIndexBufferOffset, const Buffer& indirectBuffer, uint32_t indirectBufferOffset)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_12)
+        [(__bridge id<MTLRenderCommandEncoder>)m_ptr drawIndexedPatches:numberOfPatchControlPoints
+                                                       patchIndexBuffer:(__bridge id<MTLBuffer>)patchIndexBuffer.GetPtr()
+                                                 patchIndexBufferOffset:patchIndexBufferOffset
+                                                controlPointIndexBuffer:(__bridge id<MTLBuffer>)controlPointIndexBuffer.GetPtr()
+                                          controlPointIndexBufferOffset:controlPointIndexBufferOffset
+                                                         indirectBuffer:(__bridge id<MTLBuffer>)indirectBuffer.GetPtr()
+                                                   indirectBufferOffset:indirectBufferOffset];
+#endif
+    }
+}
+
+
+//////////////////////////////////////
+// FILE: render_pass.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "render_pass.hpp"
+// #include "texture.hpp"
+#include <Metal/MTLRenderPass.h>
+
+namespace mtlpp
+{
+    RenderPassAttachmentDescriptor::RenderPassAttachmentDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLRenderPassAttachmentDescriptor alloc] init] })
+    {
+    }
+
+    Texture RenderPassAttachmentDescriptor::GetTexture() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr texture] };
+    }
+
+    uint32_t RenderPassAttachmentDescriptor::GetLevel() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr level]);
+    }
+
+    uint32_t RenderPassAttachmentDescriptor::GetSlice() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr slice]);
+    }
+
+    uint32_t RenderPassAttachmentDescriptor::GetDepthPlane() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr depthPlane]);
+    }
+
+    Texture RenderPassAttachmentDescriptor::GetResolveTexture() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr resolveTexture] };
+    }
+
+    uint32_t RenderPassAttachmentDescriptor::GetResolveLevel() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr resolveLevel]);
+    }
+
+    uint32_t RenderPassAttachmentDescriptor::GetResolveSlice() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr resolveSlice]);
+    }
+
+    uint32_t RenderPassAttachmentDescriptor::GetResolveDepthPlane() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr resolveDepthPlane]);
+    }
+
+    LoadAction RenderPassAttachmentDescriptor::GetLoadAction() const
+    {
+        Validate();
+        return LoadAction([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr loadAction]);
+    }
+
+    StoreAction RenderPassAttachmentDescriptor::GetStoreAction() const
+    {
+        Validate();
+        return StoreAction([(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr storeAction]);
+    }
+
+    void RenderPassAttachmentDescriptor::SetTexture(const Texture& texture)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setTexture:(__bridge id<MTLTexture>)texture.GetPtr()];
+    }
+
+    void RenderPassAttachmentDescriptor::SetLevel(uint32_t level)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setLevel:level];
+    }
+
+    void RenderPassAttachmentDescriptor::SetSlice(uint32_t slice)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setSlice:slice];
+    }
+
+    void RenderPassAttachmentDescriptor::SetDepthPlane(uint32_t depthPlane)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setDepthPlane:depthPlane];
+    }
+
+    void RenderPassAttachmentDescriptor::SetResolveTexture(const Texture& texture)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setResolveTexture:(__bridge id<MTLTexture>)texture.GetPtr()];
+    }
+
+    void RenderPassAttachmentDescriptor::SetResolveLevel(uint32_t resolveLevel)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setResolveLevel:resolveLevel];
+    }
+
+    void RenderPassAttachmentDescriptor::SetResolveSlice(uint32_t resolveSlice)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setResolveSlice:resolveSlice];
+    }
+
+    void RenderPassAttachmentDescriptor::SetResolveDepthPlane(uint32_t resolveDepthPlane)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setResolveDepthPlane:resolveDepthPlane];
+    }
+
+    void RenderPassAttachmentDescriptor::SetLoadAction(LoadAction loadAction)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setLoadAction:MTLLoadAction(loadAction)];
+    }
+
+    void RenderPassAttachmentDescriptor::SetStoreAction(StoreAction storeAction)
+    {
+        Validate();
+        [(__bridge MTLRenderPassAttachmentDescriptor*)m_ptr setStoreAction:MTLStoreAction(storeAction)];
+    }
+
+    RenderPassColorAttachmentDescriptor::RenderPassColorAttachmentDescriptor() :
+        RenderPassAttachmentDescriptor(ns::Handle{ (__bridge void*)[[MTLRenderPassColorAttachmentDescriptor alloc] init] })
+    {
+    }
+
+    ClearColor RenderPassColorAttachmentDescriptor::GetClearColor() const
+    {
+        Validate();
+        MTLClearColor mtlClearColor = [(__bridge MTLRenderPassColorAttachmentDescriptor*)m_ptr clearColor];
+        return ClearColor(mtlClearColor.red, mtlClearColor.green, mtlClearColor.blue, mtlClearColor.alpha);
+    }
+
+    void RenderPassColorAttachmentDescriptor::SetClearColor(const ClearColor& clearColor)
+    {
+        Validate();
+        MTLClearColor mtlClearColor = { clearColor.Red, clearColor.Green, clearColor.Blue, clearColor.Alpha };
+        [(__bridge MTLRenderPassColorAttachmentDescriptor*)m_ptr setClearColor:mtlClearColor];
+    }
+
+    RenderPassDepthAttachmentDescriptor::RenderPassDepthAttachmentDescriptor() :
+        RenderPassAttachmentDescriptor(ns::Handle{ (__bridge void*)[[MTLRenderPassDepthAttachmentDescriptor alloc] init] })
+    {
+    }
+
+    double RenderPassDepthAttachmentDescriptor::GetClearDepth() const
+    {
+        Validate();
+        return [(__bridge MTLRenderPassDepthAttachmentDescriptor*)m_ptr clearDepth];
+    }
+
+    MultisampleDepthResolveFilter RenderPassDepthAttachmentDescriptor::GetDepthResolveFilter() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(9_0)
+        return MultisampleDepthResolveFilter([(__bridge MTLRenderPassDepthAttachmentDescriptor*)m_ptr depthResolveFilter]);
+#else
+        return MultisampleDepthResolveFilter(0);
+#endif
+    }
+
+    void RenderPassDepthAttachmentDescriptor::SetClearDepth(double clearDepth)
+    {
+        Validate();
+        [(__bridge MTLRenderPassDepthAttachmentDescriptor*)m_ptr setClearDepth:clearDepth];
+    }
+
+    void RenderPassDepthAttachmentDescriptor::SetDepthResolveFilter(MultisampleDepthResolveFilter depthResolveFilter)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(9_0)
+        [(__bridge MTLRenderPassDepthAttachmentDescriptor*)m_ptr setDepthResolveFilter:MTLMultisampleDepthResolveFilter(depthResolveFilter)];
+#endif
+    }
+
+    RenderPassStencilAttachmentDescriptor::RenderPassStencilAttachmentDescriptor() :
+        RenderPassAttachmentDescriptor(ns::Handle{ (__bridge void*)[[MTLRenderPassStencilAttachmentDescriptor alloc] init] })
+    {
+    }
+
+    uint32_t RenderPassStencilAttachmentDescriptor::GetClearStencil() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPassStencilAttachmentDescriptor*)m_ptr clearStencil]);
+    }
+
+    void RenderPassStencilAttachmentDescriptor::SetClearStencil(uint32_t clearStencil)
+    {
+        Validate();
+        [(__bridge MTLRenderPassStencilAttachmentDescriptor*)m_ptr setClearStencil:clearStencil];
+    }
+
+    RenderPassDescriptor::RenderPassDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLRenderPassDescriptor alloc] init] })
+    {
+    }
+
+    ns::Array<RenderPassColorAttachmentDescriptor> RenderPassDescriptor::GetColorAttachments() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPassDescriptor*)m_ptr colorAttachments] };
+    }
+
+    RenderPassDepthAttachmentDescriptor RenderPassDescriptor::GetDepthAttachment() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPassDescriptor*)m_ptr depthAttachment] };
+    }
+
+    RenderPassStencilAttachmentDescriptor RenderPassDescriptor::GetStencilAttachment() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPassDescriptor*)m_ptr stencilAttachment] };
+    }
+
+    Buffer RenderPassDescriptor::GetVisibilityResultBuffer() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPassDescriptor*)m_ptr visibilityResultBuffer] };
+    }
+
+    uint32_t RenderPassDescriptor::GetRenderTargetArrayLength() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        return uint32_t([(__bridge MTLRenderPassDescriptor*)m_ptr renderTargetArrayLength]);
+#else
+        return 0;
+#endif
+    }
+
+    void RenderPassDescriptor::SetDepthAttachment(const RenderPassDepthAttachmentDescriptor& depthAttachment)
+    {
+        Validate();
+        [(__bridge MTLRenderPassDescriptor*)m_ptr setDepthAttachment:(__bridge MTLRenderPassDepthAttachmentDescriptor*)depthAttachment.GetPtr()];
+    }
+
+    void RenderPassDescriptor::SetStencilAttachment(const RenderPassStencilAttachmentDescriptor& stencilAttachment)
+    {
+        Validate();
+        [(__bridge MTLRenderPassDescriptor*)m_ptr setStencilAttachment:(__bridge MTLRenderPassStencilAttachmentDescriptor*)stencilAttachment.GetPtr()];
+    }
+
+    void RenderPassDescriptor::SetVisibilityResultBuffer(const Buffer& visibilityResultBuffer)
+    {
+        Validate();
+        [(__bridge MTLRenderPassDescriptor*)m_ptr setVisibilityResultBuffer:(__bridge id<MTLBuffer>)visibilityResultBuffer.GetPtr()];
+    }
+
+    void RenderPassDescriptor::SetRenderTargetArrayLength(uint32_t renderTargetArrayLength)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        [(__bridge MTLRenderPassDescriptor*)m_ptr setRenderTargetArrayLength:renderTargetArrayLength];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: render_pipeline.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "render_pipeline.hpp"
+// #include "vertex_descriptor.hpp"
+#include <Metal/MTLRenderPipeline.h>
+
+namespace mtlpp
+{
+    RenderPipelineColorAttachmentDescriptor::RenderPipelineColorAttachmentDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLRenderPipelineColorAttachmentDescriptor alloc] init] })
+    {
+    }
+
+    PixelFormat RenderPipelineColorAttachmentDescriptor::GetPixelFormat() const
+    {
+        Validate();
+        return PixelFormat([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr pixelFormat]);
+    }
+
+    bool RenderPipelineColorAttachmentDescriptor::IsBlendingEnabled() const
+    {
+        Validate();
+        return [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr isBlendingEnabled];
+    }
+
+    BlendFactor RenderPipelineColorAttachmentDescriptor::GetSourceRgbBlendFactor() const
+    {
+        Validate();
+        return BlendFactor([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr sourceRGBBlendFactor]);
+    }
+
+    BlendFactor RenderPipelineColorAttachmentDescriptor::GetDestinationRgbBlendFactor() const
+    {
+        Validate();
+        return BlendFactor([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr destinationRGBBlendFactor]);
+    }
+
+    BlendOperation RenderPipelineColorAttachmentDescriptor::GetRgbBlendOperation() const
+    {
+        Validate();
+        return BlendOperation([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr rgbBlendOperation]);
+    }
+
+    BlendFactor RenderPipelineColorAttachmentDescriptor::GetSourceAlphaBlendFactor() const
+    {
+        Validate();
+        return BlendFactor([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr sourceAlphaBlendFactor]);
+    }
+
+    BlendFactor RenderPipelineColorAttachmentDescriptor::GetDestinationAlphaBlendFactor() const
+    {
+        Validate();
+        return BlendFactor([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr destinationAlphaBlendFactor]);
+    }
+
+    BlendOperation RenderPipelineColorAttachmentDescriptor::GetAlphaBlendOperation() const
+    {
+        Validate();
+        return BlendOperation([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr alphaBlendOperation]);
+    }
+
+    ColorWriteMask RenderPipelineColorAttachmentDescriptor::GetWriteMask() const
+    {
+        Validate();
+        return ColorWriteMask([(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr writeMask]);
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetPixelFormat(PixelFormat pixelFormat)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setPixelFormat:MTLPixelFormat(pixelFormat)];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetBlendingEnabled(bool blendingEnabled)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setBlendingEnabled:blendingEnabled];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetSourceRgbBlendFactor(BlendFactor sourceRgbBlendFactor)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setSourceRGBBlendFactor:MTLBlendFactor(sourceRgbBlendFactor)];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetDestinationRgbBlendFactor(BlendFactor destinationRgbBlendFactor)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setDestinationRGBBlendFactor:MTLBlendFactor(destinationRgbBlendFactor)];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetRgbBlendOperation(BlendOperation rgbBlendOperation)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setRgbBlendOperation:MTLBlendOperation(rgbBlendOperation)];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetSourceAlphaBlendFactor(BlendFactor sourceAlphaBlendFactor)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setSourceAlphaBlendFactor:MTLBlendFactor(sourceAlphaBlendFactor)];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetDestinationAlphaBlendFactor(BlendFactor destinationAlphaBlendFactor)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setDestinationAlphaBlendFactor:MTLBlendFactor(destinationAlphaBlendFactor)];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetAlphaBlendOperation(BlendOperation alphaBlendOperation)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setAlphaBlendOperation:MTLBlendOperation(alphaBlendOperation)];
+    }
+
+    void RenderPipelineColorAttachmentDescriptor::SetWriteMask(ColorWriteMask writeMask)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineColorAttachmentDescriptor*)m_ptr setWriteMask:MTLColorWriteMask(writeMask)];
+    }
+
+    RenderPipelineReflection::RenderPipelineReflection() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLRenderPipelineReflection alloc] init] })
+    {
+    }
+
+    const ns::Array<Argument> RenderPipelineReflection::GetVertexArguments() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPipelineReflection*)m_ptr vertexArguments] };
+    }
+
+    const ns::Array<Argument> RenderPipelineReflection::GetFragmentArguments() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPipelineReflection*)m_ptr fragmentArguments] };
+    }
+
+    RenderPipelineDescriptor::RenderPipelineDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLRenderPipelineDescriptor alloc] init] })
+    {
+    }
+
+    ns::String RenderPipelineDescriptor::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPipelineDescriptor*)m_ptr label] };
+    }
+
+    Function RenderPipelineDescriptor::GetVertexFunction() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPipelineDescriptor*)m_ptr vertexFunction] };
+    }
+
+    Function RenderPipelineDescriptor::GetFragmentFunction() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPipelineDescriptor*)m_ptr fragmentFunction] };
+    }
+
+    VertexDescriptor RenderPipelineDescriptor::GetVertexDescriptor() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPipelineDescriptor*)m_ptr vertexDescriptor] };
+    }
+
+    uint32_t RenderPipelineDescriptor::GetSampleCount() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLRenderPipelineDescriptor*)m_ptr sampleCount]);
+    }
+
+    bool RenderPipelineDescriptor::IsAlphaToCoverageEnabled() const
+    {
+        Validate();
+        return [(__bridge MTLRenderPipelineDescriptor*)m_ptr isAlphaToCoverageEnabled];
+    }
+
+    bool RenderPipelineDescriptor::IsAlphaToOneEnabled() const
+    {
+        Validate();
+        return [(__bridge MTLRenderPipelineDescriptor*)m_ptr isAlphaToOneEnabled];
+    }
+
+    bool RenderPipelineDescriptor::IsRasterizationEnabled() const
+    {
+        Validate();
+        return [(__bridge MTLRenderPipelineDescriptor*)m_ptr isRasterizationEnabled];
+    }
+
+    ns::Array<RenderPipelineColorAttachmentDescriptor> RenderPipelineDescriptor::GetColorAttachments() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLRenderPipelineDescriptor*)m_ptr colorAttachments] };
+    }
+
+    PixelFormat RenderPipelineDescriptor::GetDepthAttachmentPixelFormat() const
+    {
+        Validate();
+        return PixelFormat([(__bridge MTLRenderPipelineDescriptor*)m_ptr depthAttachmentPixelFormat]);
+    }
+
+    PixelFormat RenderPipelineDescriptor::GetStencilAttachmentPixelFormat() const
+    {
+        Validate();
+        return PixelFormat([(__bridge MTLRenderPipelineDescriptor*)m_ptr stencilAttachmentPixelFormat]);
+    }
+
+    PrimitiveTopologyClass RenderPipelineDescriptor::GetInputPrimitiveTopology() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        return PrimitiveTopologyClass([(__bridge MTLRenderPipelineDescriptor*)m_ptr inputPrimitiveTopology]);
+#else
+        return PrimitiveTopologyClass(0);
+#endif
+    }
+
+    TessellationPartitionMode RenderPipelineDescriptor::GetTessellationPartitionMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return TessellationPartitionMode([(__bridge MTLRenderPipelineDescriptor*)m_ptr tessellationPartitionMode]);
+#else
+        return TessellationPartitionMode(0);
+#endif
+    }
+
+    uint32_t RenderPipelineDescriptor::GetMaxTessellationFactor() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLRenderPipelineDescriptor*)m_ptr maxTessellationFactor]);
+#else
+        return 0;
+#endif
+    }
+
+    bool RenderPipelineDescriptor::IsTessellationFactorScaleEnabled() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return [(__bridge MTLRenderPipelineDescriptor*)m_ptr isTessellationFactorScaleEnabled];
+#else
+        return false;
+#endif
+    }
+
+    TessellationFactorFormat RenderPipelineDescriptor::GetTessellationFactorFormat() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return TessellationFactorFormat([(__bridge MTLRenderPipelineDescriptor*)m_ptr tessellationFactorFormat]);
+#else
+        return TessellationFactorFormat(0);
+#endif
+    }
+
+    TessellationControlPointIndexType RenderPipelineDescriptor::GetTessellationControlPointIndexType() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return TessellationControlPointIndexType([(__bridge MTLRenderPipelineDescriptor*)m_ptr tessellationControlPointIndexType]);
+#else
+        return TessellationControlPointIndexType(0);
+#endif
+    }
+
+    TessellationFactorStepFunction RenderPipelineDescriptor::GetTessellationFactorStepFunction() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return TessellationFactorStepFunction([(__bridge MTLRenderPipelineDescriptor*)m_ptr tessellationFactorStepFunction]);
+#else
+        return TessellationFactorStepFunction(0);
+#endif
+    }
+
+    Winding RenderPipelineDescriptor::GetTessellationOutputWindingOrder() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return Winding([(__bridge MTLRenderPipelineDescriptor*)m_ptr tessellationOutputWindingOrder]);
+#else
+        return Winding(0);
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    void RenderPipelineDescriptor::SetVertexFunction(const Function& vertexFunction)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setVertexFunction:(__bridge id<MTLFunction>)vertexFunction.GetPtr()];
+    }
+
+    void RenderPipelineDescriptor::SetFragmentFunction(const Function& fragmentFunction)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setFragmentFunction:(__bridge id<MTLFunction>)fragmentFunction.GetPtr()];
+    }
+
+    void RenderPipelineDescriptor::SetVertexDescriptor(const VertexDescriptor& vertexDescriptor)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setVertexDescriptor:(__bridge MTLVertexDescriptor*)vertexDescriptor.GetPtr()];
+    }
+
+    void RenderPipelineDescriptor::SetSampleCount(uint32_t sampleCount)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setSampleCount:sampleCount];
+    }
+
+    void RenderPipelineDescriptor::SetAlphaToCoverageEnabled(bool alphaToCoverageEnabled)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setAlphaToCoverageEnabled:alphaToCoverageEnabled];
+    }
+
+    void RenderPipelineDescriptor::SetAlphaToOneEnabled(bool alphaToOneEnabled)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setAlphaToOneEnabled:alphaToOneEnabled];
+    }
+
+    void RenderPipelineDescriptor::SetRasterizationEnabled(bool rasterizationEnabled)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setRasterizationEnabled:rasterizationEnabled];
+    }
+
+    void RenderPipelineDescriptor::SetDepthAttachmentPixelFormat(PixelFormat depthAttachmentPixelFormat)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setDepthAttachmentPixelFormat:MTLPixelFormat(depthAttachmentPixelFormat)];
+    }
+
+    void RenderPipelineDescriptor::SetStencilAttachmentPixelFormat(PixelFormat depthAttachmentPixelFormat)
+    {
+        Validate();
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setStencilAttachmentPixelFormat:MTLPixelFormat(depthAttachmentPixelFormat)];
+    }
+
+    void RenderPipelineDescriptor::SetInputPrimitiveTopology(PrimitiveTopologyClass inputPrimitiveTopology)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setInputPrimitiveTopology:MTLPrimitiveTopologyClass(inputPrimitiveTopology)];
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetTessellationPartitionMode(TessellationPartitionMode tessellationPartitionMode)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setTessellationPartitionMode:MTLTessellationPartitionMode(tessellationPartitionMode)];
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetMaxTessellationFactor(uint32_t maxTessellationFactor)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setMaxTessellationFactor:maxTessellationFactor];
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetTessellationFactorScaleEnabled(bool tessellationFactorScaleEnabled)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setTessellationFactorScaleEnabled:tessellationFactorScaleEnabled];
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetTessellationFactorFormat(TessellationFactorFormat tessellationFactorFormat)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setTessellationFactorFormat:MTLTessellationFactorFormat(tessellationFactorFormat)];
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetTessellationControlPointIndexType(TessellationControlPointIndexType tessellationControlPointIndexType)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setTessellationControlPointIndexType:MTLTessellationControlPointIndexType(tessellationControlPointIndexType)];
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetTessellationFactorStepFunction(TessellationFactorStepFunction tessellationFactorStepFunction)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setTessellationFactorStepFunction:MTLTessellationFactorStepFunction(tessellationFactorStepFunction)];
+#endif
+    }
+
+    void RenderPipelineDescriptor::SetTessellationOutputWindingOrder(Winding tessellationOutputWindingOrder)
+    {
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr setTessellationOutputWindingOrder:MTLWinding(tessellationOutputWindingOrder)];
+#endif
+    }
+
+    void RenderPipelineDescriptor::Reset()
+    {
+        [(__bridge MTLRenderPipelineDescriptor*)m_ptr reset];
+    }
+
+    ns::String RenderPipelineState::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLRenderPipelineState>)m_ptr label] };
+    }
+
+    Device RenderPipelineState::GetDevice() const
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLRenderPipelineState>)m_ptr device] };
+    }
+}
+
+//////////////////////////////////////
+// FILE: resource.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "resource.hpp"
+// #include "heap.hpp"
+#include <Metal/MTLResource.h>
+
+namespace mtlpp
+{
+    ns::String Resource::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLResource>)m_ptr label] };
+    }
+
+    CpuCacheMode Resource::GetCpuCacheMode() const
+    {
+        Validate();
+        return CpuCacheMode([(__bridge id<MTLResource>)m_ptr cpuCacheMode]);
+    }
+
+    StorageMode Resource::GetStorageMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return StorageMode([(__bridge id<MTLResource>)m_ptr storageMode]);
+#else
+        return StorageMode(0);
+#endif
+    }
+
+    Heap Resource::GetHeap() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLResource>)m_ptr heap] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    bool Resource::IsAliasable() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        return [(__bridge id<MTLResource>)m_ptr isAliasable];
+#else
+        return false;
+#endif
+    }
+
+    void Resource::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge id<MTLResource>)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    PurgeableState Resource::SetPurgeableState(PurgeableState state)
+    {
+        Validate();
+        return PurgeableState([(__bridge id<MTLResource>)m_ptr setPurgeableState:MTLPurgeableState(state)]);
+    }
+
+    void Resource::MakeAliasable() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_IOS(10_0)
+        [(__bridge id<MTLResource>)m_ptr makeAliasable];
+#endif
+    }
+}
+
+//////////////////////////////////////
+// FILE: sampler.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "sampler.hpp"
+#include <Metal/MTLSampler.h>
+
+namespace mtlpp
+{
+    SamplerDescriptor::SamplerDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLSamplerDescriptor alloc] init] })
+    {
+    }
+
+    SamplerMinMagFilter SamplerDescriptor::GetMinFilter() const
+    {
+        Validate();
+        return SamplerMinMagFilter([(__bridge MTLSamplerDescriptor*)m_ptr minFilter]);
+    }
+
+    SamplerMinMagFilter SamplerDescriptor::GetMagFilter() const
+    {
+        Validate();
+        return SamplerMinMagFilter([(__bridge MTLSamplerDescriptor*)m_ptr magFilter]);
+    }
+
+    SamplerMipFilter SamplerDescriptor::GetMipFilter() const
+    {
+        Validate();
+        return SamplerMipFilter([(__bridge MTLSamplerDescriptor*)m_ptr mipFilter]);
+    }
+
+    uint32_t SamplerDescriptor::GetMaxAnisotropy() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLSamplerDescriptor*)m_ptr maxAnisotropy]);
+    }
+
+    SamplerAddressMode SamplerDescriptor::GetSAddressMode() const
+    {
+        Validate();
+        return SamplerAddressMode([(__bridge MTLSamplerDescriptor*)m_ptr sAddressMode]);
+    }
+
+    SamplerAddressMode SamplerDescriptor::GetTAddressMode() const
+    {
+        Validate();
+        return SamplerAddressMode([(__bridge MTLSamplerDescriptor*)m_ptr tAddressMode]);
+    }
+
+    SamplerAddressMode SamplerDescriptor::GetRAddressMode() const
+    {
+        Validate();
+        return SamplerAddressMode([(__bridge MTLSamplerDescriptor*)m_ptr rAddressMode]);
+    }
+
+    SamplerBorderColor SamplerDescriptor::GetBorderColor() const
+    {
+#if MTLPP_IS_AVAILABLE_MAC(10_12)
+        return SamplerBorderColor([(__bridge MTLSamplerDescriptor*)m_ptr borderColor]);
+#else
+        return SamplerBorderColor(0);
+#endif
+    }
+
+    bool SamplerDescriptor::IsNormalizedCoordinates() const
+    {
+        Validate();
+        return [(__bridge MTLSamplerDescriptor*)m_ptr normalizedCoordinates];
+    }
+
+    float SamplerDescriptor::GetLodMinClamp() const
+    {
+        Validate();
+        return [(__bridge MTLSamplerDescriptor*)m_ptr lodMinClamp];
+    }
+
+    float SamplerDescriptor::GetLodMaxClamp() const
+    {
+        Validate();
+        return [(__bridge MTLSamplerDescriptor*)m_ptr lodMaxClamp];
+    }
+
+    CompareFunction SamplerDescriptor::GetCompareFunction() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return CompareFunction([(__bridge MTLSamplerDescriptor*)m_ptr compareFunction]);
+#else
+        return CompareFunction(0);
+#endif
+    }
+
+    ns::String SamplerDescriptor::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLSamplerDescriptor*)m_ptr label] };
+    }
+
+    void SamplerDescriptor::SetMinFilter(SamplerMinMagFilter minFilter)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setMinFilter:MTLSamplerMinMagFilter(minFilter)];
+    }
+
+    void SamplerDescriptor::SetMagFilter(SamplerMinMagFilter magFilter)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setMagFilter:MTLSamplerMinMagFilter(magFilter)];
+    }
+
+    void SamplerDescriptor::SetMipFilter(SamplerMipFilter mipFilter)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setMipFilter:MTLSamplerMipFilter(mipFilter)];
+    }
+
+    void SamplerDescriptor::SetMaxAnisotropy(uint32_t maxAnisotropy)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setMaxAnisotropy:maxAnisotropy];
+    }
+
+    void SamplerDescriptor::SetSAddressMode(SamplerAddressMode sAddressMode)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setSAddressMode:MTLSamplerAddressMode(sAddressMode)];
+    }
+
+    void SamplerDescriptor::SetTAddressMode(SamplerAddressMode tAddressMode)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setTAddressMode:MTLSamplerAddressMode(tAddressMode)];
+    }
+
+    void SamplerDescriptor::SetRAddressMode(SamplerAddressMode rAddressMode)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setRAddressMode:MTLSamplerAddressMode(rAddressMode)];
+    }
+
+    void SamplerDescriptor::SetBorderColor(SamplerBorderColor borderColor)
+    {
+#if MTLPP_IS_AVAILABLE_MAC(10_12)
+        [(__bridge MTLSamplerDescriptor*)m_ptr setBorderColor:MTLSamplerBorderColor(borderColor)];
+#endif
+    }
+
+    void SamplerDescriptor::SetNormalizedCoordinates(bool normalizedCoordinates)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setNormalizedCoordinates:normalizedCoordinates];
+    }
+
+    void SamplerDescriptor::SetLodMinClamp(float lodMinClamp)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setLodMinClamp:lodMinClamp];
+    }
+
+    void SamplerDescriptor::SetLodMaxClamp(float lodMaxClamp)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setLodMaxClamp:lodMaxClamp];
+    }
+
+    void SamplerDescriptor::SetCompareFunction(CompareFunction compareFunction)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge MTLSamplerDescriptor*)m_ptr setCompareFunction:MTLCompareFunction(compareFunction)];
+#endif
+    }
+
+    void SamplerDescriptor::SetLabel(const ns::String& label)
+    {
+        Validate();
+        [(__bridge MTLSamplerDescriptor*)m_ptr setLabel:(__bridge NSString*)label.GetPtr()];
+    }
+
+    ns::String SamplerState::GetLabel() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLSamplerState>)m_ptr label] };
+    }
+
+    Device SamplerState::GetDevice() const
+    {
+        Validate();
+        return ns::Handle { (__bridge void*)[(__bridge id<MTLSamplerState>)m_ptr device] };
+    }
+}
+
+
+//////////////////////////////////////
+// FILE: stage_input_output_descriptor.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "stage_input_output_descriptor.hpp"
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+#   include <Metal/MTLStageInputOutputDescriptor.h>
+#endif
+
+namespace mtlpp
+{
+    BufferLayoutDescriptor::BufferLayoutDescriptor() :
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLBufferLayoutDescriptor alloc] init] })
+#else
+        ns::Object(ns::Handle{ nullptr })
+#endif
+    {
+    }
+
+    uint32_t BufferLayoutDescriptor::GetStride() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLBufferLayoutDescriptor*)m_ptr stride]);
+#else
+        return 0;
+#endif
+    }
+
+    StepFunction BufferLayoutDescriptor::GetStepFunction() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return StepFunction([(__bridge MTLBufferLayoutDescriptor*)m_ptr stepFunction]);
+#else
+        return StepFunction(0);
+#endif
+    }
+
+    uint32_t BufferLayoutDescriptor::GetStepRate() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLBufferLayoutDescriptor*)m_ptr stepRate]);
+#else
+        return 0;
+#endif
+    }
+
+    void BufferLayoutDescriptor::SetStride(uint32_t stride)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLBufferLayoutDescriptor*)m_ptr setStride:stride];
+#endif
+    }
+
+    void BufferLayoutDescriptor::SetStepFunction(StepFunction stepFunction)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLBufferLayoutDescriptor*)m_ptr setStepFunction:MTLStepFunction(stepFunction)];
+#endif
+    }
+
+    void BufferLayoutDescriptor::SetStepRate(uint32_t stepRate)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLBufferLayoutDescriptor*)m_ptr setStepRate:stepRate];
+#endif
+    }
+
+    AttributeDescriptor::AttributeDescriptor() :
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLAttributeDescriptor alloc] init] })
+#else
+        ns::Object(ns::Handle{ nullptr })
+#endif
+    {
+    }
+
+    AttributeFormat AttributeDescriptor::GetFormat() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return AttributeFormat([(__bridge MTLAttributeDescriptor*)m_ptr format]);
+#else
+        return AttributeFormat(0);
+#endif
+    }
+
+    uint32_t AttributeDescriptor::GetOffset() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLAttributeDescriptor*)m_ptr offset]);
+#else
+        return 0;
+#endif
+    }
+
+    uint32_t AttributeDescriptor::GetBufferIndex() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLAttributeDescriptor*)m_ptr bufferIndex]);
+#else
+        return 0;
+#endif
+    }
+
+    void AttributeDescriptor::SetFormat(AttributeFormat format)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLAttributeDescriptor*)m_ptr setFormat:MTLAttributeFormat(format)];
+#endif
+    }
+
+    void AttributeDescriptor::SetOffset(uint32_t offset)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLAttributeDescriptor*)m_ptr setOffset:offset];
+#endif
+    }
+
+    void AttributeDescriptor::SetBufferIndex(uint32_t bufferIndex)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLAttributeDescriptor*)m_ptr setBufferIndex:bufferIndex];
+#endif
+    }
+
+    StageInputOutputDescriptor::StageInputOutputDescriptor() :
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLStageInputOutputDescriptor alloc] init] })
+#else
+        ns::Object(ns::Handle{ nullptr })
+#endif
+    {
+    }
+
+    ns::Array<BufferLayoutDescriptor> StageInputOutputDescriptor::GetLayouts() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge MTLStageInputOutputDescriptor*)m_ptr layouts] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    ns::Array<AttributeDescriptor> StageInputOutputDescriptor::GetAttributes() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ (__bridge void*)[(__bridge MTLStageInputOutputDescriptor*)m_ptr attributes] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    IndexType StageInputOutputDescriptor::GetIndexType() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return IndexType([(__bridge MTLStageInputOutputDescriptor*)m_ptr indexType]);
+#else
+        return IndexType(0);
+#endif
+    }
+
+    uint32_t StageInputOutputDescriptor::GetIndexBufferIndex() const
+   {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return uint32_t([(__bridge MTLStageInputOutputDescriptor*)m_ptr indexBufferIndex]);
+#else
+        return 0;
+#endif
+    }
+
+   void StageInputOutputDescriptor::SetIndexType(IndexType indexType)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLStageInputOutputDescriptor*)m_ptr setIndexType:MTLIndexType(indexType)];
+#endif
+    }
+
+    void StageInputOutputDescriptor::SetIndexBufferIndex(uint32_t indexBufferIndex)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLStageInputOutputDescriptor*)m_ptr setIndexBufferIndex:indexBufferIndex];
+#endif
+    }
+
+    void StageInputOutputDescriptor::Reset()
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        [(__bridge MTLStageInputOutputDescriptor*)m_ptr reset];
+#endif
+    }
+}
+
+
+//////////////////////////////////////
+// FILE: texture.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "texture.hpp"
+#include <Metal/MTLTexture.h>
+
+namespace mtlpp
+{
+    TextureDescriptor::TextureDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLTextureDescriptor alloc] init] })
+    {
+    }
+
+    TextureDescriptor TextureDescriptor::Texture2DDescriptor(PixelFormat pixelFormat, uint32_t width, uint32_t height, bool mipmapped)
+    {
+        return ns::Handle{ (__bridge void*)[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormat(pixelFormat)
+                                                                                              width:width
+                                                                                             height:height
+                                                                                          mipmapped:mipmapped] };
+    }
+
+    TextureDescriptor TextureDescriptor::TextureCubeDescriptor(PixelFormat pixelFormat, uint32_t size, bool mipmapped)
+    {
+        return ns::Handle{ (__bridge void*)[MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:MTLPixelFormat(pixelFormat)
+                                                                                                 size:size
+                                                                                            mipmapped:mipmapped] };
+    }
+
+    TextureType TextureDescriptor::GetTextureType() const
+    {
+        Validate();
+        return TextureType([(__bridge MTLTextureDescriptor*)m_ptr textureType]);
+    }
+
+    PixelFormat TextureDescriptor::GetPixelFormat() const
+    {
+        Validate();
+        return PixelFormat([(__bridge MTLTextureDescriptor*)m_ptr pixelFormat]);
+    }
+
+    uint32_t TextureDescriptor::GetWidth() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLTextureDescriptor*)m_ptr width]);
+    }
+
+    uint32_t TextureDescriptor::GetHeight() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLTextureDescriptor*)m_ptr height]);
+    }
+
+    uint32_t TextureDescriptor::GetDepth() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLTextureDescriptor*)m_ptr depth]);
+    }
+
+    uint32_t TextureDescriptor::GetMipmapLevelCount() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLTextureDescriptor*)m_ptr mipmapLevelCount]);
+    }
+
+    uint32_t TextureDescriptor::GetSampleCount() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLTextureDescriptor*)m_ptr sampleCount]);
+    }
+
+    uint32_t TextureDescriptor::GetArrayLength() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLTextureDescriptor*)m_ptr arrayLength]);
+    }
+
+    ResourceOptions TextureDescriptor::GetResourceOptions() const
+    {
+        Validate();
+        return ResourceOptions([(__bridge MTLTextureDescriptor*)m_ptr resourceOptions]);
+    }
+
+    CpuCacheMode TextureDescriptor::GetCpuCacheMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return CpuCacheMode([(__bridge MTLTextureDescriptor*)m_ptr cpuCacheMode]);
+#else
+        return CpuCacheMode(0);
+#endif
+    }
+
+    StorageMode TextureDescriptor::GetStorageMode() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return StorageMode([(__bridge MTLTextureDescriptor*)m_ptr storageMode]);
+#else
+        return StorageMode(0);
+#endif
+    }
+
+    TextureUsage TextureDescriptor::GetUsage() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return TextureUsage([(__bridge MTLTextureDescriptor*)m_ptr usage]);
+#else
+        return TextureUsage(0);
+#endif
+    }
+
+    void TextureDescriptor::SetTextureType(TextureType textureType)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setTextureType:MTLTextureType(textureType)];
+    }
+
+    void TextureDescriptor::SetPixelFormat(PixelFormat pixelFormat)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setPixelFormat:MTLPixelFormat(pixelFormat)];
+    }
+
+    void TextureDescriptor::SetWidth(uint32_t width)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setWidth:width];
+    }
+
+    void TextureDescriptor::SetHeight(uint32_t height)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setHeight:height];
+    }
+
+    void TextureDescriptor::SetDepth(uint32_t depth)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setDepth:depth];
+    }
+
+    void TextureDescriptor::SetMipmapLevelCount(uint32_t mipmapLevelCount)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setMipmapLevelCount:mipmapLevelCount];
+    }
+
+    void TextureDescriptor::SetSampleCount(uint32_t sampleCount)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setSampleCount:sampleCount];
+    }
+
+    void TextureDescriptor::SetArrayLength(uint32_t arrayLength)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setArrayLength:arrayLength];
+    }
+
+    void TextureDescriptor::SetResourceOptions(ResourceOptions resourceOptions)
+    {
+        Validate();
+        [(__bridge MTLTextureDescriptor*)m_ptr setResourceOptions:MTLResourceOptions(resourceOptions)];
+    }
+
+    void TextureDescriptor::SetCpuCacheMode(CpuCacheMode cpuCacheMode)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge MTLTextureDescriptor*)m_ptr setCpuCacheMode:MTLCPUCacheMode(cpuCacheMode)];
+#endif
+    }
+
+    void TextureDescriptor::SetStorageMode(StorageMode storageMode)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge MTLTextureDescriptor*)m_ptr setStorageMode:MTLStorageMode(storageMode)];
+#endif
+    }
+
+    void TextureDescriptor::SetUsage(TextureUsage usage)
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        [(__bridge MTLTextureDescriptor*)m_ptr setUsage:MTLTextureUsage(usage)];
+#endif
+    }
+
+    Resource Texture::GetRootResource() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 8_0)
+#   if MTLPP_IS_AVAILABLE(10_12, 10_0)
+        return ns::Handle{ nullptr };
+#   else
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLTexture>)m_ptr rootResource] };
+#   endif
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    Texture Texture::GetParentTexture() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLTexture>)m_ptr parentTexture] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+    }
+
+    uint32_t Texture::GetParentRelativeLevel() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr parentRelativeLevel]);
+#else
+        return 0;
+#endif
+
+    }
+
+    uint32_t Texture::GetParentRelativeSlice() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_11, 9_0)
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr parentRelativeSlice]);
+#else
+        return 0;
+#endif
+
+    }
+
+    Buffer Texture::GetBuffer() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 9_0)
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLTexture>)m_ptr buffer] };
+#else
+        return ns::Handle{ nullptr };
+#endif
+
+    }
+
+    uint32_t Texture::GetBufferOffset() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 9_0)
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr bufferOffset]);
+#else
+        return 0;
+#endif
+
+    }
+
+    uint32_t Texture::GetBufferBytesPerRow() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE(10_12, 9_0)
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr bufferBytesPerRow]);
+#else
+        return 0;
+#endif
+
+    }
+
+    uint32_t Texture::GetIOSurfacePlane() const
+    {
+        Validate();
+#if MTLPP_IS_AVAILABLE_MAC(10_11)
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr iosurfacePlane]);
+#else
+        return 0;
+#endif
+    }
+
+    TextureType Texture::GetTextureType() const
+    {
+        Validate();
+        return TextureType([(__bridge id<MTLTexture>)m_ptr textureType]);
+    }
+
+    PixelFormat Texture::GetPixelFormat() const
+    {
+        Validate();
+        return PixelFormat([(__bridge id<MTLTexture>)m_ptr pixelFormat]);
+    }
+
+    uint32_t Texture::GetWidth() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr width]);
+    }
+
+    uint32_t Texture::GetHeight() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr height]);
+    }
+
+    uint32_t Texture::GetDepth() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr depth]);
+    }
+
+    uint32_t Texture::GetMipmapLevelCount() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr mipmapLevelCount]);
+    }
+
+    uint32_t Texture::GetSampleCount() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr sampleCount]);
+    }
+
+    uint32_t Texture::GetArrayLength() const
+    {
+        Validate();
+        return uint32_t([(__bridge id<MTLTexture>)m_ptr arrayLength]);
+    }
+
+    TextureUsage Texture::GetUsage() const
+    {
+        Validate();
+        return TextureUsage([(__bridge id<MTLTexture>)m_ptr usage]);
+    }
+
+    bool Texture::IsFrameBufferOnly() const
+    {
+        Validate();
+        return [(__bridge id<MTLTexture>)m_ptr isFramebufferOnly];
+    }
+
+    void Texture::GetBytes(void* pixelBytes, uint32_t bytesPerRow, uint32_t bytesPerImage, const Region& fromRegion, uint32_t mipmapLevel, uint32_t slice)
+    {
+        Validate();
+        [(__bridge id<MTLTexture>)m_ptr getBytes:pixelBytes
+                                     bytesPerRow:bytesPerRow
+                                   bytesPerImage:bytesPerImage
+                                      fromRegion:MTLRegionMake3D(fromRegion.Origin.X, fromRegion.Origin.Y, fromRegion.Origin.Z, fromRegion.Size.Width, fromRegion.Size.Height, fromRegion.Size.Depth)
+                                     mipmapLevel:mipmapLevel
+                                           slice:slice];
+    }
+
+    void Texture::Replace(const Region& region, uint32_t mipmapLevel, uint32_t slice, void* pixelBytes, uint32_t bytesPerRow, uint32_t bytesPerImage)
+    {
+        Validate();
+        [(__bridge id<MTLTexture>)m_ptr replaceRegion:MTLRegionMake3D(region.Origin.X, region.Origin.Y, region.Origin.Z, region.Size.Width, region.Size.Height, region.Size.Depth)
+                                          mipmapLevel:mipmapLevel
+                                                slice:slice
+                                            withBytes:pixelBytes
+                                          bytesPerRow:bytesPerRow
+                                        bytesPerImage:bytesPerImage];
+    }
+
+    void Texture::GetBytes(void* pixelBytes, uint32_t bytesPerRow, const Region& fromRegion, uint32_t mipmapLevel)
+    {
+        Validate();
+        [(__bridge id<MTLTexture>)m_ptr getBytes:pixelBytes
+                                     bytesPerRow:bytesPerRow
+                                      fromRegion:MTLRegionMake3D(fromRegion.Origin.X, fromRegion.Origin.Y, fromRegion.Origin.Z, fromRegion.Size.Width, fromRegion.Size.Height, fromRegion.Size.Depth)
+                                     mipmapLevel:mipmapLevel];
+    }
+
+    void Texture::Replace(const Region& region, uint32_t mipmapLevel, void* pixelBytes, uint32_t bytesPerRow)
+    {
+        Validate();
+        [(__bridge id<MTLTexture>)m_ptr replaceRegion:MTLRegionMake3D(region.Origin.X, region.Origin.Y, region.Origin.Z, region.Size.Width, region.Size.Height, region.Size.Depth)
+                                          mipmapLevel:mipmapLevel
+                                            withBytes:pixelBytes
+                                          bytesPerRow:bytesPerRow];
+    }
+
+    Texture Texture::NewTextureView(PixelFormat pixelFormat)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLTexture>)m_ptr newTextureViewWithPixelFormat:MTLPixelFormat(pixelFormat)] };
+    }
+
+    Texture Texture::NewTextureView(PixelFormat pixelFormat, TextureType textureType, const ns::Range& mipmapLevelRange, const ns::Range& sliceRange)
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge id<MTLTexture>)m_ptr newTextureViewWithPixelFormat:MTLPixelFormat(pixelFormat)
+                                                                                             textureType:MTLTextureType(textureType)
+                                                                                                  levels:NSMakeRange(mipmapLevelRange.Location, mipmapLevelRange.Length)
+                                                                                                  slices:NSMakeRange(sliceRange.Location, sliceRange.Length)] };
+    }
+}
+
+//////////////////////////////////////
+// FILE: vertex_descriptor.mm
+//////////////////////////////////////
+/*
+ * Copyright 2016 Nikolay Aleksiev. All rights reserved.
+ * License: https://github.com/naleksiev/mtlpp/blob/master/LICENSE
+ */
+
+// #include "vertex_descriptor.hpp"
+#include <Metal/MTLVertexDescriptor.h>
+
+namespace mtlpp
+{
+    VertexBufferLayoutDescriptor::VertexBufferLayoutDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLVertexBufferLayoutDescriptor alloc] init] })
+    {
+    }
+
+    uint32_t VertexBufferLayoutDescriptor::GetStride() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLVertexBufferLayoutDescriptor*)m_ptr stride]);
+    }
+
+    uint32_t VertexBufferLayoutDescriptor::GetStepRate() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLVertexBufferLayoutDescriptor*)m_ptr stepRate]);
+    }
+
+    VertexStepFunction VertexBufferLayoutDescriptor::GetStepFunction() const
+    {
+        Validate();
+        return VertexStepFunction([(__bridge MTLVertexBufferLayoutDescriptor*)m_ptr stepFunction]);
+    }
+
+    void VertexBufferLayoutDescriptor::SetStride(uint32_t stride)
+    {
+        Validate();
+        [(__bridge MTLVertexBufferLayoutDescriptor*)m_ptr setStride:stride];
+    }
+
+    void VertexBufferLayoutDescriptor::SetStepRate(uint32_t stepRate)
+    {
+        Validate();
+        [(__bridge MTLVertexBufferLayoutDescriptor*)m_ptr setStepRate:stepRate];
+    }
+
+    void VertexBufferLayoutDescriptor::SetStepFunction(VertexStepFunction stepFunction)
+    {
+        Validate();
+        [(__bridge MTLVertexBufferLayoutDescriptor*)m_ptr setStepFunction:MTLVertexStepFunction(stepFunction)];
+    }
+
+    VertexAttributeDescriptor::VertexAttributeDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLVertexAttributeDescriptor alloc] init] })
+    {
+    }
+
+    VertexFormat VertexAttributeDescriptor::GetFormat() const
+    {
+        Validate();
+        return VertexFormat([(__bridge MTLVertexAttributeDescriptor*)m_ptr format]);
+    }
+
+    uint32_t VertexAttributeDescriptor::GetOffset() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLVertexAttributeDescriptor*)m_ptr offset]);
+    }
+
+    uint32_t VertexAttributeDescriptor::GetBufferIndex() const
+    {
+        Validate();
+        return uint32_t([(__bridge MTLVertexAttributeDescriptor*)m_ptr bufferIndex]);
+    }
+
+    void VertexAttributeDescriptor::SetFormat(VertexFormat format)
+    {
+        Validate();
+        [(__bridge MTLVertexAttributeDescriptor*)m_ptr setFormat:MTLVertexFormat(format)];
+    }
+
+    void VertexAttributeDescriptor::SetOffset(uint32_t offset)
+    {
+        Validate();
+        [(__bridge MTLVertexAttributeDescriptor*)m_ptr setOffset:offset];
+    }
+
+    void VertexAttributeDescriptor::SetBufferIndex(uint32_t bufferIndex)
+    {
+        Validate();
+        [(__bridge MTLVertexAttributeDescriptor*)m_ptr setBufferIndex:bufferIndex];
+    }
+
+    VertexDescriptor::VertexDescriptor() :
+        ns::Object(ns::Handle{ (__bridge void*)[[MTLVertexDescriptor alloc] init] })
+    {
+    }
+
+    ns::Array<VertexBufferLayoutDescriptor> VertexDescriptor::GetLayouts() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLVertexDescriptor*)m_ptr layouts] };
+    }
+
+    ns::Array<VertexAttributeDescriptor> VertexDescriptor::GetAttributes() const
+    {
+        Validate();
+        return ns::Handle{ (__bridge void*)[(__bridge MTLVertexDescriptor*)m_ptr attributes] };
+    }
+
+    void VertexDescriptor::Reset()
+    {
+        Validate();
+        [(__bridge MTLVertexDescriptor*)m_ptr reset];
+    }
+}
+