首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成的SPIR-V代码有什么问题,如何验证?

生成的SPIR-V代码有什么问题,如何验证?
EN

Stack Overflow用户
提问于 2020-07-03 10:41:23
回答 1查看 620关注 0票数 0

我有一些生成的SPIR-V代码,我想使用与vulkan API。但是,当我试图用Exception thrown at 0x00007FFB68D933CB (nvoglv64.dll) in vulkanCompute.exe: 0xC0000005: Access violation reading location 0x0000000000000008.创建样条时,我得到了一个vkCreateComputePipelines

API调用应该很好,因为相同的代码适用于用glslangValidator编译的着色器。因此,我假设生成的SPIR码必须以某种方式被错误地形成。

我用khronos的验证器工具检查了SPIR代码,使用的是spirv-val --target-env vulkan1.1 mainV.spv,没有错误.无论如何,我们也知道这个工具还不完整。

我还尝试使用Radeon来编译我的SPIR代码,它也可以在着色操场上在线获得,这个工具抛出了错误的Error: Error: internal error: Bil::BilInstructionConvert::Create(60) Code Not Tested!,这并没有多大帮助,但是鼓励了这样的假设:代码格式错误。

遗憾的是,SPIR代码很难在这里发布,但是它在着色操场的链接中。

有人知道我的设置有什么问题吗?或者知道如何更好地验证我的SPIR-V代码,而不需要手动检查所有700行代码。

我认为问题不存在,但无论如何,这里是c++主机代码:

代码语言:javascript
复制
#include "vulkan/vulkan.hpp"

#include <iostream>
#include <fstream>
#include <vector>
#define BAIL_ON_BAD_RESULT(result)                             \
if (VK_SUCCESS != (result))                                  \
{                                                            \
  fprintf(stderr, "Failure at %u %s\n", __LINE__, __FILE__); \
  exit(-1);                                                  \
}

VkResult vkGetBestComputeQueueNPH(vk::PhysicalDevice &physicalDevice, uint32_t &queueFamilyIndex)
{

  auto properties = physicalDevice.getQueueFamilyProperties();
  int i = 0;
  for (auto prop : properties)
  {
    vk::QueueFlags maskedFlags = (~(vk::QueueFlagBits::eTransfer | vk::QueueFlagBits::eSparseBinding) & prop.queueFlags);
    if (!(vk::QueueFlagBits::eGraphics & maskedFlags) && (vk::QueueFlagBits::eCompute & maskedFlags))
    {
      queueFamilyIndex = i;
      return VK_SUCCESS;
    }
    i++;
  }
  i = 0;
  for (auto prop : properties)
  {
    vk::QueueFlags maskedFlags = (~(vk::QueueFlagBits::eTransfer | vk::QueueFlagBits::eSparseBinding) & prop.queueFlags);
    if (vk::QueueFlagBits::eCompute & maskedFlags)
    {
      queueFamilyIndex = i;
      return VK_SUCCESS;
    }
    i++;
  }
  return VK_ERROR_INITIALIZATION_FAILED;
}

