|
9 | 9 | bool Renderer::createComputePipeline() { |
10 | 10 | try { |
11 | 11 | // Read compute shader code |
12 | | - auto computeShaderCode = readFile("shaders/compute.spv"); |
| 12 | + auto computeShaderCode = readFile("shaders/hrtf.spv"); |
13 | 13 |
|
14 | 14 | // Create shader module |
15 | 15 | vk::raii::ShaderModule computeShaderModule = createShaderModule(computeShaderCode); |
@@ -99,18 +99,38 @@ bool Renderer::createComputePipeline() { |
99 | 99 |
|
100 | 100 | computeDescriptorPool = vk::raii::DescriptorPool(device, poolInfo); |
101 | 101 |
|
102 | | - return true; |
| 102 | + return createComputeCommandPool(); |
103 | 103 | } catch (const std::exception& e) { |
104 | 104 | std::cerr << "Failed to create compute pipeline: " << e.what() << std::endl; |
105 | 105 | return false; |
106 | 106 | } |
107 | 107 | } |
108 | 108 |
|
| 109 | +// Create compute command pool |
| 110 | +bool Renderer::createComputeCommandPool() { |
| 111 | + try { |
| 112 | + vk::CommandPoolCreateInfo poolInfo{ |
| 113 | + .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, |
| 114 | + .queueFamilyIndex = queueFamilyIndices.computeFamily.value() |
| 115 | + }; |
| 116 | + |
| 117 | + computeCommandPool = vk::raii::CommandPool(device, poolInfo); |
| 118 | + return true; |
| 119 | + } catch (const std::exception& e) { |
| 120 | + std::cerr << "Failed to create compute command pool: " << e.what() << std::endl; |
| 121 | + return false; |
| 122 | + } |
| 123 | +} |
| 124 | + |
109 | 125 | // Dispatch compute shader |
110 | | -void Renderer::DispatchCompute(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, |
111 | | - vk::Buffer inputBuffer, vk::Buffer outputBuffer, |
112 | | - vk::Buffer hrtfBuffer, vk::Buffer paramsBuffer) { |
| 126 | +vk::raii::Fence Renderer::DispatchCompute(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, |
| 127 | + vk::Buffer inputBuffer, vk::Buffer outputBuffer, |
| 128 | + vk::Buffer hrtfBuffer, vk::Buffer paramsBuffer) { |
113 | 129 | try { |
| 130 | + // Create fence for synchronization |
| 131 | + vk::FenceCreateInfo fenceInfo{}; |
| 132 | + vk::raii::Fence computeFence(device, fenceInfo); |
| 133 | + |
114 | 134 | // Create descriptor sets |
115 | 135 | vk::DescriptorSetAllocateInfo allocInfo{ |
116 | 136 | .descriptorPool = *computeDescriptorPool, |
@@ -182,47 +202,62 @@ void Renderer::DispatchCompute(uint32_t groupCountX, uint32_t groupCountY, uint3 |
182 | 202 |
|
183 | 203 | device.updateDescriptorSets(descriptorWrites, {}); |
184 | 204 |
|
185 | | - // Create command buffer |
| 205 | + // Create command buffer using dedicated compute command pool |
186 | 206 | vk::CommandBufferAllocateInfo cmdAllocInfo{ |
187 | | - .commandPool = *commandPool, |
| 207 | + .commandPool = *computeCommandPool, |
188 | 208 | .level = vk::CommandBufferLevel::ePrimary, |
189 | 209 | .commandBufferCount = 1 |
190 | 210 | }; |
191 | 211 |
|
192 | 212 | auto commandBuffers = device.allocateCommandBuffers(cmdAllocInfo); |
193 | | - vk::CommandBuffer cmdBuffer = commandBuffers[0]; |
194 | | - vk::raii::CommandBuffer commandBuffer(device, cmdBuffer, *commandPool); |
| 213 | + // Use RAII wrapper temporarily for recording to preserve dispatch loader |
| 214 | + vk::raii::CommandBuffer commandBufferRaii = std::move(commandBuffers[0]); |
195 | 215 |
|
196 | 216 | // Begin command buffer |
197 | 217 | vk::CommandBufferBeginInfo beginInfo{ |
198 | 218 | .flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit |
199 | 219 | }; |
200 | 220 |
|
201 | | - commandBuffer.begin(beginInfo); |
| 221 | + commandBufferRaii.begin(beginInfo); |
202 | 222 |
|
203 | 223 | // Bind compute pipeline |
204 | | - commandBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, *computePipeline); |
| 224 | + commandBufferRaii.bindPipeline(vk::PipelineBindPoint::eCompute, *computePipeline); |
205 | 225 |
|
206 | | - // Bind descriptor sets |
207 | | - commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eCompute, *computePipelineLayout, 0, reinterpret_cast<std::vector<vk::DescriptorSet> &>(computeDescriptorSets), {}); |
| 226 | + // Bind descriptor sets - properly convert RAII descriptor set to regular descriptor set |
| 227 | + std::vector<vk::DescriptorSet> descriptorSetsToBindRaw; |
| 228 | + descriptorSetsToBindRaw.reserve(1); |
| 229 | + descriptorSetsToBindRaw.push_back(*computeDescriptorSets[0]); |
| 230 | + commandBufferRaii.bindDescriptorSets(vk::PipelineBindPoint::eCompute, *computePipelineLayout, 0, descriptorSetsToBindRaw, {}); |
208 | 231 |
|
209 | 232 | // Dispatch compute shader |
210 | | - commandBuffer.dispatch(groupCountX, groupCountY, groupCountZ); |
| 233 | + commandBufferRaii.dispatch(groupCountX, groupCountY, groupCountZ); |
211 | 234 |
|
212 | 235 | // End command buffer |
213 | | - commandBuffer.end(); |
| 236 | + commandBufferRaii.end(); |
| 237 | + |
| 238 | + // Extract raw command buffer for submission and release RAII ownership |
| 239 | + // This prevents premature destruction while preserving the recorded commands |
| 240 | + vk::CommandBuffer rawCommandBuffer = *commandBufferRaii; |
| 241 | + commandBufferRaii.release(); // Release RAII ownership to prevent destruction |
214 | 242 |
|
215 | | - // Submit command buffer |
| 243 | + // Submit command buffer with fence for synchronization |
216 | 244 | vk::SubmitInfo submitInfo{ |
217 | 245 | .commandBufferCount = 1, |
218 | | - .pCommandBuffers = &*commandBuffer |
| 246 | + .pCommandBuffers = &rawCommandBuffer |
219 | 247 | }; |
220 | 248 |
|
221 | | - computeQueue.submit(submitInfo, nullptr); |
| 249 | + // Use mutex to ensure thread-safe access to compute queue |
| 250 | + { |
| 251 | + std::lock_guard<std::mutex> lock(queueMutex); |
| 252 | + computeQueue.submit(submitInfo, *computeFence); |
| 253 | + } |
222 | 254 |
|
223 | | - // Wait for compute to complete |
224 | | - computeQueue.waitIdle(); |
| 255 | + // Return fence for non-blocking synchronization |
| 256 | + return computeFence; |
225 | 257 | } catch (const std::exception& e) { |
226 | 258 | std::cerr << "Failed to dispatch compute shader: " << e.what() << std::endl; |
| 259 | + // Return a null fence on error |
| 260 | + vk::FenceCreateInfo fenceInfo{}; |
| 261 | + return vk::raii::Fence(device, fenceInfo); |
227 | 262 | } |
228 | 263 | } |
0 commit comments