Browse Source

Vulkan: beginnings of texture+sampler support

rdb 10 years ago
parent
commit
0a89e5e33f

+ 4 - 0
panda/src/vulkandisplay/config_vulkandisplay.cxx

@@ -15,7 +15,9 @@
 #include "vulkanGraphicsPipe.h"
 #include "vulkanGraphicsPipe.h"
 #include "vulkanGraphicsStateGuardian.h"
 #include "vulkanGraphicsStateGuardian.h"
 #include "vulkanGraphicsWindow.h"
 #include "vulkanGraphicsWindow.h"
+#include "vulkanSamplerContext.h"
 #include "vulkanShaderContext.h"
 #include "vulkanShaderContext.h"
+#include "vulkanTextureContext.h"
 #include "vulkanVertexBufferContext.h"
 #include "vulkanVertexBufferContext.h"
 #include "graphicsPipeSelection.h"
 #include "graphicsPipeSelection.h"
 #include "dconfig.h"
 #include "dconfig.h"
@@ -47,7 +49,9 @@ init_libvulkandisplay() {
   VulkanGraphicsPipe::init_type();
   VulkanGraphicsPipe::init_type();
   VulkanGraphicsStateGuardian::init_type();
   VulkanGraphicsStateGuardian::init_type();
   VulkanGraphicsWindow::init_type();
   VulkanGraphicsWindow::init_type();
+  VulkanSamplerContext::init_type();
   VulkanShaderContext::init_type();
   VulkanShaderContext::init_type();
+  VulkanTextureContext::init_type();
   VulkanVertexBufferContext::init_type();
   VulkanVertexBufferContext::init_type();
 
 
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();

+ 2 - 0
panda/src/vulkandisplay/p3vulkandisplay_composite1.cxx

@@ -2,5 +2,7 @@
 #include "vulkanGraphicsPipe.cxx"
 #include "vulkanGraphicsPipe.cxx"
 #include "vulkanGraphicsStateGuardian.cxx"
 #include "vulkanGraphicsStateGuardian.cxx"
 #include "vulkanGraphicsWindow.cxx"
 #include "vulkanGraphicsWindow.cxx"
+#include "vulkanSamplerContext.cxx"
 #include "vulkanShaderContext.cxx"
 #include "vulkanShaderContext.cxx"
+#include "vulkanTextureContext.cxx"
 #include "vulkanVertexBufferContext.cxx"
 #include "vulkanVertexBufferContext.cxx"

+ 203 - 0
panda/src/vulkandisplay/vulkanGraphicsPipe.cxx

@@ -160,6 +160,209 @@ VulkanGraphicsPipe() {
   _queue_families.resize(num_families);
   _queue_families.resize(num_families);
   vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &num_families, &_queue_families[0]);
   vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &num_families, &_queue_families[0]);
 
 
