Exemplo n.º 1
0
t_env		*wolf3d_init(int ac, char **av)
{
	t_env *env;

	if (!(env = (t_env*)malloc(sizeof(t_env))))
		wolf3d_exit(&env, "wolf3d_init: malloc");
	env->color = color_get(255, 255, 255, 0);
	env->dist = 0;
	env->ac = ac;
	env->av = av;
	env->ray.dir.x = 0;
	env->ray.dir.x = 0;
	env->ray.inter.x = 0;
	env->ray.inter.x = 0;
	env->ev_draw_map = 0;
	env->ev_color = 0;
	wolf3d_map_load(env);
	if (wolf3d_player_init(env) == 0)
		wolf3d_exit(&env, "Place a '#' in map to have a spawn !");
	if (((env)->mlx = mlx_init()) == NULL)
		wolf3d_exit(&env, "wolf3d_init: mlx_init");
	if ((env->win = mlx_new_window(env->mlx, WIDTH, HEIGHT, TITLE)) == NULL)
		wolf3d_exit(&env, "wolf3d_init: mlx_new_window");
	(env)->img = NULL;
	img_clear(env);
	init_texture(env);
	return (env);
}
Exemplo n.º 2
0
	void Grass::Init()
	{
		init_shader();
		init_buffer();
		init_vertexArray();
		init_texture();
	}
Exemplo n.º 3
0
Arquivo: menu.c Projeto: telenc/wolf3d
void	init_load(t_wolf *wolf)
{
  void	*img;
  int	w;
  int	h;
  int	bpp;
  int	size_line;
  int	endian;

  wolf->screen = 1;
  w = 1000;
  h = 800;
  if (wolf->texture == NULL)
    {
      wolf->texture = my_malloc(sizeof(t_texture));
      wolf->texture->load = NULL;
      wolf->texture->wall_one = NULL;
    }
  if (wolf->texture->load == NULL)
    wolf->texture->load = create_texture("texture/load.xpm", wolf);
  if (wolf->texture->wall_one == NULL)
    init_texture(wolf);
  mlx_put_image_to_window(wolf->mlx, wolf->win,
			  wolf->texture->load->image, 0, 0);
}
Exemplo n.º 4
0
	void Cube::init()
	{
		init_shader();
		init_buffer();
		init_vertexArray();
		init_texture();
	}
Exemplo n.º 5
0
void Rectangle::Init()
{
	init_buffer();
	init_vertexArray();
	init_shader();
	init_texture();
}
Exemplo n.º 6
0
void Cube::Init(ID3D11Device *pD3D11Device, ID3D11DeviceContext *pD3D11DeviceContext, HWND hWnd)
{
 
	init_buffer(pD3D11Device, pD3D11DeviceContext);
	init_shader(pD3D11Device, hWnd);
	init_texture(pD3D11Device);
}
Exemplo n.º 7
0
int init_opengl()
{
    GLuint v, f;

    view_width = 320;
    view_height = 200;

    v = u2gl_compile_vertex_shader(vertex_shader_texture);
    f = u2gl_compile_fragment_shader(fragment_shader_texture);
    u2gl_create_program(&bg_program, f, v);
    u2gl_check_error("create program bg");

    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);

    //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glClearColor(.0, .0, .0, 0);
    u2gl_check_error("init_opengl");

    init_texture();
    u2gl_check_error("init_texture");

    u2gl_projection(0, view_width, 0, view_height, &bg_program);

    return 0;
}
Exemplo n.º 8
0
void		opengl_before_loop(t_opengl *o)
{
	o->m_projection = matrice_projection(60.0f, 1.0f, 100.0f);
	o->m_view = matrice_init();
	o->m_view.mat[3][2] = 10;
	o->m_view.mat[3][1] = -3;
	o->m_model = matrice_init();
	o->m_rotate = matrice_rotate_y(3);
	o->program = load_program();
	o->m_view_location = glGetUniformLocation(o->program, "view");
	o->m_model_location = glGetUniformLocation(o->program, "model");
	o->m_projection_location = glGetUniformLocation(o->program, "projection");
	glGenBuffers(1, &(o->vertex_buffer));
	glBindBuffer(GL_ARRAY_BUFFER, o->vertex_buffer);
	glBufferData(GL_ARRAY_BUFFER, listvertex_size(o->listvertex)
		* sizeof(float), o->buffvertex, GL_STATIC_DRAW);
	glGenBuffers(1, &(o->element_buffer));
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, o->element_buffer);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, listfragment_size(o->listfragment)
		* sizeof(int), o->bufffragment, GL_STATIC_DRAW);
	glGenBuffers(1, &o->normal_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, o->normal_buffer);
	glBufferData(GL_ARRAY_BUFFER, listvertex_size(o->listvertex)
		* sizeof(float), &o->buffnormal[0].x, GL_STATIC_DRAW);
	init_texture(o);
}
Exemplo n.º 9
0
	void Scene::Init()
	{
		init_buffer();
		init_vertexArray();
		init_shader();
		init_texture();
		oglDebug.Debug();
	}
Exemplo n.º 10
0
void TriangleApp::init()
{
	init_shader();
	init_buffer();
	init_vertexArray();
	init_texture();
	init_windowInfo();
}
Exemplo n.º 11
0
	void Plane::init()
	{

		m_LightGUI.v_init();

		init_buffer();
		init_vertexArray();
		init_shader();
		init_texture();
	}
