Index: trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_device.cpp
===================================================================
--- trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_device.cpp	(revision 108576)
+++ trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_device.cpp	(revision 108577)
@@ -3114,4 +3114,23 @@
      || dxvkDevice->queues().videoDecode.queueHandle == VK_NULL_HANDLE)
       return;
+
+    /* Filter out profiles that do not work well. */
+    std::vector<VkVideoCodecOperationFlagBitsKHR> vulkanVideoDecodeBlacklist;
+
+    if (dxvkDevice->adapter()->matchesDriver(VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA, 0, 0)) {
+      /* H265: decoded picture consists of multiple small tiles with garbled content. */
+      vulkanVideoDecodeBlacklist.push_back(VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
+
+      /* AV1: crash. VideoSessionMemory is allocated from DEVICE_LOCAL memory type, but
+       * anv_init_av1_cdf_tables maps ANV_VID_MEM_AV1_CDF_DEFAULTS_* buffers in order to
+       * initialize them. The mapped pointer is inaccessible.
+       * Tested on Intel Arc B570 discrete GPU.
+       */
+      vulkanVideoDecodeBlacklist.push_back(VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR);
+    }
+    else if (dxvkDevice->adapter()->matchesDriver(VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, 0, 0)) {
+      /* H265: same as VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA. */
+      vulkanVideoDecodeBlacklist.push_back(VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
+    }
 
     /*
@@ -3205,4 +3224,32 @@
     };
 
+    const struct D3D11VideoDecoderProfile profile_ModeAV1_VLD_Profile0 = {
+      /* .guid = */ DXVA_ModeAV1_VLD_Profile0,  /* D3D11_DECODER_PROFILE_AV1_VLD_PROFILE0 */
+      /* .decoderConfigs = */ std::vector<D3D11_VIDEO_DECODER_CONFIG> {
+        {
+          /* .guidConfigBitstreamEncryption = */ DXVA2_NoEncrypt,
+          /* .guidConfigMBcontrolEncryption = */ DXVA2_NoEncrypt,
+          /* .guidConfigResidDiffEncryption = */ DXVA2_NoEncrypt,
+          /* .ConfigBitstreamRaw = */ 1,
+          /* .ConfigMBcontrolRasterOrder = */ 0,
+          /* .ConfigResidDiffHost = */ 0,
+          /* .ConfigSpatialResid8 = */ 0,
+          /* .ConfigResid8Subtraction = */ 0,
+          /* .ConfigSpatialHost8or9Clipping = */ 0,
+          /* .ConfigSpatialResidInterleaved = */ 0,
+          /* .ConfigIntraResidUnsigned = */ 0,
+          /* .ConfigResidDiffAccelerator = */ 0,
+          /* .ConfigHostInverseScan = */ 0,
+          /* .ConfigSpecificIDCT = */ 0,
+          /* .Config4GroupedCoefs = */ 0,
+          /* .ConfigMinRenderTargetBuffCount = */ 3,
+          /* .ConfigDecoderSpecific = */ 0
+        }
+      },
+      /* .supportedFormats = */ std::vector<DXGI_FORMAT> {
+          DXGI_FORMAT_NV12
+      }
+    };
+
     /*
      * Add desired Vulkan profile descriptions to the 'mappings'.
@@ -3237,5 +3284,5 @@
       };
     m_vulkanDecodeProfiles[1].profileInfo            =
-      { VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR, &m_vulkanDecodeProfiles[1].h264ProfileInfo,
+      { VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR, &m_vulkanDecodeProfiles[1].h265ProfileInfo,
         VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR,
         VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR,
@@ -3253,5 +3300,26 @@
     mappings.back().d3dProfiles.push_back(profile_ModeHEVC_VLD_Main);
 
-    /// @todo More Vulkan profiles: AV1
+    m_vulkanDecodeProfiles[2].profileName            = "AV1";
+    m_vulkanDecodeProfiles[2].av1ProfileInfo         =
+      { VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR, nullptr,
+        STD_VIDEO_AV1_PROFILE_MAIN,
+        VK_TRUE /* filmGrainSupport */
+      };
+    m_vulkanDecodeProfiles[2].profileInfo            =
+      { VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR, &m_vulkanDecodeProfiles[2].av1ProfileInfo,
+        VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR,
+        VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR,
+        VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,
+        VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR
+      };
+    m_vulkanDecodeProfiles[2].decodeAV1Capabilities =
+      { VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR };
+    m_vulkanDecodeProfiles[2].decodeCapabilities     =
+      { VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR, &m_vulkanDecodeProfiles[2].decodeAV1Capabilities };
+    m_vulkanDecodeProfiles[2].videoCapabilities      =
+      { VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR, &m_vulkanDecodeProfiles[2].decodeCapabilities };
+
+    mappings.push_back({ m_vulkanDecodeProfiles[2] });
+    mappings.back().d3dProfiles.push_back(profile_ModeAV1_VLD_Profile0);
 
     /*
@@ -3262,4 +3330,10 @@
 
     for (auto& m: mappings) {
+      const auto it = std::find_if(vulkanVideoDecodeBlacklist.begin(), vulkanVideoDecodeBlacklist.end(),
+        [ op = m.dxvkProfile.profileInfo.videoCodecOperation ](VkVideoCodecOperationFlagBitsKHR v) -> bool
+          { return v == op; });
+      if (it != vulkanVideoDecodeBlacklist.end())
+        continue;
+
       VkResult vr = vki->vkGetPhysicalDeviceVideoCapabilitiesKHR(physicalDevice,
         &m.dxvkProfile.profileInfo, &m.dxvkProfile.videoCapabilities);
Index: trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_device.h
===================================================================
--- trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_device.h	(revision 108576)
+++ trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_device.h	(revision 108577)
@@ -703,5 +703,5 @@
 
     /* Vulkan video profiles, supported by DxvkVideoDecoder. Not necessarily supported by hardware. */
-    std::array<DxvkVideoDecodeProfileInfo, 2> m_vulkanDecodeProfiles;
+    std::array<DxvkVideoDecodeProfileInfo, 3> m_vulkanDecodeProfiles;
 
     /* Supported D3D11 profiles with a reference to the underlaying Vulkan profile (m_vulkanDecodeProfiles).
Index: trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_video.cpp
===================================================================
--- trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_video.cpp	(revision 108576)
+++ trunk/src/libs/dxvk-2.3.1/src/d3d11/d3d11_video.cpp	(revision 108577)
@@ -25,5 +25,5 @@
 
     /* Arbitrary. Sufficiently big for a compressed frame (usually). */