+  // Get a list of supported texture formats.
+  if (vulkandisplay_cat.is_debug()) {
+    vulkandisplay_cat.debug() << "Supported texture formats:\n";
+
+    static const char *const format_strings[] = {
+      "UNDEFINED",
+      "R4G4_UNORM_PACK8",
+      "R4G4B4A4_UNORM_PACK16",
+      "B4G4R4A4_UNORM_PACK16",
+      "R5G6B5_UNORM_PACK16",
+      "B5G6R5_UNORM_PACK16",
+      "R5G5B5A1_UNORM_PACK16",
+      "B5G5R5A1_UNORM_PACK16",
+      "A1R5G5B5_UNORM_PACK16",
+      "R8_UNORM",
+      "R8_SNORM",
+      "R8_USCALED",
+      "R8_SSCALED",
+      "R8_UINT",
+      "R8_SINT",
+      "R8_SRGB",
+      "R8G8_UNORM",
+      "R8G8_SNORM",
+      "R8G8_USCALED",
+      "R8G8_SSCALED",
+      "R8G8_UINT",
+      "R8G8_SINT",
+      "R8G8_SRGB",
+      "R8G8B8_UNORM",
+      "R8G8B8_SNORM",
+      "R8G8B8_USCALED",
+      "R8G8B8_SSCALED",
+      "R8G8B8_UINT",
+      "R8G8B8_SINT",
+      "R8G8B8_SRGB",
+      "B8G8R8_UNORM",
+      "B8G8R8_SNORM",
+      "B8G8R8_USCALED",
+      "B8G8R8_SSCALED",
+      "B8G8R8_UINT",
+      "B8G8R8_SINT",
+      "B8G8R8_SRGB",
+      "R8G8B8A8_UNORM",
+      "R8G8B8A8_SNORM",
+      "R8G8B8A8_USCALED",
+      "R8G8B8A8_SSCALED",
+      "R8G8B8A8_UINT",
+      "R8G8B8A8_SINT",
+      "R8G8B8A8_SRGB",
+      "B8G8R8A8_UNORM",
+      "B8G8R8A8_SNORM",
+      "B8G8R8A8_USCALED",
+      "B8G8R8A8_SSCALED",
+      "B8G8R8A8_UINT",
+      "B8G8R8A8_SINT",
+      "B8G8R8A8_SRGB",
+      "A8B8G8R8_UNORM_PACK32",
+      "A8B8G8R8_SNORM_PACK32",
+      "A8B8G8R8_USCALED_PACK32",
+      "A8B8G8R8_SSCALED_PACK32",
+      "A8B8G8R8_UINT_PACK32",
+      "A8B8G8R8_SINT_PACK32",
+      "A8B8G8R8_SRGB_PACK32",
+      "A2R10G10B10_UNORM_PACK32",
+      "A2R10G10B10_SNORM_PACK32",
+      "A2R10G10B10_USCALED_PACK32",
+      "A2R10G10B10_SSCALED_PACK32",
+      "A2R10G10B10_UINT_PACK32",
+      "A2R10G10B10_SINT_PACK32",
+      "A2B10G10R10_UNORM_PACK32",
+      "A2B10G10R10_SNORM_PACK32",
+      "A2B10G10R10_USCALED_PACK32",
+      "A2B10G10R10_SSCALED_PACK32",
+      "A2B10G10R10_UINT_PACK32",
+      "A2B10G10R10_SINT_PACK32",
+      "R16_UNORM",
+      "R16_SNORM",
+      "R16_USCALED",
+      "R16_SSCALED",
+      "R16_UINT",
+      "R16_SINT",
+      "R16_SFLOAT",
+      "R16G16_UNORM",
+      "R16G16_SNORM",
+      "R16G16_USCALED",
+      "R16G16_SSCALED",
+      "R16G16_UINT",
+      "R16G16_SINT",
+      "R16G16_SFLOAT",
+      "R16G16B16_UNORM",
+      "R16G16B16_SNORM",
+      "R16G16B16_USCALED",
+      "R16G16B16_SSCALED",
+      "R16G16B16_UINT",
+      "R16G16B16_SINT",
+      "R16G16B16_SFLOAT",
+      "R16G16B16A16_UNORM",
+      "R16G16B16A16_SNORM",
+      "R16G16B16A16_USCALED",
+      "R16G16B16A16_SSCALED",
+      "R16G16B16A16_UINT",
+      "R16G16B16A16_SINT",
+      "R16G16B16A16_SFLOAT",
+      "R32_UINT",
+      "R32_SINT",
+      "R32_SFLOAT",
+      "R32G32_UINT",
+      "R32G32_SINT",
+      "R32G32_SFLOAT",
+      "R32G32B32_UINT",
+      "R32G32B32_SINT",
+      "R32G32B32_SFLOAT",
+      "R32G32B32A32_UINT",
+      "R32G32B32A32_SINT",
+      "R32G32B32A32_SFLOAT",
+      "R64_UINT",
+      "R64_SINT",
+      "R64_SFLOAT",
+      "R64G64_UINT",
+      "R64G64_SINT",
+      "R64G64_SFLOAT",
+      "R64G64B64_UINT",
+      "R64G64B64_SINT",
+      "R64G64B64_SFLOAT",
+      "R64G64B64A64_UINT",
+      "R64G64B64A64_SINT",
+      "R64G64B64A64_SFLOAT",
+      "B10G11R11_UFLOAT_PACK32",
+      "E5B9G9R9_UFLOAT_PACK32",
+      "D16_UNORM",
+      "X8_D24_UNORM_PACK32",
+      "D32_SFLOAT",
+      "S8_UINT",
+      "D16_UNORM_S8_UINT",
+      "D24_UNORM_S8_UINT",
+      "D32_SFLOAT_S8_UINT",
+      "BC1_RGB_UNORM_BLOCK",
+      "BC1_RGB_SRGB_BLOCK",
+      "BC1_RGBA_UNORM_BLOCK",
+      "BC1_RGBA_SRGB_BLOCK",
+      "BC2_UNORM_BLOCK",
+      "BC2_SRGB_BLOCK",
+      "BC3_UNORM_BLOCK",
+      "BC3_SRGB_BLOCK",
+      "BC4_UNORM_BLOCK",
+      "BC4_SNORM_BLOCK",
+      "BC5_UNORM_BLOCK",
+      "BC5_SNORM_BLOCK",
+      "BC6H_UFLOAT_BLOCK",
+      "BC6H_SFLOAT_BLOCK",
+      "BC7_UNORM_BLOCK",
+      "BC7_SRGB_BLOCK",
+      "ETC2_R8G8B8_UNORM_BLOCK",
+      "ETC2_R8G8B8_SRGB_BLOCK",
+      "ETC2_R8G8B8A1_UNORM_BLOCK",
+      "ETC2_R8G8B8A1_SRGB_BLOCK",
+      "ETC2_R8G8B8A8_UNORM_BLOCK",
+      "ETC2_R8G8B8A8_SRGB_BLOCK",
+      "EAC_R11_UNORM_BLOCK",
+      "EAC_R11_SNORM_BLOCK",
+      "EAC_R11G11_UNORM_BLOCK",
+      "EAC_R11G11_SNORM_BLOCK",
+      "ASTC_4x4_UNORM_BLOCK",
+      "ASTC_4x4_SRGB_BLOCK",
+      "ASTC_5x4_UNORM_BLOCK",
+      "ASTC_5x4_SRGB_BLOCK",
+      "ASTC_5x5_UNORM_BLOCK",
+      "ASTC_5x5_SRGB_BLOCK",
+      "ASTC_6x5_UNORM_BLOCK",
+      "ASTC_6x5_SRGB_BLOCK",
+      "ASTC_6x6_UNORM_BLOCK",
+      "ASTC_6x6_SRGB_BLOCK",
+      "ASTC_8x5_UNORM_BLOCK",
+      "ASTC_8x5_SRGB_BLOCK",
+      "ASTC_8x6_UNORM_BLOCK",
+      "ASTC_8x6_SRGB_BLOCK",
+      "ASTC_8x8_UNORM_BLOCK",
+      "ASTC_8x8_SRGB_BLOCK",
+      "ASTC_10x5_UNORM_BLOCK",
+      "ASTC_10x5_SRGB_BLOCK",
+      "ASTC_10x6_UNORM_BLOCK",
+      "ASTC_10x6_SRGB_BLOCK",
+      "ASTC_10x8_UNORM_BLOCK",
+      "ASTC_10x8_SRGB_BLOCK",
+      "ASTC_10x10_UNORM_BLOCK",
+      "ASTC_10x10_SRGB_BLOCK",
+      "ASTC_12x10_UNORM_BLOCK",
+      "ASTC_12x10_SRGB_BLOCK",
+      "ASTC_12x12_UNORM_BLOCK",
+      "ASTC_12x12_SRGB_BLOCK",
+    };
+
+    for (int i = 1; i < VK_FORMAT_RANGE_SIZE; ++i) {
+      VkFormatProperties fmt_props;
+      vkGetPhysicalDeviceFormatProperties(_gpu, (VkFormat)i, &fmt_props);
+
+      if (fmt_props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
+        vulkandisplay_cat.debug()
+          << "  VK_FORMAT_" << format_strings[i] << "\n";
+      }
+    }
+  }
+
   _is_valid = true;
   _is_valid = true;
 }
 }
 
 

