ソースを参照

vulkan: fixes to pass validation on newer SDK versions

rdb 8 年 前
コミット
84db0908fd

+ 12 - 7
panda/src/vulkandisplay/vulkanGraphicsStateGuardian.cxx

@@ -153,7 +153,7 @@ VulkanGraphicsStateGuardian(GraphicsEngine *engine, VulkanGraphicsPipe *pipe,
 
   // Create a pipeline layout.  We'll do that here for now.
   VkPushConstantRange ranges[2];
-  ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
+  ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
   ranges[0].offset = 0;
   ranges[0].size = 64;
   ranges[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
@@ -410,7 +410,7 @@ prepare_texture(Texture *texture, int view) {
   image_info.arrayLayers = num_layers;
   image_info.samples = VK_SAMPLE_COUNT_1_BIT;
   image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
-  image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+  image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
   image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
   image_info.queueFamilyIndexCount = 0;
   image_info.pQueueFamilyIndices = NULL;
@@ -509,7 +509,7 @@ prepare_texture(Texture *texture, int view) {
       generate_mipmaps = false;
     } else {
       // We'll be generating mipmaps from it, so mark it as transfer source.
-      image_info.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+      image_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
     }
   }
 
@@ -670,6 +670,11 @@ prepare_texture(Texture *texture, int view) {
     return (TextureContext *)NULL;
   }
 
+  if (vulkandisplay_cat.is_debug()) {
+    vulkandisplay_cat.debug()
+      << "Created image " << image << " and view " << image_view << " for texture " << *texture << "\n";
+  }
+
   VulkanTextureContext *tc = new VulkanTextureContext(get_prepared_objects(), texture, view);
   tc->_format = image_info.format;
   tc->_extent = image_info.extent;
@@ -1021,8 +1026,8 @@ prepare_sampler(const SamplerState &sampler) {
   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.anisotropyEnable = VK_FALSE;
-  sampler_info.maxAnisotropy = sampler.get_anisotropic_degree();
+  sampler_info.anisotropyEnable = (sampler.get_effective_anisotropic_degree() > 1);
+  sampler_info.maxAnisotropy = sampler.get_effective_anisotropic_degree();
   sampler_info.compareEnable = VK_FALSE;
   sampler_info.compareOp = VK_COMPARE_OP_NEVER;
   sampler_info.minLod = sampler.get_min_lod();
@@ -1400,7 +1405,7 @@ set_state_and_transform(const RenderState *state,
   // Put the modelview projection matrix in the push constants.
   CPT(TransformState) combined = _projection_mat->compose(trans);
   LMatrix4f matrix = LCAST(float, combined->get_mat());
-  vkCmdPushConstants(_cmd, _pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 64, matrix.get_data());
+  vkCmdPushConstants(_cmd, _pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, matrix.get_data());
 
   const ColorScaleAttrib *color_scale_attrib;
   state->get_attrib_def(color_scale_attrib);
@@ -2389,7 +2394,7 @@ make_pipeline(const RenderState *state, const GeomVertexFormat *format,
   raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
   raster_info.pNext = NULL;
   raster_info.flags = 0;
-  raster_info.depthClampEnable = VK_TRUE;
+  raster_info.depthClampEnable = VK_FALSE;
   raster_info.rasterizerDiscardEnable = VK_FALSE;
 
   if (_supported_geom_rendering & Geom::GR_render_mode_wireframe) {

+ 70 - 20
panda/src/vulkandisplay/vulkanGraphicsWindow.cxx

@@ -80,6 +80,12 @@ begin_frame(FrameMode mode, Thread *current_thread) {
     return false;
   }
 
+#ifdef HAVE_X11
+  if (_awaiting_configure) {
+    return false;
+  }
+#endif
+
   if (vulkandisplay_cat.is_spam()) {
     vulkandisplay_cat.spam()
       << "Drawing " << this << ": exposed.\n";
@@ -150,11 +156,6 @@ begin_frame(FrameMode mode, Thread *current_thread) {
   VkCommandBuffer cmd = vkgsg->_cmd;
 
   VkClearValue clears[2];
-  LColor clear_color = get_clear_color();
-  clears[0].color.float32[0] = clear_color[0];
-  clears[0].color.float32[1] = clear_color[1];
-  clears[0].color.float32[2] = clear_color[2];
-  clears[0].color.float32[3] = clear_color[3];
 
   VkRenderPassBeginInfo begin_info;
   begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -165,7 +166,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
   begin_info.renderArea.offset.y = 0;
   begin_info.renderArea.extent.width = _size[0];
   begin_info.renderArea.extent.height = _size[1];
-  begin_info.clearValueCount = 1;
+  begin_info.clearValueCount = 0;
   begin_info.pClearValues = clears;
 
   if (!get_clear_color_active()) {
@@ -176,7 +177,10 @@ begin_frame(FrameMode mode, Thread *current_thread) {
       // time if we don't want the validation layer to yell at us.
       // We clear it to an arbitrary arbitrary color.  We'll just pick the
       // color returned by get_clear_color(), even if it is meaningless.
-      buffer._tc->clear_color_image(cmd, clears[0].color);
+
+      // Actually, doing this causes the validation layer to yell even louder
+      // because the image has no VK_IMAGE_USAGE_TRANSFER_DST_BIT.
+      //buffer._tc->clear_color_image(cmd, clears[0].color);
     }
 
     buffer._tc->transition(cmd, vkgsg->_graphics_queue_family_index,
@@ -188,13 +192,16 @@ begin_frame(FrameMode mode, Thread *current_thread) {
     buffer._tc->_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
     buffer._tc->_access_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
     buffer._tc->_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+
+    LColor clear_color = get_clear_color();
+    clears[begin_info.clearValueCount].color.float32[0] = clear_color[0];
+    clears[begin_info.clearValueCount].color.float32[1] = clear_color[1];
+    clears[begin_info.clearValueCount].color.float32[2] = clear_color[2];
+    clears[begin_info.clearValueCount].color.float32[3] = clear_color[3];
+    ++begin_info.clearValueCount;
   }
 
   if (_depth_stencil_tc != NULL) {
-    begin_info.clearValueCount++;
-    clears[1].depthStencil.depth = get_clear_depth();
-    clears[1].depthStencil.stencil = get_clear_stencil();
-
     // Transition the depth-stencil image to a consistent state.
     if (!get_clear_depth_active() || !get_clear_stencil_active()) {
       _depth_stencil_tc->transition(cmd, vkgsg->_graphics_queue_family_index,
@@ -208,6 +215,12 @@ begin_frame(FrameMode mode, Thread *current_thread) {
       _depth_stencil_tc->_stage_mask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
                                        VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
     }
+
+    if (get_clear_depth_active() || get_clear_stencil_active()) {
+      clears[begin_info.clearValueCount].depthStencil.depth = get_clear_depth();
+      clears[begin_info.clearValueCount].depthStencil.stencil = get_clear_stencil();
+      ++begin_info.clearValueCount;
+    }
   }
 
   vkCmdBeginRenderPass(cmd, &begin_info, VK_SUBPASS_CONTENTS_INLINE);
@@ -238,10 +251,18 @@ end_frame(FrameMode mode, Thread *current_thread) {
     vkgsg->_render_pass = VK_NULL_HANDLE;
 
     // The driver implicitly transitioned this to the final layout.
-    _swap_buffers[_image_index]._tc->_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+    SwapBuffer &buffer = _swap_buffers[_image_index];
+    buffer._tc->_layout = _final_layout;
+    buffer._tc->_access_mask = VK_ACCESS_MEMORY_READ_BIT;
 
     // Now we can do copy-to-texture, now that the render pass has ended.
     copy_to_textures();
+
+    // If we copied the textures, transition it back to the present state.
+    buffer._tc->transition(cmd, vkgsg->_graphics_queue_family_index,
+                           VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                           VK_ACCESS_MEMORY_READ_BIT);
   }
 
   // Note: this will close the command buffer.
@@ -300,6 +321,8 @@ end_flip() {
   VkResult err;
 
   SwapBuffer &buffer = _swap_buffers[_image_index];
+
+  // Make sure it is in the state we expect it to be.
   nassertv(buffer._tc->_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
 
   VkResult results[1];
@@ -526,7 +549,14 @@ open_window() {
     _depth_stencil_aspect_mask |= 0;
   }
 
+  // Don't create the swapchain yet if we haven't yet gotten the configure
+  // notify event, since we don't know the final size yet.
+#ifdef HAVE_X11
+  _swapchain_size.set(-1, -1);
+  return setup_render_pass() && (_awaiting_configure || create_swapchain());
+#else
   return setup_render_pass() && create_swapchain();
+#endif
 }
 
 /**
@@ -546,6 +576,22 @@ setup_render_pass() {
       << "Creating render pass for VulkanGraphicsWindow " << this << "\n";
   }
 
+  {
+    // Do we intend to copy the framebuffer to a texture?
+    _final_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+    CDReader cdata(_cycler);
+    RenderTextures::const_iterator ri;
+    for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
+      if ((*ri)._plane == RTP_color) {
+        RenderTextureMode mode = (*ri)._rtm_mode;
+        if (mode == RTM_copy_texture || mode == RTM_copy_ram) {
+          _final_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+          break;
+        }
+      }
+    }
+  }
+
   // Now we want to create a render pass, and for that we need to describe the
   // framebuffer attachments as well as any subpasses we'd like to use.
   VkAttachmentDescription attachments[2];
@@ -557,7 +603,7 @@ setup_render_pass() {
   attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
   attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
   attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-  attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+  attachments[0].finalLayout = _final_layout;
 
   attachments[1].flags = 0;
   attachments[1].format = _depth_stencil_format;
@@ -732,6 +778,10 @@ create_swapchain() {
   num_images = min(surf_caps.maxImageCount, num_images);
   num_images = max(surf_caps.minImageCount, num_images);
 
+  _swapchain_size.set(
+    max(min((uint32_t)_size[0], surf_caps.maxImageExtent.width), surf_caps.minImageExtent.width),
+    max(min((uint32_t)_size[1], surf_caps.maxImageExtent.height), surf_caps.minImageExtent.height));
+
   // Get the supported presentation modes for this surface.
   uint32_t num_present_modes = 0;
   err = vkGetPhysicalDeviceSurfacePresentModesKHR(vkpipe->_gpu, _surface, &num_present_modes, NULL);
@@ -744,12 +794,13 @@ create_swapchain() {
   VkSwapchainCreateInfoKHR swapchain_info;
   swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
   swapchain_info.pNext = NULL;
+  swapchain_info.flags = 0;
   swapchain_info.surface = _surface;
   swapchain_info.minImageCount = num_images;
   swapchain_info.imageFormat = _surface_format.format;
   swapchain_info.imageColorSpace = _surface_format.colorSpace;
-  swapchain_info.imageExtent.width = _size[0];
-  swapchain_info.imageExtent.height = _size[1];
+  swapchain_info.imageExtent.width = _swapchain_size[0];
+  swapchain_info.imageExtent.height = _swapchain_size[1];
   swapchain_info.imageArrayLayers = 1;
   swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
   swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
@@ -842,8 +893,8 @@ create_swapchain() {
     depth_img_info.flags = 0;
     depth_img_info.imageType = VK_IMAGE_TYPE_2D;
     depth_img_info.format = _depth_stencil_format;
-    depth_img_info.extent.width = _size[0];
-    depth_img_info.extent.height = _size[1];
+    depth_img_info.extent.width = swapchain_info.imageExtent.width;
+    depth_img_info.extent.height = swapchain_info.imageExtent.height;
     depth_img_info.extent.depth = 1;
     depth_img_info.mipLevels = 1;
     depth_img_info.arrayLayers = 1;
@@ -940,8 +991,8 @@ create_swapchain() {
   fb_info.renderPass = _render_pass;
   fb_info.attachmentCount = 1 + (int)have_ds;
   fb_info.pAttachments = attach_views;
-  fb_info.width = _size[0];
-  fb_info.height = _size[1];
+  fb_info.width = swapchain_info.imageExtent.width;
+  fb_info.height = swapchain_info.imageExtent.height;
   fb_info.layers = 1;
 
   for (uint32_t i = 0; i < num_images; ++i) {
@@ -954,6 +1005,5 @@ create_swapchain() {
     }
   }
 
-  _swapchain_size = _size;
   return true;
 }

+ 1 - 0
panda/src/vulkandisplay/vulkanGraphicsWindow.h

@@ -77,6 +77,7 @@ private:
   typedef pvector<SwapBuffer> SwapBuffers;
   SwapBuffers _swap_buffers;
   uint32_t _image_index;
+  VkImageLayout _final_layout;
 
   VulkanTextureContext *_depth_stencil_tc;
   VkFormat _depth_stencil_format;

+ 3 - 0
panda/src/x11display/x11GraphicsWindow.cxx

@@ -992,6 +992,9 @@ open_window() {
     _parent_window_handle->attach_child(_window_handle);
   }
 
+  // Before we start rendering, we wait for the final dimensions from the
+  // window manager.
+  _awaiting_configure = true;
   return true;
 }