如何打印 Spir-V OpConstant 的文字值?

问题描述 投票:0回答:1

我有一个来自 Github 的 Spir-V 解析器,它能够处理和修改 Spir-V 二进制文件。目前,我只想打印出

OpConstant
变量的字面值。 不幸的是,它没有打印出正确的值。 为了测试该应用程序,我将一个非常简单的 glsl 着色器转换为 Spir-V,然后使用下面的代码。

我的问题是我无法打印出

OpConstant
的字面值。它应该是常数的第四个词。
operands
指针应该表示第二个单词,所以这就是为什么我在写出字面值时添加+2。您可以在下图中看到
OpConstant
的结构。

OpConstant word order 然而,它并不像着色器中那样

18.0f
。我还尝试进一步移动指针,因此在指针指向的地址上添加+1。

着色器是这样的:

#version 450
float value = 18.0f;

void main() {
}

这是完整的解析器代码。只需一个cpp:

#include <stdint.h>
#include <stdlib.h>
#include <string>
#include <direct.h> // _getcwd
#include <stdio.h>  // printf
#include <string.h> // strlen
#include <iostream>
#include <stddef.h>
#include <stdio.h>

#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#else
static inline uint32_t bswap_32(uint32_t x) {
    return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) |
        ((x & 0x0000ff00) << 8) | ((x & 0x000000ff) << 24);
}
#endif

struct sv_instr {
    uint16_t word_count;
    uint16_t opcode;
    uint32_t* operands;
};

struct sv_module {
    uint32_t magic;
    uint32_t version;
    uint32_t generator;
    uint32_t bound;
    uint32_t reserved;

    struct sv_instr* instrs;
    int num_instrs;
};

#define SV_MAGIC 0x07230203
#define SV_MAGIC_REV 0x03022307


int sv_read_instr(struct sv_instr* dst, uint32_t** words, int* num_words) {
    if (*num_words < 1)
        return -1;

    dst->word_count = **words >> 16;
    dst->opcode = **words & 0xFFFF;

    /*
     * WordCount needs to be at least 1, to encode the WordCount and
     * Opcode itself
     */
    if (dst->word_count < 1)
        return -1; /* malformed instruction */

    if (dst->word_count > *num_words)
        return -1; /* not enough data */

    dst->operands = *words+1;
        
    *words += dst->word_count;
    *num_words -= dst->word_count;
    return 0;
}

int sv_read(struct sv_module* dst, uint32_t* words, int num_words) {
    /* check if we have enough data to read header */
    if (num_words < 5)
        return -1;

    dst->magic = *words++;
    dst->version = *words++;
    dst->generator = *words++;
    dst->bound = *words++;
    dst->reserved = *words++;

    /* verify header-data */
    if (dst->magic != SV_MAGIC)
        return -1;

    num_words -= 5;

    dst->instrs = NULL;
    dst->num_instrs = 0;
    while (num_words > 0) {
        struct sv_instr instr;
        if (sv_read_instr(&instr, &words, &num_words) < 0)
            return -1;

        dst->instrs = (sv_instr*)realloc(dst->instrs, (dst->num_instrs + 1) * sizeof(instr));
        if (!dst->instrs)
            return -1;

        dst->instrs[dst->num_instrs++] = instr;
    }

    return 0;
}


int main() {

    const char* filename = "x64\\Debug\\shader.vert.spv";

    FILE* file = NULL;
    errno_t err = fopen_s(&file, filename, "rb");
    if (err != 0) {
        perror("fopen_s");
        return 1;
    }

    struct sv_module mod;
    uint32_t word, * words = NULL;
    int num_words = 0, i;

    while (fread(&word, 4, 1, file) == 1) {
        words = (uint32_t*)realloc(words, (num_words + 1) * 4);
        if (!words) {
            perror("realloc");
            fclose(file);
            abort();
        }
        words[num_words++] = word;
    }

    fclose(file);

    /* byte-swap input if needed */
    if (num_words > 0 && words[0] == SV_MAGIC_REV)
        for (i = 0; i < num_words; ++i)
            words[i] = bswap_32(words[i]);

    printf("words: %d\n", num_words);

    if (sv_read(&mod, words, num_words) < 0) {
        fprintf(stderr, "failed to read SPIR-V module\n");
        return 1;
    }

    for (i = 0; i < mod.num_instrs; ++i) {
        if (mod.instrs[i].opcode == 43) {  // getting the OpConstant
            // printing out the literal value
            std::cout << *(mod.instrs[i].operands+2) << std::endl;
        }
    }

    return 0;
}
parsing bytecode opcode spir-v
1个回答
0
投票

代码很好,但是如果您想获取 OpConstant 的字面值,请使用

*reinterpret_cast<>()
来检索它,如下所示:

 std::cout << *reinterpret_cast<float*>(mod.instrs[i].operands+2) << std::endl;
© www.soinside.com 2019 - 2024. All rights reserved.