Skip to content

Commit 2474b4d

Browse files
committed
raytracing: Initial Vulkan support
- Vulkan implementations in `RenderingDeviceDriverVulkan` - Raytracing instruction list in `RenderingDeviceGraph` - Functions to create acceleration structures and raytracing pipelines in `RenderingDevice` - Raygen, Miss, and ClosestHit shader stages support - GDScript bindings
1 parent 5efd124 commit 2474b4d

19 files changed

+1977
-36
lines changed

doc/classes/RenderingDevice.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2021,7 +2021,10 @@
20212021
<constant name="UNIFORM_TYPE_INPUT_ATTACHMENT" value="9" enum="UniformType">
20222022
Input attachment uniform.
20232023
</constant>
2024-
<constant name="UNIFORM_TYPE_MAX" value="10" enum="UniformType">
2024+
<constant name="UNIFORM_TYPE_ACCELERATION_STRUCTURE" value="10" enum="UniformType">
2025+
Acceleration structure uniform.
2026+
</constant>
2027+
<constant name="UNIFORM_TYPE_MAX" value="11" enum="UniformType">
20252028
Represents the size of the [enum UniformType] enum.
20262029
</constant>
20272030
<constant name="RENDER_PRIMITIVE_POINTS" value="0" enum="RenderPrimitive">

drivers/vulkan/rendering_device_driver_vulkan.cpp

Lines changed: 548 additions & 2 deletions
Large diffs are not rendered by default.

drivers/vulkan/rendering_device_driver_vulkan.h

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
100100
bool storage_input_output_16 = false;
101101
};
102102

103+
struct RaytracingCapabilities {
104+
bool buffer_device_address_support = false;
105+
bool acceleration_structure_support = false;
106+
bool raytracing_pipeline_support = false;
107+
uint32_t shader_group_handle_size = 0;
108+
uint32_t shader_group_handle_alignment = 0;
109+
uint32_t shader_group_handle_size_aligned = 0;
110+
uint32_t shader_group_base_alignment = 0;
111+
bool validation = false;
112+
};
113+
103114
struct DeviceFunctions {
104115
PFN_vkCreateSwapchainKHR CreateSwapchainKHR = nullptr;
105116
PFN_vkDestroySwapchainKHR DestroySwapchainKHR = nullptr;
@@ -116,6 +127,10 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
116127

117128
// Debug device fault.
118129
PFN_vkGetDeviceFaultInfoEXT GetDeviceFaultInfoEXT = nullptr;
130+
131+
// Raytracing extensions.
132+
PFN_vkCreateAccelerationStructureKHR CreateAccelerationStructureKHR = nullptr;
133+
PFN_vkCreateRayTracingPipelinesKHR CreateRaytracingPipelinesKHR = nullptr;
119134
};
120135
// Debug marker extensions.
121136
VkDebugReportObjectTypeEXT _convert_to_debug_report_objectType(VkObjectType p_object_type);
@@ -138,6 +153,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
138153
VRSCapabilities vrs_capabilities;
139154
ShaderCapabilities shader_capabilities;
140155
StorageBufferCapabilities storage_buffer_capabilities;
156+
RaytracingCapabilities raytracing_capabilities;
141157
bool pipeline_cache_control_support = false;
142158
bool device_fault_support = false;
143159
#if defined(VK_TRACK_DEVICE_MEMORY)
@@ -198,6 +214,10 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
198214
VkBufferView vk_view = VK_NULL_HANDLE; // For texel buffers.
199215
};
200216

217+
private:
218+
VkDeviceAddress _buffer_get_device_address(BufferID p_buffer);
219+
220+
public:
201221
virtual BufferID buffer_create(uint64_t p_size, BitField<BufferUsageBits> p_usage, MemoryAllocationType p_allocation_type) override final;
202222
virtual bool buffer_set_texel_format(BufferID p_buffer, DataFormat p_format) override final;
203223
virtual void buffer_free(BufferID p_buffer) override final;
@@ -424,7 +444,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
424444
uint64_t vertex_input_mask = 0;
425445
uint32_t fragment_output_mask = 0;
426446
uint32_t specialization_constants_count = 0;
427-
uint32_t is_compute = 0;
447+
PipelineType pipeline_type = PipelineType::RASTERIZATION;
428448
uint32_t compute_local_size[3] = {};
429449
uint32_t set_count = 0;
430450
uint32_t push_constant_size = 0;
@@ -434,11 +454,28 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
434454
};
435455
};
436456

