https://nvpro-samples.github.io/vk_mini_path_tracer/
https://github.com/nvpro-samples/vk_mini_path_tracer
#version 460
#extension GL_EXT_debug_printf : require
layout(local_size_x = 16, local_size_y = 8, local_size_z = 1) in;
void main()
{
debugPrintfEXT("Hello from invocation (%d, %d)!\n",
gl_GlobalInvocationID.x, gl_GlobalInvocationID.y);
}
#version 460
layout(local_size_x = 16, local_size_y = 8, local_size_z = 1) in;
void main()
{
}#version 460
#extension GL_EXT_debug_printf : require
layout(local_size_x = 16, local_size_y = 8, local_size_z = 1) in;
void main()
{
debugPrintfEXT("Hello world!");
}file(GLOB_RECURSE GLSL_SOURCE_FILES "shaders/*.glsl")
foreach(GLSL ${GLSL_SOURCE_FILES})
get_filename_component(FILE_NAME ${GLSL} NAME)
_compile_GLSL(${GLSL} "shaders/${FILE_NAME}.spv" GLSL_SOURCES SPV_OUTPUT)
endforeach(GLSL)#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <fileformats/stb_image_write.h>
#include <nvh/fileoperations.hpp> // For nvh::loadFile
#include <vulkan/vulkan.h> // For the full (not only core) Vulkan API
#define NVVK_ALLOC_DEDICATED
#include <nvvk/allocator_vk.hpp> // For NVVK memory allocators
#include <nvvk/context_vk.hpp>
#include <nvvk/shaders_vk.hpp> // For nvvk::createShaderModule
#include <nvvk/structs_vk.hpp> // For nvvk::makedeviceInfo.addDeviceExtension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME);
VkValidationFeaturesEXT validationInfo = nvvk::make<VkValidationFeaturesEXT>();
VkValidationFeatureEnableEXT validationFeatureToEnable =
VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT;
validationInfo.enabledValidationFeatureCount = 1;
validationInfo.pEnabledValidationFeatures = &validationFeatureToEnable;
deviceInfo.instanceCreateInfoExt = &validationInfo;
#ifdef _WIN32
_putenv_s("DEBUG_PRINTF_TO_STDOUT", "1");
#else // If not _WIN32
putenv("DEBUG_PRINTF_TO_STDOUT=1");
#endif // _WIN32static const uint32_t workgroup_width = 16;
static const uint32_t workgroup_height = 8;std::vector<std::string> searchPaths =
{ PROJECT_ABSDIRECTORY,
PROJECT_ABSDIRECTORY "../",
PROJECT_RELDIRECTORY,
PROJECT_RELDIRECTORY "../",
PROJECT_NAME};
// used later for obj loading
VkShaderModule rayTraceModule =
nvvk::createShaderModule(context,
nvh::loadFile("shaders/raytrace.comp.glsl.spv", true, searchPaths));VkPipelineShaderStageCreateInfo shaderStageCreateInfo
= nvvk::make<VkPipelineShaderStageCreateInfo>();
shaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
shaderStageCreateInfo.module = rayTraceModule;
shaderStageCreateInfo.pName = "main";// For the moment, create an empty pipeline layout. You can
// ignore this code for now; we'll replace it in the next chapter.
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
nvvk::make<VkPipelineLayoutCreateInfo>();
pipelineLayoutCreateInfo.setLayoutCount = 0;
pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
VkPipelineLayout pipelineLayout;
NVVK_CHECK(vkCreatePipelineLayout(context,
&pipelineLayoutCreateInfo, VK_NULL_HANDLE, &pipelineLayout));typedef struct VkComputePipelineCreateInfo {
VkStructureType sType;
const void* pNext;
// Lets one modify how the pipeline works
VkPipelineCreateFlags flags;
VkPipelineShaderStageCreateInfo stage;
VkPipelineLayout layout;
// Used for deriving compute pipelines
// - we won't use this in this tutorial.
VkPipeline basePipelineHandle;
int32_t basePipelineIndex;
} VkComputePipelineCreateInfo;VkComputePipelineCreateInfo pipelineCreateInfo
= nvvk::make<VkComputePipelineCreateInfo>();
pipelineCreateInfo.stage = shaderStageCreateInfo;
pipelineCreateInfo.layout = pipelineLayout;
VkPipeline computePipeline;
NVVK_CHECK(vkCreateComputePipelines(context, // Device
VK_NULL_HANDLE, // Pipeline cache (uses default)
1, &pipelineCreateInfo, // Compute pipeline create info
VK_NULL_HANDLE, // Allocator (uses default)
&computePipeline)); // Output// Bind the compute shader pipeline
vkCmdBindPipeline(cmdBuffer,
VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
// Run the compute shader with one workgroup for now
vkCmdDispatch(cmdBuffer, 1, 1, 1);VK_ACCESS_SHADER_WRITE_BIT
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
VkMemoryBarrier memoryBarrier = nvvk::make<VkMemoryBarrier>();
memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; // Make shader writes
memoryBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; // Readable by the CPU
vkCmdPipelineBarrier(cmdBuffer, // The command buffer
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // From the compute shader
VK_PIPELINE_STAGE_HOST_BIT, // To the CPU
0, // No special flags
1, &memoryBarrier, // An array of memory barriers
0, nullptr, 0, nullptr); // No other barriersvkDestroyPipeline(context, computePipeline, nullptr);
vkDestroyShaderModule(context, rayTraceModule, nullptr);
vkDestroyPipelineLayout(context, pipelineLayout, nullptr);INFO: UNASSIGNED-DEBUG-PRINTF
--> Validation Information: [ UNASSIGNED-DEBUG-PRINTF ] Object 0: handle = 0x1cb865172d8, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x92394c89 | Hello world!
debugPrintfEXT("Hello from invocation (%d, %d)!\n",
gl_GlobalInvocationID.x, gl_GlobalInvocationID.y);INFO: UNASSIGNED-DEBUG-PRINTF
--> Validation Information: [ UNASSIGNED-DEBUG-PRINTF ] Object 0: handle = 0x283f9fc4c48, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x92394c89 | Hello from invocation (0, 0)!