-    m_bitstreamBufferSize = align(m_desc.SampleWidth * m_desc.SampleHeight / 5, 1024 * 1024);
+    m_bitstreamBufferSize = align(m_desc.SampleWidth * m_desc.SampleHeight, 1024 * 1024);
 
     m_videoDecoder = m_device->createVideoDecoder(profile,
@@ -92,4 +92,10 @@
           cbBuffer = m_bitstreamBufferSize;
           break;
+        case D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL:
+          if (m_videoDecoder->GetVideoCodecOperation() == VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR)
+            cbBuffer = 64 * 64 * sizeof(DXVA_Tile_AV1);
+          else
+            cbBuffer = 65536;
+          break;
         default:
           cbBuffer = 65536;
@@ -117,5 +123,5 @@
 
   template<typename DXVA_Slice_T>
-  static bool GetSliceOffsetsAndNALType(
+  static bool GetSliceOffsets(
           DxvkVideoDecodeInputParameters *pParms,
     const D3D11_VIDEO_DECODER_BUFFER_DESC* pSliceDesc,
@@ -128,7 +134,11 @@
      /* D3D11VideoDecoder::GetVideoDecodeInputParameters checks that 'pSliceDesc->DataSize' is less than
       * the size of D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL buffer that is assigned in
-      * D3D11VideoDecoder::GetDecoderBuffer. I.e. 'cSlices' is limuted too.
+      * D3D11VideoDecoder::GetDecoderBuffer. I.e. 'cSlices' is limited too.
       */
-     pParms->sliceOffsets.resize(cSlices);
+     if (cSlices == 0)
+       return false;
+
+     pParms->sliceOrTileOffsets.resize(cSlices);
+     pParms->sliceOrTileSizes.resize(cSlices);
 
      for (uint32_t i = 0; i < cSlices; ++i) {
@@ -147,17 +157,9 @@
          Logger::warn(str::format("D3D11VideoDecoder::GetH264: Ignored slice with wBadSliceChopping ",
            slice.wBadSliceChopping));
-         return false; /// @todo not supported yet
+         return false;
        }
 
-       pParms->sliceOffsets[i] = slice.BSNALunitDataLocation;
-
-       const uint8_t *pu8NALHdr = pBitStream + slice.BSNALunitDataLocation;
-       const uint8_t nal_unit_type = pu8NALHdr[3] & 0x1F;
-
-       Logger::debug(str::format("NAL[", i, "]=", (uint32_t)nal_unit_type, " at ",
-         slice.BSNALunitDataLocation, "/", slice.SliceBytesInBuffer));
-
-       if (i == 0)
-         pParms->nal_unit_type = nal_unit_type;
+       pParms->sliceOrTileOffsets[i] = slice.BSNALunitDataLocation;
+       pParms->sliceOrTileSizes[i] = slice.SliceBytesInBuffer;
      }
 
@@ -291,12 +293,17 @@
     /* Fetch slice offsets. */
     bool fSuccess = config.ConfigBitstreamRaw == 2
-      ? GetSliceOffsetsAndNALType<DXVA_Slice_H264_Short>(&p, pSliceDesc, pSlices, pBitStream, pBitStreamDesc->DataSize)
-      : GetSliceOffsetsAndNALType<DXVA_Slice_H264_Long>(&p, pSliceDesc, pSlices, pBitStream, pBitStreamDesc->DataSize);
+      ? GetSliceOffsets<DXVA_Slice_H264_Short>(&p, pSliceDesc, pSlices, pBitStream, pBitStreamDesc->DataSize)
+      : GetSliceOffsets<DXVA_Slice_H264_Long>(&p, pSliceDesc, pSlices, pBitStream, pBitStreamDesc->DataSize);
     if (!fSuccess)
       return false;
 
+    const uint8_t *pu8NALHdr = pBitStream + pParms->sliceOrTileOffsets[0];
+    pParms->h264.nal_unit_type = pu8NALHdr[3] & 0x1F;
+    Logger::debug(str::format("NAL=", (uint32_t)pParms->h264.nal_unit_type, " at ",
+      pParms->sliceOrTileOffsets[0], "/", pParms->sliceOrTileSizes[0]));
+
     p.h264.stdH264PictureInfo.flags.field_pic_flag           = pPicParams->field_pic_flag;
     p.h264.stdH264PictureInfo.flags.is_intra                 = pPicParams->IntraPicFlag;
-    p.h264.stdH264PictureInfo.flags.IdrPicFlag               = p.nal_unit_type == 5 ? 1 : 0; 
+    p.h264.stdH264PictureInfo.flags.IdrPicFlag               = p.h264.nal_unit_type == 5 ? 1 : 0; 
     p.h264.stdH264PictureInfo.flags.bottom_field_flag        = pPicParams->CurrPic.AssociatedFlag; /* flag is bottom field flag */
     p.h264.stdH264PictureInfo.flags.is_reference             = pPicParams->RefPicFlag;
@@ -325,29 +332,24 @@
     p.idSurface                     = pPicParams->CurrPic.Index7Bits;
 
-    if (pPicParams->IntraPicFlag) {
-      p.refFramesCount = 0;
-    }
-    else {
-      /* Reference frame surfaces. */
-      uint32_t idxRefFrame = 0;
-      for (uint32_t i = 0; i < 16; ++i) {
-        const DXVA_PicEntry_H264& r = pPicParams->RefFrameList[i];
-        if (r.bPicEntry == 0xFF)
-          continue;
-
-        DxvkRefFrameInfo& refFrameInfo = p.refFrames[idxRefFrame];
-        refFrameInfo.idSurface         = r.Index7Bits;
-        refFrameInfo.longTermReference = r.AssociatedFlag;
-        refFrameInfo.usedForReference  = (uint8_t)(pPicParams->UsedForReferenceFlags >> (2 * i)) & 0x3;
-        refFrameInfo.nonExistingFrame  = (uint8_t)(pPicParams->NonExistingFrameFlags >> i) & 0x1;
-        refFrameInfo.frame_num         = pPicParams->FrameNumList[i];
-        refFrameInfo.PicOrderCnt[0]    = pPicParams->FieldOrderCntList[i][0];
-        refFrameInfo.PicOrderCnt[1]    = pPicParams->FieldOrderCntList[i][1];
-
-        ++idxRefFrame;
-      }
-
-      p.refFramesCount = idxRefFrame;
-    }
+    /* Reference frame surfaces. */
+    uint32_t idxRefFrame = 0;
+    for (uint32_t i = 0; i < 16; ++i) {
+      const DXVA_PicEntry_H264& r = pPicParams->RefFrameList[i];
+      if (r.bPicEntry == 0xFF)
+        continue;
+
+      DxvkRefFrameInfo& refFrameInfo = p.refFrames[idxRefFrame];
+      refFrameInfo.idSurface              = r.Index7Bits;
+      refFrameInfo.h264.longTermReference = r.AssociatedFlag;
+      refFrameInfo.h264.usedForReference  = (uint8_t)(pPicParams->UsedForReferenceFlags >> (2 * i)) & 0x3;
+      refFrameInfo.h264.nonExistingFrame  = (uint8_t)(pPicParams->NonExistingFrameFlags >> i) & 0x1;
+      refFrameInfo.h264.frame_num         = pPicParams->FrameNumList[i];
+      refFrameInfo.h264.PicOrderCnt[0]    = pPicParams->FieldOrderCntList[i][0];
+      refFrameInfo.h264.PicOrderCnt[1]    = pPicParams->FieldOrderCntList[i][1];
+
+      ++idxRefFrame;
+    }
+
+    p.refFramesCount = idxRefFrame;
 
     return true;
@@ -413,10 +415,10 @@
     p.h265.vpsProfileTierLevel.general_level_idc                        = STD_VIDEO_H265_LEVEL_IDC_6_2; /* Unknown, set to maxLevelIdc by Dxvk decoder. */
 
-    p.h265.sps.flags.sps_temporal_id_nesting_flag             = 0; /// @todo Unknown
+    p.h265.sps.flags.sps_temporal_id_nesting_flag             = 0; /* Unused */
     p.h265.sps.flags.separate_colour_plane_flag               = pPicParams->separate_colour_plane_flag;
     p.h265.sps.flags.conformance_window_flag                  = 0; /* Unknown */
-    p.h265.sps.flags.sps_sub_layer_ordering_info_present_flag = 0; /// @todo Unknown
+    p.h265.sps.flags.sps_sub_layer_ordering_info_present_flag = 0; /* spsDecPicBufMgr applies to all sub-layers */
     p.h265.sps.flags.scaling_list_enabled_flag                = pPicParams->scaling_list_enabled_flag;
-    p.h265.sps.flags.sps_scaling_list_data_present_flag       = 0; /// @todo pps?
+    p.h265.sps.flags.sps_scaling_list_data_present_flag       = 0; /* Part of pps */
     p.h265.sps.flags.amp_enabled_flag                         = pPicParams->amp_enabled_flag;
     p.h265.sps.flags.sample_adaptive_offset_enabled_flag      = pPicParams->sample_adaptive_offset_enabled_flag;
@@ -427,25 +429,25 @@
     p.h265.sps.flags.strong_intra_smoothing_enabled_flag      = pPicParams->strong_intra_smoothing_enabled_flag;
     p.h265.sps.flags.vui_parameters_present_flag              = 0; /* Unused */
-    p.h265.sps.flags.sps_extension_present_flag               = 0; /// @todo unknown
-    p.h265.sps.flags.sps_range_extension_flag                 = 0; /// @todo unknown
-    p.h265.sps.flags.transform_skip_rotation_enabled_flag     = pPicParams->transform_skip_enabled_flag;
-    p.h265.sps.flags.transform_skip_context_enabled_flag      = pPicParams->transform_skip_enabled_flag;
-    p.h265.sps.flags.implicit_rdpcm_enabled_flag              = 0; /// @todo unknown
-    p.h265.sps.flags.explicit_rdpcm_enabled_flag              = 0; /// @todo unknown
-    p.h265.sps.flags.extended_precision_processing_flag       = 0; /// @todo unknown
-    p.h265.sps.flags.intra_smoothing_disabled_flag            = 0; /// @todo unknown
-    p.h265.sps.flags.high_precision_offsets_enabled_flag      = 0; /// @todo unknown
-    p.h265.sps.flags.persistent_rice_adaptation_enabled_flag  = 0; /// @todo unknown
-    p.h265.sps.flags.cabac_bypass_alignment_enabled_flag      = 0; /// @todo unknown
-    p.h265.sps.flags.sps_scc_extension_flag                   = 0; /// @todo unknown
-    p.h265.sps.flags.sps_curr_pic_ref_enabled_flag            = 0; /// @todo unknown
+    p.h265.sps.flags.sps_extension_present_flag               = 0; /* Unused */
+    p.h265.sps.flags.sps_range_extension_flag                 = 0; /* Unused */
+    p.h265.sps.flags.transform_skip_rotation_enabled_flag     = 0; /* Unused */
+    p.h265.sps.flags.transform_skip_context_enabled_flag      = 0; /* Unused */
+    p.h265.sps.flags.implicit_rdpcm_enabled_flag              = 0; /* Unused */
+    p.h265.sps.flags.explicit_rdpcm_enabled_flag              = 0; /* Unused */
+    p.h265.sps.flags.extended_precision_processing_flag       = 0; /* Unused */
+    p.h265.sps.flags.intra_smoothing_disabled_flag            = 0; /* Unused */
+    p.h265.sps.flags.high_precision_offsets_enabled_flag      = 0; /* Unused. 0 for 8 bits processing. */
+    p.h265.sps.flags.persistent_rice_adaptation_enabled_flag  = 0; /* Unused */
+    p.h265.sps.flags.cabac_bypass_alignment_enabled_flag      = 0; /* Unused */
+    p.h265.sps.flags.sps_scc_extension_flag                   = 0; /* Unused */
+    p.h265.sps.flags.sps_curr_pic_ref_enabled_flag            = 1; /* Unknown. */
     p.h265.sps.flags.palette_mode_enabled_flag                = 0; /* Unused */
     p.h265.sps.flags.sps_palette_predictor_initializers_present_flag = 0; /* Unused */
-    p.h265.sps.flags.intra_boundary_filtering_disabled_flag   = 0; /// @todo unknown
+    p.h265.sps.flags.intra_boundary_filtering_disabled_flag   = 0; /* Unused */
     p.h265.sps.chroma_format_idc                              = StdVideoH265ChromaFormatIdc(pPicParams->chroma_format_idc);
     p.h265.sps.pic_width_in_luma_samples                      = pPicParams->PicWidthInMinCbsY * MinCbSizeY;
     p.h265.sps.pic_height_in_luma_samples                     = pPicParams->PicHeightInMinCbsY * MinCbSizeY;
     p.h265.sps.sps_video_parameter_set_id                     = 0; /* Unknown, will be inferred by the Dxvk decoder. */
-    p.h265.sps.sps_max_sub_layers_minus1                      = 0; /// @todo unknown
+    p.h265.sps.sps_max_sub_layers_minus1                      = 0; /* Unknown, one sub-layer. */
     p.h265.sps.sps_seq_parameter_set_id                       = 0; /* Unknown, will be inferred by the Dxvk decoder. */
     p.h265.sps.bit_depth_luma_minus8                          = pPicParams->bit_depth_luma_minus8;
@@ -468,5 +470,5 @@
     p.h265.sps.palette_max_size                               = 0; /* Unused */
     p.h265.sps.delta_palette_max_predictor_size               = 0; /* Unused */
-    p.h265.sps.motion_vector_resolution_control_idc           = 0; /// @todo unknown
+    p.h265.sps.motion_vector_resolution_control_idc           = 0; /* Unused */
     p.h265.sps.sps_num_palette_predictor_initializers_minus1  = 0; /* Unused */
     p.h265.sps.conf_win_left_offset                           = 0; /* Unused */
@@ -474,6 +476,6 @@
     p.h265.sps.conf_win_top_offset                            = 0; /* Unused */
     p.h265.sps.conf_win_bottom_offset                         = 0; /* Unused */
-    p.h265.sps.pProfileTierLevel                              = nullptr; /// @todo unknown StdVideoH265ProfileTierLevel
-    p.h265.sps.pDecPicBufMgr                                  = nullptr; /// @todo unknown StdVideoH265DecPicBufMgr
+    p.h265.sps.pProfileTierLevel                              = nullptr; /* &p.h265.vpsProfileTierLevel */
+    p.h265.sps.pDecPicBufMgr                                  = nullptr; /* &p.h265.spsDecPicBufMgr */
     p.h265.sps.pScalingLists                                  = nullptr; /*  Part of pps */
     p.h265.sps.pShortTermRefPicSet                            = nullptr; /// @todo unknown StdVideoH265ShortTermRefPicSet
@@ -481,4 +483,15 @@
     p.h265.sps.pSequenceParameterSetVui                       = nullptr; /* Unused StdVideoH265SequenceParameterSetVui */
     p.h265.sps.pPredictorPaletteEntries                       = nullptr; /* Unused StdVideoH265PredictorPaletteEntries */
+
+    for (uint32_t i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; ++i) {
+      p.h265.spsDecPicBufMgr.max_latency_increase_plus1[i] = 0;
+    }
+    for (uint32_t i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; ++i) {
+      p.h265.spsDecPicBufMgr.max_dec_pic_buffering_minus1[i] = std::min(pPicParams->sps_max_dec_pic_buffering_minus1,
+                                                                        (uint8_t)(STD_VIDEO_H265_MAX_DPB_SIZE - 1));
+    }
+    for (uint32_t i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; ++i) {
+      p.h265.spsDecPicBufMgr.max_num_reorder_pics[i] = STD_VIDEO_H265_MAX_DPB_SIZE - 1;
+    }
 
     p.h265.pps.flags.dependent_slice_segments_enabled_flag    = pPicParams->dependent_slice_segments_enabled_flag;
@@ -498,5 +511,5 @@
     p.h265.pps.flags.loop_filter_across_tiles_enabled_flag    = pPicParams->loop_filter_across_tiles_enabled_flag;
     p.h265.pps.flags.pps_loop_filter_across_slices_enabled_flag = pPicParams->pps_loop_filter_across_slices_enabled_flag;
-    p.h265.pps.flags.deblocking_filter_control_present_flag    = 0; /// @todo unknown
+    p.h265.pps.flags.deblocking_filter_control_present_flag    = 1; /* Present */
     p.h265.pps.flags.deblocking_filter_override_enabled_flag  = pPicParams->deblocking_filter_override_enabled_flag;
     p.h265.pps.flags.pps_deblocking_filter_disabled_flag      = pPicParams->pps_deblocking_filter_disabled_flag;
@@ -504,13 +517,13 @@
     p.h265.pps.flags.lists_modification_present_flag          = pPicParams->lists_modification_present_flag;
     p.h265.pps.flags.slice_segment_header_extension_present_flag = pPicParams->slice_segment_header_extension_present_flag;
-    p.h265.pps.flags.pps_extension_present_flag               = 0; /// @todo unknown
-    p.h265.pps.flags.cross_component_prediction_enabled_flag  = 0; /// @todo unknown
-    p.h265.pps.flags.chroma_qp_offset_list_enabled_flag       = pPicParams->pps_slice_chroma_qp_offsets_present_flag; /// @todo is it?
-    p.h265.pps.flags.pps_curr_pic_ref_enabled_flag            = 0; /// @todo unknown
-    p.h265.pps.flags.residual_adaptive_colour_transform_enabled_flag = 0; /// @todo unknown
-    p.h265.pps.flags.pps_slice_act_qp_offsets_present_flag    = 0; /// @todo unknown
+    p.h265.pps.flags.pps_extension_present_flag               = 0; /* Unused */
+    p.h265.pps.flags.cross_component_prediction_enabled_flag  = 0; /* Unused */
+    p.h265.pps.flags.chroma_qp_offset_list_enabled_flag       = 0; /* Unused */
+    p.h265.pps.flags.pps_curr_pic_ref_enabled_flag            = 1; /* Unknown */
+    p.h265.pps.flags.residual_adaptive_colour_transform_enabled_flag = 0; /* Unused */
+    p.h265.pps.flags.pps_slice_act_qp_offsets_present_flag    = 0; /* Unused */
     p.h265.pps.flags.pps_palette_predictor_initializers_present_flag = 0; /* Unused */
     p.h265.pps.flags.monochrome_palette_flag                  = 0; /* Unused */
-    p.h265.pps.flags.pps_range_extension_flag                 = 0; /// @todo unknown
+    p.h265.pps.flags.pps_range_extension_flag                 = 0; /* Unused */
     p.h265.pps.pps_pic_parameter_set_id                       = 0; /* Unknown, will be inferred by the Dxvk decoder. */
     p.h265.pps.pps_seq_parameter_set_id                       = 0; /* Unknown, will be inferred by the Dxvk decoder. */
@@ -526,21 +539,22 @@
     p.h265.pps.pps_tc_offset_div2                             = pPicParams->pps_tc_offset_div2;
     p.h265.pps.log2_parallel_merge_level_minus2               = pPicParams->log2_parallel_merge_level_minus2;
-    p.h265.pps.log2_max_transform_skip_block_size_minus2      = 0; /// @todo unknown
-    p.h265.pps.diff_cu_chroma_qp_offset_depth                 = 0; /// @todo unknown
-    p.h265.pps.chroma_qp_offset_list_len_minus1               = 0; /// @todo unknown
+    p.h265.pps.log2_max_transform_skip_block_size_minus2      = pPicParams->log2_min_transform_block_size_minus2
+                                                              + pPicParams->log2_diff_max_min_transform_block_size;
+    p.h265.pps.diff_cu_chroma_qp_offset_depth                 = 0; /* Unused */
+    p.h265.pps.chroma_qp_offset_list_len_minus1               = 0; /* Unused */
     for (uint32_t i = 0; i < STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE; ++i) {
-      p.h265.pps.cb_qp_offset_list[i] = 0; /// @todo unknown
+      p.h265.pps.cb_qp_offset_list[i]                         = 0; /* Unused */
     }
     for (uint32_t i = 0; i < STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE; ++i) {
-      p.h265.pps.cr_qp_offset_list[i] = 0; /// @todo unknown
-    }
-    p.h265.pps.log2_sao_offset_scale_luma                    = 0; /// @todo unknown
-    p.h265.pps.log2_sao_offset_scale_chroma                  = 0; /// @todo unknown
-    p.h265.pps.pps_act_y_qp_offset_plus5                     = 0; /// @todo unknown
-    p.h265.pps.pps_act_cb_qp_offset_plus5                    = 0; /// @todo unknown
-    p.h265.pps.pps_act_cr_qp_offset_plus3                    = 0; /// @todo unknown
+      p.h265.pps.cr_qp_offset_list[i]                         = 0; /* Unused */
+    }
+    p.h265.pps.log2_sao_offset_scale_luma                    = 0; /* "not present, the value ... is inferred to be equal to 0." */
+    p.h265.pps.log2_sao_offset_scale_chroma                  = 0; /* "not present, the value ... is inferred to be equal to 0." */
+    p.h265.pps.pps_act_y_qp_offset_plus5                     = 0; /* Unused */
+    p.h265.pps.pps_act_cb_qp_offset_plus5                    = 0; /* Unused */
+    p.h265.pps.pps_act_cr_qp_offset_plus3                    = 0; /* Unused */
     p.h265.pps.pps_num_palette_predictor_initializers        = 0; /* Unused */
-    p.h265.pps.luma_bit_depth_entry_minus8                   = 0; /// @todo unknown
-    p.h265.pps.chroma_bit_depth_entry_minus8                 = 0; /// @todo unknown
+    p.h265.pps.luma_bit_depth_entry_minus8                   = 0; /* Unused */
+    p.h265.pps.chroma_bit_depth_entry_minus8                 = 0; /* Unused */
     p.h265.pps.num_tile_columns_minus1                       = pPicParams->num_tile_columns_minus1;
     p.h265.pps.num_tile_rows_minus1                          = pPicParams->num_tile_rows_minus1;
@@ -562,5 +576,5 @@
     }
 
-    bool fSuccess = GetSliceOffsetsAndNALType<DXVA_Slice_HEVC_Short>(
+    bool fSuccess = GetSliceOffsets<DXVA_Slice_HEVC_Short>(
       &p, pSliceDesc, pSlices, pBitStream, pBitStreamDesc->DataSize);
     if (!fSuccess)
@@ -605,39 +619,416 @@
     }
 
