1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.mediapc.cts; 17 18 import android.mediapc.cts.common.PerformanceClassEvaluator; 19 import android.mediapc.cts.common.Requirements; 20 import android.mediapc.cts.common.Requirements.VulkanRequirement; 21 import android.util.Log; 22 23 import androidx.test.ext.junit.runners.AndroidJUnit4; 24 25 import com.android.compatibility.common.util.CddTest; 26 27 import com.google.common.collect.ImmutableList; 28 29 import org.json.JSONArray; 30 import org.json.JSONException; 31 import org.json.JSONObject; 32 import org.junit.Before; 33 import org.junit.Rule; 34 import org.junit.Test; 35 import org.junit.rules.TestName; 36 import org.junit.runner.RunWith; 37 38 /** 39 * Verify Vulkan MPC requirements. 40 */ 41 @RunWith(AndroidJUnit4.class) 42 public class VulkanTest { 43 44 private static final String LOG_TAG = VulkanTest.class.getSimpleName(); 45 private static final int VK_PHYSICAL_DEVICE_TYPE_CPU = 4; 46 47 48 private static final String VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME = "VK_EXT_global_priority"; 49 private static final int VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION = 1; 50 51 private ImmutableList<JSONObject> mVulkanDevices; nativeGetVkJSON()52 private static native String nativeGetVkJSON(); 53 54 @Rule 55 public final TestName mTestName = new TestName(); 56 57 static { 58 System.loadLibrary("ctsmediapc_vulkan_jni"); 59 } 60 61 /** 62 * Test specific setup 63 */ 64 @Before setUp()65 public void setUp() throws Exception { 66 JSONObject instance = new JSONObject(nativeGetVkJSON()); 67 final JSONArray vkjson = instance.getJSONArray("devices"); 68 var builder = ImmutableList.<JSONObject>builder(); 69 for (int i = 0; i < vkjson.length(); i++) { 70 builder.add(vkjson.getJSONObject(i)); 71 } 72 mVulkanDevices = builder.build(); 73 } 74 75 /** 76 * <b>7.1.4.1/H-1-3</b> MUST support 77 * {@code VkPhysicalDeviceProtectedMemoryFeatures.protectedMemory} and 78 * {@code VK_EXT_global_priority}. 79 */ 80 @CddTest(requirements = {"7.1.4.1/H-1-3"}) 81 @Test checkVulkanProtectedMemoryAndGlobalPrioritySupport()82 public void checkVulkanProtectedMemoryAndGlobalPrioritySupport() throws Exception { 83 84 PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); 85 VulkanRequirement req = Requirements.addR7_1_4_1__H_1_3(pce); 86 87 var filteredDevices = mVulkanDevices.stream().filter(this::notCpuDevice).toList(); 88 final boolean extGlobalPriority = filteredDevices.stream().allMatch( 89 device -> hasExtension(device, VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 90 VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION)); 91 final boolean hasProtectedMemory = filteredDevices.stream().allMatch( 92 this::hasProtectedMemory); 93 94 req.setVkNonCpuDeviceCount(filteredDevices.size()); 95 req.setVkPhysicalDeviceProtectedMemory(hasProtectedMemory); 96 req.setVkExtGlobalPriority(extGlobalPriority); 97 98 pce.submitAndCheck(); 99 } 100 notCpuDevice(JSONObject device)101 private boolean notCpuDevice(JSONObject device) { 102 try { 103 return device.getJSONObject("properties").getInt("deviceType") 104 != VK_PHYSICAL_DEVICE_TYPE_CPU; 105 } catch (JSONException e) { 106 Log.e(LOG_TAG, "Failed to get device type of %s".formatted(device), e); 107 return false; 108 } 109 } 110 hasExtension(JSONObject device, String name, int minVersion)111 private static boolean hasExtension(JSONObject device, String name, int minVersion) { 112 try { 113 JSONArray extensions = device.getJSONArray("extensions"); 114 for (int i = 0; i < extensions.length(); i++) { 115 JSONObject ext = extensions.getJSONObject(i); 116 if (ext.getString("extensionName").equals(name) 117 && ext.getInt("specVersion") 118 >= minVersion) { 119 return true; 120 } 121 } 122 } catch (Exception e) { 123 Log.e(LOG_TAG, 124 "Failed to get extension %s v%s from %s".formatted(name, minVersion, device), 125 e); 126 } 127 return false; 128 } 129 hasProtectedMemory(JSONObject device)130 private boolean hasProtectedMemory(JSONObject device) { 131 try { 132 return device.getJSONObject("protectedMemoryFeatures") 133 .getInt("protectedMemory") == 1; 134 } catch (Exception e) { 135 Log.e(LOG_TAG, "Failed to test for protect memory of %s".formatted(device), e); 136 } 137 return false; 138 } 139 } 140