Browse Source

Add grayscale image compute

Compute and graphics pipeline work to gether now. The output image isn't exactly grayscale, but it's something!
master
AliMehrabani 2 weeks ago
parent
commit
c2f0a45759
  1. 2
      VkTest.pro.user
  2. 167
      VulkanTutorial1.0/ComputeAndGraphics.cpp
  3. 60
      VulkanTutorial1.0/ComputeAndGraphics.h
  4. BIN
      shaders/VulkanTutorial1.0/ComputeAndGraphics/compComp.spv
  5. 24
      shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.comp
  6. 1
      shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.vert

2
VkTest.pro.user

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.10.1, 2024-11-10T17:06:43. -->
<!-- Written by QtCreator 4.10.1, 2024-11-12T19:33:00. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

167
VulkanTutorial1.0/ComputeAndGraphics.cpp

@ -85,9 +85,9 @@ void ComputeAndGraphics::initVulkan()
createImageViews();
createRenderPass();
createDescriptorSetLayout();
// createComputeDescriptorSetLayout();
createComputeDescriptorSetLayout();
createGraphicsPipeline();
// createComputePipeline();
createComputePipeline();
createCommandPool();
createDepthResources();
createFramebuffers();
@ -96,14 +96,14 @@ void ComputeAndGraphics::initVulkan()
createTextureSampler();
createVertexBuffer();
createIndexBuffer();
// createShaderStorageBuffers();
createShaderStorageBuffers();
createUniformBuffers();
createDescriptorPool();
// createComputeDescriptorPool();
createComputeDescriptorPool();
createDescriptorSets();
// createComputeDescriptorSets();
createComputeDescriptorSets();
createCommandBuffer();
// createComputeCommandBuffers();
createComputeCommandBuffers();
createSyncObjects();
}
@ -651,9 +651,9 @@ void ComputeAndGraphics::createDescriptorSetLayout() {
void ComputeAndGraphics::createComputeDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding = createLayoutBindingInfo(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
VkDescriptorSetLayoutBinding computeLayoutBinding1 = createLayoutBindingInfo(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
VkDescriptorSetLayoutBinding computeLayoutBinding1 = createLayoutBindingInfo(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
VkDescriptorSetLayoutBinding computeLayoutBinding2 = createLayoutBindingInfo(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
VkDescriptorSetLayoutBinding computeLayoutBinding2 = createLayoutBindingInfo(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
std::vector<VkDescriptorSetLayoutBinding> bindings = {uboLayoutBinding, computeLayoutBinding1, computeLayoutBinding2};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
@ -1022,6 +1022,9 @@ void ComputeAndGraphics::createTextureImage() {
int texWidth, texHeight, texChannels;
stbi_uc* pixels = stbi_load("/home/ali-mehrabani/Qt_projects/VkTest/textures/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
VkDeviceSize imageSize = texWidth * texHeight * 4;
// qDebug() << imageSize;
// qDebug() << texWidth;
// qDebug() << texHeight;
if (!pixels) {
throw std::runtime_error("failed to load texture image!");
@ -1034,13 +1037,13 @@ void ComputeAndGraphics::createTextureImage() {
stbi_image_free(pixels);
createImage(texWidth, texHeight, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL
createImage(texWidth, texHeight, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_LINEAR
, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _textureImage, _textureImageMemory);
transitionImageLayout(_textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1);
copyBufferToImage(stagingBuffer, _textureImage, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));
transitionImageLayout(_textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
// transitionImageLayout(_textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1);
// copyBufferToImage(stagingBuffer, _textureImage, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));
// transitionImageLayout(_textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
vkDestroyBuffer(_device, stagingBuffer, nullptr);
vkFreeMemory(_device, stagingBufferMemory, nullptr);
@ -1428,61 +1431,42 @@ uint32_t ComputeAndGraphics::findMemoryType(uint32_t typeFilter, VkMemoryPropert
}
void ComputeAndGraphics::createShaderStorageBuffers() {
int texWidth, texHeight, texChannels;
stbi_uc* pixels = stbi_load("/home/ali-mehrabani/Qt_projects/VkTest/textures/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
_textureImageSize = texWidth * texHeight * 4;
_textureImageWidth = texWidth;
_textureImageHeight = texHeight;
if (!pixels) {
throw std::runtime_error("failed to load texture image!");
}
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
copyParticlesToStagingBuffer(stagingBuffer, stagingBufferMemory);
copyImageToStagingBuffer(stagingBuffer, stagingBufferMemory, pixels, _textureImageSize);
initShaderStorageBuffers(stagingBuffer);
initShaderStorageBuffers(stagingBuffer, _textureImageSize);
vkDestroyBuffer(_device, stagingBuffer, nullptr);
vkFreeMemory(_device, stagingBufferMemory, nullptr);
}
void ComputeAndGraphics::initShaderStorageBuffers(VkBuffer& stagingBuffer)
void ComputeAndGraphics::initShaderStorageBuffers(VkBuffer& stagingBuffer, VkDeviceSize bufferSize)
{
VkDeviceSize bufferSize = sizeof(Particle) * PARTICLE_COUNT;
_shaderStorageBuffers.resize(MAX_FRAMES_IN_FLIGHT);
_shaderStorageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
_shaderRawStorageBuffers.resize(MAX_FRAMES_IN_FLIGHT);
_shaderRawStorageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
_shaderTransformedStorageBuffers.resize(MAX_FRAMES_IN_FLIGHT);
_shaderTransformedStorageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _shaderStorageBuffers[i], _shaderStorageBuffersMemory[i]);
copyBuffer(stagingBuffer, _shaderStorageBuffers[i], bufferSize);
}
}
createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _shaderRawStorageBuffers[i], _shaderRawStorageBuffersMemory[i]);
copyBuffer(stagingBuffer, _shaderRawStorageBuffers[i], bufferSize);
void ComputeAndGraphics::copyParticlesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory)
{
std::vector<Particle> particles = initParticles();
VkDeviceSize bufferSize = sizeof(Particle) * PARTICLE_COUNT;
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(_device, stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, particles.data(), reinterpret_cast<size_t>(bufferSize));
vkUnmapMemory(_device, stagingBufferMemory);
}
std::vector<Particle> ComputeAndGraphics::initParticles()
{
std::default_random_engine rndEngine(static_cast<unsigned>(time(nullptr)));
std::uniform_real_distribution<float> rndDist(0.0f, 1.0f);
std::vector<Particle> particles(PARTICLE_COUNT);
for (auto& particle : particles) {
float r = 0.25f * sqrt(rndDist(rndEngine));
float theta = rndDist(rndEngine) * 2.0f * 3.14159265358979323846f;
float x = r * cos(theta) * HEIGHT / WIDTH;
float y = r * sin(theta);
particle.position = glm::vec2(x, y);
particle.velocity = glm::normalize(glm::vec2(x,y)) * 0.00025f;
particle.color = glm::vec4(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine), 1.0f);
createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _shaderTransformedStorageBuffers[i], _shaderTransformedStorageBuffersMemory[i]);
copyBuffer(stagingBuffer, _shaderTransformedStorageBuffers[i], bufferSize);
}
return particles;
}
void ComputeAndGraphics::createUniformBuffers() {
@ -1547,19 +1531,19 @@ void ComputeAndGraphics::createDescriptorSets()
std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
addUniformBufferWriteDescriptor(descriptorWrites[0], &bufferInfo, i, 0);
addUniformBufferWriteDescriptor(descriptorWrites[0], &bufferInfo, _descriptorSets[i], 0);
addImageWriteDescriptor(descriptorWrites[1], &imageInfo, i, 1);
addImageWriteDescriptor(descriptorWrites[1], &imageInfo, _descriptorSets[i], 1);
vkUpdateDescriptorSets(_device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
}
}
void ComputeAndGraphics::addUniformBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, size_t index
void ComputeAndGraphics::addUniformBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, VkDescriptorSet dstSet
, uint32_t dstBinding)
{
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = _descriptorSets[index];
descriptorWrite.dstSet = dstSet;
descriptorWrite.dstBinding = dstBinding;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@ -1567,11 +1551,11 @@ void ComputeAndGraphics::addUniformBufferWriteDescriptor(VkWriteDescriptorSet& d
descriptorWrite.pBufferInfo = bufferInfo;
}
void ComputeAndGraphics::addImageWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorImageInfo* imageInfo, size_t index
void ComputeAndGraphics::addImageWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorImageInfo* imageInfo, VkDescriptorSet dstSet
, uint32_t dstBinding)
{
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = _descriptorSets[index];
descriptorWrite.dstSet = dstSet;
descriptorWrite.dstBinding = dstBinding;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
@ -1623,24 +1607,23 @@ void ComputeAndGraphics::createComputeDescriptorSets()
std::array<VkWriteDescriptorSet, 3> descriptorWrites{};
addUniformBufferWriteDescriptor(descriptorWrites[0], &bufferInfo, i, 0);
addUniformBufferWriteDescriptor(descriptorWrites[0], &bufferInfo, _computeDescriptorSets[i], 0);
VkDescriptorBufferInfo storageBufferInfoLastFrame = createDescriptorBufferInfo(_shaderStorageBuffers[(i - 1) % MAX_FRAMES_IN_FLIGHT]
, sizeof(Particle) * PARTICLE_COUNT);
addStorageBufferWriteDescriptor(descriptorWrites[1], &storageBufferInfoLastFrame, i, 1);
VkDescriptorBufferInfo storageBufferInfoLastFrame = createDescriptorBufferInfo(_shaderRawStorageBuffers[i], _textureImageSize);
addStorageBufferWriteDescriptor(descriptorWrites[1], &storageBufferInfoLastFrame, _computeDescriptorSets[i], 1);
VkDescriptorBufferInfo storageBufferInfoCurrentFrame = createDescriptorBufferInfo(_shaderStorageBuffers[i], sizeof(Particle) * PARTICLE_COUNT);
addStorageBufferWriteDescriptor(descriptorWrites[2], &storageBufferInfoCurrentFrame, i, 2);
VkDescriptorBufferInfo storageBufferInfoCurrentFrame = createDescriptorBufferInfo(_shaderTransformedStorageBuffers[i], _textureImageSize);
addStorageBufferWriteDescriptor(descriptorWrites[2], &storageBufferInfoCurrentFrame, _computeDescriptorSets[i], 2);
vkUpdateDescriptorSets(_device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
}
}
void ComputeAndGraphics::addStorageBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, size_t index
void ComputeAndGraphics::addStorageBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, VkDescriptorSet dstSet
, uint32_t dstBinding)
{
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = _descriptorSets[index];
descriptorWrite.dstSet = dstSet;
descriptorWrite.dstBinding = dstBinding;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
@ -1657,7 +1640,7 @@ void ComputeAndGraphics::allocateComputeDescriptorSets()
allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
allocInfo.pSetLayouts = layouts.data();
_descriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
_computeDescriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
if (vkAllocateDescriptorSets(_device, &allocInfo, _computeDescriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!");
}
@ -1733,7 +1716,9 @@ void ComputeAndGraphics::mainLoop()
}
void ComputeAndGraphics::drawFrame(){
// computeSubmission();
computeSubmission();
copyTransformedBufferToTextureImage();
VkResult result = graphicsSubmission();
if (result == VK_ERROR_OUT_OF_DATE_KHR)
@ -1744,12 +1729,17 @@ void ComputeAndGraphics::drawFrame(){
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
void ComputeAndGraphics::copyTransformedBufferToTextureImage()
{
transitionImageLayout(_textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1);
copyBufferToImage(_shaderTransformedStorageBuffers[currentFrame], _textureImage, _textureImageWidth, _textureImageHeight);
transitionImageLayout(_textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
}
void ComputeAndGraphics::computeSubmission()
{
vkWaitForFences(_device, 1, &_computeInFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
updateUniformBuffer(currentFrame);
vkResetFences(_device, 1, &_computeInFlightFences[currentFrame]);
vkResetCommandBuffer(_computeCommandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
@ -1790,10 +1780,10 @@ VkResult ComputeAndGraphics::graphicsSubmission()
throw std::runtime_error("failed to acquire swap chain image!");
}
// VkSemaphore waitSemaphores[] = {_computeFinishedSemaphores[currentFrame], _imageAvailableSemaphores[currentFrame]};
// VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSemaphore waitSemaphores[] = {_imageAvailableSemaphores[currentFrame]};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSemaphore waitSemaphores[] = {_computeFinishedSemaphores[currentFrame], _imageAvailableSemaphores[currentFrame]};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
// VkSemaphore waitSemaphores[] = {_imageAvailableSemaphores[currentFrame]};
// VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSemaphore signalSemaphores[] = {_renderFinishedSemaphores[currentFrame]};
drawSubmission(imageIndex, waitSemaphores, waitStages, signalSemaphores);
@ -1825,7 +1815,7 @@ VkSubmitInfo ComputeAndGraphics::createDrawSubmitInfo(VkSemaphore* waitSemaphore
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;
submitInfo.waitSemaphoreCount = 2;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
@ -1958,7 +1948,7 @@ void ComputeAndGraphics::recordComputeCommandBuffer(VkCommandBuffer commandBuffe
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, _computePipelineLayout, 0, 1, &_computeDescriptorSets[currentFrame], 0, nullptr);
vkCmdDispatch(commandBuffer, PARTICLE_COUNT / 256, 1, 1);
vkCmdDispatch(commandBuffer, static_cast<uint32_t>(_textureImageSize / 8), 1, 1);
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to record compute command buffer!");
@ -1973,8 +1963,8 @@ void ComputeAndGraphics::updateUniformBuffer(uint32_t currentImage) {
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
UniformBufferObject ubo{};
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(22.5f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.model = glm::rotate(glm::mat4(1.0f), glm::radians(0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(glm::vec3(0.001f, 0.001f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.proj = glm::perspective(glm::radians(45.0f), _swapChainExtent.width / static_cast<float>(_swapChainExtent.height), 0.1f, 10.0f);
ubo.proj[1][1] *= -1;
@ -2030,8 +2020,10 @@ void ComputeAndGraphics::cleanPipeline()
void ComputeAndGraphics::cleanBuffers()
{
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
vkDestroyBuffer(_device, _shaderStorageBuffers[i], nullptr);
vkFreeMemory(_device, _shaderStorageBuffersMemory[i], nullptr);
vkDestroyBuffer(_device, _shaderRawStorageBuffers[i], nullptr);
vkFreeMemory(_device, _shaderRawStorageBuffersMemory[i], nullptr);
vkDestroyBuffer(_device, _shaderTransformedStorageBuffers[i], nullptr);
vkFreeMemory(_device, _shaderTransformedStorageBuffersMemory[i], nullptr);
}
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
@ -2075,6 +2067,15 @@ void ComputeAndGraphics::cleanBase()
glfwTerminate();
}
void ComputeAndGraphics::cleanDescriptors()
{
vkDestroyDescriptorPool(_device, _descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _descriptorSetLayout, nullptr);
vkDestroyDescriptorPool(_device, _computeDescriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _computeDescriptorSetLayout, nullptr);
}
void ComputeAndGraphics::cleanup()
{
cleanupSwapChain();
@ -2085,9 +2086,7 @@ void ComputeAndGraphics::cleanup()
vkDestroyImage(_device, _textureImage, nullptr);
vkFreeMemory(_device, _textureImageMemory, nullptr);
vkDestroyDescriptorPool(_device, _descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _descriptorSetLayout, nullptr);
cleanDescriptors();
cleanBuffers();

60
VulkanTutorial1.0/ComputeAndGraphics.h

@ -29,39 +29,6 @@
const int MAX_FRAMES_IN_FLIGHT = 2;
const uint32_t PARTICLE_COUNT = 8192;
struct Particle {
alignas(16) glm::vec2 position;
alignas(16) glm::vec2 velocity;
alignas(16) glm::vec4 color;
static VkVertexInputBindingDescription getBindingDescription() {
VkVertexInputBindingDescription bindingDescription{};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Particle);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return bindingDescription;
}
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Particle, position);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Particle, color);
return attributeDescriptions;
}
};
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
@ -269,19 +236,17 @@ private:
void copyIndicesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory);
void allocateAndBindBufferMemory(VkBuffer& buffer, VkDeviceMemory& bufferMemory, VkMemoryPropertyFlags properties);
void copyParticlesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory);
std::vector<Particle> initParticles();
void initShaderStorageBuffers(VkBuffer& stagingBuffer);
void initShaderStorageBuffers(VkBuffer& stagingBuffer, VkDeviceSize bufferSize);
void allocateDescriptorSets();
VkDescriptorBufferInfo createDescriptorBufferInfo(VkBuffer buffer, VkDeviceSize range);
VkDescriptorImageInfo createDescriptorImageInfo();
void addUniformBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, size_t index, uint32_t dstBinding);
void addImageWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorImageInfo* imageInfo, size_t index, uint32_t dstBinding);
void addUniformBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void addImageWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorImageInfo* imageInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void allocateComputeDescriptorSets();
void addStorageBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, size_t index, uint32_t dstBinding);
void addStorageBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void computeSubmission();
VkSubmitInfo createComputeSubmitInfo();
@ -299,6 +264,9 @@ private:
void cleanBuffers();
void cleanSyncObjects();
void cleanBase();
void cleanDescriptors();
void copyTransformedBufferToTextureImage();
const int32_t WIDTH = 800;
const int32_t HEIGHT = 600;
@ -363,6 +331,10 @@ private:
VkDescriptorPool _descriptorPool;
std::vector<VkDescriptorSet> _descriptorSets;
VkImage _RawTextureImage;
VkDeviceMemory _RawTextureImageMemory;
VkImageView _RawTextureImageView;
VkImage _textureImage;
VkDeviceMemory _textureImageMemory;
VkImageView _textureImageView;
@ -372,8 +344,14 @@ private:
VkDeviceMemory _depthImageMemory;
VkImageView _depthImageView;
std::vector<VkBuffer> _shaderStorageBuffers;
std::vector<VkDeviceMemory> _shaderStorageBuffersMemory;
std::vector<VkBuffer> _shaderRawStorageBuffers;
std::vector<VkDeviceMemory> _shaderRawStorageBuffersMemory;
std::vector<VkBuffer> _shaderTransformedStorageBuffers;
std::vector<VkDeviceMemory> _shaderTransformedStorageBuffersMemory;
VkDeviceSize _textureImageSize;
uint32_t _textureImageWidth;
uint32_t _textureImageHeight;
VkPipelineLayout _computePipelineLayout;
VkPipeline _computePipeline;
VkDescriptorSetLayout _computeDescriptorSetLayout;

BIN
shaders/VulkanTutorial1.0/ComputeAndGraphics/compComp.spv

Binary file not shown.

24
shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.comp

@ -1,32 +1,26 @@
#version 450
struct Particle {
vec2 position;
vec2 velocity;
vec4 color;
};
layout (binding = 0) uniform ParameterUBO {
float deltaTime;
} ubo;
layout(std140, binding = 2) readonly buffer ParticleSSBOIn {
Particle particlesIn[ ];
layout(std140, binding = 1) readonly buffer TexelSSBOIn {
vec4 texelsIn[];
};
layout(std140, binding = 3) buffer ParticleSSBOOut {
Particle particlesOut[ ];
layout(std140, binding = 2) buffer TexelSSBOOut {
vec4 texelsOut[];
};
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in;
void main()
{
uint index = gl_GlobalInvocationID.x;
uint idx = gl_GlobalInvocationID.x;
Particle particleIn = particlesIn[index];
vec4 texelIn = texelsIn[idx];
particlesOut[index].position = particleIn.position + particleIn.velocity.xy * ubo.deltaTime;
particlesOut[index].velocity = particleIn.velocity;
float gray = dot(texelIn.rgb, vec3(0.2627, 0.6780, 0.0593));
texelsOut[idx] = vec4(vec3(gray), 1.0);
}

1
shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.vert

@ -16,6 +16,7 @@ layout(location = 1) out vec2 fragTexCoord;
void main() {
gl_Position = vec4(inPosition, 1.0);
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
// gl_Position = vec4(inPosition, 1.0);
// gl_PointSize = 5.0;
// gl_Position = vec4(inPosition.xy, 1.0, 1.0);

Loading…
Cancel
Save