Vulkan 计算着色器不会在无限循环中停止
Vulkan compute shader not stalling on infinite loop
我正在尝试制作一个使我的程序停止的着色器:
#version 450
layout (local_size_x = 16, local_size_y = 16) in;
void main()
{
while(true) {}
}
我正在尝试像这样调用与着色器关联的管道:
static void GpuCompute(
EffectFramework& frame_work,
const std::string& shader_path)
{
auto& pipeline = frame_work.GetPipeline(shader_path);
auto h_interface = HardwareInterface::h_interface;
auto& device = h_interface->GetDevice();
auto& cmd_pool = h_interface->GetCommandPool();
auto& cmd_buffer = h_interface->GetCmdBufferTmp();
auto& queue = h_interface->GetQueue();
vk::CommandBufferAllocateInfo alloc_info(
cmd_pool, vk::CommandBufferLevel::ePrimary, 1);
auto [result, buffers] = device.allocateCommandBuffersUnique(alloc_info);
if(result != vk::Result::eSuccess)
Log::RecordLogError("Failed to create command buffers");
cmd_buffer = std::move(buffers[0]);
vk::CommandBufferBeginInfo begin_info(
vk::CommandBufferUsageFlagBits::eSimultaneousUse, nullptr);
vk::FenceCreateInfo fence_create_info = {};
fence_create_info.flags = {};
auto[result_f, fence] = device.createFenceUnique(fence_create_info);
if(result_f != vk::Result::eSuccess)
Log::RecordLogError("Failed to create compute fence");
result = cmd_buffer->begin(&begin_info);
if(result != vk::Result::eSuccess)
Log::RecordLogError("Failed to begin recording command buffer!");
_SetName(device, *cmd_buffer, "compute_cmd_buffer");
cmd_buffer->bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.GetPipeline());
cmd_buffer->dispatch(1920 / 16, 1440 / 16, 1);
cmd_buffer->end();
vk::SubmitInfo submit_info = {};
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &*cmd_buffer;
queue.submit(1, &submit_info, *fence);
device.waitForFences(1,
&*fence,
VK_TRUE,
std::numeric_limits<uint64_t>::max());
}
然而,当我 运行 我的程序时,它不会停止。我使用 renderdoc 来确保我正在调用着色器:
调度调用似乎使用了正确的着色器。
那么为什么我的代码 运行?它应该卡住计算该循环,直到宇宙热寂。
我知道它没有停滞的方式是,我也在调用计算着色器后在同一个队列和同一个威胁上渲染图形。据我了解,提交到同一队列的命令按顺序执行,因此该着色器应停止整个管道。但我仍然可以很好地与我的程序交互。
make a shader that stalls my program
当负责主要用户界面的设备停止响应时,您的操作系统和图形驱动程序不喜欢它。所述操作系统或所述图形驱动程序的用户也没有。因此,他们不允许你这样做。
任何为 "too long" 运行的着色器操作(无论它们如何定义)都将被毫不客气地终止。您的应用程序可能看起来只是继续执行,就好像分派执行到完成一样。或者您可能会丢失图形上下文。或者可能会发生硬 GPU 重置。
或者,您的着色器编译器可能只是检测到您的着色器没有可见的副作用(即:不写入任何内容),因此它完全优化了所有代码。死代码消除往往通过从着色器的输出向后工作来发挥作用。由于这是一个计算着色器,它的输出将写入 SSBO、imageStore
调用或原子更新。您的代码执行了其中的 none,因此其代码的 none 有任何输出,因此着色器不执行任何操作。
关键是,如果你想让你的 GPU 崩溃,你必须比这聪明得多。
我正在尝试制作一个使我的程序停止的着色器:
#version 450
layout (local_size_x = 16, local_size_y = 16) in;
void main()
{
while(true) {}
}
我正在尝试像这样调用与着色器关联的管道:
static void GpuCompute(
EffectFramework& frame_work,
const std::string& shader_path)
{
auto& pipeline = frame_work.GetPipeline(shader_path);
auto h_interface = HardwareInterface::h_interface;
auto& device = h_interface->GetDevice();
auto& cmd_pool = h_interface->GetCommandPool();
auto& cmd_buffer = h_interface->GetCmdBufferTmp();
auto& queue = h_interface->GetQueue();
vk::CommandBufferAllocateInfo alloc_info(
cmd_pool, vk::CommandBufferLevel::ePrimary, 1);
auto [result, buffers] = device.allocateCommandBuffersUnique(alloc_info);
if(result != vk::Result::eSuccess)
Log::RecordLogError("Failed to create command buffers");
cmd_buffer = std::move(buffers[0]);
vk::CommandBufferBeginInfo begin_info(
vk::CommandBufferUsageFlagBits::eSimultaneousUse, nullptr);
vk::FenceCreateInfo fence_create_info = {};
fence_create_info.flags = {};
auto[result_f, fence] = device.createFenceUnique(fence_create_info);
if(result_f != vk::Result::eSuccess)
Log::RecordLogError("Failed to create compute fence");
result = cmd_buffer->begin(&begin_info);
if(result != vk::Result::eSuccess)
Log::RecordLogError("Failed to begin recording command buffer!");
_SetName(device, *cmd_buffer, "compute_cmd_buffer");
cmd_buffer->bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.GetPipeline());
cmd_buffer->dispatch(1920 / 16, 1440 / 16, 1);
cmd_buffer->end();
vk::SubmitInfo submit_info = {};
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &*cmd_buffer;
queue.submit(1, &submit_info, *fence);
device.waitForFences(1,
&*fence,
VK_TRUE,
std::numeric_limits<uint64_t>::max());
}
然而,当我 运行 我的程序时,它不会停止。我使用 renderdoc 来确保我正在调用着色器:
调度调用似乎使用了正确的着色器。
那么为什么我的代码 运行?它应该卡住计算该循环,直到宇宙热寂。
我知道它没有停滞的方式是,我也在调用计算着色器后在同一个队列和同一个威胁上渲染图形。据我了解,提交到同一队列的命令按顺序执行,因此该着色器应停止整个管道。但我仍然可以很好地与我的程序交互。
make a shader that stalls my program
当负责主要用户界面的设备停止响应时,您的操作系统和图形驱动程序不喜欢它。所述操作系统或所述图形驱动程序的用户也没有。因此,他们不允许你这样做。
任何为 "too long" 运行的着色器操作(无论它们如何定义)都将被毫不客气地终止。您的应用程序可能看起来只是继续执行,就好像分派执行到完成一样。或者您可能会丢失图形上下文。或者可能会发生硬 GPU 重置。
或者,您的着色器编译器可能只是检测到您的着色器没有可见的副作用(即:不写入任何内容),因此它完全优化了所有代码。死代码消除往往通过从着色器的输出向后工作来发挥作用。由于这是一个计算着色器,它的输出将写入 SSBO、imageStore
调用或原子更新。您的代码执行了其中的 none,因此其代码的 none 有任何输出,因此着色器不执行任何操作。
关键是,如果你想让你的 GPU 崩溃,你必须比这聪明得多。