Skip to content
Snippets Groups Projects
spirv.c 116 KiB
Newer Older
    uint32_t param_type_id[MAX_REG_OUTPUT], param_id[MAX_REG_OUTPUT] = {};
    struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
    DWORD write_mask, reg_idx;
    unsigned int i, count;

    function_id = compiler->output_setup_function_id;

    void_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_VOID, 1);
    type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, 4);
    ptr_type_id = vkd3d_dxbc_compiler_get_pointer_type(compiler, type_id, SpvStorageClassPrivate);
    for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
    {
        if (compiler->private_output_variable[i])
            param_type_id[count++] = ptr_type_id;
    }
    function_type_id = vkd3d_spirv_build_op_type_function(builder, void_id, param_type_id, count);

    vkd3d_spirv_build_op_function(builder, void_id, function_id,
            SpvFunctionControlMaskNone, function_type_id);
    vkd3d_spirv_build_op_name(builder, function_id, "setup_output");

    for (i = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
    {
        if (compiler->private_output_variable[i])
            param_id[i] = vkd3d_spirv_build_op_function_parameter(builder, ptr_type_id);
    }

    vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));

    for (i = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
    {
        if (compiler->private_output_variable[i])
            param_id[i] = vkd3d_spirv_build_op_load(builder, type_id, param_id[i], SpvMemoryAccessMaskNone);
    }

    for (i = 0; i < signature->element_count; ++i)
    {
        reg_idx = signature->elements[i].register_idx;
        write_mask = signature->elements[i].mask & 0xff;

        if (!param_id[reg_idx])
            continue;

        val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, param_id[reg_idx], VKD3DSP_NOSWIZZLE, write_mask);

        if (compiler->output_info[i].component_type != VKD3D_TYPE_FLOAT)
        {
            type_id = vkd3d_spirv_get_type_id(builder, compiler->output_info[i].component_type,
                    vkd3d_write_mask_component_count(write_mask));
            val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
        }

        vkd3d_spirv_build_op_store(builder, compiler->output_info[i].id, val_id, SpvMemoryAccessMaskNone);
    }

    vkd3d_spirv_build_op_return(&compiler->spirv_builder);
    vkd3d_spirv_build_op_function_end(builder);
}

bool vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
        struct vkd3d_shader_code *spirv)
{
    struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;

    if (compiler->options & VKD3D_SHADER_STRIP_DEBUG)
        vkd3d_spirv_stream_clear(&builder->debug_stream);

    vkd3d_spirv_build_op_function_end(builder);

    if (compiler->output_setup_function_id)
        vkd3d_dxbc_compiler_emit_output_setup_function(compiler);

    if (!vkd3d_spirv_compile_module(builder, spirv))
        return false;

    if (TRACE_ON())
    {
        vkd3d_spirv_dump(spirv);
        vkd3d_spirv_validate(spirv);
    }

    return true;
}

void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler)
{
    vkd3d_spirv_builder_free(&compiler->spirv_builder);

    rb_destroy(&compiler->symbol_table, vkd3d_symbol_free, NULL);