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 10 months 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