457+
struct RaytracingShaderRegions {
458+
VkStridedDeviceAddressRegionKHR raygen;
459+
uint32_t raygen_count = 0;
460+
VkStridedDeviceAddressRegionKHR miss;
461+
uint32_t miss_count = 0;
462+
VkStridedDeviceAddressRegionKHR closest_hit;
463+
uint32_t closest_hit_count = 0;
464+
VkStridedDeviceAddressRegionKHR call;
465+
uint32_t group_count = 0;
466+
467+
// Size of one shader group handle
468+
LocalVector<uint8_t> handles_data;
469+
};
470+
437471
struct ShaderInfo {
438472
VkShaderStageFlags vk_push_constant_stages = 0;
439473
TightLocalVector<VkPipelineShaderStageCreateInfo> vk_stages_create_info;
474+
TightLocalVector<VkRayTracingShaderGroupCreateInfoKHR> vk_groups_create_info;
440475
TightLocalVector<VkDescriptorSetLayout> vk_descriptor_set_layouts;
441476
VkPipelineLayout vk_pipeline_layout = VK_NULL_HANDLE;
477+
RaytracingShaderRegions regions;
478+
BufferID sbt_buffer;
442479
};
443480

444481
public:
@@ -626,6 +663,50 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
626663

627664
virtual PipelineID compute_pipeline_create(ShaderID p_shader, VectorView<PipelineSpecializationConstant> p_specialization_constants) override final;
628665

666+
/********************/
667+
/**** RAYTRACING ****/
668+
/********************/
669+
struct AccelerationStructureInfo {
670+
VkAccelerationStructureKHR vk_acceleration_structure = VK_NULL_HANDLE;
671+
// Buffer used for the structure
672+
RDD::BufferID buffer;
673+
// Buffer used for building the structure
674+
RDD::BufferID scratch_buffer;
675+
// Buffer used for instances in a TLAS
676+
RDD::BufferID instances_buffer;
677+
678+
// Required for building
679+
VkAccelerationStructureGeometryKHR geometry;
680+
LocalVector<VkAccelerationStructureInstanceKHR> instances;
681+
VkAccelerationStructureBuildGeometryInfoKHR build_info;
682+
VkAccelerationStructureBuildRangeInfoKHR range_info;
683+
};
684+
685+
virtual AccelerationStructureID blas_create(BufferID p_vertex_buffer, uint64_t p_vertex_offset, VertexFormatID p_vertex_format, uint32_t p_vertex_count, BufferID p_index_buffer, IndexBufferFormat p_index_format, uint64_t p_index_offset_bytes, uint32_t p_index_count, BufferID p_transform_buffer, uint64_t p_transform_offset) override final;
686+
virtual AccelerationStructureID tlas_create(const LocalVector<AccelerationStructureID> &p_blases) override final;
687+
virtual void acceleration_structure_free(AccelerationStructureID p_acceleration_structure) override final;
688+
689+
private:
690+
void _acceleration_structure_create(VkAccelerationStructureTypeKHR p_type, VkAccelerationStructureBuildSizesInfoKHR p_size_info, AccelerationStructureInfo *r_accel_info);
691+
692+
public:
693+
// ----- PIPELINE -----
694+
695+
struct RaytracingPipelineInfo {
696+
VkPipeline vk_pipeline;
697+
};
698+
699+
virtual RaytracingPipelineID raytracing_pipeline_create(ShaderID p_shader, VectorView<PipelineSpecializationConstant> p_specialization_constants) override final;
700+
virtual void raytracing_pipeline_free(RaytracingPipelineID p_pipeline) override final;
701+
702+
// ----- COMMANDS -----
703+
704+
virtual void command_build_acceleration_structure(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure) override final;
705+
virtual void command_bind_raytracing_pipeline(CommandBufferID p_cmd_buffer, RaytracingPipelineID p_pipeline) override final;
706+
virtual void command_bind_raytracing_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final;
707+
virtual void command_raytracing_trace_rays(CommandBufferID p_cmd_buffer, RaytracingPipelineID p_pipeline, ShaderID p_shader, uint32_t p_width, uint32_t p_height) override final;
708+
709+
public:
629710
/*****************/
630711
/**** QUERIES ****/
631712
/*****************/