-    p.h265.stdReferenceInfo.flags.used_for_long_term_reference = 0; /// @todo unknown
-    p.h265.stdReferenceInfo.flags.unused_for_reference         = 0; /// @todo unknown
+    p.h265.stdReferenceInfo.flags.used_for_long_term_reference = 0; /* Unknown, will be set later by Dxvk decoder. */
+    p.h265.stdReferenceInfo.flags.unused_for_reference         = 0; /* Unknown, will be set later by Dxvk decoder. */
     p.h265.stdReferenceInfo.PicOrderCntVal                     = pPicParams->CurrPicOrderCntVal;
-
-    /* How many pictures to keep. */
-    p.h265.sps_max_dec_pic_buffering   = pPicParams->sps_max_dec_pic_buffering_minus1 + 1;
 
     /* The picture identifier of destination uncompressed surface. */
     p.idSurface                        = pPicParams->CurrPic.Index7Bits;
 
-    if (pPicParams->IntraPicFlag) {
-      p.refFramesCount = 0;
-    }
-    else {
-      /* Reference frame surfaces. */
-      uint32_t idxRefFrame = 0;
-      for (uint32_t i = 0; i < 15; ++i) {
-        const DXVA_PicEntry_HEVC& r = pPicParams->RefPicList[i];
-        if (r.Index7Bits == 0x7F)
-          continue;
-
-        DxvkRefFrameInfo& refFrameInfo = p.refFrames[idxRefFrame];
-        refFrameInfo.idSurface         = r.Index7Bits;
-        refFrameInfo.longTermReference = r.AssociatedFlag;
-        refFrameInfo.usedForReference  = 0x3;
-        refFrameInfo.nonExistingFrame  = 0;
-        refFrameInfo.frame_num         = 0; /* Unused */
-        refFrameInfo.PicOrderCnt[0]    = pPicParams->PicOrderCntValList[i];
-        refFrameInfo.PicOrderCnt[1]    = refFrameInfo.PicOrderCnt[0];
-
-        ++idxRefFrame;
+    /* Reference frame surfaces. */
+    uint32_t idxRefFrame = 0;
+    for (uint32_t i = 0; i < 15; ++i) {
+      const DXVA_PicEntry_HEVC& r = pPicParams->RefPicList[i];
+      if (r.Index7Bits == 0x7F)
+        continue;
+
+      DxvkRefFrameInfo& refFrameInfo = p.refFrames[idxRefFrame];
+      refFrameInfo.idSurface              = r.Index7Bits;
+      refFrameInfo.h265.longTermReference = r.AssociatedFlag;
+      refFrameInfo.h265.PicOrderCntVal    = pPicParams->PicOrderCntValList[i];
+
+      ++idxRefFrame;
+    }
+
+    p.refFramesCount                 = idxRefFrame;
+
+    return true;
+  }
+
+
+  static uint8_t highestBitSet(UINT v) {
+    /* An obvious method. Intentionally returns 0 for v=0. */
+    UINT r = 0;
+    if (v > 0xFFFF) {
+      r += 16;
+      v >>= 16;
+    }
+    if (v > 0xFF) {
+      r += 8;
+      v >>= 8;
+    }
+    if (v > 0xF) {
+      r += 4;
+      v >>= 4;
+    }
+    if (v > 0x3) {
+      r += 2;
+      v >>= 2;
+    }
+    if (v > 0x1) {
+      r += 1;
+    }
+    return (uint8_t)r;
+  }
+
+
+  static bool GetVideoDecodeAV1InputParameters(
+    const DXVA_PicParams_AV1*              pPicParams,
+    const D3D11_VIDEO_DECODER_BUFFER_DESC* pPicParamsDesc,
+    const DXVA_Tile_AV1*                   pTiles,
+    const D3D11_VIDEO_DECODER_BUFFER_DESC* pTilesDesc,
+    const uint8_t*                         pBitStream,
+    const D3D11_VIDEO_DECODER_BUFFER_DESC* pBitStreamDesc,
+          DxvkVideoDecodeInputParameters *pParms) {
+    if (pPicParams == nullptr || pTiles == nullptr || pBitStream == nullptr) {
+      Logger::warn(str::format("DXVK: Video Decode: Not enough data:"
+        " PicParams ", (uint32_t)(pPicParams != nullptr),
+        " Tiles ", (uint32_t)(pTiles != nullptr),
+        " BitStream ", (uint32_t)(pBitStream != nullptr)));
+      return false;
+    }
+
+    if (pPicParamsDesc->DataSize < sizeof(DXVA_PicParams_AV1)) {
+      Logger::warn(str::format("DXVK: Video Decode: PicParams buffer size is too small: ", pPicParamsDesc->DataSize));
+      return false;
+    }
+
+    const uint32_t cTiles = pTilesDesc->DataSize / sizeof(DXVA_Tile_AV1);
+
+    struct DxvkVideoDecodeInputParameters &p = *pParms;
+
+    const uint32_t superblockSize = pPicParams->coding.use_128x128_superblock ? 128 : 64;
+
+    p.av1.stdSequenceHeader.flags.still_picture                      = 0;
+    p.av1.stdSequenceHeader.flags.reduced_still_picture_header       = 0;
+    p.av1.stdSequenceHeader.flags.use_128x128_superblock             = pPicParams->coding.use_128x128_superblock;
+    p.av1.stdSequenceHeader.flags.enable_filter_intra                = pPicParams->coding.filter_intra;
+    p.av1.stdSequenceHeader.flags.enable_intra_edge_filter           = pPicParams->coding.intra_edge_filter;
+    p.av1.stdSequenceHeader.flags.enable_interintra_compound         = pPicParams->coding.interintra_compound;
+    p.av1.stdSequenceHeader.flags.enable_masked_compound             = pPicParams->coding.masked_compound;
+    p.av1.stdSequenceHeader.flags.enable_warped_motion               = pPicParams->coding.warped_motion;
+    p.av1.stdSequenceHeader.flags.enable_dual_filter                 = pPicParams->coding.dual_filter;
+    p.av1.stdSequenceHeader.flags.enable_order_hint                  = pPicParams->order_hint_bits > 0 ? 1 : 0;
+    p.av1.stdSequenceHeader.flags.enable_jnt_comp                    = pPicParams->coding.jnt_comp;
+    p.av1.stdSequenceHeader.flags.enable_ref_frame_mvs               = pPicParams->coding.enable_ref_frame_mvs;
+    p.av1.stdSequenceHeader.flags.frame_id_numbers_present_flag      = 0; /* No frame ids. */
+    p.av1.stdSequenceHeader.flags.enable_superres                    = pPicParams->coding.superres;
+    p.av1.stdSequenceHeader.flags.enable_cdef                        = pPicParams->coding.cdef;
+    p.av1.stdSequenceHeader.flags.enable_restoration                 = pPicParams->coding.restoration;
+    p.av1.stdSequenceHeader.flags.film_grain_params_present          = pPicParams->coding.film_grain;
+    p.av1.stdSequenceHeader.flags.timing_info_present_flag           = 0;
+    p.av1.stdSequenceHeader.flags.initial_display_delay_present_flag = 0;
+    p.av1.stdSequenceHeader.flags.reserved                           = 0;
+    p.av1.stdSequenceHeader.seq_profile                              = StdVideoAV1Profile(pPicParams->seq_profile);
+    p.av1.stdSequenceHeader.frame_width_bits_minus_1                 = highestBitSet(pPicParams->width);
+    p.av1.stdSequenceHeader.frame_height_bits_minus_1                = highestBitSet(pPicParams->height);
+    p.av1.stdSequenceHeader.max_frame_width_minus_1                  = uint16_t(pPicParams->max_width - 1);
+    p.av1.stdSequenceHeader.max_frame_height_minus_1                 = uint16_t(pPicParams->max_height - 1);
+    p.av1.stdSequenceHeader.delta_frame_id_length_minus_2            = 0; /* No frame ids. */
+    p.av1.stdSequenceHeader.additional_frame_id_length_minus_1       = 0; /* No frame ids. */
+    p.av1.stdSequenceHeader.order_hint_bits_minus_1                  = p.av1.stdSequenceHeader.flags.enable_order_hint
+                                                                     ? pPicParams->order_hint_bits - 1
+                                                                     : 0;
+    p.av1.stdSequenceHeader.seq_force_integer_mv                     = STD_VIDEO_AV1_SELECT_INTEGER_MV;
+    p.av1.stdSequenceHeader.seq_force_screen_content_tools           = STD_VIDEO_AV1_SELECT_SCREEN_CONTENT_TOOLS;
+    memset(p.av1.stdSequenceHeader.reserved1, 0, sizeof(p.av1.stdSequenceHeader.reserved1));
+    p.av1.stdSequenceHeader.pColorConfig                             = nullptr; /* &p.av1.stdColorConfig StdVideoAV1ColorConfig */
+    p.av1.stdSequenceHeader.pTimingInfo                              = nullptr; /* Unused StdVideoAV1TimingInfo */
+
+    p.av1.stdColorConfig.flags.mono_chrome                           = pPicParams->format.mono_chrome;
+    p.av1.stdColorConfig.flags.color_range                           = 0;
+    p.av1.stdColorConfig.flags.separate_uv_delta_q                   = 1;
+    p.av1.stdColorConfig.flags.color_description_present_flag        = 0;
+    p.av1.stdColorConfig.flags.reserved                              = 0;
+    p.av1.stdColorConfig.BitDepth                                    = pPicParams->bitdepth;
+    p.av1.stdColorConfig.subsampling_x                               = pPicParams->format.subsampling_x;
+    p.av1.stdColorConfig.subsampling_y                               = pPicParams->format.subsampling_y;
+    p.av1.stdColorConfig.reserved1                                   = 0;
+    p.av1.stdColorConfig.color_primaries                             = STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED;
+    p.av1.stdColorConfig.transfer_characteristics                    = STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_UNSPECIFIED;
+    p.av1.stdColorConfig.matrix_coefficients                         = STD_VIDEO_AV1_MATRIX_COEFFICIENTS_UNSPECIFIED;
+    p.av1.stdColorConfig.chroma_sample_position                      = STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_UNKNOWN;
+
+    p.av1.stdPictureInfo.flags.error_resilient_mode                  = 1;
+    p.av1.stdPictureInfo.flags.disable_cdf_update                    = pPicParams->coding.disable_cdf_update;
+    p.av1.stdPictureInfo.flags.use_superres                          = pPicParams->coding.superres;
+    p.av1.stdPictureInfo.flags.render_and_frame_size_different       = 0;
+    p.av1.stdPictureInfo.flags.allow_screen_content_tools            = pPicParams->coding.screen_content_tools;
+    p.av1.stdPictureInfo.flags.is_filter_switchable                  = StdVideoAV1InterpolationFilter(pPicParams->interp_filter)
+                                                                       == STD_VIDEO_AV1_INTERPOLATION_FILTER_SWITCHABLE;
+    p.av1.stdPictureInfo.flags.force_integer_mv                      = pPicParams->coding.integer_mv;
+    p.av1.stdPictureInfo.flags.frame_size_override_flag              = 0;
+    p.av1.stdPictureInfo.flags.buffer_removal_time_present_flag      = 0;
+    p.av1.stdPictureInfo.flags.allow_intrabc                         = pPicParams->coding.intrabc;
+    p.av1.stdPictureInfo.flags.frame_refs_short_signaling            = 0;
+    p.av1.stdPictureInfo.flags.allow_high_precision_mv               = pPicParams->coding.high_precision_mv;
+    p.av1.stdPictureInfo.flags.is_motion_mode_switchable             = pPicParams->coding.switchable_motion_mode;
+    p.av1.stdPictureInfo.flags.use_ref_frame_mvs                     = pPicParams->coding.use_ref_frame_mvs;
+    p.av1.stdPictureInfo.flags.disable_frame_end_update_cdf          = pPicParams->coding.disable_frame_end_update_cdf;
+    p.av1.stdPictureInfo.flags.allow_warped_motion                   = pPicParams->coding.warped_motion;
+    p.av1.stdPictureInfo.flags.reduced_tx_set                        = pPicParams->coding.reduced_tx_set;
+    p.av1.stdPictureInfo.flags.reference_select                      = pPicParams->coding.reference_mode;
+    p.av1.stdPictureInfo.flags.skip_mode_present                     = pPicParams->coding.skip_mode;
+    p.av1.stdPictureInfo.flags.delta_q_present                       = pPicParams->quantization.delta_q_present;
+    p.av1.stdPictureInfo.flags.delta_lf_present                      = pPicParams->loop_filter.delta_lf_present;
+    p.av1.stdPictureInfo.flags.delta_lf_multi                        = pPicParams->loop_filter.delta_lf_multi;
+    p.av1.stdPictureInfo.flags.segmentation_enabled                  = pPicParams->segmentation.enabled;
+    p.av1.stdPictureInfo.flags.segmentation_update_map               = pPicParams->segmentation.update_map;
+    p.av1.stdPictureInfo.flags.segmentation_temporal_update          = pPicParams->segmentation.temporal_update;
+    p.av1.stdPictureInfo.flags.segmentation_update_data              = pPicParams->segmentation.update_data;
+    p.av1.stdPictureInfo.flags.usesChromaLr                          = !pPicParams->format.mono_chrome
+                                                                        && (pPicParams->loop_filter.frame_restoration_type[1] != 0
+                                                                         || pPicParams->loop_filter.frame_restoration_type[2] != 0);
+    p.av1.stdPictureInfo.flags.UsesLr                                = p.av1.stdPictureInfo.flags.usesChromaLr
+                                                                       || pPicParams->loop_filter.frame_restoration_type[0] != 0;
+    p.av1.stdPictureInfo.flags.apply_grain                           = pPicParams->film_grain.apply_grain;
+    p.av1.stdPictureInfo.flags.reserved                              = 0;
+
+    p.av1.stdPictureInfo.frame_type                                  = StdVideoAV1FrameType(pPicParams->format.frame_type);
+    p.av1.stdPictureInfo.current_frame_id                            = 0; /* No frame ids. */
+    p.av1.stdPictureInfo.OrderHint                                   = p.av1.stdSequenceHeader.flags.enable_order_hint
+                                                                     ? pPicParams->order_hint
+                                                                     : 0;
+    p.av1.stdPictureInfo.primary_ref_frame                           = pPicParams->primary_ref_frame;
+    p.av1.stdPictureInfo.refresh_frame_flags                         = 0xff;
+    p.av1.stdPictureInfo.reserved1                                   = 0;
+    p.av1.stdPictureInfo.interpolation_filter                        = StdVideoAV1InterpolationFilter(pPicParams->interp_filter);
+    p.av1.stdPictureInfo.TxMode                                      = StdVideoAV1TxMode(pPicParams->coding.tx_mode);
+    p.av1.stdPictureInfo.delta_q_res                                 = pPicParams->quantization.delta_q_res;
+    p.av1.stdPictureInfo.delta_lf_res                                = pPicParams->loop_filter.delta_lf_res;
+    p.av1.stdPictureInfo.SkipModeFrame[0]                            = 0; /* Computed by dxvk decoder. */
+    p.av1.stdPictureInfo.SkipModeFrame[1]                            = 0; /* Computed by dxvk decoder. */
+    p.av1.stdPictureInfo.coded_denom                                 = pPicParams->coding.superres
+                                                                     ? pPicParams->superres_denom - 9
+                                                                     : 0;
+    memset(p.av1.stdPictureInfo.reserved2, 0, sizeof(p.av1.stdPictureInfo.reserved2));
+    for (uint32_t i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; ++i) {
+      p.av1.stdPictureInfo.OrderHints[i]                             = (uint8_t)0; /* Filled by dxvk decoder */
+    }
+    for (uint32_t i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; ++i) {
+      p.av1.stdPictureInfo.expectedFrameId[i]                        = (uint32_t)0; /* No frame ids. */
+    }
+    p.av1.stdPictureInfo.pTileInfo                                   = nullptr; /* &p.av1.stdTileInfo StdVideoAV1TileInfo */
+    p.av1.stdPictureInfo.pQuantization                               = nullptr; /* &p.av1.stdQuantization StdVideoAV1Quantization */
+    p.av1.stdPictureInfo.pSegmentation                               = nullptr; /* &p.av1.stdSegmentation StdVideoAV1Segmentation */
+    p.av1.stdPictureInfo.pLoopFilter                                 = nullptr; /* &p.av1.stdLoopFilter StdVideoAV1LoopFilter */
+    p.av1.stdPictureInfo.pCDEF                                       = nullptr; /* &p.av1.stdCDEF StdVideoAV1CDEF */
+    p.av1.stdPictureInfo.pLoopRestoration                            = nullptr; /* &p.av1.stdLoopRestoration StdVideoAV1LoopRestoration */
+    p.av1.stdPictureInfo.pGlobalMotion                               = nullptr; /* &p.av1.stdGlobalMotion StdVideoAV1GlobalMotion */
+    p.av1.stdPictureInfo.pFilmGrain                                  = nullptr; /* &p.av1.stdFilmGrain StdVideoAV1FilmGrain */
+
+    bool uniform_tile_spacing_flag = true;
+    uint16_t MaxTileDimension = 0;
+    int TileDimension = -1;
+    uint16_t MiColStart = 0; /* MiColStart in superblocks */
+    for (uint32_t i = 0; i < std::min(pPicParams->tiles.cols, (UCHAR)64); ++i) {
+      const USHORT width = pPicParams->tiles.widths[i];
+      p.av1.MiColStarts[i]                                           = MiColStart;
+      p.av1.WidthInSbsMinus1[i]                                      = width - 1;
+      MiColStart += width;
+      if (MaxTileDimension < width)
+        MaxTileDimension = width;
+      if (TileDimension == -1)
+        TileDimension = width;
+      else if (i < std::min(pPicParams->tiles.cols, (UCHAR)64) - 1) { /* The rightmost column does not count. */
+        if (TileDimension != width)
+          uniform_tile_spacing_flag = false;
       }
-
-      p.refFramesCount                 = idxRefFrame;
-    }
+    }
+    TileDimension = -1;
+    uint16_t MiRowStart = 0; /* MiRowStart in superblocks */
+    for (uint32_t i = 0; i < std::min(pPicParams->tiles.rows, (UCHAR)64); ++i) {
+      const USHORT height = pPicParams->tiles.heights[i];
+      p.av1.MiRowStarts[i]                                           = MiRowStart;
+      p.av1.HeightInSbsMinus1[i]                                     = height - 1;
+      MiRowStart += height;
+      if (MaxTileDimension < height)
+        MaxTileDimension = height;
+      if (TileDimension == -1)
+        TileDimension = height;
+      else if (i < std::min(pPicParams->tiles.rows, (UCHAR)64) - 1) { /* The bottom row does not count. */
+        if (TileDimension != height)
+          uniform_tile_spacing_flag = false;
+      }
+    }
+    p.av1.stdTileInfo.flags.uniform_tile_spacing_flag                = uniform_tile_spacing_flag ? 1 : 0;
+    p.av1.stdTileInfo.flags.reserved                                 = 0;
+    p.av1.stdTileInfo.TileCols                                       = pPicParams->tiles.cols;
+    p.av1.stdTileInfo.TileRows                                       = pPicParams->tiles.rows;
+    p.av1.stdTileInfo.context_update_tile_id                         = pPicParams->tiles.context_update_id;
+    p.av1.stdTileInfo.tile_size_bytes_minus_1                        = highestBitSet(MaxTileDimension) / 8;
+    memset(p.av1.stdTileInfo.reserved1, 0, sizeof(p.av1.stdTileInfo.reserved1));
+    p.av1.stdTileInfo.pMiColStarts                                   = nullptr; /* &p.av1.MiColStarts */
+    p.av1.stdTileInfo.pMiRowStarts                                   = nullptr; /* &p.av1.MiRowStarts */
+    p.av1.stdTileInfo.pWidthInSbsMinus1                              = nullptr; /* &p.av1.WidthInSbsMinus1 */
+    p.av1.stdTileInfo.pHeightInSbsMinus1                             = nullptr; /* &p.av1.HeightInSbsMinus1 */
+
+    p.av1.stdQuantization.flags.using_qmatrix                        = pPicParams->quantization.qm_y != 0xFF;
+    p.av1.stdQuantization.flags.diff_uv_delta                        = 1; /* "U and V delta quantizer values are coded separately" */
+    p.av1.stdQuantization.flags.reserved                             = 0;
+    p.av1.stdQuantization.base_q_idx                                 = pPicParams->quantization.base_qindex;
+    p.av1.stdQuantization.DeltaQYDc                                  = pPicParams->quantization.y_dc_delta_q;
+    p.av1.stdQuantization.DeltaQUDc                                  = pPicParams->quantization.u_dc_delta_q;
+    p.av1.stdQuantization.DeltaQUAc                                  = pPicParams->quantization.u_ac_delta_q;
+    p.av1.stdQuantization.DeltaQVDc                                  = pPicParams->quantization.v_dc_delta_q;
+    p.av1.stdQuantization.DeltaQVAc                                  = pPicParams->quantization.v_ac_delta_q;
+    p.av1.stdQuantization.qm_y                                       = p.av1.stdQuantization.flags.using_qmatrix
+                                                                     ? pPicParams->quantization.qm_y
+                                                                     : 0;
+    p.av1.stdQuantization.qm_u                                       = p.av1.stdQuantization.flags.using_qmatrix
+                                                                     ? pPicParams->quantization.qm_u
+                                                                     : 0;
+    p.av1.stdQuantization.qm_v                                       = p.av1.stdQuantization.flags.using_qmatrix
+                                                                     ? pPicParams->quantization.qm_v
+                                                                     : 0;
+
+    memcpy(p.av1.stdSegmentation.FeatureEnabled, pPicParams->segmentation.feature_mask, sizeof(p.av1.stdSegmentation.FeatureEnabled));
+    memcpy(p.av1.stdSegmentation.FeatureData, pPicParams->segmentation.feature_data, sizeof(p.av1.stdSegmentation.FeatureData));
+
+    p.av1.stdLoopFilter.flags.loop_filter_delta_enabled              = pPicParams->loop_filter.mode_ref_delta_enabled;
+    p.av1.stdLoopFilter.flags.loop_filter_delta_update               = pPicParams->loop_filter.mode_ref_delta_update;
+    p.av1.stdLoopFilter.flags.reserved                               = 0;
+    p.av1.stdLoopFilter.loop_filter_level[0]                         = pPicParams->loop_filter.filter_level[0];
+    p.av1.stdLoopFilter.loop_filter_level[1]                         = pPicParams->loop_filter.filter_level[1];
+    p.av1.stdLoopFilter.loop_filter_level[2]                         = pPicParams->loop_filter.filter_level_u;
+    p.av1.stdLoopFilter.loop_filter_level[3]                         = pPicParams->loop_filter.filter_level_v;
+    p.av1.stdLoopFilter.loop_filter_sharpness                        = pPicParams->loop_filter.sharpness_level;
+    p.av1.stdLoopFilter.update_ref_delta                             = 0xff; /* 8 elements, "loop_filter_ref_delta is present" */
+    memcpy(p.av1.stdLoopFilter.loop_filter_ref_deltas, pPicParams->loop_filter.ref_deltas, sizeof(p.av1.stdLoopFilter.loop_filter_ref_deltas));
+    p.av1.stdLoopFilter.update_mode_delta                            = 0x3; /* 2 elements, "update_mode_delta" */
+    memcpy(p.av1.stdLoopFilter.loop_filter_mode_deltas, pPicParams->loop_filter.mode_deltas, sizeof(p.av1.stdLoopFilter.loop_filter_mode_deltas));
+
+    p.av1.stdCDEF.cdef_damping_minus_3                               = pPicParams->cdef.damping;
+    p.av1.stdCDEF.cdef_bits                                          = pPicParams->cdef.bits;
+    for (uint32_t i = 0; i < 8; ++i) {
+      p.av1.stdCDEF.cdef_y_pri_strength[i]                           = pPicParams->cdef.y_strengths[i].primary;
+      p.av1.stdCDEF.cdef_y_sec_strength[i]                           = pPicParams->cdef.y_strengths[i].secondary;
+      p.av1.stdCDEF.cdef_uv_pri_strength[i]                          = pPicParams->cdef.uv_strengths[i].primary;
+      p.av1.stdCDEF.cdef_uv_sec_strength[i]                          = pPicParams->cdef.uv_strengths[i].secondary;
+    }
+
+    for (uint32_t i = 0; i < 3; ++i) {
+      p.av1.stdLoopRestoration.FrameRestorationType[i] = StdVideoAV1FrameRestorationType(pPicParams->loop_filter.frame_restoration_type[i]);
+      if (pPicParams->loop_filter.log2_restoration_unit_size[i] >= 5
+       && pPicParams->loop_filter.log2_restoration_unit_size[i] <= 8) {
+        p.av1.stdLoopRestoration.LoopRestorationSize[i] = pPicParams->loop_filter.log2_restoration_unit_size[i] - 5;
+      }
+      else {
+        p.av1.stdLoopRestoration.LoopRestorationSize[i] = 3;
+      }
+    }
+
+    /* INTRA_FRAME(0) (current frame). */
+    p.av1.stdGlobalMotion.GmType[0] = 0;
+    p.av1.stdGlobalMotion.gm_params[0][0] = 0;
+    p.av1.stdGlobalMotion.gm_params[0][1] = 0;
+    p.av1.stdGlobalMotion.gm_params[0][2] = 0;
+    p.av1.stdGlobalMotion.gm_params[0][3] = 0;
+    p.av1.stdGlobalMotion.gm_params[0][4] = 0;
+    p.av1.stdGlobalMotion.gm_params[0][5] = 0;
+    /* LAST_FRAME(1) to ALTREF_FRAME(7) */
+    for (uint32_t i = 1; i < 8; ++i) {
+      const DXVA_PicEntry_AV1& picEntry = pPicParams->frame_refs[i - 1];
+
+      if (picEntry.wminvalid) {
+        /* Pass default parameters as defined in AV1 spec 5.9.24. Global motion params syntax */
+        p.av1.stdGlobalMotion.GmType[i] = 0;
+        for (uint32_t j = 0; j < 6; ++j) {
+          p.av1.stdGlobalMotion.gm_params[i][j] = (j % 3 == 2) ? 0x10000 : 0;
+        }
+        continue;
+      }
+
+      p.av1.stdGlobalMotion.GmType[i] = picEntry.wmtype;
+      p.av1.stdGlobalMotion.gm_params[i][0] = picEntry.wmmat[0];
+      p.av1.stdGlobalMotion.gm_params[i][1] = picEntry.wmmat[1];
+      p.av1.stdGlobalMotion.gm_params[i][2] = picEntry.wmmat[2];
+      p.av1.stdGlobalMotion.gm_params[i][3] = picEntry.wmmat[3];
+      p.av1.stdGlobalMotion.gm_params[i][4] = picEntry.wmmat[4];
+      p.av1.stdGlobalMotion.gm_params[i][5] = picEntry.wmmat[5];
+    }
+
+    p.av1.stdFilmGrain.flags.chroma_scaling_from_luma                = pPicParams->film_grain.chroma_scaling_from_luma;
+    p.av1.stdFilmGrain.flags.overlap_flag                            = pPicParams->film_grain.overlap_flag;
+    p.av1.stdFilmGrain.flags.clip_to_restricted_range                = pPicParams->film_grain.clip_to_restricted_range;
+    p.av1.stdFilmGrain.flags.update_grain                            = 0; /* "ignored by AV1 decode operations" */
+    p.av1.stdFilmGrain.flags.reserved                                = 0;
+    p.av1.stdFilmGrain.grain_scaling_minus_8                         = pPicParams->film_grain.scaling_shift_minus8;
+    p.av1.stdFilmGrain.ar_coeff_lag                                  = pPicParams->film_grain.ar_coeff_lag;
+    p.av1.stdFilmGrain.ar_coeff_shift_minus_6                        = pPicParams->film_grain.ar_coeff_shift_minus6;
+    p.av1.stdFilmGrain.grain_scale_shift                             = pPicParams->film_grain.grain_scale_shift;
+    p.av1.stdFilmGrain.grain_seed                                    = pPicParams->film_grain.grain_seed;
+    p.av1.stdFilmGrain.film_grain_params_ref_idx                     = 0; /* "ignored by AV1 decode operations" */
+    p.av1.stdFilmGrain.num_y_points                                  = std::min(pPicParams->film_grain.num_y_points,
+                                                                                (uint8_t)STD_VIDEO_AV1_MAX_NUM_Y_POINTS);
+    for (uint32_t i = 0; i < p.av1.stdFilmGrain.num_y_points; ++i) {
+      p.av1.stdFilmGrain.point_y_value[i]                            = pPicParams->film_grain.scaling_points_y[i][0];
+      p.av1.stdFilmGrain.point_y_scaling[i]                          = pPicParams->film_grain.scaling_points_y[i][1];
+    }
+    p.av1.stdFilmGrain.num_cb_points                                 = std::min(pPicParams->film_grain.num_cb_points,
+                                                                                (uint8_t)STD_VIDEO_AV1_MAX_NUM_CB_POINTS);
+    for (uint32_t i = 0; i < p.av1.stdFilmGrain.num_cb_points; ++i) {
+      p.av1.stdFilmGrain.point_cb_value[i]                           = pPicParams->film_grain.scaling_points_cb[i][0];
+      p.av1.stdFilmGrain.point_cb_scaling[i]                         = pPicParams->film_grain.scaling_points_cb[i][1];
+    }
+    p.av1.stdFilmGrain.num_cr_points                                 = std::min(pPicParams->film_grain.num_cr_points,
+                                                                                (uint8_t)STD_VIDEO_AV1_MAX_NUM_CR_POINTS);
+    for (uint32_t i = 0; i < p.av1.stdFilmGrain.num_cr_points; ++i) {
+      p.av1.stdFilmGrain.point_cr_value[i]                           = pPicParams->film_grain.scaling_points_cr[i][0];
+      p.av1.stdFilmGrain.point_cr_scaling[i]                         = pPicParams->film_grain.scaling_points_cr[i][1];
+    }
+    memcpy(p.av1.stdFilmGrain.ar_coeffs_y_plus_128, pPicParams->film_grain.ar_coeffs_y, sizeof(p.av1.stdFilmGrain.ar_coeffs_y_plus_128));
+    memcpy(p.av1.stdFilmGrain.ar_coeffs_cb_plus_128, pPicParams->film_grain.ar_coeffs_cb, sizeof(p.av1.stdFilmGrain.ar_coeffs_cb_plus_128));
+    memcpy(p.av1.stdFilmGrain.ar_coeffs_cr_plus_128, pPicParams->film_grain.ar_coeffs_cr, sizeof(p.av1.stdFilmGrain.ar_coeffs_cr_plus_128));
+    p.av1.stdFilmGrain.cb_mult                                       = pPicParams->film_grain.cb_mult;
+    p.av1.stdFilmGrain.cb_luma_mult                                  = pPicParams->film_grain.cb_luma_mult;
+    p.av1.stdFilmGrain.cb_offset                                     = pPicParams->film_grain.cb_offset;
+    p.av1.stdFilmGrain.cr_mult                                       = pPicParams->film_grain.cr_mult;
+    p.av1.stdFilmGrain.cr_luma_mult                                  = pPicParams->film_grain.cr_luma_mult;
+    p.av1.stdFilmGrain.cr_offset                                     = pPicParams->film_grain.cr_offset;
+
+    p.av1.tileCount = cTiles;
+    p.sliceOrTileOffsets.resize(cTiles);
+    p.sliceOrTileSizes.resize(cTiles);
+    for (uint32_t i = 0; i < p.av1.tileCount; ++i) {
+      p.sliceOrTileOffsets[i] = pTiles[i].DataOffset;
+      p.sliceOrTileSizes[i] = pTiles[i].DataSize;
+    }
+
+    p.av1.stdReferenceInfo.flags.disable_frame_end_update_cdf        = pPicParams->coding.disable_frame_end_update_cdf;
+    p.av1.stdReferenceInfo.flags.segmentation_enabled                = pPicParams->segmentation.enabled;
+    p.av1.stdReferenceInfo.flags.reserved                            = 0;
+    p.av1.stdReferenceInfo.frame_type                                = pPicParams->format.frame_type;
+    p.av1.stdReferenceInfo.RefFrameSignBias                          = 0; /* Computed by dxvk decoder */
+    p.av1.stdReferenceInfo.OrderHint                                 = p.av1.stdSequenceHeader.flags.enable_order_hint
+                                                                     ? pPicParams->order_hint
+                                                                     : 0;
+    for (uint32_t i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; ++i) {
+      p.av1.stdReferenceInfo.SavedOrderHints[i]                      = 0; /* Filled by dxvk decoder */
+    }
+
+    /* The picture identifier of destination uncompressed surface. */
+    p.idSurface                                                      = pPicParams->CurrPicTextureIndex;
+
+    /* Reference frame surfaces. */
+    uint32_t idxRefFrame = 0;
+    for (uint32_t i = 0; i < 7; ++i) { /* Elements in ref_frames, from LAST_FRAME to ALTREF_FRAME */
+      const DXVA_PicEntry_AV1& r = pPicParams->frame_refs[i];
+      if (r.Index >= 8) /* Elements in RefFrameMapTextureIndex */
+        continue;
+
+      DxvkRefFrameInfo& refFrameInfo = p.refFrames[idxRefFrame];
+      refFrameInfo.idSurface      = pPicParams->RefFrameMapTextureIndex[r.Index];
+      refFrameInfo.av1.frame_name = i + 1; /* The frame name from LAST_FRAME to ALTREF_FRAME */
+
+      ++idxRefFrame;
+    }
+
+    p.refFramesCount                                                 = idxRefFrame;
+
+    memcpy(p.av1.RefFrameMapTextureIndex, pPicParams->RefFrameMapTextureIndex, sizeof(p.av1.RefFrameMapTextureIndex));
+
+    /* Whether this is a reference frame. */
+    p.av1.reference_frame_update                                     = pPicParams->coding.reference_frame_update;
 
     return true;
@@ -730,4 +1121,13 @@
          return true;
     }
