+static uint32_t radv_compute_valid_memory_types_attempt(struct radv_physical_device *dev,
+ enum radeon_bo_domain domains,
+ enum radeon_bo_flag flags,
+ enum radeon_bo_flag ignore_flags)
+{
+ /* Don't count GTT/CPU as relevant:
+ *
+ * - We're not fully consistent between the two.
+ * - Sometimes VRAM gets VRAM|GTT.
+ */
+ const enum radeon_bo_domain relevant_domains = RADEON_DOMAIN_VRAM |
+ RADEON_DOMAIN_GDS |
+ RADEON_DOMAIN_OA;
+ uint32_t bits = 0;
+ for (unsigned i = 0; i < dev->memory_properties.memoryTypeCount; ++i) {
+ if ((domains & relevant_domains) != (dev->memory_domains[i] & relevant_domains))
+ continue;
+
+ if ((flags & ~ignore_flags) != (dev->memory_flags[i] & ~ignore_flags))
+ continue;
+
+ bits |= 1u << i;
+ }
+
+ return bits;
+}
+
+static uint32_t radv_compute_valid_memory_types(struct radv_physical_device *dev,
+ enum radeon_bo_domain domains,
+ enum radeon_bo_flag flags)
+{
+ enum radeon_bo_flag ignore_flags = ~(RADEON_FLAG_NO_CPU_ACCESS | RADEON_FLAG_GTT_WC);
+ uint32_t bits = radv_compute_valid_memory_types_attempt(dev, domains, flags, ignore_flags);
+
+ if (!bits) {
+ ignore_flags |= RADEON_FLAG_NO_CPU_ACCESS;
+ bits = radv_compute_valid_memory_types_attempt(dev, domains, flags, ignore_flags);
+ }
+
+ return bits;
+}