CMSC23740 Common Code Library
Support code for CS23740 programming projects
Loading...
Searching...
No Matches
application.hpp
Go to the documentation of this file.
1
8/*
9 * COPYRIGHT (c) 2024 John Reppy (https://cs.uchicago.edu/~jhr)
10 * All rights reserved.
11 */
12
13#ifndef _CS237_APPLICATION_HPP_
14#define _CS237_APPLICATION_HPP_
15
16#ifndef _CS237_HPP_
17#error "cs237/application.hpp should not be included directly"
18#endif
19
20namespace cs237 {
21
22namespace __detail { class TextureBase; }
23
26
27friend class Window;
28friend class Buffer;
29friend class MemoryObj;
31friend class Texture1D;
32friend class Texture2D;
33friend class DepthBuffer;
34friend class Attachment;
35friend class DepthAttachment;
36
37public:
38
42 Application (std::vector<std::string> const &args, std::string const &name = "CS237 App");
43
44 virtual ~Application ();
45
47 virtual void run () = 0;
48
50 std::string name () const { return this->_name; }
51
53 bool debug () const { return this->_debug; }
55 bool verbose () const
56 {
57 return (this->_messages & vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose)
58 == vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose;
59 }
60
63 static std::vector<vk::ExtensionProperties> supportedExtensions ()
64 {
65 return vk::enumerateInstanceExtensionProperties(nullptr);
66 }
67
71 std::vector<vk::ExtensionProperties> supportedDeviceExtensions ()
72 {
73 return this->_gpu.enumerateDeviceExtensionProperties();
74 }
75
78 static std::vector<vk::LayerProperties> supportedLayers ()
79 {
80 return vk::enumerateInstanceLayerProperties();
81 }
82
84 vk::Device device () const { return this->_device; }
85
87 const vk::PhysicalDeviceProperties *props () const
88 {
89 if (this->_propsCache == nullptr) {
91 }
92 return this->_propsCache;
93 }
94
96 const vk::PhysicalDeviceLimits *limits () const { return &this->props()->limits; }
97
99 const vk::PhysicalDeviceFeatures *features () const
100 {
101 if (this->_featuresCache == nullptr) {
103 }
104 return this->_featuresCache;
105 }
106
110 struct SamplerInfo {
111 vk::Filter magFilter;
112 vk::Filter minFilter;
113 vk::SamplerMipmapMode mipmapMode;
114 vk::SamplerAddressMode addressModeU;
115 vk::SamplerAddressMode addressModeV;
116 vk::SamplerAddressMode addressModeW;
117 vk::BorderColor borderColor;
118
120 : magFilter(vk::Filter::eLinear), minFilter(vk::Filter::eLinear),
121 mipmapMode(vk::SamplerMipmapMode::eLinear),
122 addressModeU(vk::SamplerAddressMode::eRepeat),
123 addressModeV(vk::SamplerAddressMode::eRepeat),
124 addressModeW(vk::SamplerAddressMode::eRepeat),
125 borderColor(vk::BorderColor::eIntOpaqueBlack)
126 { }
127
130 vk::Filter magF, vk::Filter minF, vk::SamplerMipmapMode mm,
131 vk::SamplerAddressMode am, vk::BorderColor color)
132 : magFilter(magF), minFilter(minF), mipmapMode(mm),
133 addressModeU(am), addressModeV(vk::SamplerAddressMode::eRepeat),
134 addressModeW(vk::SamplerAddressMode::eRepeat), borderColor(color)
135 { }
136
139 vk::Filter magF, vk::Filter minF, vk::SamplerMipmapMode mm,
140 vk::SamplerAddressMode am1, vk::SamplerAddressMode am2,
141 vk::BorderColor color)
142 : magFilter(magF), minFilter(minF), mipmapMode(mm),
143 addressModeU(am1), addressModeV(am2),
144 addressModeW(vk::SamplerAddressMode::eRepeat), borderColor(color)
145 { }
146
147 };
148
152 vk::Sampler createSampler (SamplerInfo const &info);
153
157 vk::Sampler createDepthSampler (SamplerInfo const &info);
158
160 vk::FormatProperties formatProps (vk::Format fmt) const
161 {
162 return this->_gpu.getFormatProperties(fmt);
163 }
164
175 vk::PipelineLayout createPipelineLayout (
176 vk::ArrayProxy<vk::DescriptorSetLayout> descSets,
177 vk::ArrayProxy<vk::PushConstantRange> pcrs)
178 {
179 vk::PipelineLayoutCreateInfo layoutInfo(
180 {}, /* flags */
181 descSets, /* set layouts */
182 pcrs); /* push-constant ranges */
183
184 return this->_device.createPipelineLayout(layoutInfo);
185 }
186
190 vk::PipelineLayout createPipelineLayout (vk::DescriptorSetLayout descSet)
191 {
192 vk::PipelineLayoutCreateInfo layoutInfo(
193 {}, /* flags */
194 descSet, /* set layouts */
195 {}); /* push-constant ranges */
196
197 return this->_device.createPipelineLayout(layoutInfo);
198 }
199
230 vk::Pipeline createPipeline (
231 cs237::Shaders *shaders,
232 vk::PipelineVertexInputStateCreateInfo const &vertexInfo,
233 vk::PrimitiveTopology prim,
234 bool primRestart,
235 vk::ArrayProxy<vk::Viewport> const &viewports,
236 vk::ArrayProxy<vk::Rect2D> const &scissors,
237 bool depthClamp,
238 vk::PolygonMode polyMode,
239 vk::CullModeFlags cullMode,
240 vk::FrontFace front,
241 vk::PipelineLayout layout,
242 vk::RenderPass renderPass,
243 uint32_t subPass,
244 vk::PipelineColorBlendStateCreateInfo const &blending,
245 vk::ArrayProxy<vk::DynamicState> const &dynamic);
246
278 vk::Pipeline createPipeline (
279 cs237::Shaders *shaders,
280 vk::PipelineVertexInputStateCreateInfo const &vertexInfo,
281 vk::PrimitiveTopology prim,
282 bool primRestart,
283 vk::ArrayProxy<vk::Viewport> const &viewports,
284 vk::ArrayProxy<vk::Rect2D> const &scissors,
285 bool depthClamp,
286 vk::PolygonMode polyMode,
287 vk::CullModeFlags cullMode,
288 vk::FrontFace front,
289 vk::PipelineLayout layout,
290 vk::RenderPass renderPass,
291 uint32_t subPass,
292 vk::ArrayProxy<vk::DynamicState> const &dynamic);
293
325 vk::Pipeline createPipeline (
326 cs237::Shaders *shaders,
327 vk::PipelineVertexInputStateCreateInfo const &vertexInfo,
328 vk::PrimitiveTopology prim,
329 vk::ArrayProxy<vk::Viewport> const &viewports,
330 vk::ArrayProxy<vk::Rect2D> const &scissors,
331 vk::PolygonMode polyMode,
332 vk::CullModeFlags cullMode,
333 vk::FrontFace front,
334 vk::PipelineLayout layout,
335 vk::RenderPass renderPass,
336 uint32_t subPass,
337 vk::ArrayProxy<vk::DynamicState> const &dynamic)
338 {
339 return this->createPipeline(
340 shaders,
341 vertexInfo,
342 prim,
343 false,
344 viewports,
345 scissors,
346 false,
347 polyMode,
348 cullMode,
349 front,
350 layout,
351 renderPass,
352 subPass,
353 dynamic);
354 }
355
356/* TODO: define a ComputeShader class, since compute shaders
357 * only have one stage and get used in different contexts.
358 */
363 vk::Pipeline createComputePipeline (vk::PipelineLayout layout, cs237::Shaders *shaders);
364
367 vk::CommandBuffer newCommandBuf ()
368 {
369 vk::CommandBufferAllocateInfo allocInfo(
370 this->_cmdPool,
371 vk::CommandBufferLevel::ePrimary,
372 1); /* buffer count */
373
374 return (this->_device.allocateCommandBuffers(allocInfo))[0];
375 }
376
380 void beginCommands (vk::CommandBuffer cmdBuf, bool oneTime = false)
381 {
382 vk::CommandBufferBeginInfo beginInfo(
383 oneTime
384 ? vk::CommandBufferUsageFlagBits::eOneTimeSubmit
385 : vk::CommandBufferUsageFlags());
386 cmdBuf.begin(beginInfo);
387 }
388
391 void endCommands (vk::CommandBuffer cmdBuf) { cmdBuf.end(); }
392
395 void submitCommands (vk::CommandBuffer cmdBuf)
396 {
397 vk::CommandBuffer cmdBufs[1] = { cmdBuf };
398 vk::SubmitInfo submitInfo(
399 {},
400 {},
401 vk::ArrayProxyNoTemporaries<const vk::CommandBuffer>(1, cmdBufs),
402 {});
403 this->_queues.graphics.submit ({submitInfo});
404 this->_queues.graphics.waitIdle();
405 }
406
409 void freeCommandBuf (vk::CommandBuffer & cmdBuf)
410 {
411 this->_device.freeCommandBuffers (this->_cmdPool, cmdBuf);
412 }
413
415 template <typename T>
416 struct Queues {
420 };
421
423 Queues<uint32_t> getQIndices () const { return this->_qIdxs; }
424
425protected:
426
427 // information about swap-chain support
429 vk::SurfaceCapabilitiesKHR capabilities;
430 std::vector<vk::SurfaceFormatKHR> formats;
431 std::vector<vk::PresentModeKHR> presentModes;
432 };
433
434 std::string _name;
435 vk::DebugUtilsMessageSeverityFlagsEXT _messages;
437 bool _debug;
438 vk::Instance _instance;
439 vk::PhysicalDevice _gpu;
440 mutable vk::PhysicalDeviceProperties *_propsCache;
441 mutable vk::PhysicalDeviceFeatures *_featuresCache;
443 vk::Device _device;
446 vk::CommandPool _cmdPool;
447
451
455
459
463 void _selectDevice (vk::PhysicalDeviceFeatures *reqFeatures = nullptr);
464
471 int32_t _findMemory (uint32_t reqTypeBits, vk::MemoryPropertyFlags reqProps) const;
472
481 vk::Format _findBestFormat (
482 std::vector<vk::Format> candidates,
483 vk::ImageTiling tiling,
484 vk::FormatFeatureFlags features);
485
488
496 vk::Format _depthStencilBufferFormat (bool depth, bool stencil);
497
505 bool _getQIndices (vk::PhysicalDevice dev);
506
512
523 vk::Image _createImage (
524 uint32_t wid,
525 uint32_t ht,
526 vk::Format format,
527 vk::ImageTiling tiling,
528 vk::ImageUsageFlags usage,
529 vk::ImageLayout layout,
530 uint32_t mipLvls = 1);
531
541 vk::Image _createImage (
542 uint32_t wid,
543 uint32_t ht,
544 vk::Format format,
545 vk::ImageTiling tiling,
546 vk::ImageUsageFlags usage,
547 uint32_t mipLvls = 1)
548 {
549 return this->_createImage (
550 wid, ht, format, tiling, usage,
551 vk::ImageLayout::eUndefined,
552 mipLvls);
553 }
554
559 vk::DeviceMemory _allocImageMemory (vk::Image img, vk::MemoryPropertyFlags props);
560
567 vk::ImageView _createImageView (
568 vk::Image img, vk::Format fmt, vk::ImageAspectFlags aspectFlags);
569
576 vk::Image img,
577 vk::Format fmt,
578 vk::ImageLayout oldLayout,
579 vk::ImageLayout newLayout);
580
585 vk::Buffer _createBuffer (size_t size, vk::BufferUsageFlags usage);
586
591 vk::DeviceMemory _allocBufferMemory (vk::Buffer buf, vk::MemoryPropertyFlags props);
592
598 void _copyBuffer (vk::Buffer dstBuf, vk::Buffer srcBuf, size_t offset, size_t size);
599
608 vk::Image dstImg, vk::Buffer srcBuf, size_t size,
609 uint32_t wid, uint32_t ht=1, uint32_t depth=1);
610
611 /* debug-message support */
612 VkDebugUtilsMessengerEXT _debugMessenger;
613 void _initDebug ();
615};
616
617} // namespace cs237
618
619#endif // !_CS237_APPLICATION_HPP_
Definition texture.hpp:25
the base class for applications
Definition application.hpp:25
void _createInstance()
A helper function to create and initialize the Vulkan instance used by the application.
std::vector< vk::ExtensionProperties > supportedDeviceExtensions()
Get the list of supported Vulkan device extensions for the selected physical device.
Definition application.hpp:71
vk::Device _device
the logical device that we are using to render
Definition application.hpp:443
vk::Format _depthStencilBufferFormat(bool depth, bool stencil)
A helper function to identify the best depth/stencil-buffer attachment format for the device.
void _createLogicalDevice()
A helper function to create the logical device during initialization.
void _getPhysicalDeviceFeatures() const
function that gets the physical-device features and caches the pointer in the _featuresCache field.
vk::PhysicalDeviceFeatures * _featuresCache
a cache of the physical device properties
Definition application.hpp:441
vk::DeviceMemory _allocBufferMemory(vk::Buffer buf, vk::MemoryPropertyFlags props)
A helper function for allocating and binding device memory for a buffer.
const vk::PhysicalDeviceLimits * limits() const
access function for the physical device limits
Definition application.hpp:96
void freeCommandBuf(vk::CommandBuffer &cmdBuf)
free the command buffer
Definition application.hpp:409
VkDebugUtilsMessengerEXT _debugMessenger
Definition application.hpp:612
void _getPhysicalDeviceProperties() const
function that gets the physical-device properties and caches the pointer in the _propsCache field.
static std::vector< vk::LayerProperties > supportedLayers()
Get the list of supported layers.
Definition application.hpp:78
Application(std::vector< std::string > const &args, std::string const &name="CS237 App")
constructor for application base class
vk::Buffer _createBuffer(size_t size, vk::BufferUsageFlags usage)
create a vk::Buffer object
void _copyBufferToImage(vk::Image dstImg, vk::Buffer srcBuf, size_t size, uint32_t wid, uint32_t ht=1, uint32_t depth=1)
copy data from a buffer to an image
std::string name() const
return the application name
Definition application.hpp:50
Queues< uint32_t > _qIdxs
the queue family indices
Definition application.hpp:444
bool verbose() const
is the program in verbose mode?
Definition application.hpp:55
void _transitionImageLayout(vk::Image img, vk::Format fmt, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
A helper function for changing the layout of an image.
vk::Pipeline createComputePipeline(vk::PipelineLayout layout, cs237::Shaders *shaders)
Create a compute pipeline.
vk::PipelineLayout createPipelineLayout(vk::DescriptorSetLayout descSet)
Create a pipeline layout for a single descriptor set.
Definition application.hpp:190
vk::CommandBuffer newCommandBuf()
create and initialize a command buffer
Definition application.hpp:367
vk::Pipeline createPipeline(cs237::Shaders *shaders, vk::PipelineVertexInputStateCreateInfo const &vertexInfo, vk::PrimitiveTopology prim, bool primRestart, vk::ArrayProxy< vk::Viewport > const &viewports, vk::ArrayProxy< vk::Rect2D > const &scissors, bool depthClamp, vk::PolygonMode polyMode, vk::CullModeFlags cullMode, vk::FrontFace front, vk::PipelineLayout layout, vk::RenderPass renderPass, uint32_t subPass, vk::PipelineColorBlendStateCreateInfo const &blending, vk::ArrayProxy< vk::DynamicState > const &dynamic)
Allocate a graphics pipeline with blending support.
vk::PhysicalDeviceProperties * _propsCache
Definition application.hpp:440
void _copyBuffer(vk::Buffer dstBuf, vk::Buffer srcBuf, size_t offset, size_t size)
copy data from one buffer to another using the GPU
vk::Pipeline createPipeline(cs237::Shaders *shaders, vk::PipelineVertexInputStateCreateInfo const &vertexInfo, vk::PrimitiveTopology prim, bool primRestart, vk::ArrayProxy< vk::Viewport > const &viewports, vk::ArrayProxy< vk::Rect2D > const &scissors, bool depthClamp, vk::PolygonMode polyMode, vk::CullModeFlags cullMode, vk::FrontFace front, vk::PipelineLayout layout, vk::RenderPass renderPass, uint32_t subPass, vk::ArrayProxy< vk::DynamicState > const &dynamic)
Allocate a graphics pipeline.
bool _debug
set when validation layers should be enabled
Definition application.hpp:437
const vk::PhysicalDeviceProperties * props() const
get the physical-device properties pointer
Definition application.hpp:87
void endCommands(vk::CommandBuffer cmdBuf)
end the recording of commands in the give command buffer
Definition application.hpp:391
vk::DebugUtilsMessageSeverityFlagsEXT _messages
set to the message severity level
Definition application.hpp:435
vk::PhysicalDevice _gpu
the graphics card (aka device) that we are using
Definition application.hpp:439
vk::Instance _instance
the Vulkan instance used by the application
Definition application.hpp:438
virtual ~Application()
vk::Sampler createDepthSampler(SamplerInfo const &info)
Create a depth-texture sampler as specified.
vk::FormatProperties formatProps(vk::Format fmt) const
access function for the properties of an image format
Definition application.hpp:160
Queues< uint32_t > getQIndices() const
get the queue indices
Definition application.hpp:423
vk::Device device() const
get the logical device
Definition application.hpp:84
vk::ImageView _createImageView(vk::Image img, vk::Format fmt, vk::ImageAspectFlags aspectFlags)
A helper function for creating a Vulkan image view object for an image.
int32_t _findMemory(uint32_t reqTypeBits, vk::MemoryPropertyFlags reqProps) const
A helper function to identify the index of a device memory type that has the required type and proper...
void submitCommands(vk::CommandBuffer cmdBuf)
end the commands and submit the buffer to the graphics queue.
Definition application.hpp:395
std::string _name
the application name
Definition application.hpp:434
void beginCommands(vk::CommandBuffer cmdBuf, bool oneTime=false)
begin recording commands in the given command buffer
Definition application.hpp:380
void _selectDevice(vk::PhysicalDeviceFeatures *reqFeatures=nullptr)
A helper function to select the GPU to use.
vk::Pipeline createPipeline(cs237::Shaders *shaders, vk::PipelineVertexInputStateCreateInfo const &vertexInfo, vk::PrimitiveTopology prim, vk::ArrayProxy< vk::Viewport > const &viewports, vk::ArrayProxy< vk::Rect2D > const &scissors, vk::PolygonMode polyMode, vk::CullModeFlags cullMode, vk::FrontFace front, vk::PipelineLayout layout, vk::RenderPass renderPass, uint32_t subPass, vk::ArrayProxy< vk::DynamicState > const &dynamic)
Allocate a graphics pipeline using common defaults.
Definition application.hpp:325
const vk::PhysicalDeviceFeatures * features() const
access function for the physical device features
Definition application.hpp:99
Queues< vk::Queue > _queues
the device queues that we are using
Definition application.hpp:445
virtual void run()=0
main function for running the application
bool debug() const
is the program in debug mode?
Definition application.hpp:53
vk::PipelineLayout createPipelineLayout(vk::ArrayProxy< vk::DescriptorSetLayout > descSets, vk::ArrayProxy< vk::PushConstantRange > pcrs)
Create a pipeline layout.
Definition application.hpp:175
vk::CommandPool _cmdPool
pool for allocating command buffers
Definition application.hpp:446
vk::Sampler createSampler(SamplerInfo const &info)
Create a texture sampler as specified.
vk::Image _createImage(uint32_t wid, uint32_t ht, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, uint32_t mipLvls=1)
A helper function for creating a Vulkan image that can be used for textures or depth buffers.
Definition application.hpp:541
void _initCommandPool()
allocate the command pool for the application
vk::Image _createImage(uint32_t wid, uint32_t ht, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::ImageLayout layout, uint32_t mipLvls=1)
A helper function for creating a Vulkan image that can be used for textures or depth buffers.
static std::vector< vk::ExtensionProperties > supportedExtensions()
Get the list of supported Vulkan instance extensions.
Definition application.hpp:63
vk::Format _findBestFormat(std::vector< vk::Format > candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features)
A helper function to identify the best image format supported by the device from an ordered list of c...
bool _getQIndices(vk::PhysicalDevice dev)
A helper function to identify the queue-family indices for the physical device that we are using.
vk::DeviceMemory _allocImageMemory(vk::Image img, vk::MemoryPropertyFlags props)
A helper function for allocating and binding device memory for an image.
Frame-buffer attachments for off-screen rendering support.
Definition attachment.hpp:23
A base class for buffer objects of all kinds.
Definition buffer.hpp:23
Depth-buffer attachment for off-screen rendering.
Definition attachment.hpp:66
Definition depth-buffer.hpp:26
wrapper around Vulkan memory objects
Definition memory-obj.hpp:23
Definition shader.hpp:25
Definition texture.hpp:76
Definition texture.hpp:87
abstract base class for simple GLFW windows used to view buffers, etc.
Definition window.hpp:69
Definition aabb.hpp:22
information about queue families
Definition application.hpp:416
T compute
the queue family that supports compute
Definition application.hpp:419
T present
the queue family that supports presentation
Definition application.hpp:418
T graphics
the queue family that supports graphics
Definition application.hpp:417
Definition application.hpp:110
vk::SamplerAddressMode addressModeU
Definition application.hpp:114
SamplerInfo(vk::Filter magF, vk::Filter minF, vk::SamplerMipmapMode mm, vk::SamplerAddressMode am1, vk::SamplerAddressMode am2, vk::BorderColor color)
sampler info for 2D texture
Definition application.hpp:138
vk::SamplerMipmapMode mipmapMode
Definition application.hpp:113
vk::BorderColor borderColor
Definition application.hpp:117
vk::SamplerAddressMode addressModeW
Definition application.hpp:116
SamplerInfo(vk::Filter magF, vk::Filter minF, vk::SamplerMipmapMode mm, vk::SamplerAddressMode am, vk::BorderColor color)
sampler info for 1D texture
Definition application.hpp:129
vk::Filter magFilter
Definition application.hpp:111
SamplerInfo()
Definition application.hpp:119
vk::SamplerAddressMode addressModeV
Definition application.hpp:115
vk::Filter minFilter
Definition application.hpp:112
Definition application.hpp:428
std::vector< vk::SurfaceFormatKHR > formats
Definition application.hpp:430
vk::SurfaceCapabilitiesKHR capabilities
Definition application.hpp:429
std::vector< vk::PresentModeKHR > presentModes
Definition application.hpp:431