+    else if (videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      if (GetVideoDecodeAV1InputParameters(
+        (DXVA_PicParams_AV1*)pPicParams, pPicParamsDesc,
+        (DXVA_Tile_AV1*)pSlices, pSliceDesc,
+        (uint8_t*)pBitStream, pBitStreamDesc,
+        pParms))
+         return true;
+    }
+
     return false;
   }
Index: trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_adapter.cpp
===================================================================
--- trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_adapter.cpp	(revision 108576)
+++ trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_adapter.cpp	(revision 108577)
@@ -1062,4 +1062,5 @@
       &devExtensions.khrVideoDecodeH264,
       &devExtensions.khrVideoDecodeH265,
+      &devExtensions.khrVideoDecodeAV1,
 #endif
     }};
Index: trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_extensions.h
===================================================================
--- trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_extensions.h	(revision 108576)
+++ trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_extensions.h	(revision 108577)
@@ -334,4 +334,5 @@
     DxvkExt khrVideoDecodeH264                = { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,                  DxvkExtMode::Optional };
     DxvkExt khrVideoDecodeH265                = { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,                  DxvkExtMode::Optional };
+    DxvkExt khrVideoDecodeAV1                 = { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME,                   DxvkExtMode::Optional };
 #endif
   };