Exemplo n.º 12
0
void initialize()
{
    void *host_addr = memalign(1024*1024,HOST_SIZE);
    void *main_addr = (void*)((u64)host_addr + CB_SIZE);

    init_spu();
    init_screen(host_addr,HOST_SIZE);
    init_shader();
    init_texture();
    init_memory(main_addr,(HOST_SIZE - CB_SIZE));
}
Exemplo n.º 13
0
int tfont_init() {
    if(_tfont_init)
        return 1;

    load_image();
    init_texture();
    init_text_buf();

    _tfont_init = 1;
    return 1;
}
Exemplo n.º 14
0
void init_draw_model()
{
    load_model();
    init_shader();
    init_texture();

    const static unsigned int stride = sizeof(struct Vertex);
    glGenBuffers(1, &monster_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, monster_vbo);
    glBufferData(GL_ARRAY_BUFFER, v_num*stride, v_array, GL_STATIC_DRAW);

}
JNIEXPORT jboolean JNICALL
Java_com_parrot_freeflight_activities_base_ParrotCardboardActivity_onUpdateVideoTextureOriNative(JNIEnv *env, jobject obj, jint program, jint textureId)
{
	if (texture_initialized == FALSE) {
		init_texture();
		texture_initialized = TRUE;
	}

	opengl_video_stage_config_t *config = opengl_video_stage_get();

	if ((config != NULL) && (config->data != NULL) && (config->num_picture_decoded > current_num_picture_decoded))
	{
		if (texture.image_size.width != config->widthImage) {
			recalculate_video_texture = TRUE;
		}

		texture.bytesPerPixel       = config->bytesPerPixel;
		texture.image_size.width    = config->widthImage;
		texture.image_size.height   = config->heightImage;
		texture.texture_size.width	= config->widthTexture;
		texture.texture_size.height	= config->heightTexture;
		texture.format              = config->format;
		texture.type                = config->type;
		texture.data                = config->data;
		texture.state = OPENGL_STATE_GENERATED;

		current_num_picture_decoded = config->num_picture_decoded;
		current_num_frames = config->num_frames;
	}

	if (recalculate_video_texture) {
		recalculate_video_texture_bounds(env, obj, &texture);
		recalculate_video_texture = FALSE;
	}

	if(texture.state == OPENGL_STATE_GENERATED)
	{
		// Load the texture in the GPU
		if (texture.data != NULL) {
//			LOGD("GL_BG_VIDEO_SPRITE", "fmt: %d, w: %f, h: %f, type: %d, data: %p", texture.format, texture.texture_size.width, texture.texture_size.height, texture.type, texture.data);
//			glTexSubImage2D(GL_TEXTURE_2D, 0, texture.texture_size.width/4, 0, texture.texture_size.width/2, texture.texture_size.height, texture.format, texture.type, texture.data);
			glActiveTexture(textureId);
			glBindTexture(GL_TEXTURE_2D, textureId);
			glTexImage2D(GL_TEXTURE_2D, 0, texture.format, texture.texture_size.width, texture.texture_size.height, 0, texture.format, texture.type, texture.data);
			texture.state = OPENGL_STATE_SEND_TO_GPU;

			return TRUE;
		}
	}

	return FALSE;
}
Exemplo n.º 16
0
static void setup_opengl(ModeInfo *mi, jigglystruct *js)
{
    const GLfloat lpos0[4] = {-12, 8, 12, 0};
    const GLfloat lpos1[4] = {7, -5, 0, 0};
    const GLfloat lcol0[4] = {0.7f, 0.7f, 0.65f, 1};
    const GLfloat lcol1[4] = {0.3f, 0.2f, 0.1f, 1};
    const GLfloat scolor[4]= {0.9f, 0.9f, 0.9f, 0.5f};

    glDrawBuffer(GL_BACK);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);

    if(js->do_wireframe) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    }
    else {
        glCullFace(GL_BACK);
        glFrontFace(GL_CW);
        glEnable(GL_CULL_FACE);
    }

    if(js->color_style != COLOR_STYLE_CHROME) {
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHT1);

        glLightfv(GL_LIGHT0, GL_POSITION, lpos0);
        glLightfv(GL_LIGHT1, GL_POSITION, lpos1);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol0);
        glLightfv(GL_LIGHT1, GL_DIFFUSE, lcol1);

        glEnable(GL_COLOR_MATERIAL);
        glColor4fv(js->jiggly_color);

        glMaterialfv(GL_FRONT, GL_SPECULAR, scolor);
        glMateriali(GL_FRONT, GL_SHININESS, js->shininess);
    }
    else { /* chrome */
        init_texture(mi);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
        glEnable(GL_TEXTURE_GEN_S);
        glEnable(GL_TEXTURE_GEN_T);
        glEnable(GL_TEXTURE_2D);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    }
}
Exemplo n.º 17
0
int main(int argc,const char *argv[])
{
	s32 ret,i;
	padInfo padinfo;
	padData paddata;
	void *host_addr = memalign(1024*1024,HOST_SIZE);

	printf("rsxtest started...\n");

	init_screen(host_addr,HOST_SIZE);
	ioPadInit(7);
	init_shader();
	init_texture();

	sphere = createSphere(3.0f,32,32);
	donut = createDonut(3.0f,1.5f,32,32);
	cube = createCube(5.0f);

	ret = atexit(program_exit_callback);
	ret = sysUtilRegisterCallback(0,sysutil_exit_callback,NULL);

	P = transpose(Matrix4::perspective(DEGTORAD(45.0f),aspect_ratio,1.0f,3000.0f));

	setTexture();
	setDrawEnv();
	setRenderTarget(curr_fb);

	running = 1;
	while(running) {
		ret = sysUtilCheckCallback();

		ioPadGetInfo(&padinfo);
		for(i=0; i<MAX_PADS; i++){
			if(padinfo.status[i]){
				ioPadGetData(i, &paddata);

				if(paddata.BTN_CROSS){
					return 0;
				}
			}

		}
		
		drawFrame();
		flip();
	}

	return 0;
}
Exemplo n.º 18
0
int main(void)
{
	device_t device;
	int states[] = { RENDER_STATE_TEXTURE, RENDER_STATE_COLOR, RENDER_STATE_WIREFRAME };
	int indicator = 0;
	int kbhit = 0;
	float alpha = 1;
	float pos = 3.5;

	TCHAR *title = _T("Mini3d (software render tutorial) - ")
		_T("Left/Right: rotation, Up/Down: forward/backward, Space: switch state");

	if (screen_init(800, 600, title))
		return -1;

	device_init(&device, 800, 600, screen_fb);
	camera_at_zero(&device, 3, 0, 0);

	init_texture(&device);
	device.render_state = RENDER_STATE_TEXTURE;

	while (screen_exit == 0 && screen_keys[VK_ESCAPE] == 0) {
		screen_dispatch();
		device_clear(&device, 1);
		camera_at_zero(&device, pos, 0, 0);

		if (screen_keys[VK_UP]) pos -= 0.01f;
		if (screen_keys[VK_DOWN]) pos += 0.01f;
		if (screen_keys[VK_LEFT]) alpha += 0.01f;
		if (screen_keys[VK_RIGHT]) alpha -= 0.01f;

		if (screen_keys[VK_SPACE]) {
			if (kbhit == 0) {
				kbhit = 1;
				if (++indicator >= 3) indicator = 0;
				device.render_state = states[indicator];
			}
		}
		else {
			kbhit = 0;
		}

		draw_box(&device, alpha);
		screen_update();
		Sleep(1);
	}
	return 0;
}
Exemplo n.º 19
0
void config::bind_field(vector_field const& vf) {
   
   glm::vec2 interval(vf.min_,vf.max_);
   pipeline_.uniforms_.set("interval", interval);
   pipeline_.set_link("glyph","interval");
   pipeline_.set_link("streamline","interval");

   glm::ivec3 dim(vf.dim_[0],vf.dim_[1],vf.dim_[2]);
   pipeline_.uniforms_.set("dim", dim);
   pipeline_.set_link("glyph","dim");
   pipeline_.set_link("streamline","dim");
   pipeline_.set_link("bounding_box","dim");

   init_memory(vf.dim_);
   init_texture(vf);
}
Exemplo n.º 20
0
void initDefault(void)
{
    armData.x = 0.0;
    armData.y = (LARGE_CUBE_SIZE /2 )-1;
    armData.z = 0.0;
    armData.visible = UNVISIBLE;
    armData.inputDirection = INPUT_NO_DIRECTION;
    armData.inputEnable = INPUT_ENABLE;
    armData.inAnimation = IN_CONTROL;
    armData.counter = 0;

    init_light();
    init_texture();
    init_object();

}
Exemplo n.º 21
0
TextureAtlas::TextureAtlas(const std::string image_path):
    image(image_path, true),
    gl_image(image),
    gl_texture(0),
    reshaped(false),
    unit_w(Engine::get_tile_size()),
    unit_h(Engine::get_tile_size()),
    unit_columns(image.width  / unit_w),
    unit_rows   (image.height / unit_h),
    textures(unit_columns * unit_rows),
    sub_atlases(),
    super_atlas(),
    names_to_indexes(),
    indexes_to_names(unit_columns * unit_rows)
{
    init_texture();
}
Exemplo n.º 22
0
int main()
{
	init_display();
	if ( glGetError() != 0 )
	{
		printf("display : error\n");
		exit(-1);
	}

	init_shaders();
	if ( glGetError() != 0 )
	{
		printf("shader : error\n");
		exit(-1);
	}

	init_mesh();
	if ( glGetError() != 0 )
	{
		printf("mesh : error\n");
		exit(-1);
	}

	init_texture();
	if ( glGetError() != 0 )
	{
		printf("texture : error\n");
		exit(-1);
	}

	init_info();
	if ( glGetError() != 0 )
	{
		printf("init_info : error\n");
		exit(-1);
	}

	draw_loop();

	return (0);
}
Exemplo n.º 23
0
	void initData() {
	
		WindowManager::Instance().setFPS(30);
		textureNo = LoadTexture(L"1.BMP", *device);
		if (textureNo == -1) {
			init_texture();
		}
		initObject();
		device->setBGColor(0xFFFFFF);
		device->setRenderState(cubeNo, MAPPING);
		device->setCullBack(true);
		//device->setCVVCheck(true);
		device->setLightPosition(Light0, vector_c(4, 7, 4));
		//device->setLight(Light0, AMBIENT, Color(0xFF0000));
		device->setLight(Light0, DIFFUSE, Color(0x00FF00));
		device->activeLight(Light0);
		SetKeyFunction(VK_UP, Main::forward);
		SetKeyFunction(VK_DOWN, Main::backward);
		SetKeyFunction(VK_LEFT, Main::left);
		SetKeyFunction(VK_RIGHT, Main::right);
		SetKeyFunction(VK_SPACE, Main::space);
	}
