ULRE/example/Vulkan/VulkanAppFramework.h
2020-07-07 19:16:23 +08:00

385 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include<hgl/platform/Window.h>
#include<hgl/graph/vulkan/VKInstance.h>
#include<hgl/graph/vulkan/VKPhysicalDevice.h>
#include<hgl/graph/vulkan/VKDevice.h>
#include<hgl/graph/vulkan/VKSemaphore.h>
#include<hgl/graph/vulkan/VKBuffer.h>
#include<hgl/graph/vulkan/VKShaderModule.h>
#include<hgl/graph/vulkan/VKShaderModuleManage.h>
#include<hgl/graph/vulkan/VKImageView.h>
#include<hgl/graph/vulkan/VKRenderable.h>
#include<hgl/graph/vulkan/VKDescriptorSets.h>
#include<hgl/graph/vulkan/VKRenderPass.h>
#include<hgl/graph/vulkan/VKPipeline.h>
#include<hgl/graph/vulkan/VKCommandBuffer.h>
#include<hgl/graph/vulkan/VKFormat.h>
#include<hgl/graph/vulkan/VKFramebuffer.h>
#include<hgl/graph/vulkan/VKMaterial.h>
#include<hgl/graph/vulkan/VKMaterialInstance.h>
#include<hgl/graph/vulkan/VKRenderTarget.h>
#include<hgl/graph/SceneDB.h>
#include<hgl/graph/RenderList.h>
using namespace hgl;
using namespace hgl::graph;
class VulkanApplicationFramework
{
private:
Window * win =nullptr;
vulkan::Instance * inst =nullptr;
void OnKeyDown (KeyboardButton kb){key_status[kb]=true;}
void OnKeyUp (KeyboardButton kb){key_status[kb]=false;}
void OnKeyPress (KeyboardButton kb){KeyPress(kb);}
protected:
uint mouse_key=0;
Vector2f mouse_pos;
void OnMouseDown(int,int,uint mk){mouse_key=mk;MouseDown(mk);}
void OnMouseUp (int,int,uint mk){mouse_key=0;MouseUp(mk);}
void OnMouseMove(int x,int y){mouse_pos.Set(x,y);MouseMove();}
void OnMouseWheel(int v,int h,uint mk){MouseWheel(v,h,mk);}
protected:
vulkan::Device * device =nullptr;
vulkan::SwapchainRenderTarget * sc_render_target =nullptr;
vulkan::Semaphore * present_complete_semaphore =nullptr,
* render_complete_semaphore =nullptr;
vulkan::ShaderModuleManage * shader_manage =nullptr;
protected:
int32_t swap_chain_count =0;
vulkan::CommandBuffer ** cmd_buf =nullptr;
protected:
SceneDB * db =nullptr;
bool key_status[kbRangeSize];
public:
virtual ~VulkanApplicationFramework()
{
SAFE_CLEAR(present_complete_semaphore);
SAFE_CLEAR(render_complete_semaphore);
SAFE_CLEAR(db);
SAFE_CLEAR_OBJECT_ARRAY(cmd_buf,swap_chain_count);
SAFE_CLEAR(shader_manage);
SAFE_CLEAR(device);
SAFE_CLEAR(win);
SAFE_CLEAR(inst);
}
virtual bool Init(int w,int h)
{
hgl_zero(key_status);
#ifdef _DEBUG
if(!vulkan::CheckStrideBytesByFormat())
return(false);
#endif//
InitNativeWindowSystem();
VK_NAMESPACE::InitVulkanProperties();
win=CreateRenderWindow(OS_TEXT("VulkanTest"));
if(!win)
return(false);
if(!win->Create(w,h))
return(false);
{
VK_NAMESPACE::CreateInstanceLayerInfo cili;
memset(&cili, 0, sizeof(VK_NAMESPACE::CreateInstanceLayerInfo));
cili.lunarg.standard_validation = true;
cili.khronos.validation = true;
cili.RenderDoc.Capture = true;
inst=vulkan::CreateInstance("VulkanTest",nullptr,&cili);
if(!inst)
return(false);
}
device=CreateRenderDevice(inst,win);
if(!device)
return(false);
present_complete_semaphore =device->CreateSem();
render_complete_semaphore =device->CreateSem();
shader_manage=device->CreateShaderModuleManage();
db=new SceneDB(device);
InitCommandBuffer();
SetEventCall(win->OnResize, this,VulkanApplicationFramework,OnResize );
SetEventCall(win->OnKeyDown, this,VulkanApplicationFramework,OnKeyDown );
SetEventCall(win->OnKeyUp, this,VulkanApplicationFramework,OnKeyUp );
SetEventCall(win->OnKeyPress, this,VulkanApplicationFramework,OnKeyPress );
SetEventCall(win->OnMouseDown, this,VulkanApplicationFramework,OnMouseDown );
SetEventCall(win->OnMouseUp, this,VulkanApplicationFramework,OnMouseUp );
SetEventCall(win->OnMouseMove, this,VulkanApplicationFramework,OnMouseMove );
SetEventCall(win->OnMouseWheel, this,VulkanApplicationFramework,OnMouseWheel);
return(true);
}
virtual void Resize(int,int)=0;
virtual void KeyPress(KeyboardButton){}
virtual void MouseDown(uint){}
virtual void MouseUp(uint){}
virtual void MouseMove(){}
virtual void MouseWheel(int,int,uint){}
void OnResize(int w,int h)
{
if(w>0&&h>0)
device->Resize(w,h);
InitCommandBuffer();
Resize(w,h);
}
void InitCommandBuffer()
{
if(cmd_buf)
SAFE_CLEAR_OBJECT_ARRAY(cmd_buf,swap_chain_count);
sc_render_target=device->GetSwapchainRT();
swap_chain_count=sc_render_target->GetImageCount();
{
const VkExtent2D extent=sc_render_target->GetExtent();
cmd_buf=hgl_zero_new<vulkan::CommandBuffer *>(swap_chain_count);
for(uint i=0;i<swap_chain_count;i++)
cmd_buf[i]=device->CreateCommandBuffer(extent,2);
}
}
void BuildCommandBuffer(uint32_t index,vulkan::Pipeline *p,vulkan::MaterialInstance *mi,vulkan::Renderable *r)
{
if(!p||!mi||!r)
return;
const vulkan::IndexBuffer *ib=r->GetIndexBuffer();
vulkan::CommandBuffer *cb=cmd_buf[index];
cb->Begin();
cb->BeginRenderPass(sc_render_target->GetRenderPass(),sc_render_target->GetFramebuffer(index));
cb->Bind(p);
cb->Bind(mi->GetDescriptorSets());
cb->Bind(r);
if (ib)
cb->DrawIndexed(ib->GetCount());
else
cb->Draw(r->GetDrawCount());
cb->EndRenderPass();
cb->End();
}
void BuildCommandBuffer(vulkan::Pipeline *p,vulkan::MaterialInstance *mi,vulkan::Renderable *r)
{
for(uint32_t i=0;i<swap_chain_count;i++)
BuildCommandBuffer(i,p,mi,r);
}
void BuildCurrentCommandBuffer(vulkan::Pipeline *p,vulkan::MaterialInstance *mi,vulkan::Renderable *r)
{
BuildCommandBuffer(sc_render_target->GetCurrentFrameIndices(),p,mi,r);
}
void BuildCommandBuffer(uint32_t index,RenderList *rl)
{
if(!rl)return;
vulkan::CommandBuffer *cb=cmd_buf[index];
cb->Begin();
cb->BeginRenderPass(sc_render_target->GetRenderPass(),sc_render_target->GetFramebuffer(index));
rl->Render(cb);
cb->EndRenderPass();
cb->End();
}
void BuildCommandBuffer(RenderList *rl)
{
for(uint32_t i=0;i<swap_chain_count;i++)
BuildCommandBuffer(i,rl);
}
void BuildCurrentCommandBuffer(RenderList *rl)
{
BuildCommandBuffer(sc_render_target->GetCurrentFrameIndices(),rl);
}
public:
int AcquireNextImage()
{
return sc_render_target->AcquireNextImage(present_complete_semaphore);
}
virtual void SubmitDraw(int index)
{
VkCommandBuffer cb=*cmd_buf[index];
sc_render_target->Submit(cb,present_complete_semaphore,render_complete_semaphore);
sc_render_target->PresentBackbuffer(render_complete_semaphore);
sc_render_target->Wait();
}
virtual void Draw()
{
int index=AcquireNextImage();
if(index<0||index>=swap_chain_count)return;
SubmitDraw(index);
}
bool Run()
{
if(!win->Update())return(false);
if(win->IsVisible())
Draw();
return(true);
}
};//class VulkanApplicationFramework
class CameraAppFramework:public VulkanApplicationFramework
{
private:
vulkan::Buffer * ubo_world_matrix =nullptr;
protected:
ControlCamera camera;
float move_speed=1;
Vector2f mouse_last_pos;
public:
virtual ~CameraAppFramework()=default;
virtual bool Init(int w,int h)
{
if(!VulkanApplicationFramework::Init(w,h))
return(false);
InitCamera(w,h);
return(true);
}
virtual void InitCamera(int w,int h)
{
camera.type=CameraType::Perspective;
camera.width=w;
camera.height=h;
camera.vp_width=w;
camera.vp_height=h;
camera.center.Set(0,0,0,1);
camera.eye.Set(10,10,10,1); //xyz三个值不要一样以方便调试
camera.Refresh(); //更新矩阵计算
ubo_world_matrix=db->CreateUBO(sizeof(WorldMatrix),&camera.matrix);
}
void Resize(int w,int h)override
{
camera.width=w;
camera.height=h;
}
vulkan::Buffer *GetCameraMatrixBuffer()
{
return ubo_world_matrix;
}
virtual void BuildCommandBuffer(uint32_t index)=0;
virtual void Draw()override
{
camera.Refresh(); //更新相机矩阵
ubo_world_matrix->Write(&camera.matrix); //写入缓冲区
const uint32_t index=AcquireNextImage();
BuildCommandBuffer(index);
SubmitDraw(index);
if(key_status[kbW])camera.Forward (move_speed);else
if(key_status[kbS])camera.Backward (move_speed);else
if(key_status[kbA])camera.Left (move_speed);else
if(key_status[kbD])camera.Right (move_speed);else
if(key_status[kbR])camera.Up (move_speed);else
if(key_status[kbF])camera.Down (move_speed);else
if(key_status[kbLeft ])camera.WrapHorzRotate( move_speed);else
if(key_status[kbRight ])camera.WrapHorzRotate(-move_speed);else
if(key_status[kbUp ])camera.WrapVertRotate( move_speed);else
if(key_status[kbDown ])camera.WrapVertRotate(-move_speed);else
return;
}
virtual void KeyPress(KeyboardButton kb)override
{
if(kb==kbMinus)move_speed*=0.9f;else
if(kb==kbEquals)move_speed*=1.1f;else
return;
}
virtual void MouseDown(uint) override
{
mouse_last_pos=mouse_pos;
}
virtual void MouseMove() override
{
if(!(mouse_key&(mbLeft|mbRight)))return;
Vector2f gap=mouse_pos-mouse_last_pos;
bool update=false;
if(gap.x!=0){update=true;if(mouse_key&mbLeft)camera.HorzRotate(-gap.x/10.0f);else camera.WrapHorzRotate(gap.x);}
if(gap.y!=0){update=true;if(mouse_key&mbLeft)camera.VertRotate(-gap.y/10.0f);else camera.WrapVertRotate(gap.y);}
mouse_last_pos=mouse_pos;
}
virtual void MouseWheel(int v,int h,uint)
{
camera.Distance(1+(v/1000.0f));
}
};//class CameraAppFramework