Files
Destrum/destrum/include/destrum/Graphics/Util.h
T

228 lines
8.0 KiB
C++

#ifndef UTIL_H
#define UTIL_H
#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <optional>
#include <stdexcept>
#include <string>
#include <cassert>
#include <vulkan/vulkan.h>
#include "glm/vec4.hpp"
inline void checkVkResult(VkResult result, const char* expression, const char* file, int line)
{
if (result == VK_SUCCESS) {
return;
}
throw std::runtime_error(
std::string{"Vulkan call failed: "} + expression +
" returned " + std::to_string(static_cast<int>(result)) +
" at " + file + ":" + std::to_string(line));
}
#define VK_CHECK(call) \
do { \
const VkResult result_ = (call); \
checkVkResult(result_, #call, __FILE__, __LINE__); \
} while (0)
namespace vkutil {
struct CreateImageInfo {
VkFormat format;
VkImageUsageFlags usage;
VkImageCreateFlags flags;
VkExtent3D extent{};
std::uint32_t numLayers{1};
VkSampleCountFlagBits samples{VK_SAMPLE_COUNT_1_BIT};
VkImageTiling tiling{VK_IMAGE_TILING_OPTIMAL};
bool mipMap{false};
bool isCubemap{false};
};
void transitionImage(
VkCommandBuffer cmd,
VkImage image,
VkImageLayout currentLayout,
VkImageLayout newLayout);
void transitionImage(
VkCommandBuffer cmd,
VkImage image,
VkImageLayout currentLayout,
VkImageLayout newLayout,
const VkImageSubresourceRange& subresourceRange);
void copyImageToImage(
VkCommandBuffer cmd,
VkImage source,
VkImage destination,
VkExtent2D srcSize,
VkExtent2D dstSize,
VkFilter filter);
void copyImageToImage(
VkCommandBuffer cmd,
VkImage source,
VkImage destination,
VkExtent2D srcSize,
int destX,
int destY,
int destW,
int destH,
VkFilter filter);
void bufferHostWriteToShaderReadBarrier(
VkCommandBuffer cmd,
VkBuffer buffer,
VkDeviceSize offset = 0,
VkDeviceSize size = VK_WHOLE_SIZE);
void bufferHostWriteToTransferReadBarrier(
VkCommandBuffer cmd,
VkBuffer buffer,
VkDeviceSize offset = 0,
VkDeviceSize size = VK_WHOLE_SIZE);
// Object names (VK_EXT_debug_utils), shown in RenderDoc, Nsight and validation messages.
// All of these are no-ops when the extension isn't loaded.
void addDebugLabel(VkDevice device, VkObjectType objectType, std::uint64_t objectHandle, const char* label);
void addDebugLabel(VkDevice device, VkImage image, const char* label);
void addDebugLabel(VkDevice device, VkImageView imageView, const char* label);
void addDebugLabel(VkDevice device, VkShaderModule shaderModule, const char* label);
void addDebugLabel(VkDevice device, VkPipeline pipeline, const char* label);
void addDebugLabel(VkDevice device, VkPipelineLayout layout, const char* label);
void addDebugLabel(VkDevice device, VkBuffer buffer, const char* label);
void addDebugLabel(VkDevice device, VkSampler sampler, const char* label);
void addDebugLabel(VkDevice device, VkDescriptorPool descriptorPool, const char* label);
void addDebugLabel(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const char* label);
void addDebugLabel(VkDevice device, VkDescriptorSet descriptorSet, const char* label);
void addDebugLabel(VkDevice device, VkCommandPool commandPool, const char* label);
void addDebugLabel(VkDevice device, VkCommandBuffer commandBuffer, const char* label);
void addDebugLabel(VkDevice device, VkFence fence, const char* label);
void addDebugLabel(VkDevice device, VkSemaphore semaphore, const char* label);
void addDebugLabel(VkDevice device, VkQueue queue, const char* label);
// Command buffer regions, they nest like a stack: every begin needs a matching end
// in the same command buffer.
[[nodiscard]] bool debugLabelsEnabled();
void cmdBeginLabel(VkCommandBuffer cmd, const char* label, const glm::vec4& color = glm::vec4{1.0f});
void cmdEndLabel(VkCommandBuffer cmd);
void cmdInsertLabel(VkCommandBuffer cmd, const char* label, const glm::vec4& color = glm::vec4{1.0f});
// printf style, only formats when labels are actually recorded (cheap enough for per draw labels)
template <typename... Args>
void cmdBeginLabelFormatted(VkCommandBuffer cmd, const glm::vec4& color, const char* format, Args... args)
{
if (!debugLabelsEnabled()) {
return;
}
char label[256];
std::snprintf(label, sizeof(label), format, args...);
cmdBeginLabel(cmd, label, color);
}
class ScopedCmdLabel {
public:
ScopedCmdLabel(VkCommandBuffer cmd, const char* label, const glm::vec4& color = glm::vec4{1.0f});
~ScopedCmdLabel();
ScopedCmdLabel(const ScopedCmdLabel& other) = delete;
ScopedCmdLabel(ScopedCmdLabel&& other) noexcept = delete;
ScopedCmdLabel& operator=(const ScopedCmdLabel& other) = delete;
ScopedCmdLabel& operator=(ScopedCmdLabel&& other) noexcept = delete;
private:
VkCommandBuffer cmd{VK_NULL_HANDLE};
};
// Colors used for the renderer's labels, so passes are easy to tell apart in a capture
namespace labelColors {
inline const glm::vec4 frame{0.8f, 0.8f, 0.8f, 1.0f};
inline const glm::vec4 compute{0.9f, 0.5f, 0.1f, 1.0f};
inline const glm::vec4 shadow{0.3f, 0.3f, 0.6f, 1.0f};
inline const glm::vec4 depth{0.4f, 0.4f, 0.4f, 1.0f};
inline const glm::vec4 opaque{0.2f, 0.7f, 0.3f, 1.0f};
inline const glm::vec4 sky{0.3f, 0.6f, 0.9f, 1.0f};
inline const glm::vec4 debug{0.9f, 0.2f, 0.6f, 1.0f};
inline const glm::vec4 ui{0.9f, 0.9f, 0.2f, 1.0f};
inline const glm::vec4 transfer{0.6f, 0.4f, 0.2f, 1.0f};
inline const glm::vec4 draw{0.5f, 0.8f, 0.5f, 1.0f};
}
struct RenderingInfoParams {
VkExtent2D renderExtent;
VkImageView colorImageView{VK_NULL_HANDLE};
std::optional<glm::vec4> colorImageClearValue;
VkImageView depthImageView{VK_NULL_HANDLE};
std::optional<float> depthImageClearValue;
};
struct RenderInfo {
VkRenderingAttachmentInfo colorAttachment{};
VkRenderingAttachmentInfo depthAttachment{};
VkRenderingInfo renderingInfo{};
RenderInfo() = default;
RenderInfo(const RenderInfo& other)
: colorAttachment(other.colorAttachment),
depthAttachment(other.depthAttachment),
renderingInfo(other.renderingInfo)
{
rebind();
}
RenderInfo& operator=(const RenderInfo& other)
{
if (this != &other) {
colorAttachment = other.colorAttachment;
depthAttachment = other.depthAttachment;
renderingInfo = other.renderingInfo;
rebind();
}
return *this;
}
RenderInfo(RenderInfo&& other) noexcept
: colorAttachment(other.colorAttachment),
depthAttachment(other.depthAttachment),
renderingInfo(other.renderingInfo)
{
rebind();
}
RenderInfo& operator=(RenderInfo&& other) noexcept
{
if (this != &other) {
colorAttachment = other.colorAttachment;
depthAttachment = other.depthAttachment;
renderingInfo = other.renderingInfo;
rebind();
}
return *this;
}
void rebind()
{
renderingInfo.pColorAttachments = renderingInfo.colorAttachmentCount != 0
? &colorAttachment
: nullptr;
renderingInfo.pDepthAttachment = renderingInfo.pDepthAttachment != nullptr
? &depthAttachment
: nullptr;
}
};
RenderInfo createRenderingInfo(const RenderingInfoParams& params);
VkShaderModule loadShaderModule(const std::filesystem::path& path, VkDevice device);
}
#endif //UTIL_H