Exemplo n.º 24
0
void
init_OGL() {
	//Vars for whiteTexture
	ImageFormat format;
	unsigned char data;

	program = malloc(sizeof(Program));
	fragShader = malloc(sizeof(Shader));
	vertexShader = malloc(sizeof(Shader));

	vertPosAttrib = malloc(sizeof(Attribute));
	texCoordAttrib = malloc(sizeof(Attribute));
	
	colorUni = malloc(sizeof(Uniform));
	diffuseSamplerUni = malloc(sizeof(Uniform));

	init_shader_from_file(fragShader, FRAGMENT_SHADER, FRAGMENT_SHADER_LOC);
	init_shader_from_file(vertexShader, VERTEX_SHADER, VERTEX_SHADER_LOC);
	init_program(program, fragShader, vertexShader);
	init_attribute(vertPosAttrib, program, SVAR_VEC2, "vertPos");
	init_attribute(texCoordAttrib, program, SVAR_VEC2, "texCoord");
	init_uniform(colorUni, program, SVAR_VEC4, "color");
	init_uniform(diffuseSamplerUni, program, SVAR_SAMPLER2D, "diffuse");
	

	//Create white texture
	whiteTexture = malloc(sizeof(Texture));
	format = TEX_FMT_RED;
	data = 0xFF; //White
	init_texture(whiteTexture, format, 1, 1, &data);


	//Set default color to white
	colorRed = 1;
	colorGreen = 1;
	colorBlue = 1;
	colorAlpha = 1;
}
Exemplo n.º 25
0
    void process_depth(astra::Frame& frame)
    {
        const astra::PointFrame pointFrame = frame.get<astra::PointFrame>();

        const int width = pointFrame.width();
        const int height = pointFrame.height();

        init_texture(width, height);

        visualizer_.update(pointFrame);
        const astra::RgbPixel* vizBuffer = visualizer_.get_output();

        for (int i = 0; i < width * height; i++)
        {
            const int rgbaOffset = i * 4;
            displayBuffer_[rgbaOffset] = vizBuffer[i].r;
            displayBuffer_[rgbaOffset + 1] = vizBuffer[i].b;
            displayBuffer_[rgbaOffset + 2] = vizBuffer[i].g;
            displayBuffer_[rgbaOffset + 3] = 255;
        }

        texture_.update(displayBuffer_.get());
    }