+ 372 - 4
panda/src/vulkandisplay/vulkanGraphicsStateGuardian.cxx

@@ -160,7 +160,7 @@ VulkanGraphicsStateGuardian(GraphicsEngine *engine, VulkanGraphicsPipe *pipe,
   _supports_3d_texture = true;
   _supports_3d_texture = true;
   _supports_2d_texture_array = true;
   _supports_2d_texture_array = true;
   _supports_cube_map = true;
   _supports_cube_map = true;
-  _supports_buffer_texture = true;
+  _supports_buffer_texture = false; //TODO: add support.
   _supports_cube_map_array = (features.imageCubeArray != VK_FALSE);
   _supports_cube_map_array = (features.imageCubeArray != VK_FALSE);
   _supports_tex_non_pow2 = true;
   _supports_tex_non_pow2 = true;
   _supports_texture_srgb = true;
   _supports_texture_srgb = true;
@@ -251,8 +251,342 @@ get_driver_renderer() {
  * call Texture::prepare().
  * call Texture::prepare().
  */
  */
 TextureContext *VulkanGraphicsStateGuardian::
 TextureContext *VulkanGraphicsStateGuardian::
-prepare_texture(Texture *, int view) {
-  return (TextureContext *)NULL;
+prepare_texture(Texture *texture, int view) {
+  VulkanGraphicsPipe *vkpipe;
+  DCAST_INTO_R(vkpipe, get_pipe(), NULL);
+
+  VkResult err;
+  VkImageCreateInfo image_info;
+  image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+  image_info.pNext = NULL;
+  image_info.flags = 0;
+
+  int depth = 1;
+  int num_layers = 1;
+
+  switch (texture->get_texture_type()) {
+  case Texture::TT_1d_texture:
+    image_info.imageType = VK_IMAGE_TYPE_1D;
+    break;
+
+  case Texture::TT_cube_map:
+  case Texture::TT_cube_map_array:
+    image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+    // Fall through
+  case Texture::TT_2d_texture:
+  case Texture::TT_2d_texture_array:
+    image_info.imageType = VK_IMAGE_TYPE_2D;
+    num_layers = texture->get_z_size();
+    break;
+
+  case Texture::TT_3d_texture:
+    image_info.imageType = VK_IMAGE_TYPE_3D;
+    depth = texture->get_z_size();
+    break;
+
+  case Texture::TT_buffer_texture:
+    // Not yet supported.
+    return (TextureContext *)NULL;
+  }
+
+  //TODO: compressed formats.
+  //TODO: check format support and adjust as appropriate.  In particular,
+  // rgb8 does not seem to be supported on most drivers.
+  Texture::Format format = texture->get_format();
+  bool is_signed = !Texture::is_unsigned(texture->get_component_type());
+  switch (format) {
+  case Texture::F_depth_stencil:
+    image_info.format = VK_FORMAT_D24_UNORM_S8_UINT;
+    break;
+  case Texture::F_color_index:
+    image_info.format = VK_FORMAT_R8_UINT;
+    break;
+  case Texture::F_red:
+  case Texture::F_green:
+  case Texture::F_blue:
+    image_info.format = (VkFormat)(VK_FORMAT_R8_UNORM + is_signed);
+    break;
+  case Texture::F_rgb:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8B8_UNORM + is_signed);
+    break;
+  case Texture::F_rgb5:
+    image_info.format = VK_FORMAT_R5G6B5_UNORM_PACK16;
+    break;
+  case Texture::F_rgb8:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8B8_UNORM + is_signed);
+    break;
+  case Texture::F_rgb12:
+    image_info.format = (VkFormat)(VK_FORMAT_R16G16B16_UNORM + is_signed);
+    break;
+  case Texture::F_rgb332:
+    image_info.format = VK_FORMAT_R5G6B5_UNORM_PACK16;
+    break;
+  case Texture::F_rgba:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8B8A8_UNORM + is_signed);
+    break;
+  case Texture::F_rgbm:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8B8A8_UNORM + is_signed);
+    break;
+  case Texture::F_rgba4:
+    image_info.format = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
+    break;
+  case Texture::F_rgba5:
+    image_info.format = VK_FORMAT_R5G5B5A1_UNORM_PACK16;
+    break;
+  case Texture::F_rgba8:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8B8A8_UNORM + is_signed);
+    break;
+  case Texture::F_rgba12:
+    image_info.format = (VkFormat)(VK_FORMAT_R16G16B16A16_UNORM + is_signed);
+    break;
+  case Texture::F_luminance:
+    image_info.format = (VkFormat)(VK_FORMAT_R8_UNORM + is_signed);
+    break;
+  case Texture::F_luminance_alpha:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8_UNORM + is_signed);
+    break;
+  case Texture::F_luminance_alphamask:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8_UNORM + is_signed);
+    break;
+  case Texture::F_rgba16:
+    image_info.format = (VkFormat)(VK_FORMAT_R16G16B16A16_UNORM + is_signed);
+    break;
+  case Texture::F_rgba32:
+    image_info.format = VK_FORMAT_R32G32B32A32_SFLOAT;
+    break;
+  case Texture::F_depth_component:
+    image_info.format = (VkFormat)(VK_FORMAT_D16_UNORM + is_signed);
+    break;
+  case Texture::F_depth_component16:
+    image_info.format = (VkFormat)(VK_FORMAT_D16_UNORM + is_signed);
+    break;
+  case Texture::F_depth_component24:
+    image_info.format = (VkFormat)(VK_FORMAT_X8_D24_UNORM_PACK32 + is_signed);
+    break;
+  case Texture::F_depth_component32:
+    image_info.format = VK_FORMAT_D32_SFLOAT;
+    break;
+  case Texture::F_r16:
+    image_info.format = (VkFormat)(VK_FORMAT_R16_UNORM + is_signed);
+    break;
+  case Texture::F_rg16:
+    image_info.format = (VkFormat)(VK_FORMAT_R16G16_UNORM + is_signed);
+    break;
+  case Texture::F_rgb16:
+    image_info.format = (VkFormat)(VK_FORMAT_R16G16B16_UNORM + is_signed);
+    break;
+  case Texture::F_srgb:
+    image_info.format = VK_FORMAT_R8G8B8_SRGB;
+    break;
+  case Texture::F_srgb_alpha:
+    image_info.format = VK_FORMAT_R8G8B8A8_SRGB;
+    break;
+  case Texture::F_sluminance:
+    image_info.format = VK_FORMAT_R8_SRGB;
+    break;
+  case Texture::F_sluminance_alpha:
+    image_info.format = VK_FORMAT_R8G8B8A8_SRGB;
+    break;
+  case Texture::F_r32i:
+    image_info.format = (VkFormat)(VK_FORMAT_R32_UINT + is_signed);
+    break;
+  case Texture::F_r32:
+    image_info.format = VK_FORMAT_R32_SFLOAT;
+    break;
+  case Texture::F_rg32:
+    image_info.format = VK_FORMAT_R32G32_SFLOAT;
+    break;
+  case Texture::F_rgb32:
+    image_info.format = VK_FORMAT_R32G32B32_SFLOAT;
+    break;
+  case Texture::F_r8i:
+    image_info.format = (VkFormat)(VK_FORMAT_R8_UINT + is_signed);
+    break;
+  case Texture::F_rg8i:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8_UINT + is_signed);
+    break;
+  case Texture::F_rgb8i:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8B8_UINT + is_signed);
+    break;
+  case Texture::F_rgba8i:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8B8A8_UINT + is_signed);
+    break;
+  case Texture::F_r11_g11_b10:
+    image_info.format = VK_FORMAT_B10G11R11_UFLOAT_PACK32;
+    break;
+  case Texture::F_rgb9_e5:
+    image_info.format = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32;
+    break;
+  case Texture::F_rgb10_a2:
+    image_info.format = (VkFormat)(VK_FORMAT_A2R10G10B10_UNORM_PACK32 + is_signed);
+    break;
+  case Texture::F_rg:
+    image_info.format = (VkFormat)(VK_FORMAT_R8G8_UNORM + is_signed);
+    break;
+  }
+
+  int num_levels = 1;
+  if (texture->uses_mipmaps()) {
+    num_levels = texture->get_expected_num_mipmap_levels();
+  }
+
+  //TODO: check that size is acceptable.
+  image_info.extent.width = texture->get_x_size();
+  image_info.extent.height = texture->get_y_size();
+  image_info.extent.depth = depth;
+  image_info.mipLevels = num_levels;
+  image_info.arrayLayers = num_layers;
+  image_info.samples = VK_SAMPLE_COUNT_1_BIT;
+  image_info.tiling = VK_IMAGE_TILING_LINEAR;
+  image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
+  image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+  image_info.queueFamilyIndexCount = 0;
+  image_info.pQueueFamilyIndices = NULL;
+  image_info.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+  VkImage image;
+  err = vkCreateImage(_device, &image_info, NULL, &image);
+  if (err) {
+    vulkan_error(err, "Failed to create texture image");
+    return (TextureContext *)NULL;
+  }
+
+  // Get the memory requirements, and find an appropriate heap to alloc in.
+  VkMemoryRequirements mem_reqs;
+  vkGetImageMemoryRequirements(_device, image, &mem_reqs);
+
+  VkMemoryAllocateInfo alloc_info;
+  alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+  alloc_info.pNext = NULL;
+  alloc_info.allocationSize = mem_reqs.size;
+
+  if (!vkpipe->find_memory_type(alloc_info.memoryTypeIndex, mem_reqs.memoryTypeBits, 0)) {
+    vulkan_error(err, "Failed to find memory heap to allocate texture memory");
+    return (TextureContext *)NULL;
+  }
+
+  VkDeviceMemory memory;
+  err = vkAllocateMemory(_device, &alloc_info, NULL, &memory);
+  if (err) {
+    vulkan_error(err, "Failed to allocate memory for texture image");
+    return (TextureContext *)NULL;
+  }
+
+  // Bind memory to image.
+  err = vkBindImageMemory(_device, image, memory, 0);
+  if (err) {
+    vulkan_error(err, "Failed to bind memory to texture image");
+    return (TextureContext *)NULL;
+  }
+
+  // Now we'll create an image view that describes how we interpret the image.
+  VkImageViewCreateInfo view_info;
+  view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+  view_info.pNext = NULL;
+  view_info.flags = 0;
+  view_info.image = image;
+
+  switch (texture->get_texture_type()) {
+  case Texture::TT_1d_texture:
+    view_info.viewType = VK_IMAGE_VIEW_TYPE_1D;
+    break;
+  case Texture::TT_2d_texture:
+    view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+    break;
+  case Texture::TT_3d_texture:
+    view_info.viewType = VK_IMAGE_VIEW_TYPE_3D;
+    break;
+  case Texture::TT_2d_texture_array:
+    view_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+    break;
+  case Texture::TT_cube_map:
+    view_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
+    break;
+  case Texture::TT_buffer_texture: //TODO: figure out buffer textures in Vulkan.
+    view_info.viewType = VK_IMAGE_VIEW_TYPE_1D;
+    break;
+  case Texture::TT_cube_map_array:
+    view_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+    break;
+  }
+
+  view_info.format = image_info.format;
+
+  // We use the swizzle mask to emulate deprecated formats.
+  switch (format) {
+  case Texture::F_green:
+    view_info.components.r = VK_COMPONENT_SWIZZLE_ZERO;
+    view_info.components.g = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.b = VK_COMPONENT_SWIZZLE_ZERO;
+    view_info.components.a = VK_COMPONENT_SWIZZLE_ONE;
+    break;
+
+  case Texture::F_blue:
+    view_info.components.r = VK_COMPONENT_SWIZZLE_ZERO;
+    view_info.components.g = VK_COMPONENT_SWIZZLE_ZERO;
+    view_info.components.b = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.a = VK_COMPONENT_SWIZZLE_ZERO;
+    break;
+
+  case Texture::F_alpha:
+    view_info.components.r = VK_COMPONENT_SWIZZLE_ZERO;
+    view_info.components.g = VK_COMPONENT_SWIZZLE_ZERO;
+    view_info.components.b = VK_COMPONENT_SWIZZLE_ZERO;
+    view_info.components.a = VK_COMPONENT_SWIZZLE_R;
+    break;
+
+  case Texture::F_luminance:
+  case Texture::F_sluminance:
+    view_info.components.r = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.g = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.b = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.a = VK_COMPONENT_SWIZZLE_ONE;
+    break;
+
+  case Texture::F_luminance_alpha:
+    // F_sluminance_alpha can't be emulated using R8G8 and a swizzle mask
+    // because we need the second channel to be linear.  Beh.
+    view_info.components.r = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.g = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.b = VK_COMPONENT_SWIZZLE_R;
+    view_info.components.a = VK_COMPONENT_SWIZZLE_G;
+    break;
+
+  default:
+    view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+    view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+    view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+    view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+    break;
+  }
+
+  if (format == Texture::F_depth_stencil ||
+      format == Texture::F_depth_component ||
+      format == Texture::F_depth_component16 ||
+      format == Texture::F_depth_component24 ||
+      format == Texture::F_depth_component32) {
+    view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+  } else {
+    view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+  }
+  view_info.subresourceRange.baseMipLevel = 0;
+  view_info.subresourceRange.levelCount = num_levels;
+  view_info.subresourceRange.baseArrayLayer = 0;
+  view_info.subresourceRange.layerCount = num_layers;
+
+  VkImageView image_view;
+  err = vkCreateImageView(_device, &view_info, NULL, &image_view);
+  if (err) {
+    vulkan_error(err, "Failed to create image view for texture");
+    return (TextureContext *)NULL;
+  }
+
+  VulkanTextureContext *tc = new VulkanTextureContext(get_prepared_objects(), texture, view);
+  tc->_image = image;
+  tc->_memory = memory;
+  tc->_image_view = image_view;
+  tc->update_data_size_bytes(alloc_info.allocationSize);
+  return tc;
 }
 }
 
 
 /**
 /**
@@ -303,7 +637,41 @@ extract_texture_data(Texture *) {
  */
  */
 SamplerContext *VulkanGraphicsStateGuardian::
 SamplerContext *VulkanGraphicsStateGuardian::
 prepare_sampler(const SamplerState &sampler) {
 prepare_sampler(const SamplerState &sampler) {
-  return (SamplerContext *)NULL;
+  VkSamplerAddressMode wrap_map[] = {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+                                     VK_SAMPLER_ADDRESS_MODE_REPEAT,
+                                     VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
+                                     VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
+                                     VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
+                                     VK_SAMPLER_ADDRESS_MODE_REPEAT};
+
+  //TODO: support shadow filter and border color.
+  VkSamplerCreateInfo sampler_info;
+  sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+  sampler_info.pNext = NULL;
+  sampler_info.flags = 0;
+  sampler_info.magFilter = (VkFilter)(sampler.get_effective_magfilter() & 1);
+  sampler_info.minFilter = (VkFilter)(sampler.get_effective_minfilter() & 1);
+  sampler_info.mipmapMode = (VkSamplerMipmapMode)(sampler.get_effective_minfilter() >> 1);
+  sampler_info.addressModeU = wrap_map[sampler.get_wrap_u()];
+  sampler_info.addressModeV = wrap_map[sampler.get_wrap_v()];
+  sampler_info.addressModeW = wrap_map[sampler.get_wrap_w()];
+  sampler_info.mipLodBias = sampler.get_lod_bias();
+  sampler_info.maxAnisotropy = sampler.get_anisotropic_degree();
+  sampler_info.compareEnable = VK_FALSE;
+  sampler_info.compareOp = VK_COMPARE_OP_NEVER;
+  sampler_info.minLod = sampler.get_min_lod();
+  sampler_info.maxLod = sampler.get_max_lod();
+  sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
+  sampler_info.unnormalizedCoordinates = VK_FALSE;
+
+  VkResult err;
+  VkSampler vk_sampler;
+  err = vkCreateSampler(_device, &sampler_info, NULL, &vk_sampler);
+  if (err) {
+    return (SamplerContext *)NULL;
+  }
+
+  return new VulkanSamplerContext(sampler, vk_sampler);
 }
 }
 
 
 /**
 /**

+ 22 - 0
panda/src/vulkandisplay/vulkanSamplerContext.I

@@ -0,0 +1,22 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file vulkanSamplerContext.I
+ * @author rdb
+ * @date 2016-02-18
+ */
+
+
+/**
+ * Constructs a sampler context managing the given sampler object.
+ */
+INLINE VulkanSamplerContext::
+VulkanSamplerContext(const SamplerState &sampler_state, VkSampler sampler) :
+  SamplerContext(sampler_state),
+  _sampler(sampler) {
+}

