achirkin / easytensor

Many-dimensional type-safe numeric ops
https://hackage.haskell.org/package/easytensor
BSD 3-Clause "New" or "Revised" License
46 stars 2 forks source link

Add mechanism for easily getting field offsets #13

Closed Rotaerk closed 5 years ago

Rotaerk commented 6 years ago

I'm not really sure how this would work, exactly, but it seems like there should be some mechanism for easily getting the offset of a field in a PrimBytes instance. In my code I have this:

data Vertex =
  Vertex {
    vtxPos :: Vec3f,
    vtxColor :: Vec3f,
    vtxTexCoord :: Vec2f
  } deriving (Eq, Show, Generic)

instance PrimBytes Vertex

vertexAttributeDescriptionsAt :: Word32 -> [VkVertexInputAttributeDescription]
vertexAttributeDescriptionsAt binding =
  createVk @VkVertexInputAttributeDescription <$> [
    set @"binding" binding &*
    set @"location" 0 &*
    set @"format" VK_FORMAT_R32G32B32_SFLOAT &*
    set @"offset" 0,

    set @"binding" binding &*
    set @"location" 1 &*
    set @"format" VK_FORMAT_R32G32B32_SFLOAT &*
    set @"offset" offset1,

    set @"binding" binding &*
    set @"location" 2 &*
    set @"format" VK_FORMAT_R32G32_SFLOAT &*
    set @"offset" offset2
  ]
  where
    offset1 = fromIntegral (sizeOf $ vtxPos undefined)
    offset2 = offset1 + fromIntegral (sizeOf $ vtxColor undefined)

It'd be nice if I could just say something like offsetOf @"vtxColor". (And for that matter, why not sizeOf @"vtxColor" or just sizeOf @Vec3f or something.) Edit: Eh, not that sizeOf @Vec3f is, itself, bad, but you wouldn't want to do that to get the size of the vtxColor field, in case the type of that field changes.

achirkin commented 6 years ago

Hmm, I stumbled upon the same problem in the vulkan-triangles example, but I could not come up with a nice way to add the offset info to a PrimBytes class.

Perhaps, I could add another class, something like

class PrimBytes t => PrimByteField (name :: Symbol) t where
  offsetOf :: t -> Int

Then, I could add a generic-deriving mechanics for the record types too. Sounds like a good exercise on Generics! :)

UPDATE: The class defined above would require writing the deriving declaration for every record. Doesn't look very handy. Need to think of something a bit smarter.

achirkin commented 5 years ago

Done via Numeric.PrimBytes! The examples are available in Numeric.PrimBytesTest and in vulkan-triangles.