import vulkan 
, vulkan_utils 

import std/bitops
type 
 Depth_Stencil* = object #of RootObj
   memory*: VkDeviceMemory
   image*: VkImage
   view*: VkImageView

proc create_depth_stencil*( device: VkDevice 
                          , image_format: VKFormat 
                          , depth_format: VKFormat
                          , current_extent: VkExtent2D
                          , gpu_memory_properties: VkPhysicalDeviceMemoryProperties
                          ): Depth_Stencil =
 
 result = Depth_Stencil()
 
 var 
  memReqs: VkMemoryRequirements
  memAllloc: VkMemoryAllocateInfo
  imageViewCI: VkImageViewCreateInfo
  imageCI = VkImageCreateInfo( sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
                             , imageType: VK_IMAGE_TYPE_2D
                             , format: depth_format
                             , extent: VkExtent3D( width:  current_extent.width
                                                 , height: current_extent.height
                                                 , depth: 1
                                                 )
                             , mipLevels: 1
                             , arrayLayers: 1
                             , samples: VK_SAMPLE_COUNT_1_BIT
                             , tiling: VK_IMAGE_TILING_OPTIMAL
                             , usage: VkImageUsageFlags VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
                             , initialLayout: VK_IMAGE_LAYOUT_UNDEFINED
                             )
 
 assert vkCreateImage( device
                      , addr imageCI
                      , nil
                      , addr result.image
                      ) == VK_SUCCESS 

 # Allocate memory for the image (device local) and bind it to our image
 memAllloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
 vkGetImageMemoryRequirements( device
                             , result.image
                             , addr memReqs
                             )
 
 memAllloc.allocationSize = memReqs.size
 memAllloc.memoryTypeIndex = find_memory_with_property( gpu_memory_properties
                                          ,  memReqs.memoryTypeBits
                                          , VkMemoryPropertyFlags VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
                                          )
 
 assert vkAllocateMemory( device
                         , addr memAllloc
                         , nil
                         , addr result.memory
                         ) == VK_SUCCESS 
 
 assert vkBindImageMemory( device
                          , result.image
                          , result.memory
                          , VkDeviceSize 0
                          ) == VK_SUCCESS 

 # Create a view for the depth stencil image
 # Images aren't directly accessed in Vulkan, but rather through views described by a subresource range
 # This allows for multiple views of one image with differing ranges (e.g. for different layers)
 imageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
 imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D
 imageViewCI.format = depth_format
 imageViewCI.subresourceRange.aspectMask = VkImageAspectFlags bitor( VK_IMAGE_ASPECT_DEPTH_BIT.int
                                                                   , VK_IMAGE_ASPECT_STENCIL_BIT.int
                                                                   )
 imageViewCI.subresourceRange.baseMipLevel = 0
 imageViewCI.subresourceRange.levelCount = 1
 imageViewCI.subresourceRange.baseArrayLayer = 0
 imageViewCI.subresourceRange.layerCount = 1
 imageViewCI.image = result.image
 
 assert vkCreateImageView( device
                          , addr imageViewCI
                          , nil
                          , addr result.view
                          ) == VK_SUCCESS 

proc destroyDepthStencil*( device: VkDevice
                         , depth_stencil: var Depth_Stencil
                         ) = 
 discard vkDeviceWaitIdle device
 
 vkDestroyImageView( device
                   , depth_stencil.view
                   , nil
                   )
 
 vkDestroyImage( device
               , depth_stencil.image
               , nil
               )
 
 vkFreeMemory( device
             , depth_stencil.memory
             , nil
             )