add image sampler

feature/softbody-runtime-control
Benjamin Kraft 3 months ago
parent a2af8b14f4
commit 247c8cb9fa
  1. 4
      include/vulkan/image.hpp
  2. 1
      src/application.cpp
  3. 18
      src/vulkan/buffer.cpp
  4. 77
      src/vulkan/image.cpp

@ -14,9 +14,13 @@ public:
~Image();
VkImageView createView(VkImageAspectFlags aspectFlags);
VkSampler createSampler();
VkImage handle = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
VkSampler sampler = VK_NULL_HANDLE;
uint32_t width;
uint32_t height;
private:
VkFormat format;
void transitionLayout(VkImageLayout oldLayout, VkImageLayout newLayout);

@ -107,6 +107,7 @@ Application::Application() {
u_char* data = new u_char[imageSize];
memset(data, 0xFF, imageSize);
Image image(data, imageSize, w, h, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
image.createSampler();
}
descriptorPool->bindBuffer(*cameraUniformBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorSet::WORLD, 0);

@ -53,7 +53,25 @@ void Buffer::copyTo(Buffer *buffer) {
}
void Buffer::copyTo(Image *image) {
VkQueue queue = Instance::instance->graphicsAndPresentQueue;
CommandPool* commandPool = Instance::instance->renderingCommandPool;
VkCommandBuffer commandBuffer = commandPool->beginSingleTimeCommandBuffer();
VkBufferImageCopy region {};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageOffset = {0, 0, 0};
region.imageExtent = {image->width, image->height, 1};
region.imageSubresource.layerCount = 1;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vkCmdCopyBufferToImage(commandBuffer, handle, image->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
commandPool->endSingleTimeCommandBuffer(commandBuffer, queue);
}
void Buffer::setName(const std::string &name) {

@ -1,10 +1,10 @@
#include "vulkan/image.hpp"
#include "vulkan/instance.hpp"
#include "vulkan/buffer.hpp"
#include "vulkan/command_pool.hpp"
Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage) : format(format) {
VkImageUsageFlags usage) : format(format), width(width), height(height) {
VkImageCreateInfo imageCreateInfo {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@ -30,14 +30,20 @@ Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling til
Image::Image(void *initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage) : Image(width, height, format, tiling, usage){
Buffer stagingBuffer(size, initialData, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0);
transitionLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
stagingBuffer.copyTo(this);
transitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
Image::~Image() {
if (view)
vkDestroyImageView(Instance::GetDevice(), view, nullptr);
if (sampler)
vkDestroySampler(Instance::GetDevice(), sampler, nullptr);
vmaDestroyImage(Instance::GetAllocator(), handle, allocation);
}
@ -61,6 +67,73 @@ VkImageView Image::createView(VkImageAspectFlags aspectFlags) {
return view;
}
VkSampler Image::createSampler() {
VkSamplerCreateInfo samplerInfo {};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0;
samplerInfo.maxLod = 0.0;
vkCreateSampler(Instance::GetDevice(), &samplerInfo, nullptr, &sampler);
return sampler;
}
void Image::transitionLayout(VkImageLayout oldLayout, VkImageLayout newLayout) {
auto commandPool = Instance::instance->renderingCommandPool;
auto commandBuffer = commandPool->beginSingleTimeCommandBuffer();
VkImageMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = handle;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.layerCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
VkPipelineStageFlags sourceStage = 0;
VkPipelineStageFlags destinationStage = 0;
if ((oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL){
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL){
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
vkCmdPipelineBarrier(commandBuffer,
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier);
commandPool->endSingleTimeCommandBuffer(commandBuffer, Instance::instance->graphicsAndPresentQueue);
}

Loading…
Cancel
Save