Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HansKristian-Work/dxil-spirv.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--dxil.hpp18
-rw-r--r--dxil_parser.cpp246
-rw-r--r--dxil_parser.hpp25
-rw-r--r--dxil_spirv.cpp91
-rw-r--r--dxil_spirv_c.cpp23
-rw-r--r--dxil_spirv_c.h41
-rw-r--r--memory_stream.cpp38
-rw-r--r--memory_stream.hpp16
-rw-r--r--reference/shaders/resources/subobject-parsing.rgen54
-rw-r--r--shaders/resources/subobject-parsing.rgen15
11 files changed, 547 insertions, 22 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d12ae9b..6660877 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -131,7 +131,7 @@ if (DXIL_SPIRV_CLI)
endif()
set(DXIL_SPV_VERSION_MAJOR 2)
-set(DXIL_SPV_VERSION_MINOR 15)
+set(DXIL_SPV_VERSION_MINOR 16)
set(DXIL_SPV_VERSION_PATCH 0)
set(DXIL_SPV_VERSION ${DXIL_SPV_VERSION_MAJOR}.${DXIL_SPV_VERSION_MINOR}.${DXIL_SPV_VERSION_PATCH})
set_target_properties(dxil-spirv-c-shared PROPERTIES
diff --git a/dxil.hpp b/dxil.hpp
index 33dd216..a5ea725 100644
--- a/dxil.hpp
+++ b/dxil.hpp
@@ -99,6 +99,24 @@ enum class RuntimeDataPartType : uint32_t
SubobjectTable = 6
};
+enum class SubobjectKind : uint32_t
+{
+ StateObjectConfig = 0,
+ GlobalRootSignature = 1,
+ LocalRootSignature = 2,
+ SubobjectToExportsAssociation = 8,
+ RaytracingShaderConfig = 9,
+ RaytracingPipelineConfig = 10,
+ HitGroup = 11,
+ RaytracingPipelineConfig1 = 12
+};
+
+enum class HitGroupType : uint32_t
+{
+ Triangle = 0,
+ Procedural = 1
+};
+
enum class ComponentType : uint8_t
{
Invalid = 0,
diff --git a/dxil_parser.cpp b/dxil_parser.cpp
index cf2b6cd..60fb9c5 100644
--- a/dxil_parser.cpp
+++ b/dxil_parser.cpp
@@ -30,6 +30,11 @@ Vector<uint8_t> &DXILContainerParser::get_blob()
return dxil_blob;
}
+Vector<RDATSubobject> &DXILContainerParser::get_rdat_subobjects()
+{
+ return rdat_subobjects;
+}
+
bool DXILContainerParser::parse_dxil(MemoryStream &stream)
{
DXIL::ProgramHeader program_header;
@@ -86,8 +91,11 @@ bool DXILContainerParser::parse_iosg1(MemoryStream &stream, Vector<DXIL::IOEleme
size_t offset = stream.get_offset();
if (!stream.seek(string_offset))
return false;
- if (!stream.read_string(elements[i].semantic_name))
+
+ const char *semantic_name;
+ if (!stream.map_string_iterate(semantic_name))
return false;
+ elements[i].semantic_name = semantic_name;
if (!stream.seek(offset))
return false;
}
@@ -112,6 +120,10 @@ bool DXILContainerParser::parse_rdat(MemoryStream &stream)
if (!stream.read(offsets[i]))
return false;
+ MemoryStream string_buffer;
+ MemoryStream index_buffer;
+ MemoryStream raw_bytes;
+
for (uint32_t i = 0; i < part_count; i++)
{
if (offsets[i] + 2 * sizeof(uint32_t) > stream.get_size())
@@ -133,21 +145,241 @@ bool DXILContainerParser::parse_rdat(MemoryStream &stream)
switch (type)
{
+ case DXIL::RuntimeDataPartType::StringBuffer:
+ {
+ string_buffer = substream.create_substream(substream.get_offset(), subpart_length);
+ break;
+ }
+
+ case DXIL::RuntimeDataPartType::IndexArrays:
+ {
+ index_buffer = substream.create_substream(substream.get_offset(), subpart_length);
+ break;
+ }
+
+ case DXIL::RuntimeDataPartType::RawBytes:
+ {
+ raw_bytes = substream.create_substream(substream.get_offset(), subpart_length);
+ break;
+ }
+
case DXIL::RuntimeDataPartType::SubobjectTable:
{
- // TODO: Report any findings of SubobjectTable with failure so we
- // know where to look.
- LOGE("TODO: RDAT SubobjectTable is not handled! RTPSO creation will likely fail.\n");
- return false;
-#if 0
uint32_t record_count;
uint32_t record_stride;
if (!substream.read(record_count))
return false;
if (!substream.read(record_stride))
return false;
+
+ for (unsigned record = 0; record < record_count; record++)
+ {
+ auto record_stream =
+ substream.create_substream(substream.get_offset() + record * record_stride, record_stride);
+
+ DXIL::SubobjectKind kind;
+ if (!record_stream.read(kind))
+ return false;
+
+ switch (kind)
+ {
+ case DXIL::SubobjectKind::StateObjectConfig:
+ {
+ uint32_t name_offset;
+ if (!record_stream.read(name_offset))
+ return false;
+
+ const char *str = nullptr;
+ if (!string_buffer.map_string_absolute(str, name_offset))
+ return false;
+
+ uint32_t flag;
+ if (!record_stream.read(flag))
+ return false;
+
+ RDATSubobject elem = {};
+ elem.kind = kind;
+ elem.subobject_name = str;
+ elem.args[0] = flag;
+ rdat_subobjects.push_back(std::move(elem));
+ break;
+ }
+
+ case DXIL::SubobjectKind::RaytracingShaderConfig:
+ {
+ uint32_t name_offset;
+ if (!record_stream.read(name_offset))
+ return false;
+
+ const char *str;
+ if (!string_buffer.map_string_absolute(str, name_offset))
+ return false;
+
+ uint32_t max_payload_size, max_attribute_size;
+ if (!record_stream.read(max_payload_size))
+ return false;
+ if (!record_stream.read(max_attribute_size))
+ return false;
+
+ RDATSubobject elem = {};
+ elem.kind = kind;
+ elem.subobject_name = str;
+ elem.args[0] = max_payload_size;
+ elem.args[1] = max_attribute_size;
+ rdat_subobjects.push_back(std::move(elem));
+ break;
+ }
+
+ case DXIL::SubobjectKind::RaytracingPipelineConfig:
+ case DXIL::SubobjectKind::RaytracingPipelineConfig1:
+ {
+ uint32_t name_offset;
+ if (!record_stream.read(name_offset))
+ return false;
+
+ const char *str;
+ if (!string_buffer.map_string_absolute(str, name_offset))
+ return false;
+
+ uint32_t max_recursion_depth;
+ uint32_t flags = 0;
+
+ if (!record_stream.read(max_recursion_depth))
+ return false;
+
+ if (kind == DXIL::SubobjectKind::RaytracingPipelineConfig1)
+ if (!record_stream.read(flags))
+ return false;
+
+ RDATSubobject elem = {};
+ elem.kind = kind;
+ elem.subobject_name = str;
+ elem.args[0] = max_recursion_depth;
+ elem.args[1] = flags;
+ rdat_subobjects.push_back(std::move(elem));
+ break;
+ }
+
+ case DXIL::SubobjectKind::HitGroup:
+ {
+ uint32_t name_offset;
+ if (!record_stream.read(name_offset))
+ return false;
+
+ const char *hg_name;
+ if (!string_buffer.map_string_absolute(hg_name, name_offset))
+ return false;
+
+ DXIL::HitGroupType hit_group_type;
+ if (!record_stream.read(hit_group_type))
+ return false;
+
+ uint32_t ahit_name_offset, chit_name_offset, intersection_name_offset;
+ if (!record_stream.read(ahit_name_offset))
+ return false;
+ if (!record_stream.read(chit_name_offset))
+ return false;
+ if (!record_stream.read(intersection_name_offset))
+ return false;
+
+ const char *ahit, *chit, *intersection;
+ if (!string_buffer.map_string_absolute(ahit, ahit_name_offset))
+ return false;
+ if (!string_buffer.map_string_absolute(chit, chit_name_offset))
+ return false;
+ if (!string_buffer.map_string_absolute(intersection, intersection_name_offset))
+ return false;
+
+ RDATSubobject elem = {};
+ elem.kind = kind;
+ elem.subobject_name = hg_name;
+ elem.hit_group_type = hit_group_type;
+ elem.exports = { ahit, chit, intersection };
+ rdat_subobjects.push_back(std::move(elem));
+ break;
+ }
+
+ case DXIL::SubobjectKind::SubobjectToExportsAssociation:
+ {
+ RDATSubobject elem = {};
+ elem.kind = kind;
+ uint32_t name_offset;
+
+ if (!record_stream.read(name_offset))
+ return false;
+
+ const char *name;
+ if (!string_buffer.map_string_absolute(name, name_offset))
+ return false;
+
+ elem.subobject_name = name;
+
+ if (!record_stream.read(name_offset))
+ return false;
+ const char *object_name;
+ if (!string_buffer.map_string_absolute(object_name, name_offset))
+ return false;
+
+ elem.exports.push_back(object_name);
+
+ uint32_t index_offset;
+ if (!record_stream.read(index_offset))
+ return false;
+
+ auto index_substream = index_buffer.create_substream(sizeof(uint32_t) * index_offset);
+ uint32_t count;
+ if (!index_substream.read(count))
+ return false;
+
+ for (uint32_t export_index = 0; export_index < count; export_index++)
+ {
+ if (!index_substream.read(name_offset))
+ return false;
+ if (!string_buffer.map_string_absolute(object_name, name_offset))
+ return false;
+ elem.exports.push_back(object_name);
+ }
+
+ rdat_subobjects.push_back(std::move(elem));
+ break;
+ }
+
+ case DXIL::SubobjectKind::GlobalRootSignature:
+ case DXIL::SubobjectKind::LocalRootSignature:
+ {
+ uint32_t name_offset;
+
+ if (!record_stream.read(name_offset))
+ return false;
+
+ const char *name;
+ if (!string_buffer.map_string_absolute(name, name_offset))
+ return false;
+
+ uint32_t byte_offset;
+ uint32_t byte_size;
+ if (!record_stream.read(byte_offset))
+ return false;
+ if (!record_stream.read(byte_size))
+ return false;
+
+ auto name_substream = raw_bytes.create_substream(byte_offset, byte_size);
+ auto *data = name_substream.map_read<uint8_t>(byte_size);
+
+ RDATSubobject elem = {};
+ elem.kind = kind;
+ elem.subobject_name = name;
+ elem.payload = data;
+ elem.payload_size = byte_size;
+ rdat_subobjects.push_back(std::move(elem));
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
break;
-#endif
}
default:
diff --git a/dxil_parser.hpp b/dxil_parser.hpp
index 90a21a6..12fc25c 100644
--- a/dxil_parser.hpp
+++ b/dxil_parser.hpp
@@ -27,16 +27,41 @@ namespace dxil_spv
{
class MemoryStream;
+struct RDATSubobject
+{
+ // All strings point directly to the DXBC blob and the pointers are not owned.
+ DXIL::SubobjectKind kind;
+
+ // All subobjects have a variable name as declared in the shader.
+ const char *subobject_name;
+
+ // All exports.
+ // For hit groups, 3 strings: AnyHit, ClosestHit, Intersection. Strings may be empty if not used.
+ // For SubobjectToExportsAssociation: N strings. exports[0] is associated with the following exports.
+ DXIL::HitGroupType hit_group_type;
+ Vector<const char *> exports;
+
+ // For StateObjectConfig, RaytracingShaderConfig, RaytracingPipelineConfig(1).
+ // Each element is in struct order.
+ uint32_t args[2];
+
+ // For Global/Local Root Signatures.
+ const uint8_t *payload;
+ size_t payload_size;
+};
+
class DXILContainerParser
{
public:
bool parse_container(const void *data, size_t size);
Vector<uint8_t> &get_blob();
+ Vector<RDATSubobject> &get_rdat_subobjects();
private:
Vector<uint8_t> dxil_blob;
Vector<DXIL::IOElement> input_elements;
Vector<DXIL::IOElement> output_elements;
+ Vector<RDATSubobject> rdat_subobjects;
bool parse_dxil(MemoryStream &stream);
bool parse_iosg1(MemoryStream &stream, Vector<DXIL::IOElement> &elements);
diff --git a/dxil_spirv.cpp b/dxil_spirv.cpp
index 85a77ec..2f70e2b 100644
--- a/dxil_spirv.cpp
+++ b/dxil_spirv.cpp
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include <vector>
#include "dxil_spirv_c.h"
@@ -990,6 +991,96 @@ int main(int argc, char **argv)
}
}
+ // Dump debug output of RDAT objects if we have them.
+ if (args.glsl || args.emit_asm)
+ {
+ unsigned num_subobjects = dxil_spv_parsed_blob_get_num_rdat_subobjects(blob);
+ if (num_subobjects > 0)
+ {
+ final_output += "\n#if 0\n==== RDAT ====\n";
+ for (unsigned i = 0; i < num_subobjects; i++)
+ {
+ dxil_spv_rdat_subobject obj;
+ dxil_spv_parsed_blob_get_rdat_subobject(blob, i, &obj);
+ switch (obj.kind)
+ {
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_STATE_OBJECT_CONFIG:
+ final_output += "ShaderConfig ";
+ final_output += obj.subobject_name;
+ final_output += " = { flags = ";
+ final_output += std::to_string(obj.args[0]);
+ final_output += " };\n";
+ break;
+
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG:
+ final_output += "ShaderConfig ";
+ final_output += obj.subobject_name;
+ final_output += " = { maxPayloadSize = ";
+ final_output += std::to_string(obj.args[0]);
+ final_output += ", maxAttributeSize = ";
+ final_output += std::to_string(obj.args[1]);
+ final_output += " };\n";
+ break;
+
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG:
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1:
+ final_output += "RaytracingPipelineConfig1 ";
+ final_output += obj.subobject_name;
+ final_output += " = { maxRecursion = ";
+ final_output += std::to_string(obj.args[0]);
+ final_output += ", flags = ";
+ final_output += std::to_string(obj.args[1]);
+ final_output += " };\n";
+ break;
+
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE:
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE:
+ final_output += obj.kind == DXIL_SPV_RDAT_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE ?
+ "GlobalRootSignature " : "LocalRootSignature ";
+ final_output += obj.subobject_name;
+ final_output += " = { ";
+ final_output += std::to_string(obj.payload_size);
+ final_output += " bytes };\n";
+ break;
+
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_HIT_GROUP:
+ final_output += obj.hit_group_type == DXIL_SPV_HIT_GROUP_TYPE_TRIANGLE ?
+ "TriangleHitGroup " : "ProceduralHitGroup ";
+ final_output += obj.subobject_name;
+ assert(obj.num_exports == 3);
+ final_output += " = { ahit = \"";
+ final_output += obj.exports[0];
+ final_output += "\", chit = \"";
+ final_output += obj.exports[1];
+ final_output += "\", intersection = \"";
+ final_output += obj.exports[2];
+ final_output += "\" };\n";
+ break;
+
+ case DXIL_SPV_RDAT_SUBOBJECT_KIND_SUBOBJECT_TO_EXPORTS_ASSOCIATION:
+ final_output += "SubobjectToExportsAssociation ";
+ final_output += obj.subobject_name;
+ final_output += " = { ";
+ assert(obj.num_exports >= 1);
+ final_output += obj.exports[0];
+ final_output += ", { ";
+ for (unsigned j = 1; j < obj.num_exports; j++)
+ {
+ final_output += obj.exports[j];
+ if (j + 1 < obj.num_exports)
+ final_output += ", ";
+ }
+ final_output += " } };\n";
+ break;
+
+ default:
+ break;
+ }
+ }
+ final_output += "============\n#endif";
+ }
+ }
+
if (args.output_path.empty())
{
printf("%s\n", final_output.c_str());
diff --git a/dxil_spirv_c.cpp b/dxil_spirv_c.cpp
index a94a753..2d0a8b5 100644
--- a/dxil_spirv_c.cpp
+++ b/dxil_spirv_c.cpp
@@ -23,6 +23,7 @@
#include "llvm_bitcode_parser.hpp"
#include "logging.hpp"
#include "spirv_module.hpp"
+#include <string.h>
#include <new>
using namespace dxil_spv;
@@ -43,6 +44,7 @@ struct dxil_spv_parsed_blob_s
std::string disasm;
#endif
Vector<uint8_t> dxil_blob;
+ Vector<RDATSubobject> rdat_subobjects;
Vector<String> entry_points;
};
@@ -342,6 +344,7 @@ dxil_spv_result dxil_spv_parse_dxil_blob(const void *data, size_t size, dxil_spv
}
parsed->dxil_blob = std::move(parser.get_blob());
+ parsed->rdat_subobjects = std::move(parser.get_rdat_subobjects());
if (!parsed->bc.parse(parsed->dxil_blob.data(), parsed->dxil_blob.size()))
{
@@ -914,6 +917,26 @@ dxil_spv_result dxil_spv_converter_end_local_root_descriptor_table(
return DXIL_SPV_SUCCESS;
}
+unsigned dxil_spv_parsed_blob_get_num_rdat_subobjects(dxil_spv_parsed_blob blob)
+{
+ return unsigned(blob->rdat_subobjects.size());
+}
+
+void dxil_spv_parsed_blob_get_rdat_subobject(
+ dxil_spv_parsed_blob blob, unsigned index, dxil_spv_rdat_subobject *subobject)
+{
+ auto &sub = blob->rdat_subobjects[index];
+ subobject->kind = static_cast<dxil_spv_rdat_subobject_kind>(sub.kind);
+ subobject->subobject_name = sub.subobject_name;
+ subobject->exports = sub.exports.data();
+ subobject->num_exports = unsigned(sub.exports.size());
+ subobject->payload = sub.payload;
+ subobject->payload_size = sub.payload_size;
+ subobject->hit_group_type = static_cast<dxil_spv_hit_group_type>(sub.hit_group_type);
+ static_assert(sizeof(subobject->args) == sizeof(sub.args), "Mismatch is args size.");
+ memcpy(subobject->args, sub.args, sizeof(sub.args));
+}
+
dxil_spv_bool dxil_spv_converter_uses_subgroup_size(dxil_spv_converter converter)
{
return converter->uses_subgroup_size ? DXIL_SPV_TRUE : DXIL_SPV_FALSE;
diff --git a/dxil_spirv_c.h b/dxil_spirv_c.h
index 7a23207..1178985 100644
--- a/dxil_spirv_c.h
+++ b/dxil_spirv_c.h
@@ -28,7 +28,7 @@ extern "C" {
#endif
#define DXIL_SPV_API_VERSION_MAJOR 2
-#define DXIL_SPV_API_VERSION_MINOR 15
+#define DXIL_SPV_API_VERSION_MINOR 16
#define DXIL_SPV_API_VERSION_PATCH 0
#define DXIL_SPV_DESCRIPTOR_QA_INTERFACE_VERSION 1
@@ -163,6 +163,26 @@ typedef enum dxil_spv_vulkan_descriptor_type
DXIL_SPV_VULKAN_DESCRIPTOR_TYPE_INT_MAX = 0x7fffffff
} dxil_spv_vulkan_descriptor_type;
+typedef enum dxil_spv_rdat_subobject_kind
+{
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_STATE_OBJECT_CONFIG = 0,
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE = 1,
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE = 2,
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_SUBOBJECT_TO_EXPORTS_ASSOCIATION = 8,
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG = 9,
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG = 10,
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_HIT_GROUP = 11,
+ DXIL_SPV_RDAT_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1 = 12,
+ DXIL_SPV_RDAT_SUBOBJECT_TYPE_INT_MAX = 0x7fffffff
+} dxil_spv_rdat_subobject_kind;
+
+typedef enum dxil_spv_hit_group_type
+{
+ DXIL_SPV_HIT_GROUP_TYPE_TRIANGLE = 0,
+ DXIL_SPV_HIT_GROUP_TYPE_PROCEDURAL = 1,
+ DXIL_SPV_HIT_GROUP_TYPE_INT_MAX = 0x7fffffff
+} dxil_spv_hit_group_type;
+
typedef struct dxil_spv_d3d_binding
{
dxil_spv_shader_stage stage;
@@ -248,6 +268,19 @@ typedef dxil_spv_bool (*dxil_spv_cbv_remapper_cb)(void *userdata,
const dxil_spv_d3d_binding *d3d_uav_binding,
dxil_spv_cbv_vulkan_binding *vulkan_uav_binding);
+typedef struct dxil_spv_rdat_subobject
+{
+ // See dxil_parser.hpp for details.
+ dxil_spv_rdat_subobject_kind kind;
+ const char *subobject_name;
+ dxil_spv_hit_group_type hit_group_type;
+ const char * const *exports;
+ unsigned num_exports;
+ unsigned args[2];
+ const void *payload;
+ size_t payload_size;
+} dxil_spv_rdat_subobject;
+
typedef enum dxil_spv_log_level
{
DXIL_SPV_LOG_LEVEL_DEBUG,
@@ -471,6 +504,12 @@ DXIL_SPV_PUBLIC_API dxil_spv_result dxil_spv_parsed_blob_scan_resources(
dxil_spv_uav_remapper_cb uav_remapper,
void *userdata);
+/* For DXR, API subobjects can be embedded inside the blob. */
+DXIL_SPV_PUBLIC_API unsigned dxil_spv_parsed_blob_get_num_rdat_subobjects(
+ dxil_spv_parsed_blob blob);
+DXIL_SPV_PUBLIC_API void dxil_spv_parsed_blob_get_rdat_subobject(
+ dxil_spv_parsed_blob blob, unsigned index, dxil_spv_rdat_subobject *subobject);
+
DXIL_SPV_PUBLIC_API void dxil_spv_parsed_blob_free(dxil_spv_parsed_blob blob);
/* Parsing API */
diff --git a/memory_stream.cpp b/memory_stream.cpp
index a02a5d1..c79bf36 100644
--- a/memory_stream.cpp
+++ b/memory_stream.cpp
@@ -42,20 +42,38 @@ bool MemoryStream::read(void *buffer, size_t size)
return true;
}
-bool MemoryStream::read_string(String &str)
+const void *MemoryStream::map_read(size_t size)
{
- str.clear();
+ if (blob_offset + size > blob_size)
+ return nullptr;
+
+ const void *mapped = blob + blob_offset;
+ blob_offset += size;
+ return mapped;
+}
+
+bool MemoryStream::map_string_iterate(const char *&str)
+{
+ // Strings are C strings and can be mapped 1:1.
+ // Just need to verify they terminate properly.
+ str = reinterpret_cast<const char *>(blob + blob_offset);
+ char c;
- for (;;)
+ do
{
- char c;
if (!read(c))
return false;
else if (c == '\0')
- return true;
- else
- str += c;
- }
+ break;
+ } while (c != '\0');
+
+ return true;
+}
+
+bool MemoryStream::map_string_absolute(const char *&str, size_t offset) const
+{
+ auto substream = create_substream(offset);
+ return substream.map_string_iterate(str);
}
bool MemoryStream::seek(size_t new_offset)
@@ -74,7 +92,7 @@ bool MemoryStream::skip(size_t count)
MemoryStream MemoryStream::create_substream(size_t offset, size_t size) const
{
- if (offset + size > blob_size)
+ if (offset >= blob_size || offset + size > blob_size)
return { nullptr, 0 };
else
return { blob + offset, size };
@@ -82,7 +100,7 @@ MemoryStream MemoryStream::create_substream(size_t offset, size_t size) const
MemoryStream MemoryStream::create_substream(size_t offset) const
{
- if (offset > blob_size)
+ if (offset >= blob_size)
return { nullptr, 0 };
else
return { blob + offset, blob_size - offset };
diff --git a/memory_stream.hpp b/memory_stream.hpp
index 204b42d..abd0514 100644
--- a/memory_stream.hpp
+++ b/memory_stream.hpp
@@ -28,6 +28,7 @@ class MemoryStream
{
public:
MemoryStream(const void *blob, size_t size);
+ MemoryStream() = default;
void reset();
@@ -37,8 +38,17 @@ public:
return read(&buffer, sizeof(T));
}
+ const void *map_read(size_t byte_size);
+
+ template <typename T>
+ const T *map_read(size_t byte_size)
+ {
+ return static_cast<const T *>(map_read(byte_size));
+ }
+
bool read(void *buffer, size_t size);
- bool read_string(String &str);
+ bool map_string_iterate(const char *&str);
+ bool map_string_absolute(const char *&str, size_t offset) const;
bool seek(size_t offset);
bool skip(size_t count);
@@ -48,8 +58,8 @@ public:
MemoryStream create_substream(size_t offset) const;
private:
- const uint8_t *blob;
- size_t blob_size;
+ const uint8_t *blob = nullptr;
+ size_t blob_size = 0;
size_t blob_offset = 0;
};
} // namespace dxil_spv \ No newline at end of file
diff --git a/reference/shaders/resources/subobject-parsing.rgen b/reference/shaders/resources/subobject-parsing.rgen
new file mode 100644
index 0000000..de6575b
--- /dev/null
+++ b/reference/shaders/resources/subobject-parsing.rgen
@@ -0,0 +1,54 @@
+#version 460
+#extension GL_EXT_ray_tracing : require
+#extension GL_EXT_nonuniform_qualifier : require
+
+void main()
+{
+}
+
+
+#if 0
+// SPIR-V disassembly
+; SPIR-V
+; Version: 1.4
+; Generator: Unknown(30017); 21022
+; Bound: 7
+; Schema: 0
+OpCapability Shader
+OpCapability UniformBufferArrayDynamicIndexing
+OpCapability SampledImageArrayDynamicIndexing
+OpCapability StorageBufferArrayDynamicIndexing
+OpCapability StorageImageArrayDynamicIndexing
+OpCapability RayTracingKHR
+OpCapability RuntimeDescriptorArray
+OpCapability UniformBufferArrayNonUniformIndexing
+OpCapability SampledImageArrayNonUniformIndexing
+OpCapability StorageBufferArrayNonUniformIndexing
+OpCapability StorageImageArrayNonUniformIndexing
+OpExtension "SPV_EXT_descriptor_indexing"
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint RayGenerationNV %3 "main"
+OpName %3 "main"
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%4 = OpLabel
+OpBranch %5
+%5 = OpLabel
+OpReturn
+OpFunctionEnd
+#endif
+#if 0
+==== RDAT ====
+ShaderConfig sconf = { maxPayloadSize = 80, maxAttributeSize = 60 };
+RaytracingPipelineConfig1 pconf0 = { maxRecursion = 4, flags = 0 };
+RaytracingPipelineConfig1 pconf1 = { maxRecursion = 5, flags = 256 };
+ShaderConfig soc = { flags = 1 };
+TriangleHitGroup tri_hg = { ahit = "a", chit = "b", intersection = "" };
+TriangleHitGroup tri_hg2 = { ahit = "", chit = "b", intersection = "" };
+ProceduralHitGroup aabb_hg = { ahit = "c", chit = "d", intersection = "e" };
+SubobjectToExportsAssociation assoc1 = { A, { foo, bar, meow, nyaa, frog } };
+SubobjectToExportsAssociation assoc2 = { B, { meep, frog } };
+============
+#endif
diff --git a/shaders/resources/subobject-parsing.rgen b/shaders/resources/subobject-parsing.rgen
new file mode 100644
index 0000000..b6b9ceb
--- /dev/null
+++ b/shaders/resources/subobject-parsing.rgen
@@ -0,0 +1,15 @@
+RaytracingShaderConfig sconf = { 80, 60 };
+RaytracingPipelineConfig pconf0 = { 4 };
+RaytracingPipelineConfig1 pconf1 = { 5, RAYTRACING_PIPELINE_FLAG_SKIP_TRIANGLES };
+// DXC specifies the typo :V
+StateObjectConfig soc = { STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS };
+TriangleHitGroup tri_hg = { "a", "b" };
+TriangleHitGroup tri_hg2 = { "", "b" };
+ProceduralPrimitiveHitGroup aabb_hg = { "c", "d", "e" };
+SubobjectToExportsAssociation assoc1 = { "A", "foo;bar;meow;nyaa;frog" };
+SubobjectToExportsAssociation assoc2 = { "B", "meep;frog" };
+
+[shader("raygeneration")]
+void main()
+{
+}