Index: trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_video_decoder.cpp
===================================================================
--- trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_video_decoder.cpp	(revision 108576)
+++ trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_video_decoder.cpp	(revision 108577)
@@ -39,6 +39,7 @@
 
   DxvkVideoSessionHandle::~DxvkVideoSessionHandle() {
-    m_device->vkd()->vkDestroyVideoSessionKHR(m_device->handle(), m_videoSession, nullptr);
-    m_videoSession = VK_NULL_HANDLE;
+    if (m_videoSession != VK_NULL_HANDLE) {
+      m_device->vkd()->vkDestroyVideoSessionKHR(m_device->handle(), m_videoSession, nullptr);
+    }
   }
 
@@ -60,6 +61,7 @@
 
   DxvkVideoSessionParametersHandle::~DxvkVideoSessionParametersHandle() {
-    m_device->vkd()->vkDestroyVideoSessionParametersKHR(m_device->handle(), m_videoSessionParameters, nullptr);
-    m_videoSessionParameters = VK_NULL_HANDLE;
+    if (m_videoSessionParameters != VK_NULL_HANDLE) {
+      m_device->vkd()->vkDestroyVideoSessionParametersKHR(m_device->handle(), m_videoSessionParameters, nullptr);
+    }
   }
 
@@ -87,10 +89,12 @@
     DxvkMemoryAllocator& memAlloc)
   : m_device(device),
-    m_memAlloc(memAlloc){
+    m_memAlloc(memAlloc) {
   }
 
 
   DxvkVideoBitstreamBuffer::~DxvkVideoBitstreamBuffer() {
-    m_device->vkd()->vkDestroyBuffer(m_device->vkd()->device(), m_buffer.buffer, nullptr);
+    if (m_buffer.buffer != VK_NULL_HANDLE) {
+      m_device->vkd()->vkDestroyBuffer(m_device->vkd()->device(), m_buffer.buffer, nullptr);
+    }
   }
 
@@ -163,5 +167,5 @@
     /* Fetch data for quicker access. */
     m_mapPtr = (uint8_t *)m_buffer.memory.mapPtr(0);
-    m_length = m_buffer.memory.length();
+    m_length = bufferCreateInfo.size;
   }
 
@@ -196,4 +200,8 @@
       m_profile.decodeCapabilities.pNext = &m_profile.decodeH265Capabilities;
     }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      m_profile.profileInfo.pNext        = &m_profile.av1ProfileInfo;
+      m_profile.decodeCapabilities.pNext = &m_profile.decodeAV1Capabilities;
+    }
     else {
       throw DxvkError(str::format("DxvkVideoDecoder: videoCodecOperation ", m_profile.profileInfo.videoCodecOperation,
@@ -202,12 +210,33 @@
     m_profile.videoCapabilities.pNext    = &m_profile.decodeCapabilities;
 
+    /* Size of DPB and decode destination images. */
+    m_DPB.decodedPictureExtent = { m_sampleWidth, m_sampleHeight, 1 };
+
+    /* Align the decoder picture size to the macroblock/codingblock/superblock granularity. */
+    if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
+      /* To the macroblock */
+      m_DPB.decodedPictureExtent.width = align(m_DPB.decodedPictureExtent.width, 16);
+      m_DPB.decodedPictureExtent.height = align(m_DPB.decodedPictureExtent.height, 16);
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
+      /* To the max coding block size */
+      m_DPB.decodedPictureExtent.width = align(m_DPB.decodedPictureExtent.width, 64);
+      m_DPB.decodedPictureExtent.height = align(m_DPB.decodedPictureExtent.height, 64);
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      /* To the largest superblock granularity */
+      m_DPB.decodedPictureExtent.width = align(m_DPB.decodedPictureExtent.width, 128);
+      m_DPB.decodedPictureExtent.height = align(m_DPB.decodedPictureExtent.height, 128);
+    }
+
     /*
      * Assess capabilities.
      */
     /* Check that video resolution is supported. */
-    if (m_sampleWidth > m_profile.videoCapabilities.maxCodedExtent.width
-     || m_sampleHeight > m_profile.videoCapabilities.maxCodedExtent.height)
+    if (m_DPB.decodedPictureExtent.width > m_profile.videoCapabilities.maxCodedExtent.width
+     || m_DPB.decodedPictureExtent.height > m_profile.videoCapabilities.maxCodedExtent.height)
       throw DxvkError(str::format("DxvkVideoDecoder: requested resolution exceeds maximum: ",
-        m_sampleWidth, "x", m_sampleHeight, " > ",
+        m_DPB.decodedPictureExtent.width, "x", m_DPB.decodedPictureExtent.height, " (",
+        m_sampleWidth, "x", m_sampleHeight, ") > ",
         m_profile.videoCapabilities.maxCodedExtent.width, "x", m_profile.videoCapabilities.maxCodedExtent.height));
 
@@ -240,7 +269,17 @@
     m_bitstreamBuffer->create(profileListInfo, bitstreamBufferSize);
 
-    /* Decoded Picture Buffer (DPB), i.e. array of decoded frames. */
-    const uint32_t cMaxDPBSlots = std::max(
-      m_profile.videoCapabilities.maxActiveReferencePictures, m_profile.videoCapabilities.maxDpbSlots);
+    /* Decoded Picture Buffer (DPB), i.e. array of decoded frames.
+     * AMD mesa/vulkan driver asserts if the number of slots is greater than the spec requirement.
+     */
+    uint32_t cMaxDPBSlots = m_profile.videoCapabilities.maxDpbSlots;
+    if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
+      cMaxDPBSlots = std::min(cMaxDPBSlots, (uint32_t)16);
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
+      cMaxDPBSlots = std::min(cMaxDPBSlots, (uint32_t)STD_VIDEO_H265_MAX_DPB_SIZE);
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      cMaxDPBSlots = std::min(cMaxDPBSlots, (uint32_t)(STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME + 1));
+    }
     m_DPB.slots.resize(cMaxDPBSlots);
 
@@ -257,5 +296,5 @@
       imgInfo.flags       = 0;
       imgInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
-      imgInfo.extent      = { m_sampleWidth, m_sampleHeight, 1 };
+      imgInfo.extent      = m_DPB.decodedPictureExtent;
       imgInfo.numLayers   = 1;
       imgInfo.mipLevels   = 1;
@@ -294,8 +333,11 @@
 
       slot.imageView = m_device->createImageView(slot.image, viewInfo);
-    }
-
-    if (m_caps.distinctOutputImage) {
-      /* Create an additional output image. */
+
+      slot.deactivate();
+    }
+
+    if (m_caps.distinctOutputImage
+     || m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      /* Create an additional output image. Also for a possible usage of AV1 film grain feature. */
       DxvkImageCreateInfo imgInfo = {};
       imgInfo.pNext       = &profileListInfo;
@@ -304,5 +346,5 @@
       imgInfo.flags       = 0;
       imgInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
-      imgInfo.extent      = { m_sampleWidth, m_sampleHeight, 1 };
+      imgInfo.extent      = m_DPB.decodedPictureExtent;
       imgInfo.numLayers   = 1;
       imgInfo.mipLevels   = 1;
@@ -344,6 +386,5 @@
     sessionCreateInfo.pVideoProfile              = &m_profile.profileInfo;
     sessionCreateInfo.pictureFormat              = m_outputFormat;
-    sessionCreateInfo.maxCodedExtent.width       = m_sampleWidth;
-    sessionCreateInfo.maxCodedExtent.height      = m_sampleHeight;
+    sessionCreateInfo.maxCodedExtent             = m_profile.videoCapabilities.maxCodedExtent;
     sessionCreateInfo.referencePictureFormat     = m_outputFormat;
     sessionCreateInfo.maxDpbSlots                = m_DPB.slots.size();
@@ -422,4 +463,11 @@
 
       m_videoSessionParameters->create(m_videoSession, &h265SessionParametersCreateInfo);
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      /* Session parameter will be (re-)created in Decode because "video session parameters objects cannot be
+       * updated using the vkUpdateVideoSessionParametersKHR command. When a new AV1 sequence header is decoded
+       * from the input video bitstream the application needs to create a new video session parameters object
+       * to store it.".
+       */
     }
     else {
@@ -495,5 +543,4 @@
     DxvkContext* ctx,
     const Rc<DxvkImageView>& imageView) {
-    Logger::info(str::format("VDec: BeginFrame"));
 
     m_outputImageView = imageView;
@@ -518,5 +565,4 @@
   void DxvkVideoDecoder::EndFrame(
     DxvkContext* ctx) {
-    Logger::info(str::format("VDec: EndFrame"));
 
     if (m_profile.videoQueueHasTransfer) {
@@ -564,4 +610,40 @@
     DXVK_VD_CMP_FIELD(vps, pProfileTierLevel->general_profile_idc);
     DXVK_VD_CMP_FIELD(vps, pProfileTierLevel->general_level_idc);
+    return true;
+  }
+
+
+  static bool IsAV1SequenceHeaderEqual(
+    const StdVideoAV1SequenceHeader &sh1,
+    const StdVideoAV1SequenceHeader &sh2) {
+    DXVK_VD_CMP_FIELD(sh, flags.still_picture);
+    DXVK_VD_CMP_FIELD(sh, flags.reduced_still_picture_header);
+    DXVK_VD_CMP_FIELD(sh, flags.use_128x128_superblock);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_filter_intra);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_intra_edge_filter);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_interintra_compound);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_masked_compound);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_warped_motion);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_dual_filter);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_order_hint);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_jnt_comp);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_ref_frame_mvs);
+    DXVK_VD_CMP_FIELD(sh, flags.frame_id_numbers_present_flag);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_superres);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_cdef);
+    DXVK_VD_CMP_FIELD(sh, flags.enable_restoration);
+    DXVK_VD_CMP_FIELD(sh, flags.film_grain_params_present);
+    DXVK_VD_CMP_FIELD(sh, flags.timing_info_present_flag);
+    DXVK_VD_CMP_FIELD(sh, flags.initial_display_delay_present_flag);
+    DXVK_VD_CMP_FIELD(sh, seq_profile);
+    DXVK_VD_CMP_FIELD(sh, frame_width_bits_minus_1);
+    DXVK_VD_CMP_FIELD(sh, frame_height_bits_minus_1);
+    DXVK_VD_CMP_FIELD(sh, max_frame_width_minus_1);
+    DXVK_VD_CMP_FIELD(sh, max_frame_height_minus_1);
+    DXVK_VD_CMP_FIELD(sh, delta_frame_id_length_minus_2);
+    DXVK_VD_CMP_FIELD(sh, additional_frame_id_length_minus_1);
+    DXVK_VD_CMP_FIELD(sh, order_hint_bits_minus_1);
+    DXVK_VD_CMP_FIELD(sh, seq_force_integer_mv);
+    DXVK_VD_CMP_FIELD(sh, seq_force_screen_content_tools);
     return true;
   }
