local demo_dir = gh_utils.get_demo_dir() 		

local lib_dir = gh_utils.get_lib_dir() 		
dofile(lib_dir .. "lua/vk.lua")




    
winW, winH = gh_window.getsize(0)







-----------------------------------------------------------------------
-- Perspective camera.
--
local aspect = winW / winH
camera_params = { fov=60, znear=0.1, zfar=1000.0 }
camera = gh_camera.create_persp(camera_params.fov, aspect, camera_params.znear, camera_params.zfar)
gh_camera.set_viewport(camera, 0, 0, winW, winH)
gh_camera.set_position(camera, 0, 0, 2)
gh_camera.set_lookat(camera, 0, 0, 0, 1)
gh_camera.set_upvec(camera, 0, 1, 0, 0)





-----------------------------------------------------------------------
-- GPU buffer to store uniform data used by the shaders.
--
function UpdateCameraTransform(cam, ub)
  -- The first 64 bytes will be used to store the camera matrix.
  --
  local buffer_offset_bytes = 0
  gh_gpu_buffer.set_matrix4x4(ub, buffer_offset_bytes, cam, "camera_view_projection")
end

function UpdateObjectTransform(obj, ub)
  -- The bytes from offset 64 to 128 will be used to store the object matrix.
  --
  local buffer_offset_bytes = 64
  gh_gpu_buffer.set_matrix4x4(ub, buffer_offset_bytes, obj, "object_global_transform")
end

-- The size of the GPU must be enough to store 2 transformation matrices, at least
-- 128 bytes.
--
local ub_size = 256
ub1 = gh_gpu_buffer.create("UNIFORM", "NONE", ub_size, "")
gh_gpu_buffer.bind(ub1)

-- Maps the GPU buffer: the GPU buffer can be read and write from CPU.
-- In Vulkan, a GPU can be mapped during the life of the demo. Just unmap it in 
-- the terminate script.
--
gh_gpu_buffer.map(ub1)


-- Updates the camera matrix.
UpdateCameraTransform(camera, ub1)





-----------------------------------------------------------------------
-- SPIR-V shaders.
--
-- The SPIR-V shaders have been created from GLSL shaders using the 
-- glslangValidator.exe on Windows. This utility is available in the 
-- spirv/ folder.
--
local vertex_shader = demo_dir .. "spirv/02-vs.spv"
local pixel_shader = demo_dir .. "spirv/02-ps.spv"
color_prog = gh_gpu_program.vk_create_from_spirv_module_file("02-shader",   vertex_shader, "main",     pixel_shader, "main",    "", "",    "", "",     "", "",    "", "") 






-----------------------------------------------------------------------
-- Descriptor set that describes what resources (GPU buffer and textures) 
-- will be used for drawing.
-- In this demo, one GPU buffer will be used in the vertex shader.
--
ds = gh_vk.descriptorset_create()

-- The binding point is very important because it is used in ther vertex shader to reference
-- the GPU buffer.
local binding_point = 0
gh_vk.descriptorset_add_resource_gpu_buffer(ds, ub1, binding_point, SHADER_STAGE_VERTEX)

gh_vk.descriptorset_build(ds)
gh_vk.descriptorset_update(ds)







-----------------------------------------------------------------------
-- The pipeline object or PSO.
-- The PSO stores all graphics pipeline states (what shaders are used, depth state, blending, etc.)
-- in one place. The PSO is an immutable object: once created, it can not be changed. So if you need
-- to draw an object with solid polygon mode and another object in wireframe, you have to create 
-- two PSOs.
--
pso01 = gh_vk.pipeline_create("pso01", color_prog, "")
gh_vk.pipeline_set_attrib_4i(pso01, "DEPTH_TEST", 1, 0, 0, 0)
gh_vk.pipeline_set_attrib_4i(pso01, "FILL_MODE", POLYGON_MODE_SOLID, 0, 0, 0)
gh_vk.pipeline_set_attrib_4i(pso01, "PRIMITIVE_TYPE", PRIMITIVE_TRIANGLE, 0, 0, 0)
gh_vk.pipeline_set_attrib_4i(pso01, "CULL_MODE", POLYGON_FACE_NONE, 0, 0, 0)
pso_valid = gh_vk.pipeline_build(pso01, ds)
if (pso_valid == 0) then
	print("ERROR: pipeline pso01 is not valid.")
end








-----------------------------------------------------------------------
-- Creates an non-indexed triangle mesh: 3 vertices and 0 faces.
--
--[[
local use_std_vertex_attribs = 1 -- standard vertex attribs like gxl3d_Position.
local num_user_vertex_attribs = 0 -- no custom vertex attrib arrays.
local separate_vertex_arrays = 1 -- Separate (1) or interleaved (0) vertex attribs.
local vertex_alignment = 0
local alloc_vertex_particles = 0
gh_mesh.set_vertex_alloc_params(use_std_vertex_attribs, num_user_vertex_attribs, separate_vertex_arrays, vertex_alignment, alloc_vertex_particles)


triangle = gh_mesh.create_v2()
local num_vertices = 3
local num_faces = 0 -- non-indexed rendering
local ret = gh_mesh.alloc_mesh_data(triangle, num_vertices, num_faces)
if (ret == 1) then
  gh_mesh.set_vertex_position(triangle, 0, -1, -1, 0, 1)
  gh_mesh.set_vertex_position(triangle, 1, 0, 1, 0, 1)
  gh_mesh.set_vertex_position(triangle, 2, 1, -1, 0, 1)

  gh_mesh.set_vertex_color(triangle, 0, 1, 0, 0, 1)
  gh_mesh.set_vertex_color(triangle, 1, 0, 1, 0, 1)
  gh_mesh.set_vertex_color(triangle, 2, 0, 0, 1, 1)
end 
--]]



-- Simple way to create an unitary triangle.
--
triangle = gh_mesh.create_triangle()



UpdateObjectTransform(triangle, ub1)



-----------------------------------------------------------------------
-- Wait for GPU: be sure that all init commands are done.
--
gh_vk.wait_for_gpu()





function build_command_buffer(w, h)

	--print("demo - build_command_buffer() START")


	------ Opens the command buffer for recording.
	gh_vk.clear_color_depth_buffers(0.2, 0.2, 0.2, 1.0, 1.0)
	gh_vk.frame_command_buffer_begin()

	
	--------------------------
	gh_vk.set_viewport_scissor(0, 0, w, h)

	-- Binds the descriptor set and PSO.
	--
	gh_vk.descriptorset_bind(ds)
	gh_vk.pipeline_bind(pso01)

	-- Render the object. Keep in mind that the object is not really rendered:
	-- only the drawing command is recorded in the command buffer. The object 
	-- will be rendered later when the command buffer will be executed.  
	--
	gh_object.render(triangle)
	--------------------------

	
	----- Close the command buffer.
	gh_vk.frame_command_buffer_end()

end



swapchain_image_count = gh_vk.swapchain_get_image_count()
print("swapchain_buffer_count => " .. swapchain_image_count)

for i=0, swapchain_image_count-1 do
	gh_vk.frame_set_active_command_buffer_index(i)
	build_command_buffer(winW, winH)
end
gh_vk.frame_set_active_command_buffer_index(0)

