blob: 079e9ebdd47be3e96ebea26ae9f65d0abc3194ad [file]
/* Copyright (c) 2026 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "debug_descriptor_pass.h"
#include "module.h"
#include <cstdint>
#include <cstring>
#include <iostream>
#include <spirv/unified1/spirv.hpp>
namespace gpuav {
namespace spirv {
// Replace when we have spirv header
[[maybe_unused]] static const uint32_t debug_descriptor_encoding = 1;
[[maybe_unused]] static const uint32_t debug_descriptor_all_encoding = 2;
[[maybe_unused]] static const uint32_t debug_options_none = 0;
[[maybe_unused]] static const uint32_t debug_options_return_early = 1;
[[maybe_unused]] static const uint32_t debug_options_shader_abort = 2;
[[maybe_unused]] static const uint32_t debug_options_use_null_value = 3;
bool DebugDescriptorPass::RequiresInstrumentation(const Instruction& inst, InstructionMeta& meta) {
if (inst.Opcode() == spv::OpExtInst && inst.Word(3) == ext_import_id_) {
meta.target_instruction = &inst;
meta.dump_all = inst.Word(4) == debug_descriptor_all_encoding;
return true;
}
return false;
}
void DebugDescriptorPass::CreateFunctionCall(BasicBlock& block, InstructionIt* inst_it, const InstructionMeta& meta) {
(void)block;
(void)inst_it;
(void)meta;
uint32_t slot = binding_slot_;
(void)slot; // to silent warning until used
}
bool DebugDescriptorPass::Instrument() {
if (module_.interface_.descriptor_mode != vvl::DescriptorModeBuffer &&
module_.interface_.descriptor_mode != vvl::DescriptorModeHeap) {
return false;
}
for (const auto& inst : module_.ext_inst_imports_) {
const char* import_string = inst->GetAsString(2);
if (strcmp(import_string, "NonSemantic.DebugDescriptor") == 0) {
ext_import_id_ = inst->ResultId();
break;
}
}
if (ext_import_id_ == 0) {
return false; // no debug descriptor strings found, early return
}
for (Function& function : module_.functions_) {
if (!function.called_from_target_) {
continue;
}
for (auto block_it = function.blocks_.begin(); block_it != function.blocks_.end(); ++block_it) {
BasicBlock& current_block = **block_it;
cf_.Update(current_block);
if (debug_disable_loops_ && cf_.in_loop) {
continue;
}
auto& block_instructions = current_block.instructions_;
for (auto inst_it = block_instructions.begin(); inst_it != block_instructions.end(); ++inst_it) {
InstructionMeta meta;
if (!RequiresInstrumentation(*(inst_it->get()), meta)) {
continue;
}
instrumentations_count_++;
CreateFunctionCall(current_block, &inst_it, meta);
}
}
}
return instrumentations_count_ != 0;
}
void DebugDescriptorPass::PrintDebugInfo() const {
std::cout << "DebugDescriptorPass instrumentation count: " << instrumentations_count_ << '\n';
}
bool DebugDescriptorPass::Validate(const Function& current_function, const InstructionMeta& meta) {
// TODO - Decide if there is stuff we want to validate here or not
(void)current_function;
(void)meta;
return true;
}
} // namespace spirv
} // namespace gpuav