editor/plugins/shader_file_editor_plugin.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,10 @@ ShaderFileEditor::ShaderFileEditor() {
268268
"Fragment",
269269
"TessControl",
270270
"TessEval",
271-
"Compute"
271+
"Compute",
272+
"Raygen",
273+
"Miss",
274+
"ClosestHit",
272275
};
273276

274277
stage_hb = memnew(HBoxContainer);

gles3_builders.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ class GLES3HeaderStruct:
1010
def __init__(self):
1111
self.vertex_lines = []
1212
self.fragment_lines = []
13+
self.raygen_lines = []
14+
self.miss_lines = []
15+
self.closest_hit_lines = []
1316
self.uniforms = []
1417
self.fbos = []
1518
self.texunits = []
@@ -25,6 +28,9 @@ def __init__(self):
2528
self.line_offset = 0
2629
self.vertex_offset = 0
2730
self.fragment_offset = 0
31+
self.raygen_offset = 0
32+
self.miss_offset = 0
33+
self.closest_hit_offset = 0
2834
self.variant_defines = []
2935
self.variant_names = []
3036
self.specialization_names = []
@@ -88,6 +94,27 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct,
8894
header_data.fragment_offset = header_data.line_offset
8995
continue
9096

97+
if line.find("#[raygen]") != -1:
98+
header_data.reading = "raygen"
99+
line = fs.readline()
100+
header_data.line_offset += 1
101+
header_data.raygen_offset = header_data.line_offset
102+
continue
103+
104+
if line.find("#[miss]") != -1:
105+
header_data.reading = "miss"
106+
line = fs.readline()
107+
header_data.line_offset += 1
108+
header_data.miss_offset = header_data.line_offset
109+
continue
110+
111+
if line.find("#[closest_hit]") != -1:
112+
header_data.reading = "closest_hit"
113+
line = fs.readline()
114+
header_data.line_offset += 1
115+
header_data.closest_hit_offset = header_data.line_offset
116+
continue
117+
91118
while line.find("#include ") != -1:
92119
includeline = line.replace("#include ", "").strip()[1:-1]
93120

@@ -182,6 +209,12 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct,
182209
header_data.vertex_lines += [line]
183210
if header_data.reading == "fragment":
184211
header_data.fragment_lines += [line]
212+
if header_data.reading == "raygen":
213+
header_data.raygen_lines += [line]
214+
if header_data.reading == "miss":
215+
header_data.miss_lines += [line]
216+
if header_data.reading == "closest_hit":
217+
header_data.closest_hit_lines += [line]
185218

186219
line = fs.readline()
187220
header_data.line_offset += 1

glsl_builders.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,25 @@ def __init__(self):
1111
self.vertex_lines = []
1212
self.fragment_lines = []
1313
self.compute_lines = []
14+
self.raygen_lines = []
15+
self.miss_lines = []
16+
self.closest_hit_lines = []
1417

1518
self.vertex_included_files = []
1619
self.fragment_included_files = []
1720
self.compute_included_files = []
21+
self.raygen_included_files = []
22+
self.miss_included_files = []
23+
self.closest_hit_included_files = []
1824

