Skip to content

Commit fbb34c6

Browse files
YaaZjbrbot
authored and
jbrbot
committed
JBR-8608 Vulkan: Cleanup capability checks
1 parent b926cdc commit fbb34c6

File tree

7 files changed

+219
-170
lines changed

7 files changed

+219
-170
lines changed

src/java.desktop/share/classes/sun/java2d/vulkan/VKBlitLoops.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ private static int encode3Byte(int r, int g, int b) {
546546
}
547547

548548
private static boolean hasCap(VKSurfaceData dst, int cap) {
549-
return (dst.getGraphicsConfig().getGPU().getCaps() & cap) != 0;
549+
return dst.getGraphicsConfig().getGPU().hasCap(cap);
550550
}
551551

552552
/**

src/java.desktop/share/classes/sun/java2d/vulkan/VKEnv.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public static synchronized void init(long nativePtr) {
8080
Options.deviceNumber : 0];
8181
// Check whether the presentation is supported.
8282
for (VKGPU device : devices) {
83-
if ((device.getCaps() & VKGPU.CAP_PRESENTABLE_BIT) != 0 &&
83+
if (device.hasCap(VKGPU.CAP_PRESENTABLE_BIT) &&
8484
device.getPresentableGraphicsConfigs().findAny().isPresent()) {
8585
newState |= PRESENT_BIT;
8686
break;

src/java.desktop/share/classes/sun/java2d/vulkan/VKGPU.java

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
public class VKGPU {
4040

4141
@Native public static final int CAP_PRESENTABLE_BIT = 0x80000000;
42+
@Native public static final int CAP_LOGIC_OP_BIT = 0x40000000;
4243
@Native public static final int CAP_SAMPLED_4BYTE_BIT = 0; // Considered always supported.
4344
@Native public static final int CAP_SAMPLED_3BYTE_BIT = 1;
4445
@Native public static final int CAP_SAMPLED_565_BIT = 2;
@@ -98,6 +99,10 @@ public int getCaps() {
9899
return caps;
99100
}
100101

102+
public boolean hasCap(int cap) {
103+
return (caps & cap) == cap;
104+
}
105+
101106
/**
102107
* Initialize the device and return its native handle.
103108
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, JetBrains s.r.o.. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
#ifndef VKCapabilityUtil_h_Included
28+
#define VKCapabilityUtil_h_Included
29+
#include "VKUtil.h"
30+
31+
#define VK_KHR_VALIDATION_LAYER_NAME "VK_LAYER_KHRONOS_validation"
32+
33+
// Named entries are layers or extensions, arragned into on-stack linked list.
34+
typedef struct VKNamedEntry {
35+
pchar name;
36+
const void* found; // Pointer to the found struct.
37+
struct VKNamedEntry* next; // Pointer to the next entry.
38+
} VKNamedEntry;
39+
40+
#define DEF_NAMED_ENTRY(LIST, NAME) VKNamedEntry NAME = { NAME ## _NAME, NULL, (LIST) }; \
41+
if (NAME.name != NULL) (LIST) = &(NAME)
42+
43+
static void VKNamedEntry_LogAll(pchar what, pchar all, uint32_t count, size_t stride) {
44+
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, " Supported %s:", what)
45+
for (uint32_t i = 0; i < count; i++) {
46+
if (i == 0) J2dRlsTrace(J2D_TRACE_VERBOSE, " ")
47+
else J2dRlsTrace(J2D_TRACE_VERBOSE, ", ")
48+
J2dRlsTrace(J2D_TRACE_VERBOSE, all)
49+
all += stride;
50+
}
51+
J2dRlsTrace(J2D_TRACE_VERBOSE, "\n")
52+
}
53+
54+
static void VKNamedEntry_LogFound(const VKNamedEntry* list) {
55+
for (; list != NULL; list = list->next) {
56+
J2dRlsTraceLn2(J2D_TRACE_INFO, " %s = %s", list->name, list->found ? "true" : "false")
57+
}
58+
}
59+
60+
static void VKNamedEntry_Match(VKNamedEntry* list, pchar all, uint32_t count, size_t stride) {
61+
for (; list != NULL; list = list->next) {
62+
pchar check = all;
63+
for (uint32_t i = 0; i < count; i++) {
64+
if (strcmp(list->name, check) == 0) {
65+
list->found = check;
66+
break;
67+
}
68+
check += stride;
69+
}
70+
}
71+
}
72+
73+
static ARRAY(pchar) VKNamedEntry_CollectNames(const VKNamedEntry* list) {
74+
ARRAY(pchar) result = NULL;
75+
for (; list != NULL; list = list->next) {
76+
if (list->found) ARRAY_PUSH_BACK(result) = list->name;
77+
}
78+
return result;
79+
}
80+
81+
static void VKCapabilityUtil_LogErrors(int level, ARRAY(pchar) errors) {
82+
for (uint32_t i = 0; i < ARRAY_SIZE(errors); i++) {
83+
J2dRlsTraceLn1(level, " %s", errors[i])
84+
}
85+
}
86+
87+
#endif //VKCapabilityUtil_h_Included

src/java.desktop/share/native/common/java2d/vulkan/VKDevice.c

+56-85
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <string.h>
2828
#include "sun_java2d_vulkan_VKGPU.h"
2929
#include "VKUtil.h"
30+
#include "VKCapabilityUtil.h"
3031
#include "VKEnv.h"
3132
#include "VKAllocator.h"
3233
#include "VKRenderer.h"
@@ -71,7 +72,6 @@ static VkBool32 VKDevice_CheckAndAddFormat(VKEnv* vk, VkPhysicalDevice physicalD
7172
}
7273

7374
void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
74-
jint caps = 0;
7575
// Query device properties.
7676
VkPhysicalDeviceVulkan12Features device12Features = {
7777
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
@@ -85,27 +85,55 @@ void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
8585
VkPhysicalDeviceProperties2 deviceProperties2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 };
8686
vk->vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProperties2);
8787

88-
// Check features.
89-
J2dRlsTrace5(J2D_TRACE_INFO, "\t- %s (%d.%d.%d, %s) ",
88+
// Query supported layers.
89+
uint32_t layerCount;
90+
VK_IF_ERROR(vk->vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, NULL)) return;
91+
VkLayerProperties allLayers[layerCount];
92+
VK_IF_ERROR(vk->vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, allLayers)) return;
93+
94+
// Query supported extensions.
95+
uint32_t extensionCount;
96+
VK_IF_ERROR(vk->vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, NULL)) return;
97+
VkExtensionProperties allExtensions[extensionCount];
98+
VK_IF_ERROR(vk->vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, allExtensions)) return;
99+
100+
// Check API version.
101+
ARRAY(pchar) errors = NULL;
102+
jint caps = 0;
103+
J2dRlsTraceLn5(J2D_TRACE_INFO, "%s (%d.%d.%d, %s)",
90104
(const char *) deviceProperties2.properties.deviceName,
91105
VK_API_VERSION_MAJOR(deviceProperties2.properties.apiVersion),
92106
VK_API_VERSION_MINOR(deviceProperties2.properties.apiVersion),
93107
VK_API_VERSION_PATCH(deviceProperties2.properties.apiVersion),
94108
physicalDeviceTypeString(deviceProperties2.properties.deviceType))
95109
if (deviceProperties2.properties.apiVersion < REQUIRED_VULKAN_VERSION) {
96-
J2dRlsTraceLn(J2D_TRACE_INFO, " - unsupported API version, skipped")
97-
return;
110+
ARRAY_PUSH_BACK(errors) = "Unsupported API version";
98111
}
99112

100-
if (!deviceFeatures2.features.logicOp) {
101-
J2dRlsTraceLn(J2D_TRACE_INFO, " - hasLogicOp not supported, skipped")
102-
return;
103-
}
104-
if (!device12Features.timelineSemaphore) {
105-
J2dRlsTraceLn(J2D_TRACE_INFO, " - hasTimelineSemaphore not supported, skipped")
106-
return;
107-
}
108-
J2dRlsTraceLn(J2D_TRACE_INFO, "")
113+
// Log layers and extensions.
114+
VKNamedEntry_LogAll("device layers", allLayers[0].layerName, layerCount, sizeof(VkLayerProperties));
115+
VKNamedEntry_LogAll("device extensions", allExtensions[0].extensionName, extensionCount, sizeof(VkExtensionProperties));
116+
117+
// Check layers.
118+
VKNamedEntry* layers = NULL;
119+
#ifdef DEBUG
120+
DEF_NAMED_ENTRY(layers, VK_KHR_VALIDATION_LAYER);
121+
#endif
122+
VKNamedEntry_Match(layers, allLayers[0].layerName, layerCount, sizeof(VkLayerProperties));
123+
VKNamedEntry_LogFound(layers);
124+
125+
// Check extensions.
126+
VKNamedEntry* extensions = NULL;
127+
DEF_NAMED_ENTRY(extensions, VK_KHR_SWAPCHAIN_EXTENSION);
128+
VKNamedEntry_Match(extensions, allExtensions[0].extensionName, extensionCount, sizeof(VkExtensionProperties));
129+
VKNamedEntry_LogFound(extensions);
130+
131+
// Check features.
132+
J2dRlsTraceLn1(J2D_TRACE_INFO, " logicOp = %s", deviceFeatures2.features.logicOp ? "true" : "false")
133+
if (deviceFeatures2.features.logicOp) caps |= sun_java2d_vulkan_VKGPU_CAP_LOGIC_OP_BIT;
134+
135+
J2dRlsTraceLn1(J2D_TRACE_INFO, " timelineSemaphore = %s", device12Features.timelineSemaphore ? "true" : "false")
136+
if (!device12Features.timelineSemaphore) ARRAY_PUSH_BACK(errors) = "timelineSemaphore not supported";
109137

110138
// Query queue family properties.
111139
uint32_t queueFamilyCount = 0;
@@ -119,7 +147,8 @@ void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
119147
int64_t queueFamily = -1;
120148
for (uint32_t j = 0; j < queueFamilyCount; j++) {
121149
VkBool32 presentationSupported = VK_FALSE;
122-
if (vk->platformData != NULL && vk->platformData->checkPresentationSupport != NULL) {
150+
if (vk->presentationSupported && VK_KHR_SWAPCHAIN_EXTENSION.found &&
151+
vk->platformData != NULL && vk->platformData->checkPresentationSupport != NULL) {
123152
presentationSupported = vk->platformData->checkPresentationSupport(vk, physicalDevice, j);
124153
}
125154
char logFlags[5] = {
@@ -144,22 +173,7 @@ void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
144173
}
145174
}
146175
}
147-
if (queueFamily == -1) {
148-
J2dRlsTraceLn(J2D_TRACE_INFO, " --------------------- Suitable queue not found, skipped")
149-
return;
150-
}
151-
152-
// Query supported layers.
153-
uint32_t layerCount;
154-
VK_IF_ERROR(vk->vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, NULL)) return;
155-
VkLayerProperties layers[layerCount];
156-
VK_IF_ERROR(vk->vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, layers)) return;
157-
158-
// Query supported extensions.
159-
uint32_t extensionCount;
160-
VK_IF_ERROR(vk->vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, NULL)) return;
161-
VkExtensionProperties extensions[extensionCount];
162-
VK_IF_ERROR(vk->vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, extensions)) return;
176+
if (queueFamily == -1) ARRAY_PUSH_BACK(errors) = "Suitable queue not found";
163177

164178
// Query supported formats.
165179
J2dRlsTraceLn(J2D_TRACE_INFO, " Supported device formats:")
@@ -208,11 +222,8 @@ void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
208222

209223
// Check sampled formats capabilities.
210224
if (SRCTYPE_4BYTE->format == VK_FORMAT_UNDEFINED) {
211-
J2dRlsTraceLn(J2D_TRACE_INFO, " - 4-byte sampled format not found, skipped")
212-
ARRAY_FREE(supportedFormats);
213-
return;
214-
}
215-
caps |= sun_java2d_vulkan_VKGPU_CAP_SAMPLED_4BYTE_BIT;
225+
ARRAY_PUSH_BACK(errors) = "4-byte sampled format not found";
226+
} else caps |= sun_java2d_vulkan_VKGPU_CAP_SAMPLED_4BYTE_BIT;
216227
if (SRCTYPE_3BYTE->format != VK_FORMAT_UNDEFINED) caps |= sun_java2d_vulkan_VKGPU_CAP_SAMPLED_3BYTE_BIT;
217228
if (SRCTYPE_565->format != VK_FORMAT_UNDEFINED) caps |= sun_java2d_vulkan_VKGPU_CAP_SAMPLED_565_BIT;
218229
if (SRCTYPE_555->format != VK_FORMAT_UNDEFINED) caps |= sun_java2d_vulkan_VKGPU_CAP_SAMPLED_555_BIT;
@@ -222,61 +233,21 @@ void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
222233
vk->vkGetPhysicalDeviceFormatProperties(physicalDevice, VK_FORMAT_S8_UINT, &formatProperties);
223234
if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0) {
224235
J2dRlsTraceLn1(J2D_TRACE_INFO, " %s", "VK_FORMAT_S8_UINT (stencil)")
225-
} else {
226-
J2dRlsTraceLn(J2D_TRACE_INFO, " - VK_FORMAT_S8_UINT not supported, skipped")
227-
ARRAY_FREE(supportedFormats);
228-
return;
229-
}
236+
} else ARRAY_PUSH_BACK(errors) = "VK_FORMAT_S8_UINT not supported";
230237
}
231238

232-
// Log layers.
233-
J2dRlsTraceLn(J2D_TRACE_VERBOSE, " Supported device layers:")
234-
for (uint32_t j = 0; j < layerCount; j++) {
235-
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, " %s", (char *) layers[j].layerName)
236-
}
237-
238-
// Check extensions.
239-
J2dRlsTraceLn(J2D_TRACE_VERBOSE, " Supported device extensions:")
240-
VkBool32 hasSwapChain = VK_FALSE;
241-
for (uint32_t j = 0; j < extensionCount; j++) {
242-
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, " %s", (char *) extensions[j].extensionName)
243-
hasSwapChain = hasSwapChain || strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME, extensions[j].extensionName) == 0;
244-
}
245-
J2dRlsTraceLn(J2D_TRACE_VERBOSE, "Vulkan: Found device extensions:")
246-
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, " " VK_KHR_SWAPCHAIN_EXTENSION_NAME " = %s", hasSwapChain ? "true" : "false")
247-
248-
if (!hasSwapChain) {
249-
J2dRlsTraceLn(J2D_TRACE_INFO,
250-
" --------------------- Required " VK_KHR_SWAPCHAIN_EXTENSION_NAME " not found, skipped")
251-
ARRAY_FREE(supportedFormats);
239+
// Check found errors.
240+
if (errors != NULL) {
241+
J2dRlsTraceLn(J2D_TRACE_WARNING, " Device is not supported:")
242+
VKCapabilityUtil_LogErrors(J2D_TRACE_WARNING, errors);
243+
ARRAY_FREE(errors);
252244
return;
253245
}
254246

255-
ARRAY(pchar) deviceEnabledLayers = NULL;
256-
ARRAY(pchar) deviceEnabledExtensions = NULL;
257-
ARRAY_PUSH_BACK(deviceEnabledExtensions) = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
258-
259-
// Check validation layer.
260-
#ifdef DEBUG
261-
int validationLayerNotSupported = 1;
262-
for (uint32_t j = 0; j < layerCount; j++) {
263-
if (strcmp("VK_LAYER_KHRONOS_validation", layers[j].layerName) == 0) {
264-
validationLayerNotSupported = 0;
265-
ARRAY_PUSH_BACK(deviceEnabledLayers) = "VK_LAYER_KHRONOS_validation";
266-
break;
267-
}
268-
}
269-
if (validationLayerNotSupported) {
270-
J2dRlsTraceLn1(J2D_TRACE_INFO, " %s device layer is not supported", "VK_LAYER_KHRONOS_validation")
271-
}
272-
#endif
273-
274247
// Copy device name.
275248
char* deviceName = strdup(deviceProperties2.properties.deviceName);
276249
if (deviceName == NULL) {
277-
J2dRlsTraceLn(J2D_TRACE_ERROR, "Vulkan: Cannot duplicate deviceName")
278-
ARRAY_FREE(deviceEnabledLayers);
279-
ARRAY_FREE(deviceEnabledExtensions);
250+
J2dRlsTraceLn(J2D_TRACE_ERROR, " Cannot duplicate deviceName")
280251
ARRAY_FREE(supportedFormats);
281252
return;
282253
}
@@ -288,8 +259,8 @@ void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
288259
.handle = VK_NULL_HANDLE,
289260
.physicalDevice = physicalDevice,
290261
.queueFamily = queueFamily,
291-
.enabledLayers = deviceEnabledLayers,
292-
.enabledExtensions = deviceEnabledExtensions,
262+
.enabledLayers = VKNamedEntry_CollectNames(layers),
263+
.enabledExtensions = VKNamedEntry_CollectNames(extensions),
293264
.sampledSrcTypes = sampledSrcTypes,
294265
.supportedFormats = supportedFormats,
295266
.caps = caps

0 commit comments

Comments
 (0)