0
votes

I follow the instruction in https://developer.android.com/ndk/guides/graphics/shader-compilers?hl=zh-cn ->AOT compilation->Use Android Studio.

AAsset* file = AAssetManager_open(assetManager,
                     "shaders/tri.vert.spv", AASSET_MODE_BUFFER);
size_t fileLength = AAsset_getLength(file);
char* fileContent = new char[fileLength];
AAsset_read(file, fileContent, fileLength);

Here are my vert file and frag file, which are copied from https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Shader_modules. I put these two files in src/main/shaders

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) out vec3 fragColor;

vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);

vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);

void main() {
    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
    fragColor = colors[gl_VertexIndex];
}


#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec3 fragColor;

layout(location = 0) out vec4 outColor;

void main() {
    outColor = vec4(fragColor, 1.0);
}

But I get a message from Validation:

UNASSIGNED-CoreValidation-Shader-InconsistentSpirv(ERROR / SPEC): msgNum: 0 - SPIR-V module not valid: Invalid SPIR-V header. Objects: 1 [0] 0, type: 0, name: NULL

May someone help me to read the .spv? Thanks!


update:

    void createGraphicsPipeline(){
            LOGD("Vulkan createGraphicsPipeline");
    
            auto vertShaderCode = readFile("shaders/shader.frag.spv");
            auto fragShaderCode = readFile("shaders/shader.frag.spv");
            VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
            VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
           
            VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
            vertShaderStageInfo.sType = 
            VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
            vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
            vertShaderStageInfo.module = vertShaderModule;
            vertShaderStageInfo.pName = "main";

            VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
            fragShaderStageInfo.sType = 
            VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
            fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
            fragShaderStageInfo.module = fragShaderModule;
            fragShaderStageInfo.pName = "main";




std::vector<char> readFile(const char* filename){
        if (mAssetManager == NULL) {
            LOGD("Vulkan mAssetManager is null");
        }
        AAsset *asset = AAssetManager_open(mAssetManager, filename,
                AASSET_MODE_BUFFER);
        if (NULL == asset) {
            LOGD("Vulkan shader is null");
            throw std::runtime_error("Vulkan shader is null");
        }

        long size = AAsset_getLength(asset);
        char* fileContent = new char[size];
        AAsset_read(asset, fileContent, size);

        std::vector<char> buffer;
        buffer.insert(buffer.end(), fileContent, fileContent + strlen(fileContent));

        AAsset_close(asset);
        return buffer;
    }

VkShaderModule createShaderModule(const std::vector<char>& code){

        VkShaderModuleCreateInfo createInfo{};
        createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
        createInfo.codeSize = code.size();
        createInfo.pCode = reinterpret_cast<const uint32_t *>(code.data());
        VkShaderModule shaderModule;
        if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
            LOGD("failed to create shader module!");
            throw std::runtime_error("failed to create shader module!");
        }
        return shaderModule;
    }

update: Get errors after changing into "fileContent + size"

2021-05-10 16:59:36.310 8124-8124/com.example.vtest2 I/VALIDATION: VUID-VkPipelineShaderStageCreateInfo-pName-00707(ERROR / SPEC): msgNum: 0 - No entrypoint found named main for stage VK_SHADER_STAGE_VERTEX_BIT.. The Vulkan spec states: pName must be the name of an OpEntryPoint in module with an execution model that matches stage (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkPipelineShaderStageCreateInfo-pName-00707) Objects: 1 [0] 0, type: 0, name: NULL

2021-05-10 16:59:36.310 8124-8124/com.example.vtest2 I/VALIDATION: UNASSIGNED-CoreValidation-Shader-InputNotProduced(ERROR / SPEC): msgNum: 0 - fragment shader consumes input location 0.0 which is not written by vertex shader Objects: 1 [0] 0xd, type: 15, name: NULL

2
Can you please add the part where you pass the shader code to vkCreateShaderModule. I expect the error to be there.Sascha Willems
update, thanks so much for helping!@SaschaWillemsdreakzts

2 Answers

1
votes

You are loading the fragment shader for both the fragment and vertex stage:

auto vertShaderCode = readFile("shaders/shader.frag.spv");
auto fragShaderCode = readFile("shaders/shader.frag.spv");

the first line should probably read:

auto vertShaderCode = readFile("shaders/shader.vert.spv");

If you read the validation error carefully, it tells you that the fragment shader was successfully loaded, so your code to load shaders is fine. But the first message hints at a problem with the wrong shader being loaded in the vertex stage as noted above.

0
votes

fileContent + strlen(fileContent) This bit looks suspicous. If fileContent is SPIR-V then it's a list of u32s. With strlen you're assuming it's a c string (perhaps a remnant from when your file used to contain source code instead of compiled SPIR-V).

Try changing it to fileContent + size