packages feed

easytensor-vulkan 1.0.1.0 → 2.0.0.0

raw patch · 4 files changed

+285/−299 lines, 4 filesdep ~basedep ~dimensionsdep ~easytensorsetup-changed

Dependency ranges changed: base, dimensions, easytensor, vulkan-api

Files

LICENSE view
@@ -1,24 +1,24 @@-Copyright (c) 2018, Artem M. Chirkin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the name of the copyright holder nor the
-      names of its contributors may be used to endorse or promote products
-      derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c) 2018, Artem M. Chirkin+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:+    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.+    * Redistributions in binary form must reproduce the above copyright+      notice, this list of conditions and the following disclaimer in the+      documentation and/or other materials provided with the distribution.+    * Neither the name of the copyright holder nor the+      names of its contributors may be used to endorse or promote products+      derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple
-main = defaultMain
+import Distribution.Simple+main = defaultMain
easytensor-vulkan.cabal view
@@ -1,37 +1,39 @@-name: easytensor-vulkan
-version: 1.0.1.0
-cabal-version: >=1.22
-build-type: Simple
-license: BSD3
-license-file: LICENSE
-copyright: (c) Artem Chirkin
-maintainer: chirkin@arch.ethz.ch
-homepage: https://github.com/achirkin/easytensor#readme
-synopsis: Use easytensor with vulkan-api
-description:
-    Use easytensor DataFrame types with vulkan-api.
-    This package provides an orphan instance of PrimBytes for Vulkan structures,
-    so they can be used as elements of DataFrames.
-    In addition, it provides a few helper functions for working with array-like
-    structures.
-category: geometry, vulkan, bsd3, graphics, library, opengl
-author: Artem Chirkin
-
-source-repository head
-    type: git
-    location: https://github.com/achirkin/easytensor.git
-    subdir: easytensor-vulkan
-
-
-library
-
-    exposed-modules:
-        Graphics.Vulkan.Marshal.Create.DataFrame
-    build-depends:
-        base >=4.10 && <5,
-        dimensions >=1,
-        easytensor >=1,
-        vulkan-api >=1.1.3.1
-    default-language: Haskell2010
-    hs-source-dirs: src
-    ghc-options: -Wall
+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.1.+--+-- see: https://github.com/sol/hpack+--+-- hash: 18ec38832697f0f9a1c888134f69246d19b25aff81258412c304fdee023c00cd++name:           easytensor-vulkan+version:        2.0.0.0+synopsis:       Use easytensor with vulkan-api.+description:    Use easytensor DataFrame types with vulkan-api. This package provides an orphan instance of PrimBytes for Vulkan structures, so they can be used as elements of DataFrames. In addition, it provides a few helper functions for working with array-like structures.+category:       math, geometry, vulkan, bsd3, graphics, library, opengl+homepage:       https://github.com/achirkin/easytensor#readme+bug-reports:    https://github.com/achirkin/easytensor/issues+author:         Artem Chirkin+maintainer:     achirkin@users.noreply.github.com+copyright:      Copyright: (c) 2019 Artem Chirkin+license:        BSD3+license-file:   LICENSE+build-type:     Simple++source-repository head+  type: git+  location: https://github.com/achirkin/easytensor+  subdir: easytensor-vulkan++library+  exposed-modules:+      Graphics.Vulkan.Marshal.Create.DataFrame+  hs-source-dirs:+      src+  ghc-options: -Wall -Wcompat -Wtabs -Wmonomorphism-restriction -Wmissing-local-signatures -Wmissing-home-modules -Widentities -Wredundant-constraints+  build-depends:+      base >=4.11 && <5+    , dimensions >=2 && <3+    , easytensor >=2 && <3+    , vulkan-api >=1.2.0.0 && <2+  default-language: Haskell2010
src/Graphics/Vulkan/Marshal/Create/DataFrame.hs view
@@ -1,236 +1,220 @@-{-# LANGUAGE AllowAmbiguousTypes   #-}
-{-# LANGUAGE DataKinds             #-}
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE MagicHash             #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE PolyKinds             #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-{-# LANGUAGE TypeApplications      #-}
-{-# LANGUAGE TypeFamilies          #-}
-{-# LANGUAGE UnboxedTuples         #-}
-{-# LANGUAGE UndecidableInstances  #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
--- | This module provides an orphan instance of `PrimBytes` for `VulkanMarshalPrim`
---   structures.
---   This enables them to be stored in @DataFrames@ from @easytensor@ package.
---   Thanks to internal structure of Vulkan structures, they can be manipulated
---   inside DataFrames in a very efficient way (just by copying byte arrays).
---   However, original @DataFrames@ are based on unpinned arrays;
---   functions here check this and copy data to new pinned arrays if needed.
---
---   In addition to the orphan instance, this module provides a few
---   handy helper functions.
-module Graphics.Vulkan.Marshal.Create.DataFrame
-  ( setVec, getVec
-  , fillDataFrame, withDFPtr, setDFRef
-    -- * Helpers
-  , VulkanDataFrame (..), VkDataFrame (..)
-  ) where
-
-
-import           Foreign.Storable
-import           GHC.Base
-import           GHC.Ptr                                 (Ptr (..))
-import           Graphics.Vulkan
-import           Graphics.Vulkan.Marshal.Create
-import           Graphics.Vulkan.Marshal.Internal
-import           Numeric.DataFrame
-import           Numeric.DataFrame.Internal.Array.Family (ArraySing (..),
-                                                          ArraySingleton (..))
-import           Numeric.DataFrame.IO
-import           Numeric.Dimensions
-import           Numeric.PrimBytes
-
-
--- | Write an array of values in one go.
-setVec :: forall fname x t
-        . ( FieldType fname x ~ t
-          , PrimBytes (Vector t (FieldArrayLength fname x))
-          , CanWriteFieldArray fname x
-          )
-       => Vector t (FieldArrayLength fname x) -> CreateVkStruct x '[fname] ()
-setVec v = unsafeIOCreate $ \p -> pokeByteOff p (fieldOffset @fname @x) v
-
--- | Get an array of values, possibly without copying
---   (if vector implementation allows).
-getVec :: forall fname x t
-        . ( FieldType fname x ~ t
-          , PrimBytes (Vector t (FieldArrayLength fname x))
-          , CanReadFieldArray fname x
-          , VulkanMarshalPrim x
-          )
-       => x -> Vector t (FieldArrayLength fname x)
-getVec x
-  | ba <- unsafeByteArray x
-  , xaddr <- unsafeAddr x
-  , baddr <- byteArrayContents# ba
-  , I# off <- fieldOffset @fname @x
-  = fromBytes (minusAddr# xaddr baddr +# off) ba
-
-
-instance {-# OVERLAPPABLE#-}
-         (VulkanMarshalPrim a, Storable a) => PrimBytes a where
-    byteSize   a = case sizeOf a of (I# s) -> s
-    {-# INLINE byteSize #-}
-    byteAlign  a = case alignment a of (I# n) -> n
-    {-# INLINE byteAlign #-}
-    byteOffset a = minusAddr# (unsafeAddr a)
-                              (byteArrayContents# (unsafeByteArray a))
-    {-# INLINE byteOffset #-}
-    getBytes = unsafeByteArray
-    {-# INLINE getBytes #-}
-    fromBytes = unsafeFromByteArrayOffset
-    {-# INLINE fromBytes #-}
-    readBytes mba off = unsafeCoerce# (newVkData# f)
-      where
-        f :: Ptr a -> IO ()
-        f (Ptr addr) = IO $ \s ->
-          (# copyMutableByteArrayToAddr# (unsafeCoerce# mba)
-                 off addr (byteSize @a undefined) s
-           , () #)
-    writeBytes mba off a
-      = copyAddrToByteArray# (unsafeAddr a) mba off (byteSize @a undefined)
-    readAddr addr = unsafeCoerce# (peekVkData# (Ptr addr) :: IO a)
-    writeAddr a addr s
-      = case unsafeCoerce# (pokeVkData# (Ptr addr) a :: IO ()) s of
-         (# s', () #) -> s'
-
-
-
-
--- | Run some operation with a pointer to the first item in the frame.
---   All items of the frame are kept in a contiguous memory area accessed by
---   that pointer.
---
---   The function attempts to get an underlying `ByteArray#` without data copy;
---   otherwise, it creates a new pinned `ByteArray#` and passes a pointer to it.
---   Therefore:
---
---     * Sometimes, @Ptr a@ points to the original DF; sometimes, to a copied one.
---     * If the original DF is based on unpinned `ByteArray#`, using this
---       performs a copy anyway.
---
-withDFPtr :: VulkanDataFrame a ds
-          => DataFrame a ds -> (Ptr a -> IO b) -> IO b
-withDFPtr x k
-  | d <- frameToVkData x = do
-  b <- k (Ptr (unsafeAddr d))
-  touchVkData# d
-  return b
-
--- | A variant of `setVkRef` that writes a pointer to a contiguous array of
---   structures.
---
---   Write a pointer to a vulkan structure - member of current structure
---    and make sure the member exists as long as this structure exists.
---
---   Prefer this function to using @unsafePtr a@, because the latter
---    does not keep the dependency information in GC, which results in
---    member structure being garbage-collected and the reference being invalid.
-setDFRef :: forall fname x a ds
-          . ( CanWriteField fname x
-            , FieldType fname x ~ Ptr a
-            , VulkanDataFrame a ds
-            )
-         => DataFrame a ds -> CreateVkStruct x '[fname] ()
-setDFRef v = unsafeCoerce# f -- workaround for the hidden CreateVkStruct constr.
-  where
-    d = frameToVkData v
-    f :: Ptr x -> IO ( ([Ptr ()],[IO ()]) , ())
-    f p = (,) ([],[touchVkData# d])
-       <$> writeField @fname @x p (Ptr (unsafeAddr d))
-
-
-
--- | Given the number of elements, create a new pinned DataFrame and initialize
---   it using the provided function.
---
---   The argument function is called one time with a `Ptr` pointing to the
---   beginning of a contiguous array.
---   This array is converted into a dataframe, possibly without copying.
---
---   It is safe to pass result of this function to `withDFPtr`.
-fillDataFrame :: forall a
-               . PrimBytes a
-              => Word -> (Ptr a -> IO ()) -> IO (Vector a (XN 0))
-fillDataFrame n k
-  | Dx (_ :: Dim n) <- someDimVal n
-  , E <- inferASing' @a @'[n]
-  , E <- inferPrim' @a @'[n]
-  = do
-     mdf <- newPinnedDataFrame
-     withDataFramePtr mdf k
-     XFrame <$> unsafeFreezeDataFrame @a @'[n] mdf
-fillDataFrame _ _ = error "fillDataFrame: impossible combination of arguments."
-
-
-
-
--- | Special data type used to provide @VulkanMarshal@ instance for DataFrames.
---   It is guaranteed to be pinned.
-data VkDataFrame (t :: l) (ds :: [k]) = VkDataFrame# Addr# ByteArray#
-
-instance PrimBytes (DataFrame t ds) => Storable (VkDataFrame t ds) where
-    sizeOf _ = I# (byteSize @(DataFrame t ds) undefined)
-    {-# INLINE sizeOf #-}
-    alignment _ = I# (byteAlign @(DataFrame t ds) undefined)
-    {-# INLINE alignment #-}
-    peek = peekVkData#
-    {-# INLINE peek #-}
-    poke = pokeVkData#
-    {-# INLINE poke #-}
-
-instance VulkanMarshalPrim (VkDataFrame t ds) where
-    unsafeAddr (VkDataFrame# a _) = a
-    {-# INLINE unsafeAddr #-}
-    unsafeByteArray (VkDataFrame# _ b) = b
-    {-# INLINE unsafeByteArray #-}
-    unsafeFromByteArrayOffset off b
-      = VkDataFrame# (plusAddr# (byteArrayContents# b) off) b
-    {-# INLINE unsafeFromByteArrayOffset #-}
-
-instance PrimBytes (DataFrame t ds) => VulkanMarshal (VkDataFrame t ds) where
-    type StructFields (VkDataFrame t ds) = '[]
-    type CUnionType (VkDataFrame t ds) = 'False
-    type ReturnedOnly (VkDataFrame t ds) = 'False
-    type StructExtends (VkDataFrame t ds) = '[]
-
-
-class VulkanDataFrame a (ds :: [k]) where
-    -- | Construct a new @VkDataFrame@ possibly without copying.
-    --   It performs no copy if the @DataFrame@ implementation is a pinned @ByteArray#@.
-    frameToVkData :: DataFrame a ds -> VkDataFrame a ds
-    -- | Construct a new (pinned if implementation allows) DataFrame from VK data,
-    --   possibly without copying.
-    --
-    --   Note, this is a user responsibility to check if the real size of @VkDataFrame@
-    --   and the dimensionality @ds@ agree.
-    vkDataToFrame :: Dims ds -> VkDataFrame a ds -> DataFrame a ds
-
-
-instance (PrimBytes a, ArraySingleton a ds, Dimensions ds)
-      => VulkanDataFrame a (ds :: [Nat]) where
-    frameToVkData x = case aSing @a @ds of
-      -- Generic ByteArray implementation
-      ABase
-        | ba <- getBytes x
-        , isTrue# (isByteArrayPinned# ba) -- check if it is pinned
-        -> unsafeFromByteArrayOffset (byteOffset x) ba
-      -- For other implementations we have no other options than just to copy the data
-      _ | E <- inferPrim x -> case runRW#
-        ( \s0 -> case newAlignedPinnedByteArray#
-                        (byteSize @(DataFrame a ds) undefined)
-                        (byteAlign @(DataFrame a ds) undefined) s0 of
-          (# s1, mba #) -> unsafeFreezeByteArray# mba (writeBytes mba 0# x s1)
-        ) of (# _, ba #) -> VkDataFrame# (byteArrayContents# ba) ba
-
-    vkDataToFrame _ (VkDataFrame# addr ba)
-      | E <- inferPrim' @a @ds
-      = fromBytes (addr `minusAddr#` byteArrayContents# ba) ba
-
-instance (PrimBytes a, All KnownXNatType ds)
-      => VulkanDataFrame a (ds :: [XNat]) where
-    frameToVkData (XFrame x) = unsafeCoerce# (frameToVkData x)
-    vkDataToFrame (XDims (ds :: Dims ns)) d
-      | E <- inferASing' @a @ns = XFrame (vkDataToFrame ds (unsafeCoerce# d))
+{-# LANGUAGE AllowAmbiguousTypes   #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MagicHash             #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds             #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeApplications      #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE UnboxedTuples         #-}+{-# LANGUAGE UndecidableInstances  #-}+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- | This module provides an orphan instance of `PrimBytes` for `VulkanMarshalPrim`+--   structures.+--   This enables them to be stored in @DataFrames@ from @easytensor@ package.+--   Thanks to internal structure of Vulkan structures, they can be manipulated+--   inside DataFrames in a very efficient way (just by copying byte arrays).+--   However, original @DataFrames@ are based on unpinned arrays;+--   functions here check this and copy data to new pinned arrays if needed.+--+--   In addition to the orphan instance, this module provides a few+--   handy helper functions.+module Graphics.Vulkan.Marshal.Create.DataFrame+  ( setVec, getVec+  , fillDataFrame, withDFPtr, setDFRef+    -- * Helpers+  , VulkanDataFrame (..), VkDataFrame+  ) where+++import Foreign.Storable+import GHC.Base+import GHC.Ptr                          (Ptr (..))+import Graphics.Vulkan+import Graphics.Vulkan.Marshal.Create+import Graphics.Vulkan.Marshal.Internal+import Numeric.DataFrame+import Numeric.DataFrame.IO+import Numeric.Dimensions+import Numeric.PrimBytes+++-- | Write an array of values in one go.+setVec :: forall fname x t+        . ( FieldType fname x ~ t+          , PrimBytes t+          , KnownDim (FieldArrayLength fname x)+          , CanWriteFieldArray fname x+          )+       => Vector t (FieldArrayLength fname x) -> CreateVkStruct x '[fname] ()+setVec v+  | Dict <- inferKnownBackend @t @'[FieldArrayLength fname x]+    = unsafeIOCreate $ \p -> pokeByteOff p (fieldOffset @fname @x) v+++-- | Get an array of values, possibly without copying+--   (if vector implementation allows).+getVec :: forall fname x t a+        . ( FieldType fname x ~ t+          , PrimBytes t+          , KnownDim (FieldArrayLength fname x)+          , CanReadFieldArray fname x+          , x ~ VulkanStruct a+          )+       => x -> Vector t (FieldArrayLength fname x)+getVec x+  | ba <- unsafeByteArray x+  , xaddr <- unsafeAddr x+  , baddr <- byteArrayContents# ba+  , I# off <- fieldOffset @fname @x+  , Dict <- inferKnownBackend @t @'[FieldArrayLength fname x]+  = fromBytes (minusAddr# xaddr baddr +# off) ba++instance Storable (VulkanStruct a)=> PrimBytes (VulkanStruct a) where+    type PrimFields (VulkanStruct a) = '[]+    byteSize   a = case sizeOf a of (I# s) -> s+    {-# INLINE byteSize #-}+    byteAlign  a = case alignment a of (I# n) -> n+    {-# INLINE byteAlign #-}+    byteOffset a = minusAddr# (unsafeAddr a)+                                  (byteArrayContents# (unsafeByteArray a))+    {-# INLINE byteOffset #-}+    getBytes = unsafeByteArray+    {-# INLINE getBytes #-}+    fromBytes = unsafeFromByteArrayOffset+    {-# INLINE fromBytes #-}+    readBytes mba off = unsafeCoerce# (newVkData# @a f)+      where+        f :: Ptr (VulkanStruct a) -> IO ()+        f (Ptr addr) = IO $ \s ->+          (# copyMutableByteArrayToAddr# (unsafeCoerce# mba)+                 off addr (byteSize @(VulkanStruct a) undefined) s+           , () #)+    writeBytes mba off a+      = copyAddrToByteArray# (unsafeAddr a) mba off (byteSize @(VulkanStruct a) undefined)+    readAddr addr = unsafeCoerce# (peekVkData# (Ptr addr) :: IO (VulkanStruct a))+    writeAddr a addr s+      = case unsafeCoerce# (pokeVkData# (Ptr addr) a :: IO ()) s of+         (# s', () #) -> s'+    byteFieldOffset _ _ = negateInt# 1#++++-- | Run some operation with a pointer to the first item in the frame.+--   All items of the frame are kept in a contiguous memory area accessed by+--   that pointer.+--+--   The function attempts to get an underlying `ByteArray#` without data copy;+--   otherwise, it creates a new pinned `ByteArray#` and passes a pointer to it.+--   Therefore:+--+--     * Sometimes, @Ptr a@ points to the original DF; sometimes, to a copied one.+--     * If the original DF is based on unpinned `ByteArray#`, using this+--       performs a copy anyway.+--+withDFPtr :: VulkanDataFrame a ds+          => DataFrame a ds -> (Ptr a -> IO b) -> IO b+withDFPtr x k+  | d <- frameToVkData x = do+  b <- k (Ptr (unsafeAddr d))+  touchVkData# d+  return b++-- | A variant of `setVkRef` that writes a pointer to a contiguous array of+--   structures.+--+--   Write a pointer to a vulkan structure - member of current structure+--    and make sure the member exists as long as this structure exists.+--+--   Prefer this function to using @unsafePtr a@, because the latter+--    does not keep the dependency information in GC, which results in+--    member structure being garbage-collected and the reference being invalid.+setDFRef :: forall fname x a ds+          . ( CanWriteField fname x+            , FieldType fname x ~ Ptr a+            , VulkanDataFrame a ds+            )+         => DataFrame a ds -> CreateVkStruct x '[fname] ()+setDFRef v = unsafeCoerce# f -- workaround for the hidden CreateVkStruct constr.+  where+    d = frameToVkData v+    f :: Ptr x -> IO ( ([Ptr ()],[IO ()]) , ())+    f p = (,) ([],[touchVkData# d])+       <$> writeField @fname @x p (Ptr (unsafeAddr d))++++-- | Given the number of elements, create a new pinned DataFrame and initialize+--   it using the provided function.+--+--   The argument function is called one time with a `Ptr` pointing to the+--   beginning of a contiguous array.+--   This array is converted into a dataframe, possibly without copying.+--+--   It is safe to pass result of this function to `withDFPtr`.+fillDataFrame :: forall a+               . PrimBytes a+              => Word -> (Ptr a -> IO ()) -> IO (Vector a (XN 0))+fillDataFrame n k+  | Dx (_ :: Dim n) <- someDimVal n+  , Dict <- inferKnownBackend @a @'[n]+  = do+     mdf <- newPinnedDataFrame+     withDataFramePtr mdf k+     XFrame <$> unsafeFreezeDataFrame @a @'[n] mdf+fillDataFrame _ _ = error "fillDataFrame: impossible combination of arguments."+++++-- | Special data type used to provide @VulkanMarshal@ instance for DataFrames.+--   It is guaranteed to be pinned.+type VkDataFrame (t :: l) (ds :: [k]) = VulkanStruct (DataFrame t ds)++instance PrimBytes (DataFrame t ds) => Storable (VkDataFrame t ds) where+    sizeOf _ = I# (byteSize @(DataFrame t ds) undefined)+    {-# INLINE sizeOf #-}+    alignment _ = I# (byteAlign @(DataFrame t ds) undefined)+    {-# INLINE alignment #-}+    peek = peekVkData#+    {-# INLINE peek #-}+    poke = pokeVkData#+    {-# INLINE poke #-}++instance PrimBytes (DataFrame t ds) => VulkanMarshal (VkDataFrame t ds) where+    type StructFields (VkDataFrame t ds) = '[]+    type CUnionType (VkDataFrame t ds) = 'False+    type ReturnedOnly (VkDataFrame t ds) = 'False+    type StructExtends (VkDataFrame t ds) = '[]+++class VulkanDataFrame a (ds :: [k]) where+    -- | Construct a new @VkDataFrame@ possibly without copying.+    --   It performs no copy if the @DataFrame@ implementation is a pinned @ByteArray#@.+    frameToVkData :: DataFrame a ds -> VkDataFrame a ds+    -- | Construct a new (pinned if implementation allows) DataFrame from VK data,+    --   possibly without copying.+    --+    --   Note, this is a user responsibility to check if the real size of @VkDataFrame@+    --   and the dimensionality @ds@ agree.+    vkDataToFrame :: Dims ds -> VkDataFrame a ds -> DataFrame a ds+++instance (PrimBytes a, Dimensions ds)+      => VulkanDataFrame a (ds :: [Nat]) where+    frameToVkData x+      | Dict <- inferKnownBackend @a @ds+        = unsafeFromByteArrayOffset (byteOffset x) (getBytesPinned x)+    vkDataToFrame _ (VulkanStruct addr ba)+      | Dict <- inferKnownBackend @a @ds+        = fromBytes (addr `minusAddr#` byteArrayContents# ba) ba++instance (PrimBytes a, All KnownXNatType ds)+      => VulkanDataFrame a (ds :: [XNat]) where+    frameToVkData (XFrame x) = unsafeCoerce# (frameToVkData x)+    vkDataToFrame (XDims (ds :: Dims ns)) d+      | Dict <- inferKnownBackend @a @ns+        = XFrame (vkDataToFrame ds (unsafeCoerce# d))