Skip to content

Commit

Permalink
fix(spv-out): OpSourceContinued for large source (gfx-rs#5390)
Browse files Browse the repository at this point in the history
  • Loading branch information
wicast committed Apr 6, 2024
1 parent d814851 commit b165558
Show file tree
Hide file tree
Showing 7 changed files with 16,165 additions and 2 deletions.
53 changes: 52 additions & 1 deletion naga/src/back/spv/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ pub(super) fn bytes_to_words(bytes: &[u8]) -> Vec<Word> {

pub(super) fn string_to_words(input: &str) -> Vec<Word> {
let bytes = input.as_bytes();
let mut words = bytes_to_words(bytes);

str_bytes_to_words(bytes)
}

pub(super) fn str_bytes_to_words(bytes: &[u8]) -> Vec<Word> {
let mut words = bytes_to_words(bytes);
if bytes.len() % 4 == 0 {
// nul-termination
words.push(0x0u32);
Expand All @@ -20,6 +24,21 @@ pub(super) fn string_to_words(input: &str) -> Vec<Word> {
words
}

/// split a string into chunks and keep utf8 valid
#[allow(unstable_name_collisions)]
pub(super) fn string_to_byte_chunks(input: &str, limit: usize) -> Vec<&[u8]> {
let mut offset: usize = 0;
let mut start: usize = 0;
let mut words = vec![];
while offset < input.len() {
offset = input.floor_char_boundary(offset + limit);
words.push(input[start..offset].as_bytes());
start = offset;
}

words
}

pub(super) const fn map_storage_class(space: crate::AddressSpace) -> spirv::StorageClass {
match space {
crate::AddressSpace::Handle => spirv::StorageClass::UniformConstant,
Expand Down Expand Up @@ -107,3 +126,35 @@ pub fn global_needs_wrapper(ir_module: &crate::Module, var: &crate::GlobalVariab
_ => true,
}
}

///HACK: this is taken from std unstable, remove it when std's floor_char_boundary is stable
trait U8Internal {
fn is_utf8_char_boundary(&self) -> bool;
}

impl U8Internal for u8 {
fn is_utf8_char_boundary(&self) -> bool {
// This is bit magic equivalent to: b < 128 || b >= 192
(*self as i8) >= -0x40
}
}

trait StrUnstable {
fn floor_char_boundary(&self, index: usize) -> usize;
}

impl StrUnstable for str {
fn floor_char_boundary(&self, index: usize) -> usize {
if index >= self.len() {
self.len()
} else {
let lower_bound = index.saturating_sub(3);
let new_index = self.as_bytes()[lower_bound..=index]
.iter()
.rposition(|b| b.is_utf8_char_boundary());

// SAFETY: we know that the character boundary will be within four bytes
unsafe { lower_bound + new_index.unwrap_unchecked() }
}
}
}
36 changes: 36 additions & 0 deletions naga/src/back/spv/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,42 @@ impl super::Instruction {
instruction
}

pub(super) fn source_continued(source: &[u8]) -> Self {
let mut instruction = Self::new(Op::SourceContinued);
instruction.add_operands(helpers::str_bytes_to_words(source));
instruction
}

pub(super) fn source_auto_continued(
source_language: spirv::SourceLanguage,
version: u32,
source: &Option<DebugInfoInner>,
) -> Vec<Self> {
let mut instructions = vec![];

let with_continue = source.as_ref().and_then(|debug_info| {
(debug_info.source_code.len() > u16::MAX as usize).then_some(debug_info)
});
if let Some(debug_info) = with_continue {
let mut instruction = Self::new(Op::Source);
instruction.add_operand(source_language as u32);
instruction.add_operands(helpers::bytes_to_words(&version.to_le_bytes()));

let words = helpers::string_to_byte_chunks(debug_info.source_code, u16::MAX as usize);
instruction.add_operand(debug_info.source_file_id);
instruction.add_operands(helpers::str_bytes_to_words(words[0]));
instructions.push(instruction);
for word_bytes in words[1..].iter() {
let instruction_continue = Self::source_continued(word_bytes);
instructions.push(instruction_continue);
}
} else {
let instruction = Self::source(source_language, version, source);
instructions.push(instruction);
}
instructions
}

pub(super) fn name(target_id: Word, name: &str) -> Self {
let mut instruction = Self::new(Op::Name);
instruction.add_operand(target_id);
Expand Down
2 changes: 1 addition & 1 deletion naga/src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1899,7 +1899,7 @@ impl Writer {
source_code: debug_info.source_code,
source_file_id,
});
self.debugs.push(Instruction::source(
self.debugs.append(&mut Instruction::source_auto_continued(
spirv::SourceLanguage::Unknown,
0,
&debug_info_inner,
Expand Down
7 changes: 7 additions & 0 deletions naga/tests/in/debug-symbol-large-source.param.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(
spv: (
version: (1, 1),
debug: true,
adjust_coordinate_space: false,
),
)
Loading

0 comments on commit b165558

Please sign in to comment.