Я создал этот GLSL Compute Shader и скомпилировал его, используя "glslangValidator.exe".Тем не менее, он будет обновлять только значения «Particles [i] .Velocity», а не любые другие значения, и это происходит только в некоторых случаях.Я проверил, что правильные входные значения передаются с использованием «RenderDoc».
Биты флага использования буфера
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |VK_BUFFER_USAGE_TRANSFER_DST_BIT
и биты флага свойства
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
GLSL-шейдер
#version 450
#extension GL_ARB_separate_shader_objects : enable
struct Particle
{
vec3 Position;
vec3 Velocity;
vec3 IPosition;
vec3 IVelocity;
float LifeTime;
float ILifetime;
};
layout(binding = 0) buffer Source
{
Particle Particles[ ];
};
layout(binding = 1) uniform UBO
{
mat4 model;
mat4 view;
mat4 proj;
float time;
};
vec3 Gravity = vec3(0.0f,-0.98f,0.0f);
float dampeningFactor = 0.5;
void main(){
uint i = gl_GlobalInvocationID.x;
if(Particles[i].LifeTime > 0.0f){
Particles[i].Velocity = Particles[i].Velocity + Gravity * dampeningFactor * time;
Particles[i].Position = Particles[i].Position + Particles[i].Velocity * time;
Particles[i].LifeTime = Particles[i].LifeTime - time;
}else{
Particles[i].Velocity = Particles[i].IVelocity;
Particles[i].Position = Particles[i].IPosition;
Particles[i].LifeTime = Particles[i].ILifetime;
}
}
Привязка макета набора дескрипторов
VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[2] = {
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0 },
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0 }
};
Отправка команд
vkCmdDispatch(computeCommandBuffers, MAX_PARTICLES , 1, 1);
ОтправкаОчередь
VkSubmitInfo cSubmitInfo = {};
cSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
cSubmitInfo.commandBufferCount = 1;
cSubmitInfo.pCommandBuffers = &computeCommandBuffers;
if (vkQueueSubmit(computeQueue.getQueue(), 1, &cSubmitInfo, computeFence) != VK_SUCCESS) {
throw std::runtime_error("failed to submit compute command buffer!");
}
vkWaitForFences(device.getDevice(), 1, &computeFence, VK_TRUE, UINT64_MAX);
ОБНОВЛЕНИЕ: 13/05/2017 (дополнительная информация добавлена)
Определение структуры частиц в CPP
struct Particle {
glm::vec3 location;
glm::vec3 velocity;
glm::vec3 initLocation;
glm::vec3 initVelocity;
float lifeTime;
float initLifetime;
}
Отображение данныхв буфер хранения
void* data;
vkMapMemory(device.getDevice(), stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, particles, (size_t)bufferSize);
vkUnmapMemory(device.getDevice(), stagingBufferMemory);
copyBuffer(stagingBuffer, computeBuffer, bufferSize);
Функция копирования буфера (автор Александр Оверворде из vulkan-tutorial.com)
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
VkCommandBufferAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = commandPool.getCommandPool();
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(device.getDevice(), &allocInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
VkBufferCopy copyRegion = {};
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(graphicsQueue.getQueue(), 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(graphicsQueue.getQueue());
vkFreeCommandBuffers(device.getDevice(), commandPool.getCommandPool(), 1, &commandBuffer);
}