int main(int argc, const char *const argv[])
{
  (void)argc;
  (void)argv;

  try
  {

    // initialize the vk::ApplicationInfo structure
    vk::ApplicationInfo applicationInfo("VecAdd", 1, "Vulkan.hpp", 1, VK_API_VERSION_1_1);
    
    // initialize the vk::InstanceCreateInfo
    std::vector<char *> layers = {
      "VK_LAYER_LUNARG_api_dump",
      "VK_LAYER_KHRONOS_validation"
    };
    vk::InstanceCreateInfo instanceCreateInfo({}, &applicationInfo, static_cast<uint32_t>(layers.size()), layers.data());

    // create a UniqueInstance
    vk::UniqueInstance instance = vk::createInstanceUnique(instanceCreateInfo);

    auto physicalDevices = instance->enumeratePhysicalDevices();

    for (auto &physicalDevice : physicalDevices)
    {
    
      auto props = physicalDevice.getProperties();

      // get the QueueFamilyProperties of the first PhysicalDevice
      std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
      uint32_t computeQueueFamilyIndex = 0;

      // get the best index into queueFamiliyProperties which supports compute and stuff
      BAIL_ON_BAD_RESULT(vkGetBestComputeQueueNPH(physicalDevice, computeQueueFamilyIndex));

      std::vector<char *>extensions = {"VK_EXT_external_memory_host", "VK_KHR_shader_float16_int8"};
      // create a UniqueDevice
      float queuePriority = 0.0f;

      vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(computeQueueFamilyIndex), 1, &queuePriority);
       vk::StructureChain<vk::DeviceCreateInfo, vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceShaderFloat16Int8Features> createDeviceInfo = {
        vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo, 0, nullptr, static_cast<uint32_t>(extensions.size()), extensions.data()),
        vk::PhysicalDeviceFeatures2(),
        vk::PhysicalDeviceShaderFloat16Int8Features()
      };
      createDeviceInfo.get<vk::PhysicalDeviceFeatures2>().features.setShaderInt64(true);
      createDeviceInfo.get<vk::PhysicalDeviceShaderFloat16Int8Features>().setShaderInt8(true);
      vk::UniqueDevice device = physicalDevice.createDeviceUnique(createDeviceInfo.get<vk::DeviceCreateInfo>());

      auto memoryProperties2 = physicalDevice.getMemoryProperties2();

      vk::PhysicalDeviceMemoryProperties const &memoryProperties = memoryProperties2.memoryProperties;

      const int32_t bufferLength = 16384;

      const uint32_t bufferSize = sizeof(int32_t) * bufferLength;

      // we are going to need two buffers from this one memory
      const vk::DeviceSize memorySize = bufferSize * 3;

      // set memoryTypeIndex to an invalid entry in the properties.memoryTypes array
      uint32_t memoryTypeIndex = VK_MAX_MEMORY_TYPES;

      for (uint32_t k = 0; k < memoryProperties.memoryTypeCount; k++)
      {
        if ((vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent) & memoryProperties.memoryTypes[k].propertyFlags &&
            (memorySize < memoryProperties.memoryHeaps[memoryProperties.memoryTypes[k].heapIndex].size))
        {
          memoryTypeIndex = k;
          std::cout << "found memory " << memoryTypeIndex + 1 << " out of " << memoryProperties.memoryTypeCount << std::endl;
          break;
        }
      }

      BAIL_ON_BAD_RESULT(memoryTypeIndex == VK_MAX_MEMORY_TYPES ? VK_ERROR_OUT_OF_HOST_MEMORY : VK_SUCCESS);

      auto memory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memorySize, memoryTypeIndex));
      auto in_buffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), bufferSize, vk::BufferUsageFlagBits::eStorageBuffer, vk::SharingMode::eExclusive));
      device->bindBufferMemory(in_buffer.get(), memory.get(), 0);
      // create a DescriptorSetLayout
      std::vector<vk::DescriptorSetLayoutBinding> descriptorSetLayoutBinding{
          {0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute}};
      vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), static_cast<uint32_t>(descriptorSetLayoutBinding.size()), descriptorSetLayoutBinding.data()));

      std::cout << "Memory bound" << std::endl;

      std::ifstream myfile;
      myfile.open("shaders/MainV.spv", std::ios::ate | std::ios::binary);

      if (!myfile.is_open())
      {
        std::cout << "File not found" << std::endl;
        return EXIT_FAILURE;
      }

      auto size = myfile.tellg();
      std::vector<unsigned int> shader_spv(size / sizeof(unsigned int));
      myfile.seekg(0);
      myfile.read(reinterpret_cast<char *>(shader_spv.data()), size);
      myfile.close();

      std::cout << "Shader size: " << shader_spv.size() << std::endl;

      auto shaderModule = device->createShaderModuleUnique(vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), shader_spv.size() * sizeof(unsigned int), shader_spv.data()));

      // create a PipelineLayout using that DescriptorSetLayout
      vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get()));

      vk::ComputePipelineCreateInfo computePipelineInfo(
          vk::PipelineCreateFlags(),
          vk::PipelineShaderStageCreateInfo(
              vk::PipelineShaderStageCreateFlags(),
              vk::ShaderStageFlagBits::eCompute,
              shaderModule.get(),
              "_ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEE6VecAdd"),
          pipelineLayout.get());

      auto pipeline = device->createComputePipelineUnique(nullptr, computePipelineInfo);

      auto descriptorPoolSize = vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 2);
      auto descriptorPool = device->createDescriptorPool(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlags(), 1, 1, &descriptorPoolSize));

      auto commandPool = device->createCommandPoolUnique(vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlags(), computeQueueFamilyIndex));

      auto commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front());

      commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit)));

      commandBuffer->bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.get());
    
      commandBuffer->dispatch(bufferSize / sizeof(int32_t), 1, 1);

      commandBuffer->end();

      auto queue = device->getQueue(computeQueueFamilyIndex, 0);

      vk::SubmitInfo submitInfo(0, nullptr, nullptr, 1, &commandBuffer.get(), 0, nullptr);
      queue.submit(1, &submitInfo, vk::Fence());

      queue.waitIdle();

      printf("all done\nWoohooo!!!\n\n");
    }
  }
  catch (vk::SystemError &err)
  {
    std::cout << "vk::SystemError: " << err.what() << std::endl;
    exit(-1);
  }
  catch (std::runtime_error &err)
  {
    std::cout << "std::runtime_error: " << err.what() << std::endl;
    exit(-1);
  }
  catch (...)
  {
    std::cout << "unknown error\n";
    exit(-1);
  }

  return EXIT_SUCCESS;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-08 07:41:40

那么,在签出每行行之后,就会发现问题是当处理指针的指针时,。对我来说,从规范中还不清楚不允许使用它,但可以理解它不适用于逻辑指针。不过,这种行为很奇怪,验证器无法注意到这一点,而且编译SPIRV代码会崩溃,而不是抛出明确的错误消息。所以最终,是阴影代码错了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62713718

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档