@@ -793,5 +875,5 @@
     /* Update internal pointer(s). */
     pParms->h264.sps.pOffsetForRefFrame = &pParms->h264.spsOffsetForRefFrame;
-    pParms->h264.pps.pScalingLists = &pParms->h264.ppsScalingLists;
+    pParms->h264.pps.pScalingLists      = &pParms->h264.ppsScalingLists;
 
     /* Information about a possible update of session parameters. */
@@ -863,5 +945,6 @@
     pParms->h265.vps.pProfileTierLevel = &pParms->h265.vpsProfileTierLevel;
     pParms->h265.sps.pProfileTierLevel = &pParms->h265.vpsProfileTierLevel;
-    pParms->h265.pps.pScalingLists = &pParms->h265.ppsScalingLists;
+    pParms->h265.sps.pDecPicBufMgr     = &pParms->h265.spsDecPicBufMgr;
+    pParms->h265.pps.pScalingLists     = &pParms->h265.ppsScalingLists;
 
     /* Information about a possible update of session parameters. */
@@ -994,4 +1077,146 @@
 
 
+  VkResult DxvkVideoDecoder::UpdateSessionParametersAV1(
+    DxvkVideoDecodeInputParameters *pParms) {
+    /* Update internal pointer(s). */
+    pParms->av1.stdSequenceHeader.pColorConfig  = &pParms->av1.stdColorConfig;
+    pParms->av1.stdPictureInfo.pTileInfo        = &pParms->av1.stdTileInfo;
+    pParms->av1.stdPictureInfo.pQuantization    = &pParms->av1.stdQuantization;
+    pParms->av1.stdPictureInfo.pSegmentation    = &pParms->av1.stdSegmentation;
+    pParms->av1.stdPictureInfo.pLoopFilter      = &pParms->av1.stdLoopFilter;
+    pParms->av1.stdPictureInfo.pCDEF            = &pParms->av1.stdCDEF;
+    pParms->av1.stdPictureInfo.pLoopRestoration = &pParms->av1.stdLoopRestoration;
+    pParms->av1.stdPictureInfo.pGlobalMotion    = &pParms->av1.stdGlobalMotion;
+    pParms->av1.stdPictureInfo.pFilmGrain       = pParms->av1.stdPictureInfo.flags.apply_grain
+                                                ? &pParms->av1.stdFilmGrain
+                                                : nullptr;
+    pParms->av1.stdTileInfo.pMiColStarts        = &pParms->av1.MiColStarts[0];
+    pParms->av1.stdTileInfo.pWidthInSbsMinus1   = &pParms->av1.WidthInSbsMinus1[0];
+    pParms->av1.stdTileInfo.pMiRowStarts        = &pParms->av1.MiRowStarts[0];
+    pParms->av1.stdTileInfo.pHeightInSbsMinus1  = &pParms->av1.HeightInSbsMinus1[0];
+
+    if (m_videoSessionParameters->handle() != VK_NULL_HANDLE
+     && IsAV1SequenceHeaderEqual(pParms->av1.stdSequenceHeader, m_parameterSetCache.av1.stdSequenceHeader))
+      return VK_SUCCESS;
+
+    m_parameterSetCache.av1.stdSequenceHeader = pParms->av1.stdSequenceHeader;
+
+    /* Create videoSessionParameters with the new info. */
+    m_videoSessionParameters = new DxvkVideoSessionParametersHandle(m_device);
+
+    VkVideoDecodeAV1SessionParametersCreateInfoKHR av1SessionParametersCreateInfo =
+      { VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR };
+    av1SessionParametersCreateInfo.pStdSequenceHeader = &pParms->av1.stdSequenceHeader;
+
+    m_videoSessionParameters->create(m_videoSession, &av1SessionParametersCreateInfo);
+
+    return VK_SUCCESS;
+  }
+
+
+  static int8_t av1_get_relative_dist(const DxvkVideoDecodeInputParameters &parms,
+    uint8_t a, uint8_t b) {
+    /* AV1 spec 5.9.3. Get relative distance function */
+    int8_t diff = a - b;
+    const uint8_t m = 1 << parms.av1.stdSequenceHeader.order_hint_bits_minus_1;
+    diff = (diff & (m - 1)) - (diff & m);
+    return diff;
+  }
+
+
+  static void av1_RefFrameSignBias(DxvkVideoDecodeInputParameters &parms) {
+    if (parms.av1.stdSequenceHeader.flags.enable_order_hint) {
+      for (uint8_t i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; ++i) {
+        const uint8_t refFrameName = STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME + i;
+        const int8_t relativeDistance = av1_get_relative_dist(parms,
+          parms.av1.stdPictureInfo.OrderHints[refFrameName], parms.av1.stdPictureInfo.OrderHint);
+
+        /* Vulkan uses bit mask as array. */
+        parms.av1.stdReferenceInfo.RefFrameSignBias |= (relativeDistance > 0) << refFrameName;
+      }
+    }
+  }
+
+
+  static void av1_skip_mode_params(DxvkVideoDecodeInputParameters &parms) {
+    if (parms.av1.stdPictureInfo.frame_type == STD_VIDEO_AV1_FRAME_TYPE_KEY
+     || parms.av1.stdPictureInfo.frame_type == STD_VIDEO_AV1_FRAME_TYPE_INTRA_ONLY
+     || !parms.av1.stdPictureInfo.flags.reference_select
+     || !parms.av1.stdSequenceHeader.flags.enable_order_hint) {
+       return;
+    }
+
+    int8_t forwardIdx = -1;
+    int8_t backwardIdx = -1;
+    uint8_t forwardHint;
+    uint8_t backwardHint;
+
+    for (uint8_t i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; ++i) {
+      const uint8_t refFrameName = STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME + i;
+      const uint8_t refHint = parms.av1.stdPictureInfo.OrderHints[refFrameName];
+
+      if (av1_get_relative_dist(parms, refHint, parms.av1.stdPictureInfo.OrderHint) < 0) {
+        if (forwardIdx < 0
+         || av1_get_relative_dist(parms, refHint, forwardHint) > 0) {
+          forwardIdx = i;
+          forwardHint = refHint;
+        }
+      } else if (av1_get_relative_dist(parms, refHint, parms.av1.stdPictureInfo.OrderHint) > 0) {
+        if (backwardIdx < 0
+         || av1_get_relative_dist(parms, refHint, backwardHint) < 0 ) {
+          backwardIdx = i;
+          backwardHint = refHint;
+        }
+      }
+    }
+
+    if (forwardIdx < 0) {
+      return;
+    }
+
+    if (backwardIdx >= 0) {
+      parms.av1.stdPictureInfo.SkipModeFrame[0] = STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME
+        + std::min(forwardIdx, backwardIdx);
+      parms.av1.stdPictureInfo.SkipModeFrame[1] = STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME
+        + std::max(forwardIdx, backwardIdx);
+    }
+    else {
+      int8_t secondForwardIdx = -1;
+      uint8_t secondForwardHint;
+
+      for (uint8_t i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; ++i) {
+        const uint8_t refFrameName = STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME + i;
+        const uint8_t refHint = parms.av1.stdPictureInfo.OrderHints[refFrameName];
+
+        if (av1_get_relative_dist(parms, refHint, forwardHint) < 0) {
+          if (secondForwardIdx < 0
+           || av1_get_relative_dist(parms, refHint, secondForwardHint) > 0) {
+            secondForwardIdx = i;
+            secondForwardHint = refHint;
+          }
+        }
+      }
+
+      if (secondForwardIdx >= 0) {
+        parms.av1.stdPictureInfo.SkipModeFrame[0] = STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME
+          + std::min(forwardIdx, secondForwardIdx);
+        parms.av1.stdPictureInfo.SkipModeFrame[1] = STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME
+          + std::max(forwardIdx, secondForwardIdx);
+      }
+    }
+  }
+
+
+  static void av1ComputeParams(DxvkVideoDecodeInputParameters &parms) {
+    /* Update various parameters as described in AV1 spec. */
+
+    /* AV1 spec 5.9.2. Uncompressed header syntax */
+    av1_RefFrameSignBias(parms);
+
+    /* AV1 spec 5.9.22. Skip mode params syntax */
+    av1_skip_mode_params(parms);
+  }
+
+
   void DxvkVideoDecoder::Decode(
     DxvkContext* ctx,
@@ -1007,6 +1232,26 @@
       vr = this->UpdateSessionParametersH265(&parms);
     }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      vr = this->UpdateSessionParametersAV1(&parms);
+    }
     if (vr != VK_SUCCESS)
       return;
+
+    const bool fUseDistinctOutputImage = m_caps.distinctOutputImage
+      || (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR
+       && parms.av1.stdPictureInfo.flags.apply_grain);
+
+    VkExtent2D codedExtent = { m_sampleWidth, m_sampleHeight };
+    if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      codedExtent.width = parms.av1.stdSequenceHeader.max_frame_width_minus_1 + 1;
+      codedExtent.height = parms.av1.stdSequenceHeader.max_frame_height_minus_1 + 1;
+    }
+
+    if (codedExtent.width > m_DPB.decodedPictureExtent.width
+     || codedExtent.height > m_DPB.decodedPictureExtent.height) {
+      Logger::err(str::format("DxvkVideoDecoder: frame size (", codedExtent.width, "x", codedExtent.height, ")",
+        " exceeds DPB image size (", m_DPB.decodedPictureExtent.width, "x", m_DPB.decodedPictureExtent.height, ")"));
+      return;
+    }
 
     /*
@@ -1045,11 +1290,17 @@
     bool doIDR = false;
     if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
-      doIDR = parms.nal_unit_type == 5;
+      doIDR = parms.h264.nal_unit_type == 5;
     }
     else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
       doIDR = parms.h265.stdPictureInfo.flags.IdrPicFlag;
     }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      doIDR = parms.av1.stdPictureInfo.frame_type == STD_VIDEO_AV1_FRAME_TYPE_KEY;
+    }
     if (doIDR) /* IDR, immediate decoder reset. */
       m_DPB.reset();
+
+    if (m_DPB.fOverflow)
+      return;
 
     /*
@@ -1070,17 +1321,25 @@
         if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
           StdVideoDecodeH264ReferenceInfo& stdRefInfo = m_DPB.slots[refFrame.dpbSlotIndex].h264.stdRefInfo;
-          stdRefInfo.flags.used_for_long_term_reference = r.longTermReference;
-          stdRefInfo.flags.is_non_existing              = r.nonExistingFrame;
-          stdRefInfo.FrameNum                           = r.frame_num;
-          stdRefInfo.PicOrderCnt[0]                     = r.PicOrderCnt[0];
-          stdRefInfo.PicOrderCnt[1]                     = r.PicOrderCnt[1];
+          stdRefInfo.flags.used_for_long_term_reference = r.h264.longTermReference;
+          stdRefInfo.flags.is_non_existing              = r.h264.nonExistingFrame;
+          stdRefInfo.FrameNum                           = r.h264.frame_num;
+          stdRefInfo.PicOrderCnt[0]                     = r.h264.PicOrderCnt[0];
+          stdRefInfo.PicOrderCnt[1]                     = r.h264.PicOrderCnt[1];
         }
         else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
           StdVideoDecodeH265ReferenceInfo& stdRefInfo = m_DPB.slots[refFrame.dpbSlotIndex].h265.stdRefInfo;
-          stdRefInfo.flags.used_for_long_term_reference = r.longTermReference;
+          stdRefInfo.flags.used_for_long_term_reference = r.h265.longTermReference;
           stdRefInfo.flags.unused_for_reference         = 0; /* It is a ref frame. */
-          stdRefInfo.PicOrderCntVal                     = r.PicOrderCnt[0];
+          stdRefInfo.PicOrderCntVal                     = r.h265.PicOrderCntVal;
         }
-      }
+        else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+          StdVideoDecodeAV1ReferenceInfo& stdRefInfo = m_DPB.slots[refFrame.dpbSlotIndex].av1.stdRefInfo;
+          parms.av1.stdPictureInfo.OrderHints[r.av1.frame_name] = stdRefInfo.OrderHint;
+        }
+      }
+    }
+
+    if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      av1ComputeParams(parms);
     }
 
