summary refs log tree commit diff
path: root/src/graphics_permanent.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics_permanent.rs')
-rw-r--r--src/graphics_permanent.rs77
1 files changed, 71 insertions, 6 deletions
diff --git a/src/graphics_permanent.rs b/src/graphics_permanent.rs
index b58e8a4..63e8994 100644
--- a/src/graphics_permanent.rs
+++ b/src/graphics_permanent.rs
@@ -62,6 +62,8 @@ pub struct PermanentGraphicsState {
   // follow Vulkan's lead and let it have a short variable name.
   pub device: Device,
 
+  pub sampler: vk::Sampler,
+
   //   Vulkan has a first-class concept of command queues. We have two of
   // them, one for graphics drawing commands and one for presentation.
   //
@@ -88,6 +90,7 @@ pub struct QueueFamilyIndices {
 // for accidentally passing or returning one boolean as if it's another.
 struct EnablePortability(bool);
 struct EnableValidation(bool);
+struct EnableAnisotropy(bool);
 pub struct EnableSwapchain(pub bool);
 
 
@@ -123,14 +126,16 @@ impl PermanentGraphicsState {
 
     let (physical_device, device,
          indices, graphics_queue, presentation_queue,
-         enable_swapchain)
+         enable_anisotropy, enable_swapchain)
         = init_vulkan_device(&instance, &surface,
                              enable_validation, enable_portability)?;
 
+    let sampler = init_sampler(&device, &enable_anisotropy)?;
+
     let descriptor_set_layout = init_descriptor_set_layout(&device)?;
 
     Ok((PermanentGraphicsState {
-      window, entry, instance, debug_messager, surface, device,
+      window, entry, instance, debug_messager, surface, device, sampler,
       graphics_queue, presentation_queue
     }, GraphicsStateForReinit {
       physical_device, indices, descriptor_set_layout
@@ -139,6 +144,8 @@ impl PermanentGraphicsState {
 
   #[allow(unsafe_code)]
   pub fn destroy(self) -> () {
+    unsafe { self.device.destroy_sampler(self.sampler, None) };
+
     unsafe { self.device.destroy_device(None) };
 
     unsafe { self.instance.destroy_surface_khr(self.surface, None) };
@@ -415,7 +422,7 @@ fn init_vulkan_device(instance: &Instance, surface: &vk::SurfaceKHR,
                       enable_validation: EnableValidation,
                       enable_portability: EnablePortability)
     -> Result<(vk::PhysicalDevice, Device, QueueFamilyIndices, vk::Queue,
-               vk::Queue, EnableSwapchain)>
+               vk::Queue, EnableAnisotropy, EnableSwapchain)>
 {
   let (physical_device, indices) = pick_vulkan_device(instance, surface)?;
 
@@ -433,7 +440,10 @@ fn init_vulkan_device(instance: &Instance, surface: &vk::SurfaceKHR,
   //   Old versions of Vulkan want layers to be enabled at the device
   // level as well. Newer ones will ignore this and just use the instance
   // layers.
-  let features = vk::PhysicalDeviceFeatures::builder();
+  let available_features = unsafe {
+    instance.get_physical_device_features(physical_device)
+  };
+  let mut features = vk::PhysicalDeviceFeatures::builder();
   let mut extensions = Vec::new();
   let mut layers = Vec::new();
 
@@ -482,6 +492,16 @@ fn init_vulkan_device(instance: &Instance, surface: &vk::SurfaceKHR,
     EnableSwapchain(false)
   };
 
+  let enable_anisotropy = if available_features.sampler_anisotropy
+                             == vk::TRUE
+  {
+    features = features.sampler_anisotropy(true);
+
+    EnableAnisotropy(true)
+  } else {
+    EnableAnisotropy(false)
+  };
+
   //   We have one or more queue family indices; we don't know a priori
   // how many, because it's possible some of them are the same. We only
   // want to create one queue per distinct family, so we find the unique
@@ -526,7 +546,39 @@ fn init_vulkan_device(instance: &Instance, surface: &vk::SurfaceKHR,
 
   Ok((physical_device, device,
       indices, graphics_queue, presentation_queue,
-      enable_swapchain))
+      enable_anisotropy, enable_swapchain))
+}
+
+
+#[allow(unsafe_code)]
+fn init_sampler(device: &Device, enable_anisotropy: &EnableAnisotropy)
+    -> Result<vk::Sampler>
+{
+  let mut sampler_info = vk::SamplerCreateInfo::builder()
+          .mag_filter(vk::Filter::LINEAR)
+          .min_filter(vk::Filter::LINEAR)
+          .address_mode_u(vk::SamplerAddressMode::REPEAT)
+          .address_mode_v(vk::SamplerAddressMode::REPEAT)
+          .address_mode_w(vk::SamplerAddressMode::REPEAT)
+          .border_color(vk::BorderColor::INT_OPAQUE_BLACK)
+          .unnormalized_coordinates(false)
+          .compare_enable(false)
+          .compare_op(vk::CompareOp::ALWAYS)
+          .mipmap_mode(vk::SamplerMipmapMode::LINEAR)
+          .mip_lod_bias(0.0)
+          .min_lod(0.0)
+          .max_lod(0.0);
+  sampler_info = if enable_anisotropy.0 {
+    sampler_info.anisotropy_enable(true)
+                .max_anisotropy(16.0)
+  } else {
+    sampler_info.anisotropy_enable(false)
+                .max_anisotropy(1.0)
+  };
+
+  let sampler = unsafe { device.create_sampler(&sampler_info, None) }?;
+
+  Ok(sampler)
 }
 
 
@@ -540,7 +592,13 @@ fn init_descriptor_set_layout(device: &Device)
           .descriptor_count(1)
           .stage_flags(vk::ShaderStageFlags::VERTEX);
 
-  let bindings = [uniform_block_binding];
+  let sampler_binding = vk::DescriptorSetLayoutBinding::builder()
+          .binding(1)
+          .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
+          .descriptor_count(1)
+          .stage_flags(vk::ShaderStageFlags::FRAGMENT);
+
+  let bindings = [uniform_block_binding, sampler_binding];
   let descriptor_set_layout_info
           = vk::DescriptorSetLayoutCreateInfo::builder()
                 .bindings(&bindings);
@@ -698,6 +756,13 @@ fn score_vulkan_device(instance: &Instance, surface: &vk::SurfaceKHR,
     // selected.
   }
 
+  let features = unsafe {
+    instance.get_physical_device_features(*physical_device)
+  };
+  if features.sampler_anisotropy == vk::TRUE {
+    score += 1;
+  }
+
   Ok(Acceptable::Accepted((score, indices)))
 }