int sample_main(int argc, char *argv[]) {
    VkResult U_ASSERT_ONLY res;
    struct sample_info info = {};
    char sample_title[] = "Secondary command buffers";
    const bool depthPresent = true;

    process_command_line_args(info, argc, argv);
    init_global_layer_properties(info);
    init_instance_extension_names(info);
    init_device_extension_names(info);
    init_instance(info, sample_title);
    init_enumerate_device(info);
    init_window_size(info, 500, 500);
    init_connection(info);
    init_window(info);
    init_swapchain_extension(info);
    init_device(info);
    init_command_pool(info);
    init_command_buffer(info);
    execute_begin_command_buffer(info);
    init_device_queue(info);
    init_swap_chain(info);
    init_depth_buffer(info);
    init_uniform_buffer(info);
    init_descriptor_and_pipeline_layouts(info, true);
    init_renderpass(info, depthPresent, true, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
    init_shaders(info, vertShaderText, fragShaderText);
    init_framebuffers(info, depthPresent);
    init_vertex_buffer(info, g_vb_texture_Data, sizeof(g_vb_texture_Data), sizeof(g_vb_texture_Data[0]), true);
    init_pipeline_cache(info);
    init_pipeline(info, depthPresent);

    // we have to set up a couple of things by hand, but this
    // isn't any different to other examples

    // get two different textures
    init_texture(info, "green.ppm");
    VkDescriptorImageInfo greenTex = info.texture_data.image_info;

    init_texture(info, "lunarg.ppm");
    VkDescriptorImageInfo lunargTex = info.texture_data.image_info;

    // create two identical descriptor sets, each with a different texture but
    // identical UBOa
    VkDescriptorPoolSize pool_size[2];
    pool_size[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    pool_size[0].descriptorCount = 2;
    pool_size[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    pool_size[1].descriptorCount = 2;

    VkDescriptorPoolCreateInfo descriptor_pool = {};
    descriptor_pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    descriptor_pool.pNext = NULL;
    descriptor_pool.flags = 0;
    descriptor_pool.maxSets = 2;
    descriptor_pool.poolSizeCount = 2;
    descriptor_pool.pPoolSizes = pool_size;

    res = vkCreateDescriptorPool(info.device, &descriptor_pool, NULL, &info.desc_pool);
    assert(res == VK_SUCCESS);

    VkDescriptorSetLayout layouts[] = {info.desc_layout[0], info.desc_layout[0]};

    VkDescriptorSetAllocateInfo alloc_info[1];
    alloc_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    alloc_info[0].pNext = NULL;
    alloc_info[0].descriptorPool = info.desc_pool;
    alloc_info[0].descriptorSetCount = 2;
    alloc_info[0].pSetLayouts = layouts;

    info.desc_set.resize(2);
    res = vkAllocateDescriptorSets(info.device, alloc_info, info.desc_set.data());
    assert(res == VK_SUCCESS);

    VkWriteDescriptorSet writes[2];

    writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
    writes[0].pNext = NULL;
    writes[0].dstSet = info.desc_set[0];
    writes[0].descriptorCount = 1;
    writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    writes[0].pBufferInfo = &info.uniform_data.buffer_info;
    writes[0].dstArrayElement = 0;
    writes[0].dstBinding = 0;

    writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
    writes[1].pNext = NULL;
    writes[1].dstSet = info.desc_set[0];
    writes[1].dstBinding = 1;
    writes[1].descriptorCount = 1;
    writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    writes[1].pImageInfo = &greenTex;
    writes[1].dstArrayElement = 0;

    vkUpdateDescriptorSets(info.device, 2, writes, 0, NULL);

    writes[0].dstSet = writes[1].dstSet = info.desc_set[1];
    writes[1].pImageInfo = &lunargTex;

    vkUpdateDescriptorSets(info.device, 2, writes, 0, NULL);

    /* VULKAN_KEY_START */

    // create four secondary command buffers, for each quadrant of the screen

    VkCommandBufferAllocateInfo cmdalloc = {};
    cmdalloc.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    cmdalloc.pNext = NULL;
    cmdalloc.commandPool = info.cmd_pool;
    cmdalloc.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
    cmdalloc.commandBufferCount = 4;

    VkCommandBuffer secondary_cmds[4];

    res = vkAllocateCommandBuffers(info.device, &cmdalloc, secondary_cmds);
    assert(res == VK_SUCCESS);

    VkClearValue clear_values[2];
    clear_values[0].color.float32[0] = 0.2f;
    clear_values[0].color.float32[1] = 0.2f;
    clear_values[0].color.float32[2] = 0.2f;
    clear_values[0].color.float32[3] = 0.2f;
    clear_values[1].depthStencil.depth = 1.0f;
    clear_values[1].depthStencil.stencil = 0;

    VkSemaphore imageAcquiredSemaphore;
    VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo;
    imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    imageAcquiredSemaphoreCreateInfo.pNext = NULL;
    imageAcquiredSemaphoreCreateInfo.flags = 0;

    res = vkCreateSemaphore(info.device, &imageAcquiredSemaphoreCreateInfo, NULL, &imageAcquiredSemaphore);
    assert(res == VK_SUCCESS);

    // Get the index of the next available swapchain image:
    res = vkAcquireNextImageKHR(info.device, info.swap_chain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE,
                                &info.current_buffer);
    // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
    // return codes
    assert(res == VK_SUCCESS);

    set_image_layout(info, info.buffers[info.current_buffer].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                     VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);

    const VkDeviceSize offsets[1] = {0};

    VkViewport viewport;
    viewport.height = 200.0f;
    viewport.width = 200.0f;
    viewport.minDepth = (float)0.0f;
    viewport.maxDepth = (float)1.0f;
    viewport.x = 0;
    viewport.y = 0;

    VkRect2D scissor;
    scissor.extent.width = info.width;
    scissor.extent.height = info.height;
    scissor.offset.x = 0;
    scissor.offset.y = 0;

    // now we record four separate command buffers, one for each quadrant of the
    // screen
    VkCommandBufferInheritanceInfo cmd_buf_inheritance_info = {};
    cmd_buf_inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, cmd_buf_inheritance_info.pNext = NULL;
    cmd_buf_inheritance_info.renderPass = info.render_pass;
    cmd_buf_inheritance_info.subpass = 0;
    cmd_buf_inheritance_info.framebuffer = info.framebuffers[info.current_buffer];
    cmd_buf_inheritance_info.occlusionQueryEnable = VK_FALSE;
    cmd_buf_inheritance_info.queryFlags = 0;
    cmd_buf_inheritance_info.pipelineStatistics = 0;

    VkCommandBufferBeginInfo secondary_begin = {};
    secondary_begin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    secondary_begin.pNext = NULL;
    secondary_begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
    secondary_begin.pInheritanceInfo = &cmd_buf_inheritance_info;

    for (int i = 0; i < 4; i++) {
        vkBeginCommandBuffer(secondary_cmds[i], &secondary_begin);

        vkCmdBindPipeline(secondary_cmds[i], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
        vkCmdBindDescriptorSets(secondary_cmds[i], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0, 1,
                                &info.desc_set[i == 0 || i == 3], 0, NULL);

        vkCmdBindVertexBuffers(secondary_cmds[i], 0, 1, &info.vertex_buffer.buf, offsets);

        viewport.x = 25.0f + 250.0f * (i % 2);
        viewport.y = 25.0f + 250.0f * (i / 2);
        vkCmdSetViewport(secondary_cmds[i], 0, NUM_VIEWPORTS, &viewport);

        vkCmdSetScissor(secondary_cmds[i], 0, NUM_SCISSORS, &scissor);

        vkCmdDraw(secondary_cmds[i], 12 * 3, 1, 0, 0);

        vkEndCommandBuffer(secondary_cmds[i]);
    }

    VkRenderPassBeginInfo rp_begin;
    rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    rp_begin.pNext = NULL;
    rp_begin.renderPass = info.render_pass;
    rp_begin.framebuffer = info.framebuffers[info.current_buffer];
    rp_begin.renderArea.offset.x = 0;
    rp_begin.renderArea.offset.y = 0;
    rp_begin.renderArea.extent.width = info.width;
    rp_begin.renderArea.extent.height = info.height;
    rp_begin.clearValueCount = 2;
    rp_begin.pClearValues = clear_values;

    // specifying VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS means this
    // render pass may
    // ONLY call vkCmdExecuteCommands
    vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);

    vkCmdExecuteCommands(info.cmd, 4, secondary_cmds);

    vkCmdEndRenderPass(info.cmd);

    VkImageMemoryBarrier prePresentBarrier = {};
    prePresentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    prePresentBarrier.pNext = NULL;
    prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    prePresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
    prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    prePresentBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    prePresentBarrier.subresourceRange.baseMipLevel = 0;
    prePresentBarrier.subresourceRange.levelCount = 1;
    prePresentBarrier.subresourceRange.baseArrayLayer = 0;
    prePresentBarrier.subresourceRange.layerCount = 1;
    prePresentBarrier.image = info.buffers[info.current_buffer].image;
    vkCmdPipelineBarrier(info.cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL,
                         0, NULL, 1, &prePresentBarrier);

    res = vkEndCommandBuffer(info.cmd);
    assert(res == VK_SUCCESS);

    const VkCommandBuffer cmd_bufs[] = {info.cmd};
    VkFenceCreateInfo fenceInfo;
    VkFence drawFence;
    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    fenceInfo.pNext = NULL;
    fenceInfo.flags = 0;
    vkCreateFence(info.device, &fenceInfo, NULL, &drawFence);

    VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkSubmitInfo submit_info[1] = {};
    submit_info[0].pNext = NULL;
    submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submit_info[0].waitSemaphoreCount = 1;
    submit_info[0].pWaitSemaphores = &imageAcquiredSemaphore;
    submit_info[0].pWaitDstStageMask = &pipe_stage_flags;
    submit_info[0].commandBufferCount = 1;
    submit_info[0].pCommandBuffers = cmd_bufs;
    submit_info[0].signalSemaphoreCount = 0;
    submit_info[0].pSignalSemaphores = NULL;

    /* Queue the command buffer for execution */
    res = vkQueueSubmit(info.graphics_queue, 1, submit_info, drawFence);
    assert(res == VK_SUCCESS);

    /* Now present the image in the window */

    VkPresentInfoKHR present;
    present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    present.pNext = NULL;
    present.swapchainCount = 1;
    present.pSwapchains = &info.swap_chain;
    present.pImageIndices = &info.current_buffer;
    present.pWaitSemaphores = NULL;
    present.waitSemaphoreCount = 0;
    present.pResults = NULL;

    /* Make sure command buffer is finished before presenting */
    do {
        res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
    } while (res == VK_TIMEOUT);

    assert(res == VK_SUCCESS);
    res = vkQueuePresentKHR(info.present_queue, &present);
    assert(res == VK_SUCCESS);

    wait_seconds(1);
    if (info.save_images) write_ppm(info, "secondary_command_buffer");

    vkFreeCommandBuffers(info.device, info.cmd_pool, 4, secondary_cmds);

    /* VULKAN_KEY_END */

    vkDestroyFence(info.device, drawFence, NULL);
    vkDestroySemaphore(info.device, imageAcquiredSemaphore, NULL);
    destroy_pipeline(info);
    destroy_pipeline_cache(info);
    destroy_textures(info);
    destroy_descriptor_pool(info);
    destroy_vertex_buffer(info);
    destroy_framebuffers(info);
    destroy_shaders(info);
    destroy_renderpass(info);
    destroy_descriptor_and_pipeline_layouts(info);
    destroy_uniform_buffer(info);
    destroy_depth_buffer(info);
    destroy_swap_chain(info);
    destroy_command_buffer(info);
    destroy_command_pool(info);
    destroy_device(info);
    destroy_window(info);
    destroy_instance(info);
    return 0;
}
JNIEXPORT jboolean JNICALL
Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative(JNIEnv *env, jobject obj, jint program, jint textureId)
{
//	LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative");
	if (texture_initialized == FALSE){// && videostream::IsVideoInited()) {
		init_texture();
		texture_initialized = TRUE;
	}

	opengl_video_stage_config_t *config = opengl_video_stage_get();

#if 1
		int width,height;
#else
		int width = texture.texture_size.width;
		int height = texture.texture_size.height;
#endif
	videostream::lock_disp_buffer();
	if(videostream::GetVideoMetrics(&width,&height) != 0){
		videostream::unlock_disp_buffer();
		return FALSE;
	}
	if(width == 0 || height == 0){
		LOGI("-->width or height is zero.");
		videostream::unlock_disp_buffer();
		return FALSE;
	}
	config->widthImage = width;
	config->widthTexture = width;
	config->heightImage = height;
	config->heightTexture = height;
	config->data = videostream::GetYUVBuffer();
//	if(((indexd++)*30 / 3000)%2==0){
//		LOGI("-->------------------show 720p");
//		width = 1280;
//		height = 720;
//		config->widthImage = width;
//		config->widthTexture = width;
//		config->heightImage = height;
//		config->heightTexture = height;
//		config->data = yuvbuffer720p.data;
//	}
//	else{
//		LOGI("-->------------------show 360p");
//		width = 640;
//		height = 360;
//		config->widthImage = width;
//		config->widthTexture = width;
//		config->heightImage = height;
//		config->heightTexture = height;
//		config->data = yuvbuffer360p.data;
//	}
//	LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative1");
	if ((config != NULL) && (config->data != NULL))// && (config->num_picture_decoded > current_num_picture_decoded))
	{
		if (texture.image_size.width != config->widthImage) {
			recalculate_video_texture = TRUE;
//			LOGI("size has changed to (%d,%d)",width,height);
//			LOGI("size has changed to (%d,%d)",texture.image_size.width,config->widthImage);
//			createStream(width,height);
			indexf = 0;
		}
//		writeYUVData((char *)config->data,width,height);
		texture.bytesPerPixel       = config->bytesPerPixel;
		texture.image_size.width    = config->widthImage;
		texture.image_size.height   = config->heightImage;
		texture.texture_size.width	= config->widthTexture;
		texture.texture_size.height	= config->heightTexture;
		texture.format              = config->format;
		texture.type                = config->type;
		texture.data                = config->data;
		texture.state = OPENGL_STATE_GENERATED;

        current_num_picture_decoded = config->num_picture_decoded;
		current_num_frames = config->num_frames;
	}

	if (recalculate_video_texture) {
		recalculate_video_texture_bounds(env, obj, &texture);
		recalculate_video_texture = FALSE;
	}

	indexf++;
	if(indexf<10){
		LOGI("-->recalculate_video_texture_bounds");
		videostream::unlock_disp_buffer();
		return TRUE;
	}
	else
	{
		indexf = 10;
	}

	if(texture.state == OPENGL_STATE_GENERATED)
	{
//		LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative2");
		// Load the texture in the GPU
		if (texture.data != NULL) {
//			LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative3");
//			renderFrame();
//			LOGI("fmt: %d, w: %f, h: %f, type: %d, data: %p", texture.format, texture.texture_size.width, texture.texture_size.height, texture.type, texture.data);
//			glTexImage2D(GL_TEXTURE_2D, 0, texture.format, texture.texture_size.width, texture.texture_size.height, 0, texture.format, texture.type, texture.data);
//			checkGlError("glTexImage2D");
//			LOGI("-->video size(%d,%d)",width,height);
//			char *p = (char *)videostream::GetYUVBuffer();
			bindTexture(g_texYId, (char *)texture.data, width, height);
			bindTexture(g_texUId, (char *)texture.data + width * height, width/2, height/2);
			bindTexture(g_texVId, (char *)texture.data + width * height * 5 / 4, width/2, height/2);
			bindYUV(program);
			//MyStat();
			videostream::unlock_disp_buffer();
			texture.state = OPENGL_STATE_SEND_TO_GPU;
			return TRUE;
		}
	}

	return FALSE;

	/**
	LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative");
	if (texture_initialized == FALSE && videostream::IsVideoInited()) {
		init_texture();
		texture_initialized = TRUE;
	}

	opengl_video_stage_config_t *config = opengl_video_stage_get();

//	LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative1");
	if ((config != NULL) && (config->data != NULL))// && (config->num_picture_decoded > current_num_picture_decoded))
	{
		if (texture.image_size.width != config->widthImage) {
			recalculate_video_texture = TRUE;
		}

		texture.bytesPerPixel       = config->bytesPerPixel;
		texture.image_size.width    = config->widthImage;
		texture.image_size.height   = config->heightImage;
		texture.texture_size.width	= config->widthTexture;
		texture.texture_size.height	= config->heightTexture;
		texture.format              = config->format;
		texture.type                = config->type;
		texture.data                = config->data;
		texture.state = OPENGL_STATE_GENERATED;

        current_num_picture_decoded = config->num_picture_decoded;
		current_num_frames = config->num_frames;
	}

	if (recalculate_video_texture) {
		recalculate_video_texture_bounds(env, obj, &texture);
		recalculate_video_texture = FALSE;
	}

	if(texture.state == OPENGL_STATE_GENERATED)
	{
//		LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative2");
		// Load the texture in the GPU
		if (texture.data != NULL) {
//			LOGI("-->Java_com_vmc_ipc_view_gl_GLBGVideoSprite_onUpdateVideoTextureNative3");
			renderFrame();
//			LOGI("fmt: %d, w: %f, h: %f, type: %d, data: %p", texture.format, texture.texture_size.width, texture.texture_size.height, texture.type, texture.data);
//			glTexImage2D(GL_TEXTURE_2D, 0, texture.format, texture.texture_size.width, texture.texture_size.height, 0, texture.format, texture.type, texture.data);
//			checkGlError("glTexImage2D");
#if 1
			int width,height;
#else
			int width = texture.texture_size.width;
			int height = texture.texture_size.height;
#endif
			videostream::lock_disp_buffer();
			videostream::GetVideoMetrics(&width,&height);
			LOGI("-->video size(%d,%d)",width,height);
			char *p = (char *)videostream::GetYUVBuffer();
			bindTexture(g_texYId, p, width, height);
			bindTexture(g_texUId, p + width * height, width/2, height/2);
			bindTexture(g_texVId, p + width * height * 5 / 4, width/2, height/2);
			bindYUV(program);
			//MyStat();
			videostream::unlock_disp_buffer();
			texture.state = OPENGL_STATE_SEND_TO_GPU;
			return TRUE;
		}
	}

	return FALSE;
	**/
}
Exemplo n.º 28
0
int sample_main(int argc, char *argv[]) {
    VkResult U_ASSERT_ONLY res;
    struct sample_info info = {};
    char sample_title[] = "Multiple Descriptor Sets";

    process_command_line_args(info, argc, argv);
    init_global_layer_properties(info);
    init_instance_extension_names(info);
    init_device_extension_names(info);
    init_instance(info, sample_title);
    init_enumerate_device(info);
    init_window_size(info, 500, 500);
    init_connection(info);
    init_window(info);
    init_swapchain_extension(info);
    init_device(info);
    init_command_pool(info);
    init_command_buffer(info);
    execute_begin_command_buffer(info);
    init_device_queue(info);
    init_swap_chain(info);
    init_depth_buffer(info);
    // Sample from a green texture to easily see that we've pulled correct texel
    // value
    const char *textureName = "green.ppm";
    init_texture(info, textureName);
    init_uniform_buffer(info);
    init_renderpass(info, true);
    init_shaders(info, vertShaderText, fragShaderText);
    init_framebuffers(info, true);
    init_vertex_buffer(info, g_vb_texture_Data, sizeof(g_vb_texture_Data), sizeof(g_vb_texture_Data[0]), true);

    /* VULKAN_KEY_START */

    // Set up two descriptor sets
    static const unsigned descriptor_set_count = 2;

    // Create first layout to contain uniform buffer data
    VkDescriptorSetLayoutBinding uniform_binding[1] = {};
    uniform_binding[0].binding = 0;
    uniform_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    uniform_binding[0].descriptorCount = 1;
    uniform_binding[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
    uniform_binding[0].pImmutableSamplers = NULL;
    VkDescriptorSetLayoutCreateInfo uniform_layout_info[1] = {};
    uniform_layout_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    uniform_layout_info[0].pNext = NULL;
    uniform_layout_info[0].bindingCount = 1;
    uniform_layout_info[0].pBindings = uniform_binding;

    // Create second layout containing combined sampler/image data
    VkDescriptorSetLayoutBinding sampler2D_binding[1] = {};
    sampler2D_binding[0].binding = 0;
    sampler2D_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    sampler2D_binding[0].descriptorCount = 1;
    sampler2D_binding[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
    sampler2D_binding[0].pImmutableSamplers = NULL;
    VkDescriptorSetLayoutCreateInfo sampler2D_layout_info[1] = {};
    sampler2D_layout_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    sampler2D_layout_info[0].pNext = NULL;
    sampler2D_layout_info[0].bindingCount = 1;
    sampler2D_layout_info[0].pBindings = sampler2D_binding;

    // Create multiple sets, using each createInfo
    static const unsigned uniform_set_index = 0;
    static const unsigned sampler_set_index = 1;
    VkDescriptorSetLayout descriptor_layouts[descriptor_set_count] = {};
    res = vkCreateDescriptorSetLayout(info.device, uniform_layout_info, NULL, &descriptor_layouts[uniform_set_index]);
    assert(res == VK_SUCCESS);
    res = vkCreateDescriptorSetLayout(info.device, sampler2D_layout_info, NULL, &descriptor_layouts[sampler_set_index]);
    assert(res == VK_SUCCESS);

    // Create pipeline layout with multiple descriptor sets
    VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo[1] = {};
    pipelineLayoutCreateInfo[0].sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    pipelineLayoutCreateInfo[0].pNext = NULL;
    pipelineLayoutCreateInfo[0].pushConstantRangeCount = 0;
    pipelineLayoutCreateInfo[0].pPushConstantRanges = NULL;
    pipelineLayoutCreateInfo[0].setLayoutCount = descriptor_set_count;
    pipelineLayoutCreateInfo[0].pSetLayouts = descriptor_layouts;
    res = vkCreatePipelineLayout(info.device, pipelineLayoutCreateInfo, NULL, &info.pipeline_layout);
    assert(res == VK_SUCCESS);

    // Create a single pool to contain data for our two descriptor sets
    VkDescriptorPoolSize type_count[2] = {};
    type_count[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    type_count[0].descriptorCount = 1;
    type_count[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    type_count[1].descriptorCount = 1;

    VkDescriptorPoolCreateInfo pool_info[1] = {};
    pool_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    pool_info[0].pNext = NULL;
    pool_info[0].maxSets = descriptor_set_count;
    pool_info[0].poolSizeCount = sizeof(type_count) / sizeof(VkDescriptorPoolSize);
    pool_info[0].pPoolSizes = type_count;

    VkDescriptorPool descriptor_pool[1] = {};
    res = vkCreateDescriptorPool(info.device, pool_info, NULL, descriptor_pool);
    assert(res == VK_SUCCESS);

    VkDescriptorSetAllocateInfo alloc_info[1];
    alloc_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    alloc_info[0].pNext = NULL;
    alloc_info[0].descriptorPool = descriptor_pool[0];
    alloc_info[0].descriptorSetCount = descriptor_set_count;
    alloc_info[0].pSetLayouts = descriptor_layouts;

    // Populate descriptor sets
    VkDescriptorSet descriptor_sets[descriptor_set_count] = {};
    res = vkAllocateDescriptorSets(info.device, alloc_info, descriptor_sets);
    assert(res == VK_SUCCESS);

    // Using empty brace initializer on the next line triggers a bug in older
    // versions of gcc, so memset instead
    VkWriteDescriptorSet descriptor_writes[2];
    memset(descriptor_writes, 0, sizeof(descriptor_writes));

    // Populate with info about our uniform buffer
    descriptor_writes[0] = {};
    descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
    descriptor_writes[0].pNext = NULL;
    descriptor_writes[0].dstSet = descriptor_sets[uniform_set_index];
    descriptor_writes[0].descriptorCount = 1;
    descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    descriptor_writes[0].pBufferInfo = &info.uniform_data.buffer_info;  // populated by init_uniform_buffer()
    descriptor_writes[0].dstArrayElement = 0;
    descriptor_writes[0].dstBinding = 0;

    // Populate with info about our sampled image
    descriptor_writes[1] = {};
    descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
    descriptor_writes[1].pNext = NULL;
    descriptor_writes[1].dstSet = descriptor_sets[sampler_set_index];
    descriptor_writes[1].descriptorCount = 1;
    descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    descriptor_writes[1].pImageInfo = &info.texture_data.image_info;  // populated by init_texture()
    descriptor_writes[1].dstArrayElement = 0;
    descriptor_writes[1].dstBinding = 0;

    vkUpdateDescriptorSets(info.device, descriptor_set_count, descriptor_writes, 0, NULL);

    /* VULKAN_KEY_END */

    // Call remaining boilerplate utils
    init_pipeline_cache(info);
    init_pipeline(info, true);

    // The remaining is identical to drawtexturedcube
    VkClearValue clear_values[2];
    clear_values[0].color.float32[0] = 0.2f;
    clear_values[0].color.float32[1] = 0.2f;
    clear_values[0].color.float32[2] = 0.2f;
    clear_values[0].color.float32[3] = 0.2f;
    clear_values[1].depthStencil.depth = 1.0f;
    clear_values[1].depthStencil.stencil = 0;

    VkSemaphore imageAcquiredSemaphore;
    VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo;
    imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    imageAcquiredSemaphoreCreateInfo.pNext = NULL;
    imageAcquiredSemaphoreCreateInfo.flags = 0;

    res = vkCreateSemaphore(info.device, &imageAcquiredSemaphoreCreateInfo, NULL, &imageAcquiredSemaphore);
    assert(res == VK_SUCCESS);

    // Get the index of the next available swapchain image:
    res = vkAcquireNextImageKHR(info.device, info.swap_chain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE,
                                &info.current_buffer);
    // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
    // return codes
    assert(res == VK_SUCCESS);

    VkRenderPassBeginInfo rp_begin;
    rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    rp_begin.pNext = NULL;
    rp_begin.renderPass = info.render_pass;
    rp_begin.framebuffer = info.framebuffers[info.current_buffer];
    rp_begin.renderArea.offset.x = 0;
    rp_begin.renderArea.offset.y = 0;
    rp_begin.renderArea.extent.width = info.width;
    rp_begin.renderArea.extent.height = info.height;
    rp_begin.clearValueCount = 2;
    rp_begin.pClearValues = clear_values;

    vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);

    vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
    vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0, descriptor_set_count,
                            descriptor_sets, 0, NULL);

    const VkDeviceSize offsets[1] = {0};
    vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets);

    init_viewports(info);
    init_scissors(info);

    vkCmdDraw(info.cmd, 12 * 3, 1, 0, 0);
    vkCmdEndRenderPass(info.cmd);
    res = vkEndCommandBuffer(info.cmd);
    assert(res == VK_SUCCESS);

    const VkCommandBuffer cmd_bufs[] = {info.cmd};
    VkFenceCreateInfo fenceInfo;
    VkFence drawFence;
    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    fenceInfo.pNext = NULL;
    fenceInfo.flags = 0;
    vkCreateFence(info.device, &fenceInfo, NULL, &drawFence);

    VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkSubmitInfo submit_info[1] = {};
    submit_info[0].pNext = NULL;
    submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submit_info[0].waitSemaphoreCount = 1;
    submit_info[0].pWaitSemaphores = &imageAcquiredSemaphore;
    submit_info[0].pWaitDstStageMask = &pipe_stage_flags;
    submit_info[0].commandBufferCount = 1;
    submit_info[0].pCommandBuffers = cmd_bufs;
    submit_info[0].signalSemaphoreCount = 0;
    submit_info[0].pSignalSemaphores = NULL;

    /* Queue the command buffer for execution */
    res = vkQueueSubmit(info.graphics_queue, 1, submit_info, drawFence);
    assert(res == VK_SUCCESS);

    /* Now present the image in the window */

    VkPresentInfoKHR present;
    present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    present.pNext = NULL;
    present.swapchainCount = 1;
    present.pSwapchains = &info.swap_chain;
    present.pImageIndices = &info.current_buffer;
    present.pWaitSemaphores = NULL;
    present.waitSemaphoreCount = 0;
    present.pResults = NULL;

    /* Make sure command buffer is finished before presenting */
    do {
        res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
    } while (res == VK_TIMEOUT);
    assert(res == VK_SUCCESS);
    res = vkQueuePresentKHR(info.present_queue, &present);
    assert(res == VK_SUCCESS);

    wait_seconds(1);
    if (info.save_images) write_ppm(info, "multiple_sets");

    vkDestroySemaphore(info.device, imageAcquiredSemaphore, NULL);
    vkDestroyFence(info.device, drawFence, NULL);
    destroy_pipeline(info);
    destroy_pipeline_cache(info);
    destroy_textures(info);

    // instead of destroy_descriptor_pool(info);
    vkDestroyDescriptorPool(info.device, descriptor_pool[0], NULL);

    destroy_vertex_buffer(info);
    destroy_framebuffers(info);
    destroy_shaders(info);
    destroy_renderpass(info);

    // instead of destroy_descriptor_and_pipeline_layouts(info);
    for (int i = 0; i < descriptor_set_count; i++) vkDestroyDescriptorSetLayout(info.device, descriptor_layouts[i], NULL);
    vkDestroyPipelineLayout(info.device, info.pipeline_layout, NULL);

    destroy_uniform_buffer(info);
    destroy_depth_buffer(info);
    destroy_swap_chain(info);
    destroy_command_buffer(info);
    destroy_command_pool(info);
    destroy_device(info);
    destroy_window(info);
    destroy_instance(info);
    return 0;
}
int sample_main(int argc, char *argv[]) {
    VkResult U_ASSERT_ONLY res;
    struct sample_info info = {};
    char sample_title[] = "SPIR-V Specialization";
    const bool depthPresent = true;

    process_command_line_args(info, argc, argv);
    init_global_layer_properties(info);
    init_instance_extension_names(info);
    init_device_extension_names(info);
    init_instance(info, sample_title);
    init_enumerate_device(info);
    init_window_size(info, 500, 500);
    init_connection(info);
    init_window(info);
    init_swapchain_extension(info);
    init_device(info);
    init_command_pool(info);
    init_command_buffer(info);
    execute_begin_command_buffer(info);
    init_device_queue(info);
    init_swap_chain(info);
    init_depth_buffer(info);
    init_texture(info);
    init_uniform_buffer(info);
    init_descriptor_and_pipeline_layouts(info, true);
    init_renderpass(info, depthPresent);

    /* VULKAN_KEY_START */

    // Pass in nullptr for fragment shader so we can setup specialization
    init_shaders(info, vertShaderText, nullptr);

    // This structure maps constant ids to data locations.
    // NOTE: Padding bool to 32-bits for simplicity
    const VkSpecializationMapEntry entries[] =
        // id,  offset,                size
        {{5, 0, sizeof(uint32_t)},
         {7, 1 * sizeof(uint32_t), sizeof(uint32_t)},
         {8, 2 * sizeof(uint32_t), sizeof(uint32_t)},
         {9, 3 * sizeof(uint32_t), sizeof(uint32_t)}};

    // Initialize the values we want our mini-ubershader to use
    const bool drawUserColor = true;
    const float userColor[] = {0.0f, 0.0f, 1.0f};

    // Populate our data entry
    uint32_t data[4] = {};
    data[0] = drawUserColor ? 1 : 0;
    ((float *)data)[1] = userColor[0];
    ((float *)data)[2] = userColor[1];
    ((float *)data)[3] = userColor[2];

    // Set up the info describing our spec map and data
    const VkSpecializationInfo specInfo = {
        4,                  // mapEntryCount
        entries,            // pMapEntries
        4 * sizeof(float),  // dataSize
        data,               // pData
    };

    // Provide the specialization data to fragment stage
    info.shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    info.shaderStages[1].pNext = NULL;
    info.shaderStages[1].pSpecializationInfo = &specInfo;
    info.shaderStages[1].flags = 0;
    info.shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
    info.shaderStages[1].pName = "main";

    VkShaderModuleCreateInfo moduleCreateInfo;
    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
    moduleCreateInfo.pNext = NULL;
    moduleCreateInfo.flags = 0;

    if (use_SPIRV_asm) {
        // Use the hand edited SPIR-V assembly
        spv_context spvContext = spvContextCreate(SPV_ENV_VULKAN_1_0);
        spv_binary fragmentBinary = {};
        spv_diagnostic fragmentDiag = {};
        spv_result_t fragmentResult = spvTextToBinary(spvContext, fragmentSPIRV_specialized.c_str(),
                                                      fragmentSPIRV_specialized.length(), &fragmentBinary, &fragmentDiag);
        if (fragmentDiag) {
            printf("Diagnostic info from fragment shader:\n");
            spvDiagnosticPrint(fragmentDiag);
        }
        assert(fragmentResult == SPV_SUCCESS);
        moduleCreateInfo.codeSize = fragmentBinary->wordCount * sizeof(unsigned int);
        moduleCreateInfo.pCode = fragmentBinary->code;
        spvDiagnosticDestroy(fragmentDiag);
        spvContextDestroy(spvContext);

    } else {
        // Convert GLSL to SPIR-V
        init_glslang();
        std::vector<unsigned int> fragSpv;
        bool U_ASSERT_ONLY retVal = GLSLtoSPV(VK_SHADER_STAGE_FRAGMENT_BIT, fragShaderText, fragSpv);
        assert(retVal);
        finalize_glslang();

        moduleCreateInfo.codeSize = fragSpv.size() * sizeof(unsigned int);
        moduleCreateInfo.pCode = fragSpv.data();
    }

    res = vkCreateShaderModule(info.device, &moduleCreateInfo, NULL, &info.shaderStages[1].module);
    assert(res == VK_SUCCESS);

    /* VULKAN_KEY_END */

    init_framebuffers(info, depthPresent);
    init_vertex_buffer(info, g_vb_texture_Data, sizeof(g_vb_texture_Data), sizeof(g_vb_texture_Data[0]), true);
    init_descriptor_pool(info, true);
    init_descriptor_set(info, true);
    init_pipeline_cache(info);
    init_pipeline(info, depthPresent);
    init_presentable_image(info);

    VkClearValue clear_values[2];
    init_clear_color_and_depth(info, clear_values);

    VkRenderPassBeginInfo rp_begin;
    init_render_pass_begin_info(info, rp_begin);
    rp_begin.clearValueCount = 2;
    rp_begin.pClearValues = clear_values;

    vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);

    vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
    vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS,
                            info.desc_set.data(), 0, NULL);

    const VkDeviceSize offsets[1] = {0};
    vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets);

    init_viewports(info);
    init_scissors(info);

    vkCmdDraw(info.cmd, 12 * 3, 1, 0, 0);
    vkCmdEndRenderPass(info.cmd);
    res = vkEndCommandBuffer(info.cmd);
    assert(res == VK_SUCCESS);

    VkFence drawFence = {};
    init_fence(info, drawFence);
    VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkSubmitInfo submit_info = {};
    init_submit_info(info, submit_info, pipe_stage_flags);

    /* Queue the command buffer for execution */
    res = vkQueueSubmit(info.graphics_queue, 1, &submit_info, drawFence);
    assert(res == VK_SUCCESS);

    /* Now present the image in the window */
    VkPresentInfoKHR present = {};
    init_present_info(info, present);

    /* Make sure command buffer is finished before presenting */
    do {
        res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
    } while (res == VK_TIMEOUT);
    assert(res == VK_SUCCESS);
    res = vkQueuePresentKHR(info.present_queue, &present);
    assert(res == VK_SUCCESS);

    wait_seconds(1);
    if (info.save_images) write_ppm(info, "spirv_specialization");

    vkDestroyFence(info.device, drawFence, NULL);
    vkDestroySemaphore(info.device, info.imageAcquiredSemaphore, NULL);
    destroy_pipeline(info);
    destroy_pipeline_cache(info);
    destroy_textures(info);
    destroy_descriptor_pool(info);
    destroy_vertex_buffer(info);
    destroy_framebuffers(info);
    destroy_shaders(info);
    destroy_renderpass(info);
    destroy_descriptor_and_pipeline_layouts(info);
    destroy_uniform_buffer(info);
    destroy_depth_buffer(info);
    destroy_swap_chain(info);
    destroy_command_buffer(info);
    destroy_command_pool(info);
    destroy_device(info);
    destroy_window(info);
    destroy_instance(info);
    return 0;
}
int sample_main(int argc, char *argv[]) {
    VkResult U_ASSERT_ONLY res;
    struct sample_info info = {};
    char sample_title[] = "Draw Textured Cube";
    const bool depthPresent = true;

    process_command_line_args(info, argc, argv);
    init_global_layer_properties(info);
    init_instance_extension_names(info);
    init_device_extension_names(info);
    init_instance(info, sample_title);
    init_enumerate_device(info);
    init_window_size(info, 500, 500);
    init_connection(info);
    init_window(info);
    init_swapchain_extension(info);
    init_device(info);
    init_command_pool(info);
    init_command_buffer(info);
    execute_begin_command_buffer(info);
    init_device_queue(info);
    init_swap_chain(info);
    init_depth_buffer(info);
    init_texture(info);
    init_uniform_buffer(info);
    init_descriptor_and_pipeline_layouts(info, true);
    init_renderpass(info, depthPresent);
    init_shaders(info, vertShaderText, fragShaderText);
    init_framebuffers(info, depthPresent);
    init_vertex_buffer(info, g_vb_texture_Data, sizeof(g_vb_texture_Data),
                       sizeof(g_vb_texture_Data[0]), true);
    init_descriptor_pool(info, true);
    init_descriptor_set(info, true);
    init_pipeline_cache(info);
    init_pipeline(info, depthPresent);

    /* VULKAN_KEY_START */

    VkClearValue clear_values[2];
    clear_values[0].color.float32[0] = 0.2f;
    clear_values[0].color.float32[1] = 0.2f;
    clear_values[0].color.float32[2] = 0.2f;
    clear_values[0].color.float32[3] = 0.2f;
    clear_values[1].depthStencil.depth = 1.0f;
    clear_values[1].depthStencil.stencil = 0;

    VkSemaphore presentCompleteSemaphore;
    VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo;
    presentCompleteSemaphoreCreateInfo.sType =
        VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    presentCompleteSemaphoreCreateInfo.pNext = NULL;
    presentCompleteSemaphoreCreateInfo.flags = 0;

    res = vkCreateSemaphore(info.device, &presentCompleteSemaphoreCreateInfo,
                            NULL, &presentCompleteSemaphore);
    assert(res == VK_SUCCESS);

    // Get the index of the next available swapchain image:
    res = vkAcquireNextImageKHR(info.device, info.swap_chain, UINT64_MAX,
                                presentCompleteSemaphore, VK_NULL_HANDLE,
                                &info.current_buffer);
    // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
    // return codes
    assert(res == VK_SUCCESS);

    set_image_layout(info, info.buffers[info.current_buffer].image,
                     VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);

    VkRenderPassBeginInfo rp_begin;
    rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    rp_begin.pNext = NULL;
    rp_begin.renderPass = info.render_pass;
    rp_begin.framebuffer = info.framebuffers[info.current_buffer];
    rp_begin.renderArea.offset.x = 0;
    rp_begin.renderArea.offset.y = 0;
    rp_begin.renderArea.extent.width = info.width;
    rp_begin.renderArea.extent.height = info.height;
    rp_begin.clearValueCount = 2;
    rp_begin.pClearValues = clear_values;

    vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);

    vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
    vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
                            info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS,
                            info.desc_set.data(), 0, NULL);

    const VkDeviceSize offsets[1] = {0};
    vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets);

    init_viewports(info);
    init_scissors(info);

    vkCmdDraw(info.cmd, 12 * 3, 1, 0, 0);
    vkCmdEndRenderPass(info.cmd);

    VkImageMemoryBarrier prePresentBarrier = {};
    prePresentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    prePresentBarrier.pNext = NULL;
    prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    prePresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
    prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    prePresentBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    prePresentBarrier.subresourceRange.baseMipLevel = 0;
    prePresentBarrier.subresourceRange.levelCount = 1;
    prePresentBarrier.subresourceRange.baseArrayLayer = 0;
    prePresentBarrier.subresourceRange.layerCount = 1;
    prePresentBarrier.image = info.buffers[info.current_buffer].image;
    vkCmdPipelineBarrier(info.cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                         VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0,
                         NULL, 1, &prePresentBarrier);

    res = vkEndCommandBuffer(info.cmd);
    assert(res == VK_SUCCESS);

    const VkCommandBuffer cmd_bufs[] = {info.cmd};
    VkFenceCreateInfo fenceInfo;
    VkFence drawFence;
    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    fenceInfo.pNext = NULL;
    fenceInfo.flags = 0;
    vkCreateFence(info.device, &fenceInfo, NULL, &drawFence);

    VkPipelineStageFlags pipe_stage_flags =
        VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    VkSubmitInfo submit_info[1] = {};
    submit_info[0].pNext = NULL;
    submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submit_info[0].waitSemaphoreCount = 1;
    submit_info[0].pWaitSemaphores = &presentCompleteSemaphore;
    submit_info[0].pWaitDstStageMask = &pipe_stage_flags;
    submit_info[0].commandBufferCount = 1;
    submit_info[0].pCommandBuffers = cmd_bufs;
    submit_info[0].signalSemaphoreCount = 0;
    submit_info[0].pSignalSemaphores = NULL;

    /* Queue the command buffer for execution */
    res = vkQueueSubmit(info.queue, 1, submit_info, drawFence);
    assert(res == VK_SUCCESS);

    /* Now present the image in the window */

    VkPresentInfoKHR present;
    present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    present.pNext = NULL;
    present.swapchainCount = 1;
    present.pSwapchains = &info.swap_chain;
    present.pImageIndices = &info.current_buffer;
    present.pWaitSemaphores = NULL;
    present.waitSemaphoreCount = 0;
    present.pResults = NULL;

    /* Make sure command buffer is finished before presenting */
    do {
        res =
            vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
    } while (res == VK_TIMEOUT);
    assert(res == VK_SUCCESS);
    res = vkQueuePresentKHR(info.queue, &present);
    assert(res == VK_SUCCESS);

    wait_seconds(1);
    /* VULKAN_KEY_END */
    if (info.save_images)
        write_ppm(info, "drawtexturedcube");

    vkDestroyFence(info.device, drawFence, NULL);
    vkDestroySemaphore(info.device, presentCompleteSemaphore, NULL);
    destroy_pipeline(info);
    destroy_pipeline_cache(info);
    destroy_textures(info);
    destroy_descriptor_pool(info);
    destroy_vertex_buffer(info);
    destroy_framebuffers(info);
    destroy_shaders(info);
    destroy_renderpass(info);
    destroy_descriptor_and_pipeline_layouts(info);
    destroy_uniform_buffer(info);
    destroy_depth_buffer(info);
    destroy_swap_chain(info);
    destroy_command_buffer(info);
    destroy_command_pool(info);
    destroy_device(info);
    destroy_window(info);
    destroy_instance(info);
    return 0;
}