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"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!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> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>

167
VulkanTutorial1.0/ComputeAndGraphics.cpp

@ -85,9 +85,9 @@ void ComputeAndGraphics::initVulkan()
createImageViews(); createImageViews();
createRenderPass(); createRenderPass();
createDescriptorSetLayout(); createDescriptorSetLayout();
// createComputeDescriptorSetLayout(); createComputeDescriptorSetLayout();
createGraphicsPipeline(); createGraphicsPipeline();
// createComputePipeline(); createComputePipeline();
createCommandPool(); createCommandPool();
createDepthResources(); createDepthResources();
createFramebuffers(); createFramebuffers();
@ -96,14 +96,14 @@ void ComputeAndGraphics::initVulkan()
createTextureSampler(); createTextureSampler();
createVertexBuffer(); createVertexBuffer();
createIndexBuffer(); createIndexBuffer();
// createShaderStorageBuffers(); createShaderStorageBuffers();
createUniformBuffers(); createUniformBuffers();
createDescriptorPool(); createDescriptorPool();
// createComputeDescriptorPool(); createComputeDescriptorPool();
createDescriptorSets(); createDescriptorSets();
// createComputeDescriptorSets(); createComputeDescriptorSets();
createCommandBuffer(); createCommandBuffer();
// createComputeCommandBuffers(); createComputeCommandBuffers();
createSyncObjects(); createSyncObjects();
} }
@ -651,9 +651,9 @@ void ComputeAndGraphics::createDescriptorSetLayout() {
void ComputeAndGraphics::createComputeDescriptorSetLayout() { void ComputeAndGraphics::createComputeDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding = createLayoutBindingInfo(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); 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}; std::vector<VkDescriptorSetLayoutBinding> bindings = {uboLayoutBinding, computeLayoutBinding1, computeLayoutBinding2};
VkDescriptorSetLayoutCreateInfo layoutInfo{}; VkDescriptorSetLayoutCreateInfo layoutInfo{};
@ -1022,6 +1022,9 @@ void ComputeAndGraphics::createTextureImage() {
int texWidth, texHeight, texChannels; int texWidth, texHeight, texChannels;
stbi_uc* pixels = stbi_load("/home/ali-mehrabani/Qt_projects/VkTest/textures/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); 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; VkDeviceSize imageSize = texWidth * texHeight * 4;
// qDebug() << imageSize;
// qDebug() << texWidth;
// qDebug() << texHeight;
if (!pixels) { if (!pixels) {
throw std::runtime_error("failed to load texture image!"); throw std::runtime_error("failed to load texture image!");
@ -1034,13 +1037,13 @@ void ComputeAndGraphics::createTextureImage() {
stbi_image_free(pixels); 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_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _textureImage, _textureImageMemory); , 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); // 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)); // 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_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
vkDestroyBuffer(_device, stagingBuffer, nullptr); vkDestroyBuffer(_device, stagingBuffer, nullptr);
vkFreeMemory(_device, stagingBufferMemory, nullptr); vkFreeMemory(_device, stagingBufferMemory, nullptr);
@ -1428,61 +1431,42 @@ uint32_t ComputeAndGraphics::findMemoryType(uint32_t typeFilter, VkMemoryPropert
} }
void ComputeAndGraphics::createShaderStorageBuffers() { 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; VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory; VkDeviceMemory stagingBufferMemory;
copyParticlesToStagingBuffer(stagingBuffer, stagingBufferMemory); copyImageToStagingBuffer(stagingBuffer, stagingBufferMemory, pixels, _textureImageSize);
initShaderStorageBuffers(stagingBuffer); initShaderStorageBuffers(stagingBuffer, _textureImageSize);
vkDestroyBuffer(_device, stagingBuffer, nullptr); vkDestroyBuffer(_device, stagingBuffer, nullptr);
vkFreeMemory(_device, stagingBufferMemory, nullptr); vkFreeMemory(_device, stagingBufferMemory, nullptr);
} }
void ComputeAndGraphics::initShaderStorageBuffers(VkBuffer& stagingBuffer) void ComputeAndGraphics::initShaderStorageBuffers(VkBuffer& stagingBuffer, VkDeviceSize bufferSize)
{ {
VkDeviceSize bufferSize = sizeof(Particle) * PARTICLE_COUNT; _shaderRawStorageBuffers.resize(MAX_FRAMES_IN_FLIGHT);
_shaderStorageBuffers.resize(MAX_FRAMES_IN_FLIGHT); _shaderRawStorageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
_shaderStorageBuffersMemory.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++) { 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 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, _shaderStorageBuffers[i], _shaderStorageBuffersMemory[i]); , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _shaderRawStorageBuffers[i], _shaderRawStorageBuffersMemory[i]);
copyBuffer(stagingBuffer, _shaderStorageBuffers[i], bufferSize); copyBuffer(stagingBuffer, _shaderRawStorageBuffers[i], bufferSize);
}
}
void ComputeAndGraphics::copyParticlesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory) 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]);
std::vector<Particle> particles = initParticles(); copyBuffer(stagingBuffer, _shaderTransformedStorageBuffers[i], bufferSize);
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);
}
return particles;
} }
void ComputeAndGraphics::createUniformBuffers() { void ComputeAndGraphics::createUniformBuffers() {
@ -1547,19 +1531,19 @@ void ComputeAndGraphics::createDescriptorSets()
std::array<VkWriteDescriptorSet, 2> descriptorWrites{}; 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); 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) , uint32_t dstBinding)
{ {
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = _descriptorSets[index]; descriptorWrite.dstSet = dstSet;
descriptorWrite.dstBinding = dstBinding; descriptorWrite.dstBinding = dstBinding;
descriptorWrite.dstArrayElement = 0; descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@ -1567,11 +1551,11 @@ void ComputeAndGraphics::addUniformBufferWriteDescriptor(VkWriteDescriptorSet& d
descriptorWrite.pBufferInfo = bufferInfo; 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) , uint32_t dstBinding)
{ {
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = _descriptorSets[index]; descriptorWrite.dstSet = dstSet;
descriptorWrite.dstBinding = dstBinding; descriptorWrite.dstBinding = dstBinding;
descriptorWrite.dstArrayElement = 0; descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
@ -1623,24 +1607,23 @@ void ComputeAndGraphics::createComputeDescriptorSets()
std::array<VkWriteDescriptorSet, 3> descriptorWrites{}; 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] VkDescriptorBufferInfo storageBufferInfoLastFrame = createDescriptorBufferInfo(_shaderRawStorageBuffers[i], _textureImageSize);
, sizeof(Particle) * PARTICLE_COUNT); addStorageBufferWriteDescriptor(descriptorWrites[1], &storageBufferInfoLastFrame, _computeDescriptorSets[i], 1);
addStorageBufferWriteDescriptor(descriptorWrites[1], &storageBufferInfoLastFrame, i, 1);
VkDescriptorBufferInfo storageBufferInfoCurrentFrame = createDescriptorBufferInfo(_shaderStorageBuffers[i], sizeof(Particle) * PARTICLE_COUNT); VkDescriptorBufferInfo storageBufferInfoCurrentFrame = createDescriptorBufferInfo(_shaderTransformedStorageBuffers[i], _textureImageSize);
addStorageBufferWriteDescriptor(descriptorWrites[2], &storageBufferInfoCurrentFrame, i, 2); addStorageBufferWriteDescriptor(descriptorWrites[2], &storageBufferInfoCurrentFrame, _computeDescriptorSets[i], 2);
vkUpdateDescriptorSets(_device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); 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) , uint32_t dstBinding)
{ {
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = _descriptorSets[index]; descriptorWrite.dstSet = dstSet;
descriptorWrite.dstBinding = dstBinding; descriptorWrite.dstBinding = dstBinding;
descriptorWrite.dstArrayElement = 0; descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 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.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
allocInfo.pSetLayouts = layouts.data(); allocInfo.pSetLayouts = layouts.data();
_descriptorSets.resize(MAX_FRAMES_IN_FLIGHT); _computeDescriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
if (vkAllocateDescriptorSets(_device, &allocInfo, _computeDescriptorSets.data()) != VK_SUCCESS) { if (vkAllocateDescriptorSets(_device, &allocInfo, _computeDescriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!"); throw std::runtime_error("failed to allocate descriptor sets!");
} }
@ -1733,7 +1716,9 @@ void ComputeAndGraphics::mainLoop()
} }
void ComputeAndGraphics::drawFrame(){ void ComputeAndGraphics::drawFrame(){
// computeSubmission(); computeSubmission();
copyTransformedBufferToTextureImage();
VkResult result = graphicsSubmission(); VkResult result = graphicsSubmission();
if (result == VK_ERROR_OUT_OF_DATE_KHR) if (result == VK_ERROR_OUT_OF_DATE_KHR)
@ -1744,12 +1729,17 @@ void ComputeAndGraphics::drawFrame(){
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; 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() void ComputeAndGraphics::computeSubmission()
{ {
vkWaitForFences(_device, 1, &_computeInFlightFences[currentFrame], VK_TRUE, UINT64_MAX); vkWaitForFences(_device, 1, &_computeInFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
updateUniformBuffer(currentFrame);
vkResetFences(_device, 1, &_computeInFlightFences[currentFrame]); vkResetFences(_device, 1, &_computeInFlightFences[currentFrame]);
vkResetCommandBuffer(_computeCommandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0); vkResetCommandBuffer(_computeCommandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
@ -1790,10 +1780,10 @@ VkResult ComputeAndGraphics::graphicsSubmission()
throw std::runtime_error("failed to acquire swap chain image!"); throw std::runtime_error("failed to acquire swap chain image!");
} }
// VkSemaphore waitSemaphores[] = {_computeFinishedSemaphores[currentFrame], _imageAvailableSemaphores[currentFrame]}; VkSemaphore waitSemaphores[] = {_computeFinishedSemaphores[currentFrame], _imageAvailableSemaphores[currentFrame]};
// VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSemaphore waitSemaphores[] = {_imageAvailableSemaphores[currentFrame]}; // VkSemaphore waitSemaphores[] = {_imageAvailableSemaphores[currentFrame]};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; // VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSemaphore signalSemaphores[] = {_renderFinishedSemaphores[currentFrame]}; VkSemaphore signalSemaphores[] = {_renderFinishedSemaphores[currentFrame]};
drawSubmission(imageIndex, waitSemaphores, waitStages, signalSemaphores); drawSubmission(imageIndex, waitSemaphores, waitStages, signalSemaphores);
@ -1825,7 +1815,7 @@ VkSubmitInfo ComputeAndGraphics::createDrawSubmitInfo(VkSemaphore* waitSemaphore
VkSubmitInfo submitInfo{}; VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1; submitInfo.waitSemaphoreCount = 2;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages; 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); 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) { if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to record compute command buffer!"); 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(); float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
UniformBufferObject ubo{}; UniformBufferObject ubo{};
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(22.5f), 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(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 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 = glm::perspective(glm::radians(45.0f), _swapChainExtent.width / static_cast<float>(_swapChainExtent.height), 0.1f, 10.0f);
ubo.proj[1][1] *= -1; ubo.proj[1][1] *= -1;
@ -2030,8 +2020,10 @@ void ComputeAndGraphics::cleanPipeline()
void ComputeAndGraphics::cleanBuffers() void ComputeAndGraphics::cleanBuffers()
{ {
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
vkDestroyBuffer(_device, _shaderStorageBuffers[i], nullptr); vkDestroyBuffer(_device, _shaderRawStorageBuffers[i], nullptr);
vkFreeMemory(_device, _shaderStorageBuffersMemory[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++) { for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
@ -2075,6 +2067,15 @@ void ComputeAndGraphics::cleanBase()
glfwTerminate(); glfwTerminate();
} }
void ComputeAndGraphics::cleanDescriptors()
{
vkDestroyDescriptorPool(_device, _descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _descriptorSetLayout, nullptr);
vkDestroyDescriptorPool(_device, _computeDescriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _computeDescriptorSetLayout, nullptr);
}
void ComputeAndGraphics::cleanup() void ComputeAndGraphics::cleanup()
{ {
cleanupSwapChain(); cleanupSwapChain();
@ -2085,9 +2086,7 @@ void ComputeAndGraphics::cleanup()
vkDestroyImage(_device, _textureImage, nullptr); vkDestroyImage(_device, _textureImage, nullptr);
vkFreeMemory(_device, _textureImageMemory, nullptr); vkFreeMemory(_device, _textureImageMemory, nullptr);
vkDestroyDescriptorPool(_device, _descriptorPool, nullptr); cleanDescriptors();
vkDestroyDescriptorSetLayout(_device, _descriptorSetLayout, nullptr);
cleanBuffers(); cleanBuffers();

60
VulkanTutorial1.0/ComputeAndGraphics.h

@ -29,39 +29,6 @@
const int MAX_FRAMES_IN_FLIGHT = 2; 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 { struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily; std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily; std::optional<uint32_t> presentFamily;
@ -269,19 +236,17 @@ private:
void copyIndicesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory); void copyIndicesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory);
void allocateAndBindBufferMemory(VkBuffer& buffer, VkDeviceMemory& bufferMemory, VkMemoryPropertyFlags properties); void allocateAndBindBufferMemory(VkBuffer& buffer, VkDeviceMemory& bufferMemory, VkMemoryPropertyFlags properties);
void copyParticlesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory);
std::vector<Particle> initParticles(); void initShaderStorageBuffers(VkBuffer& stagingBuffer, VkDeviceSize bufferSize);
void initShaderStorageBuffers(VkBuffer& stagingBuffer);
void allocateDescriptorSets(); void allocateDescriptorSets();
VkDescriptorBufferInfo createDescriptorBufferInfo(VkBuffer buffer, VkDeviceSize range); VkDescriptorBufferInfo createDescriptorBufferInfo(VkBuffer buffer, VkDeviceSize range);
VkDescriptorImageInfo createDescriptorImageInfo(); VkDescriptorImageInfo createDescriptorImageInfo();
void addUniformBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, size_t index, uint32_t dstBinding); void addUniformBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void addImageWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorImageInfo* imageInfo, size_t index, uint32_t dstBinding); void addImageWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorImageInfo* imageInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void allocateComputeDescriptorSets(); 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(); void computeSubmission();
VkSubmitInfo createComputeSubmitInfo(); VkSubmitInfo createComputeSubmitInfo();
@ -299,6 +264,9 @@ private:
void cleanBuffers(); void cleanBuffers();
void cleanSyncObjects(); void cleanSyncObjects();
void cleanBase(); void cleanBase();
void cleanDescriptors();
void copyTransformedBufferToTextureImage();
const int32_t WIDTH = 800; const int32_t WIDTH = 800;
const int32_t HEIGHT = 600; const int32_t HEIGHT = 600;
@ -363,6 +331,10 @@ private:
VkDescriptorPool _descriptorPool; VkDescriptorPool _descriptorPool;
std::vector<VkDescriptorSet> _descriptorSets; std::vector<VkDescriptorSet> _descriptorSets;
VkImage _RawTextureImage;
VkDeviceMemory _RawTextureImageMemory;
VkImageView _RawTextureImageView;
VkImage _textureImage; VkImage _textureImage;
VkDeviceMemory _textureImageMemory; VkDeviceMemory _textureImageMemory;
VkImageView _textureImageView; VkImageView _textureImageView;
@ -372,8 +344,14 @@ private:
VkDeviceMemory _depthImageMemory; VkDeviceMemory _depthImageMemory;
VkImageView _depthImageView; VkImageView _depthImageView;
std::vector<VkBuffer> _shaderStorageBuffers; std::vector<VkBuffer> _shaderRawStorageBuffers;
std::vector<VkDeviceMemory> _shaderStorageBuffersMemory; std::vector<VkDeviceMemory> _shaderRawStorageBuffersMemory;
std::vector<VkBuffer> _shaderTransformedStorageBuffers;
std::vector<VkDeviceMemory> _shaderTransformedStorageBuffersMemory;
VkDeviceSize _textureImageSize;
uint32_t _textureImageWidth;
uint32_t _textureImageHeight;
VkPipelineLayout _computePipelineLayout; VkPipelineLayout _computePipelineLayout;
VkPipeline _computePipeline; VkPipeline _computePipeline;
VkDescriptorSetLayout _computeDescriptorSetLayout; 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 #version 450
struct Particle {
vec2 position;
vec2 velocity;
vec4 color;
};
layout (binding = 0) uniform ParameterUBO { layout (binding = 0) uniform ParameterUBO {
float deltaTime; float deltaTime;
} ubo; } ubo;
layout(std140, binding = 2) readonly buffer ParticleSSBOIn { layout(std140, binding = 1) readonly buffer TexelSSBOIn {
Particle particlesIn[ ]; vec4 texelsIn[];
}; };
layout(std140, binding = 3) buffer ParticleSSBOOut { layout(std140, binding = 2) buffer TexelSSBOOut {
Particle particlesOut[ ]; 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() 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; float gray = dot(texelIn.rgb, vec3(0.2627, 0.6780, 0.0593));
particlesOut[index].velocity = particleIn.velocity; 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() { void main() {
gl_Position = vec4(inPosition, 1.0); gl_Position = vec4(inPosition, 1.0);
gl_Position = ubo.proj * ubo.view * ubo.model * 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_PointSize = 5.0;
// gl_Position = vec4(inPosition.xy, 1.0, 1.0); // gl_Position = vec4(inPosition.xy, 1.0, 1.0);

Loading…
Cancel
Save