+ 16 - 0
panda/src/vulkandisplay/vulkanSamplerContext.cxx

@@ -0,0 +1,16 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file vulkanSamplerContext.cxx
+ * @author rdb
+ * @date 2016-02-19
+ */
+
+#include "vulkanSamplerContext.h"
+
+TypeHandle VulkanSamplerContext::_type_handle;

+ 53 - 0
panda/src/vulkandisplay/vulkanSamplerContext.h

@@ -0,0 +1,53 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file vulkanSamplerContext.h
+ * @author rdb
+ * @date 2016-02-19
+ */
+
+#ifndef VULKANSAMPLERCONTEXT_H
+#define VULKANSAMPLERCONTEXT_H
+
+#include "config_vulkandisplay.h"
+#include "samplerContext.h"
+
+/**
+ * Manages a Vulkan sampler object.
+ */
+class EXPCL_VULKANDISPLAY VulkanSamplerContext : public SamplerContext {
+public:
+  INLINE VulkanSamplerContext(const SamplerState &sampler_state, VkSampler sampler);
+  ~VulkanSamplerContext() {};
+
+  ALLOC_DELETED_CHAIN(VulkanSamplerContext);
+
+public:
+  VkSampler _sampler;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    SamplerContext::init_type();
+    register_type(_type_handle, "VulkanSamplerContext",
+                  SamplerContext::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "vulkanSamplerContext.I"
+
+#endif  // VULKANSAMPLERCONTEXT_H

+ 25 - 0
panda/src/vulkandisplay/vulkanTextureContext.I

@@ -0,0 +1,25 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file vulkanTextureContext.I
+ * @author rdb
+ * @date 2016-02-19
+ */
+
+
+/**
+ * Constructs a Texture context.  Follow this up with calls to fill in the
+ * image, allocate the memory and create an image view.
+ */
+INLINE VulkanTextureContext::
+VulkanTextureContext(PreparedGraphicsObjects *pgo, Texture *texture, int view) :
+  TextureContext(pgo, texture, view),
+  _image(VK_NULL_HANDLE),
+  _memory(VK_NULL_HANDLE),
+  _image_view(VK_NULL_HANDLE) {
+}

+ 16 - 0
panda/src/vulkandisplay/vulkanTextureContext.cxx

@@ -0,0 +1,16 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file vulkanTextureContext.cxx
+ * @author rdb
+ * @date 2016-02-19
+ */
+
+#include "vulkanTextureContext.h"
+
+TypeHandle VulkanTextureContext::_type_handle;

+ 55 - 0
panda/src/vulkandisplay/vulkanTextureContext.h

@@ -0,0 +1,55 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file vulkanTextureContext.h
+ * @author rdb
+ * @date 2016-02-19
+ */
+
+#ifndef VULKANTEXTURECONTEXT_H
+#define VULKANTEXTURECONTEXT_H
+
+#include "config_vulkandisplay.h"
+#include "textureContext.h"
+
+/**
+ * Manages a Vulkan image and device memory.
+ */
+class EXPCL_VULKANDISPLAY VulkanTextureContext : public TextureContext {
+public:
+  INLINE VulkanTextureContext(PreparedGraphicsObjects *pgo, Texture *texture, int view);
+  ~VulkanTextureContext() {};
+
+  ALLOC_DELETED_CHAIN(VulkanTextureContext);
+
+public:
+  VkImage _image;
+  VkDeviceMemory _memory;
+  VkImageView _image_view;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TextureContext::init_type();
+    register_type(_type_handle, "VulkanTextureContext",
+                  TextureContext::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "vulkanTextureContext.I"
+
+#endif  // VULKANTEXTURECONTEXT_H