1
+ /*
2
+ * Copyright LWJGL. All rights reserved.
3
+ * License terms: https://www.lwjgl.org/license
4
+ */
5
+ package org .lwjgl .demo .vulkan .khronos ;
6
+
7
+ import org .lwjgl .*;
8
+ import org .lwjgl .system .*;
9
+ import org .lwjgl .vulkan .*;
10
+
11
+ import java .io .*;
12
+ import java .nio .*;
13
+ import java .util .*;
14
+
15
+ import static org .lwjgl .demo .util .IOUtil .*;
16
+ import static org .lwjgl .system .MemoryStack .*;
17
+ import static org .lwjgl .util .shaderc .Shaderc .*;
18
+ import static org .lwjgl .vulkan .KHRSurface .*;
19
+ import static org .lwjgl .vulkan .VK10 .*;
20
+
21
+ /** Base class and utilities for the hello_triangle samples. */
22
+ public abstract class Demo implements AutoCloseable {
23
+
24
+ static final long UINT64_MAX = 0xFFFFFFFFFFFFFFFFL ;
25
+
26
+ static final boolean VK_DEBUG ;
27
+ static {
28
+ String property = System .getProperty ("debug" );
29
+ VK_DEBUG = property == null || Boolean .parseBoolean (property );
30
+ }
31
+
32
+ protected Demo () {
33
+ }
34
+
35
+ abstract boolean prepare (Window window );
36
+ abstract boolean resize ();
37
+ abstract void update ();
38
+
39
+ static void VK_CHECK (int vkResult ) {
40
+ if (vkResult != VK_SUCCESS ) {
41
+ throw new RuntimeException ("Detected Vulkan error: " + vkResult );
42
+ }
43
+ }
44
+
45
+ static void select_surface_format (VkPhysicalDevice gpu , long surface , VkSurfaceFormatKHR formatOut , int ... preferred_formats ) {
46
+ if (preferred_formats .length == 0 ) {
47
+ preferred_formats = new int [] {
48
+ VK_FORMAT_R8G8B8A8_SRGB ,
49
+ VK_FORMAT_B8G8R8A8_SRGB ,
50
+ VK_FORMAT_A8B8G8R8_SRGB_PACK32
51
+ };
52
+ }
53
+
54
+ try (MemoryStack stack = MemoryStack .stackPush ()) {
55
+ IntBuffer pi = stack .mallocInt (1 );
56
+
57
+ VK_CHECK (vkGetPhysicalDeviceSurfaceFormatsKHR (gpu , surface , pi , null ));
58
+ int surface_format_count = pi .get (0 );
59
+ assert (0 < surface_format_count );
60
+
61
+ try (VkSurfaceFormatKHR .Buffer supported_surface_formats = VkSurfaceFormatKHR .calloc (surface_format_count )) {
62
+ VK_CHECK (vkGetPhysicalDeviceSurfaceFormatsKHR (gpu , surface , pi , supported_surface_formats ));
63
+
64
+ // We use the first supported format as a fallback in case none of the preferred formats is available
65
+ int it = 0 ;
66
+
67
+ out :
68
+ for (int i = 0 ; i < surface_format_count ; i ++) {
69
+ int supportedFormat = supported_surface_formats .get (i ).format ();
70
+ for (int format : preferred_formats ) {
71
+ if (format == supportedFormat ) {
72
+ it = i ;
73
+ break out ;
74
+ }
75
+ }
76
+ }
77
+
78
+ supported_surface_formats .get (it , formatOut );
79
+ }
80
+ }
81
+ }
82
+
83
+ static long compile_shader (String fileName , int shaderType , long compiler , long options ) {
84
+ ByteBuffer shader_source ;
85
+ try {
86
+ shader_source = ioResourceToByteBuffer (fileName , 1024 );
87
+ } catch (IOException e ) {
88
+ throw new RuntimeException ("Failed to load shader source" , e );
89
+ }
90
+
91
+ long result ;
92
+ try (MemoryStack stack = stackPush ()) {
93
+ result = shaderc_compile_into_spv (
94
+ compiler ,
95
+ shader_source ,
96
+ shaderType ,
97
+ stack .UTF8 (fileName ),
98
+ stack .UTF8 ("main" ),
99
+ options
100
+ );
101
+ }
102
+
103
+ if (shaderc_result_get_compilation_status (result ) != shaderc_compilation_status_success ) {
104
+ throw new RuntimeException ("Shader compilation failed: " + shaderc_result_get_error_message (result ));
105
+ }
106
+
107
+ return result ;
108
+ }
109
+
110
+
111
+ public static class Instance {
112
+
113
+ private final VkInstance handle ;
114
+
115
+ private final List <PhysicalDevice > gpus = new ArrayList <>();
116
+
117
+ Instance (VkInstance instance ) {
118
+ handle = instance ;
119
+ if (handle .address () != VK_NULL_HANDLE ) {
120
+ query_gpus ();
121
+ } else {
122
+ throw new RuntimeException ("Instance not valid" );
123
+ }
124
+ }
125
+
126
+ void query_gpus () {
127
+ try (MemoryStack stack = MemoryStack .stackPush ()) {
128
+ // Querying valid physical devices on the machine
129
+ IntBuffer physical_device_count = stack .mallocInt (1 );
130
+ VK_CHECK (vkEnumeratePhysicalDevices (handle , physical_device_count , null ));
131
+
132
+ if (physical_device_count .get (0 ) < 1 ) {
133
+ throw new RuntimeException ("Couldn't find a physical device that supports Vulkan." );
134
+ }
135
+
136
+ PointerBuffer physical_devices = stack .mallocPointer (physical_device_count .get (0 ));
137
+ VK_CHECK (vkEnumeratePhysicalDevices (handle , physical_device_count , physical_devices ));
138
+
139
+ // Create gpus wrapper objects from the VkPhysicalDevice's
140
+ for (int i = 0 ; i < physical_devices .capacity (); ++i ) {
141
+ gpus .add (new PhysicalDevice (new VkPhysicalDevice (physical_devices .get (i ), handle )));
142
+ }
143
+ }
144
+ }
145
+
146
+ public void free () {
147
+ for (PhysicalDevice gpu : gpus ) {
148
+ gpu .free ();
149
+ }
150
+ vkDestroyInstance (handle , null );
151
+ }
152
+
153
+ public VkInstance getHandle () {
154
+ return handle ;
155
+ }
156
+
157
+ }
158
+
159
+ static class PhysicalDevice {
160
+
161
+ private final VkPhysicalDevice handle ;
162
+
163
+ private final VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures .calloc ();
164
+ private final VkPhysicalDeviceProperties properties = VkPhysicalDeviceProperties .calloc ();
165
+ private final VkPhysicalDeviceMemoryProperties memory_properties = VkPhysicalDeviceMemoryProperties .calloc ();
166
+
167
+ private final VkQueueFamilyProperties .Buffer queue_family_properties ;
168
+ private final VkExtensionProperties .Buffer device_extensions ;
169
+
170
+ PhysicalDevice (VkPhysicalDevice physical_device ) {
171
+ handle = physical_device ;
172
+
173
+ vkGetPhysicalDeviceFeatures (physical_device , features );
174
+ vkGetPhysicalDeviceProperties (physical_device , properties );
175
+ vkGetPhysicalDeviceMemoryProperties (physical_device , memory_properties );
176
+
177
+ System .out .printf ("Found GPU: %s%n" , properties .deviceNameString ());
178
+ try (MemoryStack stack = stackPush ()) {
179
+ IntBuffer queue_family_properties_count = stack .mallocInt (1 );
180
+ vkGetPhysicalDeviceQueueFamilyProperties (physical_device , queue_family_properties_count , null );
181
+
182
+ queue_family_properties = VkQueueFamilyProperties .calloc (queue_family_properties_count .get (0 ));
183
+ vkGetPhysicalDeviceQueueFamilyProperties (physical_device , queue_family_properties_count , queue_family_properties );
184
+
185
+ IntBuffer device_extension_count = stack .mallocInt (1 );
186
+ VK_CHECK (vkEnumerateDeviceExtensionProperties (get_handle (), (ByteBuffer )null , device_extension_count , null ));
187
+
188
+ device_extensions = VkExtensionProperties .calloc (device_extension_count .get (0 ));
189
+ VK_CHECK (vkEnumerateDeviceExtensionProperties (get_handle (), (ByteBuffer )null , device_extension_count , device_extensions ));
190
+ }
191
+
192
+ // Display supported extensions
193
+ if (device_extensions .capacity () > 0 ) {
194
+ if (VK_DEBUG ) {
195
+ System .out .println ("[debug] Device supports the following extensions:" );
196
+ }
197
+ for (VkExtensionProperties extension : device_extensions ) {
198
+ if (VK_DEBUG ) {
199
+ System .out .printf ("[debug] \t %s%n" , extension .extensionNameString ());
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ public VkPhysicalDevice get_handle () {
206
+ return handle ;
207
+ }
208
+
209
+ public void free () {
210
+ device_extensions .free ();
211
+ queue_family_properties .free ();
212
+ memory_properties .free ();
213
+ properties .free ();
214
+ features .free ();
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Swapchain state
220
+ */
221
+ static class SwapchainDimensions {
222
+ // Width of the swapchain.
223
+ int width ;
224
+
225
+ // Height of the swapchain.
226
+ int height ;
227
+
228
+ // Pixel format of the swapchain.
229
+ int format ;
230
+
231
+ SwapchainDimensions (int width , int height , int format ) {
232
+ this .width = width ;
233
+ this .height = height ;
234
+ this .format = format ;
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Per-frame data
240
+ */
241
+ static class PerFrame {
242
+ long queue_submit_fence = VK_NULL_HANDLE ;
243
+ long primary_command_pool = VK_NULL_HANDLE ;
244
+
245
+ VkCommandBuffer primary_command_buffer ;
246
+
247
+ long swapchain_acquire_semaphore = VK_NULL_HANDLE ;
248
+ long swapchain_release_semaphore = VK_NULL_HANDLE ;
249
+ }
250
+
251
+ }
0 commit comments