1925
self.reading = ""
2026
self.line_offset = 0
2127
self.vertex_offset = 0
2228
self.fragment_offset = 0
2329
self.compute_offset = 0
30+
self.raygen_offset = 0
31+
self.miss_offset = 0
32+
self.closest_hit_offset = 0
2433

2534

2635
def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth: int) -> RDHeaderStruct:
@@ -53,6 +62,27 @@ def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth:
5362
header_data.compute_offset = header_data.line_offset
5463
continue
5564

65+
if line.find("#[raygen]") != -1:
66+
header_data.reading = "raygen"
67+
line = fs.readline()
68+
header_data.line_offset += 1
69+
header_data.raygen_offset = header_data.line_offset
70+
continue
71+
72+
if line.find("#[miss]") != -1:
73+
header_data.reading = "miss"
74+
line = fs.readline()
75+
header_data.line_offset += 1
76+
header_data.miss_offset = header_data.line_offset
77+
continue
78+
79+
if line.find("#[closest_hit]") != -1:
80+
header_data.reading = "closest_hit"
81+
line = fs.readline()
82+
header_data.line_offset += 1
83+
header_data.closest_hit_offset = header_data.line_offset
84+
continue
85+
5686
while line.find("#include ") != -1:
5787
includeline = line.replace("#include ", "").strip()[1:-1]
5888

@@ -74,6 +104,20 @@ def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth:
74104
header_data.compute_included_files += [included_file]
75105
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
76106
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
107+
elif included_file not in header_data.raygen_included_files and header_data.reading == "raygen":
108+
header_data.raygen_included_files += [included_file]
109+
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
110+
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
111+
elif included_file not in header_data.miss_included_files and header_data.reading == "miss":
112+
header_data.miss_included_files += [included_file]
113+
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
114+
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
115+
elif (
116+
included_file not in header_data.closest_hit_included_files and header_data.reading == "closest_hit"
117+
):
118+
header_data.closest_hit_included_files += [included_file]
119+
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
120+
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
77121

78122
line = fs.readline()
79123

@@ -85,6 +129,12 @@ def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth:
85129
header_data.fragment_lines += [line]
86130
if header_data.reading == "compute":
87131
header_data.compute_lines += [line]
132+
if header_data.reading == "raygen":
133+
header_data.raygen_lines += [line]
134+
if header_data.reading == "miss":
135+
header_data.miss_lines += [line]
136+
if header_data.reading == "closest_hit":
137+
header_data.closest_hit_lines += [line]
88138

89139
line = fs.readline()
90140
header_data.line_offset += 1
@@ -109,7 +159,14 @@ def build_rd_header(
109159
out_file_ifdef = out_file_base.replace(".", "_").upper()
110160
out_file_class = out_file_base.replace(".glsl.gen.h", "").title().replace("_", "").replace(".", "") + "ShaderRD"
111161

112-
if header_data.compute_lines:
162+
if header_data.raygen_lines:
163+
body_parts = [
164+
"static const char _raygen_code[] = {\n%s\n\t\t};" % to_raw_cstring(header_data.raygen_lines),
165+
"static const char _miss_code[] = {\n%s\n\t\t};" % to_raw_cstring(header_data.miss_lines),
166+
"static const char _closest_hit_code[] = {\n%s\n\t\t};" % to_raw_cstring(header_data.closest_hit_lines),
167+
f'setup_raytracing(_raygen_code, _miss_code, _closest_hit_code, "{out_file_class}");',
168+
]
169+
elif header_data.compute_lines:
113170
body_parts = [
114171
"static const char _compute_code[] = {\n%s\n\t\t};" % to_raw_cstring(header_data.compute_lines),
115172
f'setup(nullptr, nullptr, _compute_code, "{out_file_class}");',

modules/glslang/register_types.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
4848
EShLangFragment,
4949
EShLangTessControl,
5050
EShLangTessEvaluation,
51-
EShLangCompute
51+
EShLangCompute,
52+
EShLangRayGen,
53+
EShLangMiss,
54+
EShLangClosestHit,
5255
};
5356

5457
int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100

0 commit comments

Comments
 (0)