<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Thanks for the head-up Marek, I will update once I have hardware
      access.<br>
    </p>
    <div class="moz-cite-prefix">On 6/21/19 7:33 PM, Marek Olšák wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAAxE2A7xALhY7E8T51ZxOD2DBkcY8Otz7g=vezOUO_s89-+d0A@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div class="gmail_quote">
          <div class="gmail_attr">Gfx10 remembers sample positions in
            compressed Z/S memory, so the hw doesn't need the decompress
            pass for shader loads.</div>
          <div class="gmail_attr"><br>
          </div>
          <div class="gmail_attr">Marek<br>
          </div>
          <div dir="ltr" class="gmail_attr"><br>
          </div>
          <div dir="ltr" class="gmail_attr">On Wed, May 22, 2019 at 4:20
            PM Marek Olšák <<a href="mailto:maraeo@gmail.com"
              moz-do-not-send="true">maraeo@gmail.com</a>> wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">
            <div dir="ltr">
              <div class="gmail_quote">
                <div class="gmail_attr">The depth decompress pass needs
                  to know the sample locations.<br>
                </div>
                <div class="gmail_attr"><br>
                </div>
                <div class="gmail_attr">If shader loads read from
                  compressed depth, the texture hardware will always use
                  the standard locations for decompression.</div>
                <div class="gmail_attr"><br>
                </div>
                <div class="gmail_attr">Marek<br>
                </div>
                <div dir="ltr" class="gmail_attr"><br>
                </div>
                <div dir="ltr" class="gmail_attr">On Tue, May 21, 2019
                  at 8:17 PM Bas Nieuwenhuizen <<a
                    href="mailto:bas@basnieuwenhuizen.nl"
                    target="_blank" moz-do-not-send="true">bas@basnieuwenhuizen.nl</a>>
                  wrote:<br>
                </div>
                <blockquote class="gmail_quote" style="margin:0px 0px
                  0px 0.8ex;border-left:1px solid
                  rgb(204,204,204);padding-left:1ex">So this does not
                  seem to use the sample locations during layout
                  transitions?<br>
                  <br>
                  AFAIK those are needed for e.g. HTILE decompression as
                  it is based on<br>
                  equations somehow.<br>
                  <br>
                  On Thu, May 16, 2019 at 11:51 AM Samuel Pitoiset<br>
                  <<a href="mailto:samuel.pitoiset@gmail.com"
                    target="_blank" moz-do-not-send="true">samuel.pitoiset@gmail.com</a>>
                  wrote:<br>
                  ><br>
                  > Basically, this extension allows applications to
                  use custom<br>
                  > sample locations. It doesn't support variable
                  sample locations<br>
                  > during subpass. Note that we don't have to upload
                  the user<br>
                  > sample locations because the spec doesn't allow
                  this.<br>
                  ><br>
                  > Only enabled on VI+ because it's untested on
                  older chips.<br>
                  ><br>
                  > v2: - change sampleLocationCoordinateRange[1] to
                  0.9375<br>
                  >     - compute and emit
                  PA_SC_CENTROID_PRIORITY_{0,1}<br>
                  >     - rebased on top of master<br>
                  >     - some cleanups<br>
                  ><br>
                  > Signed-off-by: Samuel Pitoiset <<a
                    href="mailto:samuel.pitoiset@gmail.com"
                    target="_blank" moz-do-not-send="true">samuel.pitoiset@gmail.com</a>><br>
                  > ---<br>
                  >  src/amd/vulkan/radv_cmd_buffer.c  | 223
                  ++++++++++++++++++++++++++++++<br>
                  >  src/amd/vulkan/radv_device.c      |  27 ++++<br>
                  >  src/amd/vulkan/radv_extensions.py |   1 +<br>
                  >  src/amd/vulkan/radv_pipeline.c    |  30 ++++<br>
                  >  src/amd/vulkan/radv_private.h     |  26 +++-<br>
                  >  5 files changed, 300 insertions(+), 7
                  deletions(-)<br>
                  ><br>
                  > diff --git a/src/amd/vulkan/radv_cmd_buffer.c
                  b/src/amd/vulkan/radv_cmd_buffer.c<br>
                  > index 4f592bc7f68..fb79c1c6713 100644<br>
                  > --- a/src/amd/vulkan/radv_cmd_buffer.c<br>
                  > +++ b/src/amd/vulkan/radv_cmd_buffer.c<br>
                  > @@ -105,6 +105,7 @@
                  radv_bind_dynamic_state(struct radv_cmd_buffer
                  *cmd_buffer,<br>
                  >         dest->viewport.count =
                  src->viewport.count;<br>
                  >         dest->scissor.count =
                  src->scissor.count;<br>
                  >         dest->discard_rectangle.count =
                  src->discard_rectangle.count;<br>
                  > +       dest->sample_location.count =
                  src->sample_location.count;<br>
                  ><br>
                  >         if (copy_mask &
                  RADV_DYNAMIC_VIEWPORT) {<br>
                  >                 if
                  (memcmp(&dest->viewport.viewports,
                  &src->viewport.viewports,<br>
                  > @@ -192,6 +193,22 @@
                  radv_bind_dynamic_state(struct radv_cmd_buffer
                  *cmd_buffer,<br>
                  >                 }<br>
                  >         }<br>
                  ><br>
                  > +       if (copy_mask &
                  RADV_DYNAMIC_SAMPLE_LOCATIONS) {<br>
                  > +               if
                  (dest->sample_location.per_pixel !=
                  src->sample_location.per_pixel ||<br>
                  > +                 
                   dest->sample_location.grid_size.width !=
                  src->sample_location.grid_size.width ||<br>
                  > +                 
                   dest->sample_location.grid_size.height !=
                  src->sample_location.grid_size.height ||<br>
                  > +                 
                   memcmp(&dest->sample_location.locations,<br>
                  > +                         
                  &src->sample_location.locations,<br>
                  > +                         
                  src->sample_location.count *
                  sizeof(VkSampleLocationEXT))) {<br>
                  > +                     
                   dest->sample_location.per_pixel =
                  src->sample_location.per_pixel;<br>
                  > +                     
                   dest->sample_location.grid_size =
                  src->sample_location.grid_size;<br>
                  > +                     
                   typed_memcpy(dest->sample_location.locations,<br>
                  > +                                   
                  src->sample_location.locations,<br>
                  > +                                   
                  src->sample_location.count);<br>
                  > +                       dest_mask |=
                  RADV_DYNAMIC_SAMPLE_LOCATIONS;<br>
                  > +               }<br>
                  > +       }<br>
                  > +<br>
                  >         cmd_buffer->state.dirty |= dest_mask;<br>
                  >  }<br>
                  ><br>
                  > @@ -632,6 +649,190 @@
                  radv_emit_descriptor_pointers(struct radv_cmd_buffer
                  *cmd_buffer,<br>
                  >         }<br>
                  >  }<br>
                  ><br>
                  > +/**<br>
                  > + * Convert the user sample locations to hardware
                  sample locations (the values<br>
                  > + * that will be emitted by
                  PA_SC_AA_SAMPLE_LOCS_PIXEL_*).<br>
                  > + */<br>
                  > +static void<br>
                  > +radv_convert_user_sample_locs(struct
                  radv_sample_locations_state *state,<br>
                  > +                             uint32_t x,
                  uint32_t y, VkOffset2D *sample_locs)<br>
                  > +{<br>
                  > +       uint32_t x_offset = x %
                  state->grid_size.width;<br>
                  > +       uint32_t y_offset = y %
                  state->grid_size.height;<br>
                  > +       uint32_t num_samples =
                  (uint32_t)state->per_pixel;<br>
                  > +       VkSampleLocationEXT *user_locs;<br>
                  > +       uint32_t pixel_offset;<br>
                  > +<br>
                  > +       pixel_offset = (x_offset + y_offset *
                  state->grid_size.width) * num_samples;<br>
                  > +<br>
                  > +       assert(pixel_offset <=
                  MAX_SAMPLE_LOCATIONS);<br>
                  > +       user_locs =
                  &state->locations[pixel_offset];<br>
                  > +<br>
                  > +       for (uint32_t i = 0; i < num_samples;
                  i++) {<br>
                  > +               float shifted_pos_x =
                  user_locs[i].x - 0.5;<br>
                  > +               float shifted_pos_y =
                  user_locs[i].y - 0.5;<br>
                  > +<br>
                  > +               int32_t scaled_pos_x =
                  floor(shifted_pos_x * 16);<br>
                  > +               int32_t scaled_pos_y =
                  floor(shifted_pos_y * 16);<br>
                  > +<br>
                  > +               sample_locs[i].x =
                  CLAMP(scaled_pos_x, -8, 7);<br>
                  > +               sample_locs[i].y =
                  CLAMP(scaled_pos_y, -8, 7);<br>
                  > +       }<br>
                  > +}<br>
                  > +<br>
                  > +/**<br>
                  > + * Compute the PA_SC_AA_SAMPLE_LOCS_PIXEL_* mask
                  based on hardware sample<br>
                  > + * locations.<br>
                  > + */<br>
                  > +static void<br>
                  > +radv_compute_sample_locs_pixel(uint32_t
                  num_samples, VkOffset2D *sample_locs,<br>
                  > +                              uint32_t
                  *sample_locs_pixel)<br>
                  > +{<br>
                  > +       for (uint32_t i = 0; i < num_samples;
                  i++) {<br>
                  > +               uint32_t sample_reg_idx = i / 4;<br>
                  > +               uint32_t sample_loc_idx = i % 4;<br>
                  > +               int32_t pos_x = sample_locs[i].x;<br>
                  > +               int32_t pos_y = sample_locs[i].y;<br>
                  > +<br>
                  > +               uint32_t shift_x = 8 *
                  sample_loc_idx;<br>
                  > +               uint32_t shift_y = shift_x + 4;<br>
                  > +<br>
                  > +               sample_locs_pixel[sample_reg_idx]
                  |= (pos_x & 0xf) << shift_x;<br>
                  > +               sample_locs_pixel[sample_reg_idx]
                  |= (pos_y & 0xf) << shift_y;<br>
                  > +       }<br>
                  > +}<br>
                  > +<br>
                  > +/**<br>
                  > + * Compute the PA_SC_CENTROID_PRIORITY_* mask
                  based on the top left hardware<br>
                  > + * sample locations.<br>
                  > + */<br>
                  > +static uint64_t<br>
                  > +radv_compute_centroid_priority(struct
                  radv_cmd_buffer *cmd_buffer,<br>
                  > +                              VkOffset2D
                  *sample_locs,<br>
                  > +                              uint32_t
                  num_samples)<br>
                  > +{<br>
                  > +       uint32_t
                  centroid_priorities[num_samples];<br>
                  > +       uint32_t sample_mask = num_samples - 1;<br>
                  > +       uint32_t distances[num_samples];<br>
                  > +       uint64_t centroid_priority = 0;<br>
                  > +<br>
                  > +       /* Compute the distances from center for
                  each sample. */<br>
                  > +       for (int i = 0; i < num_samples; i++)
                  {<br>
                  > +               distances[i] = (sample_locs[i].x
                  * sample_locs[i].x) +<br>
                  > +                              (sample_locs[i].y
                  * sample_locs[i].y);<br>
                  > +       }<br>
                  > +<br>
                  > +       /* Compute the centroid priorities by
                  looking at the distances array. */<br>
                  > +       for (int i = 0; i < num_samples; i++)
                  {<br>
                  > +               uint32_t min_idx = 0;<br>
                  > +<br>
                  > +               for (int j = 1; j <
                  num_samples; j++) {<br>
                  > +                       if (distances[j] <
                  distances[min_idx])<br>
                  > +                               min_idx = j;<br>
                  > +               }<br>
                  > +<br>
                  > +               centroid_priorities[i] = min_idx;<br>
                  > +               distances[min_idx] = 0xffffffff;<br>
                  > +       }<br>
                  > +<br>
                  > +       /* Compute the final centroid priority.
                  */<br>
                  > +       for (int i = 0; i < 8; i++) {<br>
                  > +               centroid_priority |=<br>
                  > +                       centroid_priorities[i
                  & sample_mask] << (i * 4);<br>
                  > +       }<br>
                  > +<br>
                  > +       return centroid_priority << 32 |
                  centroid_priority;<br>
                  > +}<br>
                  > +<br>
                  > +/**<br>
                  > + * Emit the sample locations that are specified
                  with VK_EXT_sample_locations.<br>
                  > + */<br>
                  > +static void<br>
                  > +radv_emit_sample_locations(struct
                  radv_cmd_buffer *cmd_buffer)<br>
                  > +{<br>
                  > +       struct radv_pipeline *pipeline =
                  cmd_buffer->state.pipeline;<br>
                  > +       struct radv_multisample_state *ms =
                  &pipeline-><a href="http://graphics.ms"
                    rel="noreferrer" target="_blank"
                    moz-do-not-send="true">graphics.ms</a>;<br>
                  > +       struct radv_sample_locations_state
                  *sample_location =<br>
                  > +             
                   &cmd_buffer->state.dynamic.sample_location;<br>
                  > +       uint32_t num_samples =
                  (uint32_t)sample_location->per_pixel;<br>
                  > +       struct radeon_cmdbuf *cs =
                  cmd_buffer->cs;<br>
                  > +       uint32_t sample_locs_pixel[4][2] = {};<br>
                  > +       VkOffset2D sample_locs[4][8]; /* 8 is the
                  max. sample count supported */<br>
                  > +       uint32_t max_sample_dist = 0;<br>
                  > +       uint64_t centroid_priority;<br>
                  > +<br>
                  > +       if
                  (!cmd_buffer->state.dynamic.sample_location.count)<br>
                  > +               return;<br>
                  > +<br>
                  > +       /* Convert the user sample locations to
                  hardware sample locations. */<br>
                  > +     
                   radv_convert_user_sample_locs(sample_location, 0, 0,
                  sample_locs[0]);<br>
                  > +     
                   radv_convert_user_sample_locs(sample_location, 1, 0,
                  sample_locs[1]);<br>
                  > +     
                   radv_convert_user_sample_locs(sample_location, 0, 1,
                  sample_locs[2]);<br>
                  > +     
                   radv_convert_user_sample_locs(sample_location, 1, 1,
                  sample_locs[3]);<br>
                  > +<br>
                  > +       /* Compute the
                  PA_SC_AA_SAMPLE_LOCS_PIXEL_* mask. */<br>
                  > +       for (uint32_t i = 0; i < 4; i++) {<br>
                  > +             
                   radv_compute_sample_locs_pixel(num_samples,
                  sample_locs[i],<br>
                  > +                                             
                  sample_locs_pixel[i]);<br>
                  > +       }<br>
                  > +<br>
                  > +       /* Compute the PA_SC_CENTROID_PRIORITY_*
                  mask. */<br>
                  > +       centroid_priority =<br>
                  > +             
                   radv_compute_centroid_priority(cmd_buffer,
                  sample_locs[0],<br>
                  > +                                             
                  num_samples);<br>
                  > +<br>
                  > +       /* Compute the maximum sample distance
                  from the specified locations. */<br>
                  > +       for (uint32_t i = 0; i < num_samples;
                  i++) {<br>
                  > +               VkOffset2D offset =
                  sample_locs[0][i];<br>
                  > +               max_sample_dist =
                  MAX2(max_sample_dist,<br>
                  > +                                     
                  MAX2(abs(offset.x), abs(offset.y)));<br>
                  > +       }<br>
                  > +<br>
                  > +       /* Emit the specified user sample
                  locations. */<br>
                  > +       switch (num_samples) {<br>
                  > +       case 2:<br>
                  > +       case 4:<br>
                  > +               radeon_set_context_reg(cs,
                  R_028BF8_PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0,
                  sample_locs_pixel[0][0]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C08_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0,
                  sample_locs_pixel[1][0]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C18_PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0,
                  sample_locs_pixel[2][0]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C28_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0,
                  sample_locs_pixel[3][0]);<br>
                  > +               break;<br>
                  > +       case 8:<br>
                  > +               radeon_set_context_reg(cs,
                  R_028BF8_PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0,
                  sample_locs_pixel[0][0]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C08_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0,
                  sample_locs_pixel[1][0]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C18_PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0,
                  sample_locs_pixel[2][0]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C28_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0,
                  sample_locs_pixel[3][0]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028BFC_PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1,
                  sample_locs_pixel[0][1]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C0C_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1,
                  sample_locs_pixel[1][1]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C1C_PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1,
                  sample_locs_pixel[2][1]);<br>
                  > +               radeon_set_context_reg(cs,
                  R_028C2C_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1,
                  sample_locs_pixel[3][1]);<br>
                  > +               break;<br>
                  > +       default:<br>
                  > +               unreachable("invalid number of
                  samples");<br>
                  > +       }<br>
                  > +<br>
                  > +       /* Emit the maximum sample distance and
                  the centroid priority. */<br>
                  > +       uint32_t pa_sc_aa_config =
                  ms->pa_sc_aa_config;<br>
                  > +<br>
                  > +       pa_sc_aa_config &=
                  C_028BE0_MAX_SAMPLE_DIST;<br>
                  > +       pa_sc_aa_config |=
                  S_028BE0_MAX_SAMPLE_DIST(max_sample_dist);<br>
                  > +<br>
                  > +       radeon_set_context_reg_seq(cs,
                  R_028BE0_PA_SC_AA_CONFIG, 1);<br>
                  > +       radeon_emit(cs, pa_sc_aa_config);<br>
                  > +<br>
                  > +       radeon_set_context_reg_seq(cs,
                  R_028BD4_PA_SC_CENTROID_PRIORITY_0, 2);<br>
                  > +       radeon_emit(cs, centroid_priority);<br>
                  > +       radeon_emit(cs, centroid_priority
                  >> 32);<br>
                  > +<br>
                  > +       /* GFX9: Flush DFSM when the AA mode
                  changes. */<br>
                  > +       if
                  (cmd_buffer->device->dfsm_allowed) {<br>
                  > +               radeon_emit(cs,
                  PKT3(PKT3_EVENT_WRITE, 0, 0));<br>
                  > +               radeon_emit(cs,
                  EVENT_TYPE(V_028A90_FLUSH_DFSM) | EVENT_INDEX(0));<br>
                  > +       }<br>
                  > +<br>
                  > +     
                   cmd_buffer->state.context_roll_without_scissor_emitted
                  = true;<br>
                  > +}<br>
                  > +<br>
                  >  static void<br>
                  >  radv_emit_inline_push_consts(struct
                  radv_cmd_buffer *cmd_buffer,<br>
                  >                              struct radv_pipeline
                  *pipeline,<br>
                  > @@ -1775,6 +1976,9 @@
                  radv_cmd_buffer_flush_dynamic_state(struct
                  radv_cmd_buffer *cmd_buffer)<br>
                  >         if (states &
                  RADV_CMD_DIRTY_DYNAMIC_DISCARD_RECTANGLE)<br>
                  >               
                   radv_emit_discard_rectangle(cmd_buffer);<br>
                  ><br>
                  > +       if (states &
                  RADV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS)<br>
                  > +             
                   radv_emit_sample_locations(cmd_buffer);<br>
                  > +<br>
                  >         cmd_buffer->state.dirty &=
                  ~states;<br>
                  >  }<br>
                  ><br>
                  > @@ -3266,6 +3470,25 @@ void
                  radv_CmdSetDiscardRectangleEXT(<br>
                  >         state->dirty |=
                  RADV_CMD_DIRTY_DYNAMIC_DISCARD_RECTANGLE;<br>
                  >  }<br>
                  ><br>
                  > +void radv_CmdSetSampleLocationsEXT(<br>
                  > +       VkCommandBuffer                         
                     commandBuffer,<br>
                  > +       const VkSampleLocationsInfoEXT*         
                     pSampleLocationsInfo)<br>
                  > +{<br>
                  > +       RADV_FROM_HANDLE(radv_cmd_buffer,
                  cmd_buffer, commandBuffer);<br>
                  > +       struct radv_cmd_state *state =
                  &cmd_buffer->state;<br>
                  > +<br>
                  > +     
                   assert(pSampleLocationsInfo->sampleLocationsCount
                  <= MAX_SAMPLE_LOCATIONS);<br>
                  > +<br>
                  > +     
                   state->dynamic.sample_location.per_pixel =
                  pSampleLocationsInfo->sampleLocationsPerPixel;<br>
                  > +     
                   state->dynamic.sample_location.grid_size =
                  pSampleLocationsInfo->sampleLocationGridSize;<br>
                  > +       state->dynamic.sample_location.count =
                  pSampleLocationsInfo->sampleLocationsCount;<br>
                  > +     
                   typed_memcpy(&state->dynamic.sample_location.locations[0],<br>
                  > +                   
                  pSampleLocationsInfo->pSampleLocations,<br>
                  > +                   
                  pSampleLocationsInfo->sampleLocationsCount);<br>
                  > +<br>
                  > +       state->dirty |=
                  RADV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;<br>
                  > +}<br>
                  > +<br>
                  >  void radv_CmdExecuteCommands(<br>
                  >         VkCommandBuffer                         
                     commandBuffer,<br>
                  >         uint32_t                                 
                    commandBufferCount,<br>
                  > diff --git a/src/amd/vulkan/radv_device.c
                  b/src/amd/vulkan/radv_device.c<br>
                  > index c0e317a97e5..e523bba1223 100644<br>
                  > --- a/src/amd/vulkan/radv_device.c<br>
                  > +++ b/src/amd/vulkan/radv_device.c<br>
                  > @@ -1360,6 +1360,19 @@ void
                  radv_GetPhysicalDeviceProperties2(<br>
                  >                       
                   props->maxDescriptorSetUpdateAfterBindInlineUniformBlocks
                  = MAX_INLINE_UNIFORM_BLOCK_COUNT;<br>
                  >                         break;<br>
                  >                 }<br>
                  > +               case
                  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT:
                  {<br>
                  > +                     
                   VkPhysicalDeviceSampleLocationsPropertiesEXT
                  *properties =<br>
                  > +                             
                   (VkPhysicalDeviceSampleLocationsPropertiesEXT *)ext;<br>
                  > +                     
                   properties->sampleLocationSampleCounts =
                  VK_SAMPLE_COUNT_2_BIT |<br>
                  > +                                               
                                  VK_SAMPLE_COUNT_4_BIT |<br>
                  > +                                               
                                  VK_SAMPLE_COUNT_8_BIT;<br>
                  > +                     
                   properties->maxSampleLocationGridSize =
                  (VkExtent2D){ 2 , 2 };<br>
                  > +                     
                   properties->sampleLocationCoordinateRange[0] =
                  0.0f;<br>
                  > +                     
                   properties->sampleLocationCoordinateRange[1] =
                  0.9375f;<br>
                  > +                     
                   properties->sampleLocationSubPixelBits = 4;<br>
                  > +                     
                   properties->variableSampleLocations = VK_FALSE;<br>
                  > +                       break;<br>
                  > +               }<br>
                  >                 default:<br>
                  >                         break;<br>
                  >                 }<br>
                  > @@ -5361,3 +5374,17 @@ VkResult
                  radv_GetCalibratedTimestampsEXT(<br>
                  ><br>
                  >         return VK_SUCCESS;<br>
                  >  }<br>
                  > +<br>
                  > +void
                  radv_GetPhysicalDeviceMultisamplePropertiesEXT(<br>
                  > +    VkPhysicalDevice                           
                  physicalDevice,<br>
                  > +    VkSampleCountFlagBits                     
                   samples,<br>
                  > +    VkMultisamplePropertiesEXT*               
                   pMultisampleProperties)<br>
                  > +{<br>
                  > +       if (samples & (VK_SAMPLE_COUNT_2_BIT
                  |<br>
                  > +                      VK_SAMPLE_COUNT_4_BIT |<br>
                  > +                      VK_SAMPLE_COUNT_8_BIT)) {<br>
                  > +             
                   pMultisampleProperties->maxSampleLocationGridSize
                  = (VkExtent2D){ 2, 2 };<br>
                  > +       } else {<br>
                  > +             
                   pMultisampleProperties->maxSampleLocationGridSize
                  = (VkExtent2D){ 0, 0 };<br>
                  > +       }<br>
                  > +}<br>
                  > diff --git a/src/amd/vulkan/radv_extensions.py
                  b/src/amd/vulkan/radv_extensions.py<br>
                  > index 0b5af56a435..2c2c4dc74d2 100644<br>
                  > --- a/src/amd/vulkan/radv_extensions.py<br>
                  > +++ b/src/amd/vulkan/radv_extensions.py<br>
                  > @@ -119,6 +119,7 @@ EXTENSIONS = [<br>
                  >      Extension('VK_EXT_memory_priority',         
                           1, True),<br>
                  >      Extension('VK_EXT_pci_bus_info',           
                            2, True),<br>
                  >     
                  Extension('VK_EXT_pipeline_creation_feedback',       
                  1, True),<br>
                  > +    Extension('VK_EXT_sample_locations',       
                            1, 'device->rad_info.chip_class >=
                  GFX8'),<br>
                  >      Extension('VK_EXT_sampler_filter_minmax',   
                           1, 'device->rad_info.chip_class >=
                  GFX7'),<br>
                  >      Extension('VK_EXT_scalar_block_layout',     
                           1, 'device->rad_info.chip_class >=
                  GFX7'),<br>
                  >     
                  Extension('VK_EXT_shader_viewport_index_layer',     
                   1, True),<br>
                  > diff --git a/src/amd/vulkan/radv_pipeline.c
                  b/src/amd/vulkan/radv_pipeline.c<br>
                  > index 56fd65bec29..7f8e00b5c3c 100644<br>
                  > --- a/src/amd/vulkan/radv_pipeline.c<br>
                  > +++ b/src/amd/vulkan/radv_pipeline.c<br>
                  > @@ -1267,6 +1267,8 @@ static unsigned
                  radv_dynamic_state_mask(VkDynamicState state)<br>
                  >                 return
                  RADV_DYNAMIC_STENCIL_REFERENCE;<br>
                  >         case
                  VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT:<br>
                  >                 return
                  RADV_DYNAMIC_DISCARD_RECTANGLE;<br>
                  > +       case
                  VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:<br>
                  > +               return
                  RADV_DYNAMIC_SAMPLE_LOCATIONS;<br>
                  >         default:<br>
                  >                 unreachable("Unhandled dynamic
                  state");<br>
                  >         }<br>
                  > @@ -1297,6 +1299,11 @@ static uint32_t
                  radv_pipeline_needed_dynamic_state(const
                  VkGraphicsPipelineCreat<br>
                  >         if
                  (!vk_find_struct_const(pCreateInfo->pNext,
                  PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT))<br>
                  >                 states &=
                  ~RADV_DYNAMIC_DISCARD_RECTANGLE;<br>
                  ><br>
                  > +       if (!pCreateInfo->pMultisampleState ||<br>
                  > +         
                   !vk_find_struct_const(pCreateInfo->pMultisampleState->pNext,<br>
                  > +                               
                   PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT))<br>
                  > +               states &=
                  ~RADV_DYNAMIC_SAMPLE_LOCATIONS;<br>
                  > +<br>
                  >         /* TODO: blend constants & line
                  width. */<br>
                  ><br>
                  >         return states;<br>
                  > @@ -1426,6 +1433,29 @@
                  radv_pipeline_init_dynamic_state(struct radv_pipeline
                  *pipeline,<br>
                  >                 }<br>
                  >         }<br>
                  ><br>
                  > +       if (needed_states &
                  RADV_DYNAMIC_SAMPLE_LOCATIONS) {<br>
                  > +               const
                  VkPipelineSampleLocationsStateCreateInfoEXT
                  *sample_location_info =<br>
                  > +                     
                   vk_find_struct_const(pCreateInfo->pMultisampleState->pNext,<br>
                  > +                                           
                  PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT);<br>
                  > +               /* If sampleLocationsEnable is
                  VK_FALSE, the default sample<br>
                  > +                * locations are used and the
                  values specified in<br>
                  > +                * sampleLocationsInfo are
                  ignored.<br>
                  > +                */<br>
                  > +               if
                  (sample_location_info->sampleLocationsEnable) {<br>
                  > +                       const
                  VkSampleLocationsInfoEXT *pSampleLocationsInfo =<br>
                  > +                             
                   &sample_location_info->sampleLocationsInfo;<br>
                  > +<br>
                  > +                     
                   assert(pSampleLocationsInfo->sampleLocationsCount
                  <= MAX_SAMPLE_LOCATIONS);<br>
                  > +<br>
                  > +                     
                   dynamic->sample_location.per_pixel =
                  pSampleLocationsInfo->sampleLocationsPerPixel;<br>
                  > +                     
                   dynamic->sample_location.grid_size =
                  pSampleLocationsInfo->sampleLocationGridSize;<br>
                  > +                     
                   dynamic->sample_location.count =
                  pSampleLocationsInfo->sampleLocationsCount;<br>
                  > +                     
                   typed_memcpy(&dynamic->sample_location.locations[0],<br>
                  > +                                   
                  pSampleLocationsInfo->pSampleLocations,<br>
                  > +                                   
                  pSampleLocationsInfo->sampleLocationsCount);<br>
                  > +               }<br>
                  > +       }<br>
                  > +<br>
                  >         pipeline->dynamic_state.mask = states;<br>
                  >  }<br>
                  ><br>
                  > diff --git a/src/amd/vulkan/radv_private.h
                  b/src/amd/vulkan/radv_private.h<br>
                  > index 7834a505562..5c84bf74352 100644<br>
                  > --- a/src/amd/vulkan/radv_private.h<br>
                  > +++ b/src/amd/vulkan/radv_private.h<br>
                  > @@ -91,6 +91,7 @@ typedef uint32_t xcb_window_t;<br>
                  >  #define MAX_VIEWPORTS   16<br>
                  >  #define MAX_SCISSORS    16<br>
                  >  #define MAX_DISCARD_RECTANGLES 4<br>
                  > +#define MAX_SAMPLE_LOCATIONS 32<br>
                  >  #define MAX_PUSH_CONSTANTS_SIZE 128<br>
                  >  #define MAX_PUSH_DESCRIPTORS 32<br>
                  >  #define MAX_DYNAMIC_UNIFORM_BUFFERS 16<br>
                  > @@ -852,7 +853,8 @@ enum radv_dynamic_state_bits
                  {<br>
                  >         RADV_DYNAMIC_STENCIL_WRITE_MASK   = 1
                  << 7,<br>
                  >         RADV_DYNAMIC_STENCIL_REFERENCE    = 1
                  << 8,<br>
                  >         RADV_DYNAMIC_DISCARD_RECTANGLE    = 1
                  << 9,<br>
                  > -       RADV_DYNAMIC_ALL                  = (1
                  << 10) - 1,<br>
                  > +       RADV_DYNAMIC_SAMPLE_LOCATIONS     = 1
                  << 10,<br>
                  > +       RADV_DYNAMIC_ALL                  = (1
                  << 11) - 1,<br>
                  >  };<br>
                  ><br>
                  >  enum radv_cmd_dirty_bits {<br>
                  > @@ -868,12 +870,13 @@ enum radv_cmd_dirty_bits {<br>
                  >       
                   RADV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK        = 1
                  << 7,<br>
                  >         RADV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE 
                         = 1 << 8,<br>
                  >         RADV_CMD_DIRTY_DYNAMIC_DISCARD_RECTANGLE 
                         = 1 << 9,<br>
                  > -       RADV_CMD_DIRTY_DYNAMIC_ALL               
                         = (1 << 10) - 1,<br>
                  > -       RADV_CMD_DIRTY_PIPELINE                 
                          = 1 << 10,<br>
                  > -       RADV_CMD_DIRTY_INDEX_BUFFER             
                          = 1 << 11,<br>
                  > -       RADV_CMD_DIRTY_FRAMEBUFFER               
                         = 1 << 12,<br>
                  > -       RADV_CMD_DIRTY_VERTEX_BUFFER             
                         = 1 << 13,<br>
                  > -       RADV_CMD_DIRTY_STREAMOUT_BUFFER         
                          = 1 << 14,<br>
                  > +       RADV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS 
                          = 1 << 10,<br>
                  > +       RADV_CMD_DIRTY_DYNAMIC_ALL               
                         = (1 << 11) - 1,<br>
                  > +       RADV_CMD_DIRTY_PIPELINE                 
                          = 1 << 11,<br>
                  > +       RADV_CMD_DIRTY_INDEX_BUFFER             
                          = 1 << 12,<br>
                  > +       RADV_CMD_DIRTY_FRAMEBUFFER               
                         = 1 << 13,<br>
                  > +       RADV_CMD_DIRTY_VERTEX_BUFFER             
                         = 1 << 14,<br>
                  > +       RADV_CMD_DIRTY_STREAMOUT_BUFFER         
                          = 1 << 15,<br>
                  >  };<br>
                  ><br>
                  >  enum radv_cmd_flush_bits {<br>
                  > @@ -950,6 +953,13 @@ struct
                  radv_discard_rectangle_state {<br>
                  >         VkRect2D                                 
                          rectangles[MAX_DISCARD_RECTANGLES];<br>
                  >  };<br>
                  ><br>
                  > +struct radv_sample_locations_state {<br>
                  > +       VkSampleCountFlagBits per_pixel;<br>
                  > +       VkExtent2D grid_size;<br>
                  > +       uint32_t count;<br>
                  > +       VkSampleLocationEXT
                  locations[MAX_SAMPLE_LOCATIONS];<br>
                  > +};<br>
                  > +<br>
                  >  struct radv_dynamic_state {<br>
                  >         /**<br>
                  >          * Bitmask of (1 <<
                  VK_DYNAMIC_STATE_*).<br>
                  > @@ -992,6 +1002,8 @@ struct radv_dynamic_state {<br>
                  >         } stencil_reference;<br>
                  ><br>
                  >         struct radv_discard_rectangle_state     
                           discard_rectangle;<br>
                  > +<br>
                  > +       struct radv_sample_locations_state       
                          sample_location;<br>
                  >  };<br>
                  ><br>
                  >  extern const struct radv_dynamic_state
                  default_dynamic_state;<br>
                  > --<br>
                  > 2.21.0<br>
                  ><br>
                  > _______________________________________________<br>
                  > mesa-dev mailing list<br>
                  > <a href="mailto:mesa-dev@lists.freedesktop.org"
                    target="_blank" moz-do-not-send="true">mesa-dev@lists.freedesktop.org</a><br>
                  > <a
                    href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev"
                    rel="noreferrer" target="_blank"
                    moz-do-not-send="true">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
                  _______________________________________________<br>
                  mesa-dev mailing list<br>
                  <a href="mailto:mesa-dev@lists.freedesktop.org"
                    target="_blank" moz-do-not-send="true">mesa-dev@lists.freedesktop.org</a><br>
                  <a
                    href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev"
                    rel="noreferrer" target="_blank"
                    moz-do-not-send="true">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a></blockquote>
              </div>
            </div>
          </blockquote>
        </div>
      </div>
    </blockquote>
  </body>
</html>