ULRE/example/common/VulkanAppFramework.h

438 lines
12 KiB
C
Raw Normal View History

2019-05-08 00:25:40 +08:00
#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/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>
2020-01-20 15:39:39 +08:00
#include<hgl/graph/vulkan/VKMaterialInstance.h>
#include<hgl/graph/vulkan/VKRenderTarget.h>
2020-09-02 18:16:15 +08:00
#include<hgl/graph/vulkan/VKDatabase.h>
#include<hgl/graph/RenderList.h>
using namespace hgl;
using namespace hgl::graph;
class VulkanApplicationFramework
{
2019-06-11 16:18:49 +08:00
private:
Window * win =nullptr;
vulkan::Instance * inst =nullptr;
2019-06-14 19:56:21 +08:00
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;
2020-01-23 21:00:35 +08:00
2019-07-17 04:49:16 +08:00
protected:
int32_t swap_chain_count =0;
vulkan::CommandBuffer ** cmd_buf =nullptr;
Color4f clear_color;
protected:
vulkan::Database * db =nullptr;
bool key_status[kbRangeSize];
public:
virtual ~VulkanApplicationFramework()
{
SAFE_CLEAR(db);
SAFE_CLEAR_OBJECT_ARRAY(cmd_buf,swap_chain_count);
SAFE_CLEAR(device);
2020-01-23 21:00:35 +08:00
SAFE_CLEAR(win);
SAFE_CLEAR(inst);
}
virtual bool Init(int w,int h)
{
hgl_zero(key_status);
clear_color.Zero();
#ifdef _DEBUG
if(!vulkan::CheckStrideBytesByFormat())
return(false);
#endif//
2019-04-30 19:01:44 +08:00
InitNativeWindowSystem();
2019-11-14 17:57:46 +08:00
VK_NAMESPACE::InitVulkanProperties();
win=CreateRenderWindow(OS_TEXT("VulkanTest"));
if(!win)
return(false);
if(!win->Create(w,h))
return(false);
2019-11-14 17:57:46 +08:00
{
VK_NAMESPACE::CreateInstanceLayerInfo cili;
2020-09-28 11:16:45 +08:00
hgl_zero(cili);
2019-11-14 17:57:46 +08:00
cili.lunarg.standard_validation = true;
cili.khronos.validation = true;
cili.RenderDoc.Capture = true;
2020-07-07 19:16:23 +08:00
inst=vulkan::CreateInstance("VulkanTest",nullptr,&cili);
2019-11-14 17:57:46 +08:00
if(!inst)
return(false);
}
device=CreateRenderDevice(inst,win);
if(!device)
return(false);
db=new vulkan::Database(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 );
2019-06-14 19:56:21 +08:00
SetEventCall(win->OnMouseDown, this,VulkanApplicationFramework,OnMouseDown );
SetEventCall(win->OnMouseUp, this,VulkanApplicationFramework,OnMouseUp );
SetEventCall(win->OnMouseMove, this,VulkanApplicationFramework,OnMouseMove );
SetEventCall(win->OnMouseWheel, this,VulkanApplicationFramework,OnMouseWheel);
2019-06-14 19:56:21 +08:00
return(true);
}
virtual void Resize(int,int)=0;
virtual void KeyPress(KeyboardButton){}
2019-06-14 19:56:21 +08:00
virtual void MouseDown(uint){}
virtual void MouseUp(uint){}
virtual void MouseMove(){}
virtual void MouseWheel(int,int,uint){}
2020-01-23 21:00:35 +08:00
2019-07-17 04:49:16 +08:00
void OnResize(int w,int h)
{
if(w>0&&h>0)
device->Resize(w,h);
2019-07-17 04:49:16 +08:00
InitCommandBuffer();
Resize(w,h);
}
void InitCommandBuffer()
{
if(cmd_buf)
2019-06-28 20:46:32 +08:00
SAFE_CLEAR_OBJECT_ARRAY(cmd_buf,swap_chain_count);
2020-01-23 21:00:35 +08:00
2019-07-17 04:49:16 +08:00
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(int32_t i=0;i<swap_chain_count;i++)
cmd_buf[i]=device->CreateCommandBuffer(extent,2);
}
}
void BuildCommandBuffer(vulkan::RenderTarget *rt,vulkan::RenderableInstance *ri)
{
if(!rt||!ri)
return;
vulkan::CommandBuffer *cb=rt->GetCommandBuffer();
const vulkan::IndexBuffer *ib=ri->GetIndexBuffer();
cb->Begin();
cb->BindFramebuffer(rt);
cb->BindPipeline(ri->GetPipeline());
cb->BindDescriptorSets(ri->GetDescriptorSets());
cb->BindVAB(ri);
if (ib)
cb->DrawIndexed(ib->GetCount());
else
cb->Draw(ri->GetDrawCount());
cb->EndRenderPass();
cb->End();
}
void SetClearColor(COLOR cc)
{
clear_color.Use(cc,1.0);
}
void BuildCommandBuffer(uint32_t index,vulkan::RenderableInstance *ri)
{
if(!ri)
return;
const vulkan::IndexBuffer *ib=ri->GetIndexBuffer();
2019-06-18 00:48:05 +08:00
vulkan::CommandBuffer *cb=cmd_buf[index];
2020-01-23 21:00:35 +08:00
cb->SetClearColor(0,clear_color.r,clear_color.g,clear_color.b);
2019-06-18 00:48:05 +08:00
cb->Begin();
cb->BindFramebuffer(sc_render_target->GetRenderPass(),sc_render_target->GetFramebuffer(index));
cb->BindPipeline(ri->GetPipeline());
cb->BindDescriptorSets(ri->GetDescriptorSets());
cb->BindVAB(ri);
2019-06-18 00:48:05 +08:00
if (ib)
cb->DrawIndexed(ib->GetCount());
else
cb->Draw(ri->GetDrawCount());
2019-06-18 00:48:05 +08:00
cb->EndRenderPass();
2019-06-18 00:48:05 +08:00
cb->End();
}
2020-01-23 21:00:35 +08:00
void BuildCommandBuffer(vulkan::RenderableInstance *ri)
2019-06-18 00:48:05 +08:00
{
for(int32_t i=0;i<swap_chain_count;i++)
BuildCommandBuffer(i,ri);
}
void BuildCurrentCommandBuffer(vulkan::RenderableInstance *ri)
{
BuildCommandBuffer(sc_render_target->GetCurrentFrameIndices(),ri);
2019-06-18 00:48:05 +08:00
}
2019-06-18 00:48:05 +08:00
void BuildCommandBuffer(uint32_t index,RenderList *rl)
{
2020-01-23 21:00:35 +08:00
if(!rl)return;
2019-06-18 00:48:05 +08:00
vulkan::CommandBuffer *cb=cmd_buf[index];
cb->Begin();
cb->BindFramebuffer(sc_render_target->GetRenderPass(),sc_render_target->GetFramebuffer(index));
2019-06-18 00:48:05 +08:00
rl->Render(cb);
cb->EndRenderPass();
cb->End();
}
void BuildCommandBuffer(RenderList *rl)
{
for(int32_t i=0;i<swap_chain_count;i++)
2019-06-18 00:48:05 +08:00
BuildCommandBuffer(i,rl);
}
2020-01-23 21:00:35 +08:00
2019-06-18 00:48:05 +08:00
void BuildCurrentCommandBuffer(RenderList *rl)
2020-01-23 21:00:35 +08:00
{
BuildCommandBuffer(sc_render_target->GetCurrentFrameIndices(),rl);
}
public:
2019-06-18 00:48:05 +08:00
int AcquireNextImage()
{
return sc_render_target->AcquireNextImage();
2019-06-18 00:48:05 +08:00
}
virtual void SubmitDraw(int index)
2019-06-18 00:48:05 +08:00
{
VkCommandBuffer cb=*cmd_buf[index];
2020-01-23 21:00:35 +08:00
sc_render_target->Submit(cb);
sc_render_target->PresentBackbuffer();
sc_render_target->WaitQueue();
sc_render_target->WaitFence();
}
2019-06-18 00:48:05 +08:00
virtual void Draw()
{
int index=AcquireNextImage();
2019-07-01 17:04:02 +08:00
if(index<0||index>=swap_chain_count)return;
2019-06-18 00:48:05 +08:00
SubmitDraw(index);
}
2019-04-30 19:01:44 +08:00
bool Run()
{
if(!win->Update())return(false);
if(win->IsVisible())
Draw();
return(true);
}
2020-09-21 17:19:47 +08:00
public: //pipeline
vulkan::Pipeline *CreatePipeline(vulkan::Material *mtl,const vulkan::InlinePipeline &ip,const Prim &prim=Prim::Triangles,const bool prim_restart=false)
{
return db->CreatePipeline(mtl,sc_render_target,ip,prim,prim_restart);
}
vulkan::Pipeline *CreatePipeline(vulkan::MaterialInstance *mi,const vulkan::InlinePipeline &ip,const Prim &prim=Prim::Triangles,const bool prim_restart=false)
{
return db->CreatePipeline(mi,sc_render_target,ip,prim,prim_restart);
}
2020-09-21 17:19:47 +08:00
vulkan::Pipeline *CreatePipeline(vulkan::Material *mtl,vulkan::PipelineData *pd,const Prim &prim=Prim::Triangles,const bool prim_restart=false)
{
return db->CreatePipeline(mtl,sc_render_target,pd,prim,prim_restart);
}
vulkan::Pipeline *CreatePipeline(vulkan::MaterialInstance *mi,vulkan::PipelineData *pd,const Prim &prim=Prim::Triangles,const bool prim_restart=false)
{
return db->CreatePipeline(mi,sc_render_target,pd,prim,prim_restart);
}
vulkan::Pipeline *CreatePipeline(vulkan::Material *mtl,const OSString &pipeline_name,const Prim &prim=Prim::Triangles,const bool prim_restart=false)
{
return db->CreatePipeline(mtl,sc_render_target,pipeline_name,prim,prim_restart);
}
vulkan::Pipeline *CreatePipeline(vulkan::MaterialInstance *mi,const OSString &pipeline_name,const Prim &prim=Prim::Triangles,const bool prim_restart=false)
{
return db->CreatePipeline(mi,sc_render_target,pipeline_name,prim,prim_restart);
}
};//class VulkanApplicationFramework
class CameraAppFramework:public VulkanApplicationFramework
{
private:
vulkan::Buffer * ubo_world_matrix =nullptr;
protected:
ControlCamera camera;
float move_speed=1;
2019-06-14 19:56:21 +08:00
Vector2f mouse_last_pos;
public:
virtual ~CameraAppFramework()=default;
virtual bool Init(int w,int h)
{
if(!VulkanApplicationFramework::Init(w,h))
return(false);
2020-01-23 21:00:35 +08:00
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);
}
2020-01-23 21:00:35 +08:00
void Resize(int w,int h)override
{
camera.width=w;
camera.height=h;
}
vulkan::Buffer *GetCameraMatrixBuffer()
{
return ubo_world_matrix;
}
2019-06-18 00:48:05 +08:00
virtual void BuildCommandBuffer(uint32_t index)=0;
2019-06-14 20:01:46 +08:00
virtual void Draw()override
{
camera.Refresh(); //更新相机矩阵
ubo_world_matrix->Write(&camera.matrix); //写入缓冲区
const uint32_t index=AcquireNextImage();
2019-06-18 00:48:05 +08:00
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
2019-11-25 22:05:05 +08:00
if(key_status[kbLeft ])camera.WrapHorzRotate( move_speed);else
if(key_status[kbRight ])camera.WrapHorzRotate(-move_speed);else
2019-11-25 22:05:05 +08:00
if(key_status[kbUp ])camera.WrapVertRotate( move_speed);else
if(key_status[kbDown ])camera.WrapVertRotate(-move_speed);else
return;
}
2019-06-14 19:56:21 +08:00
virtual void KeyPress(KeyboardButton kb)override
{
if(kb==kbMinus)move_speed*=0.9f;else
if(kb==kbEquals)move_speed*=1.1f;else
return;
}
2019-06-14 19:56:21 +08:00
virtual void MouseDown(uint) override
{
mouse_last_pos=mouse_pos;
}
virtual void MouseMove() override
{
if(!(mouse_key&(mbLeft|mbRight)))return;
2019-06-14 19:56:21 +08:00
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);}
2019-06-14 19:56:21 +08:00
mouse_last_pos=mouse_pos;
}
virtual void MouseWheel(int v,int h,uint)
{
camera.Distance(1+(v/1000.0f));
}
};//class CameraAppFramework