@@ -1105,13 +1364,29 @@
     for (uint32_t i = 0; i < m_DPB.slots.size(); ++i) {
       DxvkDPBSlot& slot = m_DPB.slots[m_DPB.idxCurrentDPBSlot];
-      bool isLongReference = false;
+      bool keepSlot = false;
       if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
-        isLongReference = slot.h264.stdRefInfo.flags.used_for_long_term_reference != 0;
+        keepSlot = slot.h264.stdRefInfo.flags.used_for_long_term_reference != 0;
+        for (uint32_t i = 0; i < parms.refFramesCount && !keepSlot; ++i) {
+          const DxvkRefFrameInfo& r = parms.refFrames[i];
+          keepSlot = r.idSurface == slot.idSurface;
+        }
       }
       else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
-        isLongReference = slot.h265.stdRefInfo.flags.used_for_long_term_reference != 0;
+        keepSlot = slot.h265.stdRefInfo.flags.used_for_long_term_reference != 0;
+        for (uint32_t i = 0; i < parms.refFramesCount && !keepSlot; ++i) {
+          const DxvkRefFrameInfo& r = parms.refFrames[i];
+          keepSlot = r.idSurface == slot.idSurface;
+        }
+      }
+      else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+        /* Keep frames those are included in RefFrameMapTextureIndex */
+        for (uint32_t i = 0; i < 8 && !keepSlot; ++i) {
+          if (slot.idSurface == parms.av1.RefFrameMapTextureIndex[i]) {
+            keepSlot = true;
+          }
+        }
       }
       if (slot.isActive
-       && isLongReference) {
+       && keepSlot) {
         m_DPB.idxCurrentDPBSlot = (m_DPB.idxCurrentDPBSlot + 1) % m_DPB.slots.size();
         continue;
@@ -1135,8 +1410,8 @@
       /* No free slots. This can happen only if entire DPB is occupied by long-term references,
        * which is probably due to an invalid video stream.
-       * Try to recover by resetting the DPB.
+       * Skip frames until the next IDR frame.
        */
-      m_DPB.reset();
-      dstSlotIndex = 0;
+      m_DPB.fOverflow = true;
+      return;
     }
 
@@ -1149,4 +1424,8 @@
     else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
       dstDPBSlot.h265.stdRefInfo  = parms.h265.stdReferenceInfo;
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      dstDPBSlot.av1.stdRefInfo   = parms.av1.stdReferenceInfo;
+      /* dstDPBSlot.av1.stdRefInfo.SavedOrderHints are updated after decoding of the frame. */
     }
     dstDPBSlot.idSurface          = DXVK_VIDEO_DECODER_SURFACE_INVALID; /* Reference picture will be associated later. */
@@ -1181,5 +1460,5 @@
     ctx->emitPipelineBarrier(DxvkCmdBuffer::VDecBuffer, &dependencyInfo);
 
-    if (m_caps.distinctOutputImage) {
+    if (fUseDistinctOutputImage) {
       /*
        * Prepare decode destination layout.
@@ -1211,5 +1490,8 @@
     }
     else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
-      maxRefFrames = parms.h265.sps_max_dec_pic_buffering;
+      maxRefFrames = parms.h265.spsDecPicBufMgr.max_dec_pic_buffering_minus1[0] + 1;
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      maxRefFrames = STD_VIDEO_AV1_REFS_PER_FRAME;
     }
     const uint32_t maxRefSlotsCount = std::min(parms.refFramesCount, maxRefFrames);
@@ -1218,4 +1500,5 @@
     std::vector<VkVideoDecodeH264DpbSlotInfoKHR> h264DpbSlotInfo(maxRefSlotsCount + 1);
     std::vector<VkVideoDecodeH265DpbSlotInfoKHR> h265DpbSlotInfo(maxRefSlotsCount + 1);
+    std::vector<VkVideoDecodeAV1DpbSlotInfoKHR> av1DpbSlotInfo(maxRefSlotsCount + 1);
     std::vector<VkVideoPictureResourceInfoKHR> pictureResourceInfo(maxRefSlotsCount + 1);
     std::vector<VkVideoReferenceSlotInfoKHR> referenceSlotsInfo(maxRefSlotsCount + 1);
@@ -1238,4 +1521,16 @@
         continue;
       }
+
+      /* Skip if the frame id has been already added to referenceSlotsInfo. */
+      uint32_t j = 0;
+      for (; j < refSlotsCount; ++j) {
+        if (referenceSlotsInfo[j].slotIndex == dpbSlotIndex) {
+          Logger::debug(str::format("DPBM: DPB[", dpbSlotIndex, "]: reference picture [", i, "]",
+            " (added at ", refSlotsCount, ") already exists at ", j));
+          break;
+        }
+      }
+      if (j < refSlotsCount)
+        continue;
 
       if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
@@ -1251,9 +1546,18 @@
         pNext = &h265DpbSlotInfo[refSlotsCount];
       }
+      else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+        av1DpbSlotInfo[refSlotsCount] =
+          { VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR };
+        av1DpbSlotInfo[refSlotsCount].pStdReferenceInfo = &m_DPB.slots[dpbSlotIndex].av1.stdRefInfo;
+        pNext = &av1DpbSlotInfo[refSlotsCount];
+      }
+      else {
+        pNext = nullptr;
+      }
 
       pictureResourceInfo[refSlotsCount] =
         { VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR };
       pictureResourceInfo[refSlotsCount].codedOffset      = { 0, 0 };
-      pictureResourceInfo[refSlotsCount].codedExtent      = { m_sampleWidth, m_sampleHeight };
+      pictureResourceInfo[refSlotsCount].codedExtent      = codedExtent;
       pictureResourceInfo[refSlotsCount].baseArrayLayer   = 0; /* "relative to the image subresource range" of the view */
       pictureResourceInfo[refSlotsCount].imageViewBinding = m_DPB.slots[dpbSlotIndex].imageView->handle();
@@ -1281,9 +1585,15 @@
       pNext = &h265DpbSlotInfo[refSlotsCount];
     }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      av1DpbSlotInfo[refSlotsCount] =
+        { VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR };
+      av1DpbSlotInfo[refSlotsCount].pStdReferenceInfo = &dstDPBSlot.av1.stdRefInfo;
+      pNext = &av1DpbSlotInfo[refSlotsCount];
+    }
 
     pictureResourceInfo[refSlotsCount] =
       { VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR };
     pictureResourceInfo[refSlotsCount].codedOffset      = { 0, 0 };
-    pictureResourceInfo[refSlotsCount].codedExtent      = { m_sampleWidth, m_sampleHeight };
+    pictureResourceInfo[refSlotsCount].codedExtent      = codedExtent;
     pictureResourceInfo[refSlotsCount].baseArrayLayer   = 0; /* "relative to the image subresource range" of the view */
     pictureResourceInfo[refSlotsCount].imageViewBinding = dstDPBSlot.imageView->handle();
@@ -1305,13 +1615,17 @@
 #ifdef DEBUG
     Logger::debug(str::format("VREF: beginVideoCoding: dstSlotIndex=", dstSlotIndex,
-      " ", m_sampleWidth, "x", m_sampleHeight));
+      " ", codedExtent.width, "x", codedExtent.height));
     for (uint32_t i = 0; i < beginCodingInfo.referenceSlotCount; ++i) {
       auto &s = beginCodingInfo.pReferenceSlots[i];
       const DxvkDPBSlot& dpbSlot = m_DPB.slots[s.slotIndex == -1 ? dstSlotIndex : s.slotIndex];
-      int32_t FrameNum = 0;
+
+      int32_t FrameNum = -1;
       if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR)
         FrameNum = dpbSlot.h264.stdRefInfo.FrameNum;
       else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR)
         FrameNum = dpbSlot.h265.stdRefInfo.PicOrderCntVal;
+      else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR)
+        FrameNum = dpbSlot.av1.stdRefInfo.OrderHint;
+
       Logger::debug(str::format("VREF:  RefSlot[", i, "]: slotIndex=", s.slotIndex,
         ", FrameNum=", FrameNum,
@@ -1350,16 +1664,48 @@
     VkVideoDecodeH265PictureInfoKHR h265PictureInfo =
       { VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR };
+    VkVideoDecodeAV1PictureInfoKHR av1PictureInfo =
+      { VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_KHR };
 
     if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
       h264PictureInfo.pStdPictureInfo = &parms.h264.stdH264PictureInfo;
-      h264PictureInfo.sliceCount      = parms.sliceOffsets.size();
-      h264PictureInfo.pSliceOffsets   = parms.sliceOffsets.data();
+      h264PictureInfo.sliceCount      = parms.sliceOrTileOffsets.size();
+      h264PictureInfo.pSliceOffsets   = parms.sliceOrTileOffsets.data();
       pNext = &h264PictureInfo;
     }
     else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
       h265PictureInfo.pStdPictureInfo      = &parms.h265.stdPictureInfo;
-      h265PictureInfo.sliceSegmentCount    = parms.sliceOffsets.size();
-      h265PictureInfo.pSliceSegmentOffsets = parms.sliceOffsets.data();
+      h265PictureInfo.sliceSegmentCount    = parms.sliceOrTileOffsets.size();
+      h265PictureInfo.pSliceSegmentOffsets = parms.sliceOrTileOffsets.data();
       pNext = &h265PictureInfo;
+    }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      av1PictureInfo.pStdPictureInfo               = &parms.av1.stdPictureInfo;
+      for (uint32_t i = 0; i < VK_MAX_VIDEO_AV1_REFERENCES_PER_FRAME_KHR; ++i) {
+        av1PictureInfo.referenceNameSlotIndices[i] = -1;
+        if (i >= parms.refFramesCount)
+          continue;
+
+        const DxvkRefFrameInfo& r = parms.refFrames[i];
+
+        itRefFrame = m_DPB.refFrames.find(r.idSurface);
+        if (itRefFrame == m_DPB.refFrames.end()) {
+          /* Skip invalid reference frame. */
+          continue;
+        }
+
+        const int32_t dpbSlotIndex = itRefFrame->second.dpbSlotIndex;
+        if (dpbSlotIndex == -1) {
+          /* Skip invalid reference frame. */
+          continue;
+        }
+
+        av1PictureInfo.referenceNameSlotIndices[i] = dpbSlotIndex;
+      }
+
+      av1PictureInfo.frameHeaderOffset             = 0;
+      av1PictureInfo.tileCount                     = parms.av1.tileCount;
+      av1PictureInfo.pTileOffsets                  = parms.sliceOrTileOffsets.data();
+      av1PictureInfo.pTileSizes                    = parms.sliceOrTileSizes.data();
+      pNext = &av1PictureInfo;
     }
 
@@ -1373,10 +1719,10 @@
       { VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR };
     decodeInfo.dstPictureResource.codedOffset      = { 0, 0 };
-    decodeInfo.dstPictureResource.codedExtent      = { m_sampleWidth, m_sampleHeight };
+    decodeInfo.dstPictureResource.codedExtent      = codedExtent;
     /* "baseArrayLayer relative to the image subresource range the image view specified in
      * imageViewBinding was created with."
      */
     decodeInfo.dstPictureResource.baseArrayLayer   = 0;
-    if (m_caps.distinctOutputImage) {
+    if (fUseDistinctOutputImage) {
       decodeInfo.dstPictureResource.imageViewBinding = m_imageViewDecodeDst->handle();
     }
@@ -1393,9 +1739,13 @@
       auto &s = decodeInfo.pReferenceSlots[i];
       const DxvkDPBSlot& dpbSlot = m_DPB.slots[s.slotIndex];
-      int32_t FrameNum = 0;
+
+      int32_t FrameNum = -1;
       if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR)
         FrameNum = dpbSlot.h264.stdRefInfo.FrameNum;
       else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR)
         FrameNum = dpbSlot.h265.stdRefInfo.PicOrderCntVal;
+      else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR)
+        FrameNum = dpbSlot.av1.stdRefInfo.OrderHint;
+
       Logger::debug(str::format("VREF:  RefSlot[", i, "]: slotIndex=", s.slotIndex,
         ", FrameNum=", FrameNum,
@@ -1407,7 +1757,11 @@
                    : (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR)
                    ? dstDPBSlot.h265.stdRefInfo.PicOrderCntVal
+                   : (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR)
+                   ? dstDPBSlot.av1.stdRefInfo.OrderHint
                    : -1),
       ", is_ref=", (uint32_t)(m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR
                    ? parms.h264.stdH264PictureInfo.flags.is_reference
+                   : (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR)
+                   ? parms.av1.reference_frame_update
                    : 0),
       ", view=", dstDPBSlot.imageView->handle()));
@@ -1430,5 +1784,5 @@
     uint32_t decodedArrayLayer;
     VkImageLayout decodedPictureLayout;
-    if (m_caps.distinctOutputImage) {
+    if (fUseDistinctOutputImage) {
       decodedPicture       = m_imageDecodeDst;
       decodedArrayLayer    = 0;
@@ -1440,4 +1794,49 @@
       decodedPictureLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
     }
+
+    /* Prepare parameters for copying decoded image to the output view. */
+    VkExtent3D outputExtent = m_outputImageView->imageInfo().extent;
+    VkExtent3D copyExtent = {
+      std::min(outputExtent.width, m_DPB.decodedPictureExtent.width),
+      std::min(outputExtent.height, m_DPB.decodedPictureExtent.height),
+      1 };
+
+    std::array<VkImageCopy2, 2> regions{{
+      { VK_STRUCTURE_TYPE_IMAGE_COPY_2 },
+      { VK_STRUCTURE_TYPE_IMAGE_COPY_2 }}};
+    /* Y plane. */
+    regions[0].srcSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_0_BIT;
+    //regions[0].srcSubresource.mipLevel       = 0;
+    regions[0].srcSubresource.baseArrayLayer   = decodedArrayLayer;
+    regions[0].srcSubresource.layerCount       = 1;
+    //regions[0].srcOffset                     = { 0, 0, 0 };
+    regions[0].dstSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_0_BIT;
+    //regions[0].dstSubresource.mipLevel       = 0;
+    regions[0].dstSubresource.baseArrayLayer   = m_outputImageView->info().minLayer;
+    regions[0].dstSubresource.layerCount       = 1;
+    //regions[0].dstOffset                     = { 0, 0, 0 };
+    regions[0].extent                          = copyExtent;
+
+    /* CbCr plane at half resolution. */
+    regions[1].srcSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_1_BIT;
+    //regions[1].srcSubresource.mipLevel       = 0;
+    regions[1].srcSubresource.baseArrayLayer   = decodedArrayLayer;
+    regions[1].srcSubresource.layerCount       = 1;
+    //regions[1].srcOffset                     = { 0, 0, 0 };
+    regions[1].dstSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_1_BIT;
+    //regions[1].dstSubresource.mipLevel       = 0;
+    regions[1].dstSubresource.baseArrayLayer   = m_outputImageView->info().minLayer;
+    regions[1].dstSubresource.layerCount       = 1;
+    //regions[1].dstOffset                     = { 0, 0, 0 };
+    regions[1].extent                          = { copyExtent.width / 2, copyExtent.height / 2, 1 };
+
+    VkCopyImageInfo2 copyImageInfo =
+      { VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 };
+    copyImageInfo.srcImage       = decodedPicture->handle();
+    copyImageInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+    copyImageInfo.dstImage       = m_outputImageView->imageHandle();
+    copyImageInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+    copyImageInfo.regionCount    = 2;
+    copyImageInfo.pRegions       = regions.data();
 
     if (m_profile.videoQueueHasTransfer) {
@@ -1467,42 +1866,5 @@
       ctx->emitPipelineBarrier(DxvkCmdBuffer::VDecBuffer, &dependencyInfo);
 
-      /* Copy decoded image -> output image. Y plane. */
-      std::array<VkImageCopy2, 2> regions{{
-        { VK_STRUCTURE_TYPE_IMAGE_COPY_2 },
-        { VK_STRUCTURE_TYPE_IMAGE_COPY_2 }}};
-      regions[0].srcSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_0_BIT;
-      //regions[0].srcSubresource.mipLevel       = 0;
-      regions[0].srcSubresource.baseArrayLayer   = decodedArrayLayer;
-      regions[0].srcSubresource.layerCount       = 1;
-      //regions[0].srcOffset                     = { 0, 0, 0 };
-      regions[0].dstSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_0_BIT;
-      //regions[0].dstSubresource.mipLevel       = 0;
-      regions[0].dstSubresource.baseArrayLayer   = m_outputImageView->info().minLayer;
-      regions[0].dstSubresource.layerCount       = 1;
-      //regions[0].dstOffset                     = { 0, 0, 0 };
-      regions[0].extent                          = { m_sampleWidth, m_sampleHeight, 1 };
-
-      /* CbCr plane at half resolution. */
-      regions[1].srcSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_1_BIT;
-      //regions[1].srcSubresource.mipLevel       = 0;
-      regions[1].srcSubresource.baseArrayLayer   = decodedArrayLayer;
-      regions[1].srcSubresource.layerCount       = 1;
-      //regions[1].srcOffset                     = { 0, 0, 0 };
-      regions[1].dstSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_1_BIT;
-      //regions[1].dstSubresource.mipLevel       = 0;
-      regions[1].dstSubresource.baseArrayLayer   = m_outputImageView->info().minLayer;
-      regions[1].dstSubresource.layerCount       = 1;
-      //regions[1].dstOffset                     = { 0, 0, 0 };
-      regions[1].extent                          = { m_sampleWidth / 2, m_sampleHeight / 2, 1 };
-
-      VkCopyImageInfo2 copyImageInfo =
-        { VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 };
-      copyImageInfo.srcImage       = decodedPicture->handle();
-      copyImageInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
-      copyImageInfo.dstImage       = m_outputImageView->imageHandle();
-      copyImageInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
-      copyImageInfo.regionCount    = 2;
-      copyImageInfo.pRegions       = regions.data();
-
+      /* Copy decoded image -> output image. */
       ctx->emitCopyImage(DxvkCmdBuffer::VDecBuffer, &copyImageInfo);
 
@@ -1573,42 +1935,5 @@
       ctx->emitPipelineBarrier(DxvkCmdBuffer::InitBuffer, &dependencyInfo);
 
-      /* Copy decoded image -> output image. Y plane. */
-      std::array<VkImageCopy2, 2> regions{{
-        { VK_STRUCTURE_TYPE_IMAGE_COPY_2 },
-        { VK_STRUCTURE_TYPE_IMAGE_COPY_2 }}};
-      regions[0].srcSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_0_BIT;
-      //regions[0].srcSubresource.mipLevel       = 0;
-      regions[0].srcSubresource.baseArrayLayer   = decodedArrayLayer;
-      regions[0].srcSubresource.layerCount       = 1;
-      //regions[0].srcOffset                     = { 0, 0, 0 };
-      regions[0].dstSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_0_BIT;
-      //regions[0].dstSubresource.mipLevel       = 0;
-      regions[0].dstSubresource.baseArrayLayer   = m_outputImageView->info().minLayer;
-      regions[0].dstSubresource.layerCount       = 1;
-      //regions[0].dstOffset                     = { 0, 0, 0 };
-      regions[0].extent                          = { m_sampleWidth, m_sampleHeight, 1 };
-
-      /* CbCr plane at half resolution. */
-      regions[1].srcSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_1_BIT;
-      //regions[1].srcSubresource.mipLevel       = 0;
-      regions[1].srcSubresource.baseArrayLayer   = decodedArrayLayer;
-      regions[1].srcSubresource.layerCount       = 1;
-      //regions[1].srcOffset                     = { 0, 0, 0 };
-      regions[1].dstSubresource.aspectMask       = VK_IMAGE_ASPECT_PLANE_1_BIT;
-      //regions[1].dstSubresource.mipLevel       = 0;
-      regions[1].dstSubresource.baseArrayLayer   = m_outputImageView->info().minLayer;
-      regions[1].dstSubresource.layerCount       = 1;
-      //regions[1].dstOffset                     = { 0, 0, 0 };
-      regions[1].extent                          = { m_sampleWidth / 2, m_sampleHeight / 2, 1 };
-
-      VkCopyImageInfo2 copyImageInfo =
-        { VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 };
-      copyImageInfo.srcImage       = decodedPicture->handle();
-      copyImageInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
-      copyImageInfo.dstImage       = m_outputImageView->imageHandle();
-      copyImageInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
-      copyImageInfo.regionCount    = 2;
-      copyImageInfo.pRegions       = regions.data();
-
+      /* Copy decoded image -> output image. */
       ctx->emitCopyImage(DxvkCmdBuffer::InitBuffer, &copyImageInfo);
 
@@ -1662,10 +1987,10 @@
     else
       ctx->trackResource(DxvkAccess::Write, dstDPBSlot.image); /* Same image in every slot. */
-    if (m_caps.distinctOutputImage)
+    if (fUseDistinctOutputImage)
       ctx->trackResource(DxvkAccess::Write, m_imageDecodeDst);
     ctx->trackResource(DxvkAccess::Read, m_bitstreamBuffer);
 
     /*
-     * Keep reference picture.
+     * Keep reference picture and update its information if necessary.
      */
     bool activateSlot = false;
@@ -1676,4 +2001,11 @@
       activateSlot = true; /* It is not known yet if the picture is a reference. */
     }
+    else if (m_profile.profileInfo.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
+      activateSlot = parms.av1.reference_frame_update;
+      if (activateSlot) {
+        for (uint32_t i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; ++i)
+          dstDPBSlot.av1.stdRefInfo.SavedOrderHints[i] = parms.av1.stdPictureInfo.OrderHints[i];
+      }
+    }
     if (activateSlot) {
       dstDPBSlot.isActive = true;
Index: trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_video_decoder.h
===================================================================
--- trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_video_decoder.h	(revision 108576)
+++ trunk/src/libs/dxvk-2.3.1/src/dxvk/dxvk_video_decoder.h	(revision 108577)
@@ -47,4 +47,5 @@
       VkVideoDecodeH264ProfileInfoKHR     h264ProfileInfo;
       VkVideoDecodeH265ProfileInfoKHR     h265ProfileInfo;
+      VkVideoDecodeAV1ProfileInfoKHR      av1ProfileInfo;
     };
     /* Vulkan profile info. */
@@ -54,4 +55,5 @@
       VkVideoDecodeH264CapabilitiesKHR    decodeH264Capabilities;
       VkVideoDecodeH265CapabilitiesKHR    decodeH265Capabilities;
+      VkVideoDecodeAV1CapabilitiesKHR     decodeAV1Capabilities;
     };
     VkVideoDecodeCapabilitiesKHR          decodeCapabilities;
@@ -65,10 +67,21 @@
 
   struct DxvkRefFrameInfo {
-    uint8_t  idSurface;
-    uint8_t  longTermReference : 1;
-    uint8_t  usedForReference : 2;
-    uint8_t  nonExistingFrame : 1;
-    uint16_t frame_num;
-    int32_t  PicOrderCnt[2];
+    uint8_t      idSurface;
+    union {
+      struct {
+        uint8_t  longTermReference : 1;
+        uint8_t  usedForReference : 2;
+        uint8_t  nonExistingFrame : 1;
+        uint16_t frame_num;
+        int32_t  PicOrderCnt[2];
+      } h264;
+      struct {
+        uint8_t  longTermReference : 1;
+        int32_t  PicOrderCntVal;
+      } h265;
+      struct {
+        uint8_t  frame_name;
+      } av1;
+    };
   };
 
@@ -85,4 +98,6 @@
         StdVideoDecodeH264PictureInfo    stdH264PictureInfo;
         StdVideoDecodeH264ReferenceInfo  stdH264ReferenceInfo;
+
+        uint8_t                          nal_unit_type;
       } h264;
       struct {
@@ -90,4 +105,5 @@
         StdVideoH265ProfileTierLevel     vpsProfileTierLevel;
         StdVideoH265SequenceParameterSet sps;
+        StdVideoH265DecPicBufMgr         spsDecPicBufMgr;
         StdVideoH265PictureParameterSet  pps;
         StdVideoH265ScalingLists         ppsScalingLists;
@@ -95,12 +111,35 @@
         StdVideoDecodeH265PictureInfo    stdPictureInfo;
         StdVideoDecodeH265ReferenceInfo  stdReferenceInfo;
-
-        uint8_t                          sps_max_dec_pic_buffering;
       } h265;
-    };
-
-    uint8_t                            nal_unit_type;
-
-    std::vector<uint32_t>              sliceOffsets;
+      struct {
+        StdVideoAV1SequenceHeader        stdSequenceHeader;
+        StdVideoAV1ColorConfig           stdColorConfig;
+
+        StdVideoDecodeAV1PictureInfo     stdPictureInfo;
+        StdVideoAV1TileInfo              stdTileInfo;
+        uint16_t                         MiColStarts[64];
+        uint16_t                         MiRowStarts[64];
+        uint16_t                         WidthInSbsMinus1[64];
+        uint16_t                         HeightInSbsMinus1[64];
+        StdVideoAV1Quantization          stdQuantization;
+        StdVideoAV1Segmentation          stdSegmentation;
+        StdVideoAV1LoopFilter            stdLoopFilter;
+        StdVideoAV1CDEF                  stdCDEF;
+        StdVideoAV1LoopRestoration       stdLoopRestoration;
+        StdVideoAV1GlobalMotion          stdGlobalMotion;
+        StdVideoAV1FilmGrain             stdFilmGrain;
+
+        uint32_t                         tileCount;
+
+        StdVideoDecodeAV1ReferenceInfo   stdReferenceInfo;
+
+        uint8_t                          RefFrameMapTextureIndex[8];
+
+        bool                             reference_frame_update;
+      } av1;
+    };
+
+    std::vector<uint32_t>              sliceOrTileOffsets;
+    std::vector<uint32_t>              sliceOrTileSizes;
 
     uint8_t                            idSurface;
@@ -282,21 +321,32 @@
      */
     struct DxvkDPBSlot {
+      /* These fields will be assigned during video decoder initialization. */
       Rc<DxvkImage>                     image = nullptr;
       Rc<DxvkImageView>                 imageView = nullptr;
       uint32_t                          baseArrayLayer = 0;
-      bool                              isActive = false;
-      struct {
-        StdVideoDecodeH264ReferenceInfo   stdRefInfo = {};
-      } h264;
-      struct {
-        StdVideoDecodeH265ReferenceInfo   stdRefInfo = {};
-      } h265;
-      uint8_t                           idSurface = DXVK_VIDEO_DECODER_SURFACE_INVALID;
+
+      /* These fields are updated during decoding process. */
+      bool                              isActive;
+      union {
+        struct {
+          StdVideoDecodeH264ReferenceInfo stdRefInfo;
+        } h264;
+        struct {
+          StdVideoDecodeH265ReferenceInfo stdRefInfo;
+        } h265;
+        struct {
+          StdVideoDecodeAV1ReferenceInfo  stdRefInfo;
+        } av1;
+        uint8_t                           stdRefInfoData[
+          std::max(sizeof(StdVideoDecodeH264ReferenceInfo),
+          std::max(sizeof(StdVideoDecodeH265ReferenceInfo),
+                   sizeof(StdVideoDecodeAV1ReferenceInfo)))];
+      };
+      uint8_t                           idSurface;
 
       void deactivate() {
-        this->isActive           = false;
-        this->h264.stdRefInfo    = {};
-        this->h265.stdRefInfo    = {};
-        this->idSurface          = DXVK_VIDEO_DECODER_SURFACE_INVALID;
+        this->isActive = false;
+        memset(this->stdRefInfoData, 0, sizeof(this->stdRefInfoData));
+        this->idSurface = DXVK_VIDEO_DECODER_SURFACE_INVALID;
       }
     };
@@ -311,4 +361,8 @@
       std::vector<DxvkDPBSlot>          slots;
       int                               idxCurrentDPBSlot = 0;
+      bool                              fOverflow = false;
+
+      /* Size of DPB images. */
+      VkExtent3D                        decodedPictureExtent = { 0, 0, 1 };
 
       /* Uncompressed surface id (idSurface) -> frame information. */
@@ -319,4 +373,5 @@
           slot.deactivate();
         this->idxCurrentDPBSlot = 0;
+        this->fOverflow = false;
         this->refFrames.clear();
       }
@@ -344,4 +399,7 @@
         std::array<StdVideoH265PictureParameterSet, 256>  pps;
       } h265;
+      struct {
+        StdVideoAV1SequenceHeader                         stdSequenceHeader;
+      } av1;
     };
     DxvkParameterSetCache               m_parameterSetCache;
@@ -357,4 +415,7 @@
 
     VkResult UpdateSessionParametersH265(
+      DxvkVideoDecodeInputParameters *pParms);
+
+    VkResult UpdateSessionParametersAV1(
       DxvkVideoDecodeInputParameters *pParms);
 
