当前位置: 首页 > article >正文

webgpu 编译并集成到Qt中

Dawn库编译

dawn 开源库编译 https://dawn.googlesource.com/dawn
set http_proxy=http://127.0.0.1:1080
set https_proxy=http://127.0.0.1:1080
下载gclient https://storage.googleapis.com/chrome-infra/depot_tools.zip
# 引导 gclient 配置
cp scripts/standalone.gclient .gclient
# 使用 gclient 拉取外部依赖与工具链
gclient sync
使用cmake 编译

一般来说我们要编译的是动态库,通过cmake 传入参数 -DBUILD_SHARED_LIBS=1,但是在编译dawn_common库时会出现,这个库只能是静态库,需要手动修改配置(可以用cmake-gui生成vs工程再修改dawn_common为静态库)。

mkdir build1
cd build1
cmake .. 
make -j8
编译结果

dawn20241113.7z

集成到Qt程序中

初始化webgpu 相关信息;
//初始化instance dawnProcSetProcs这个函数必须写,否则启动会报错。
 dawnProcSetProcs(&dawn::native::GetProcs());
 wgpu::InstanceDescriptor instanceDescriptor = {};
 instanceDescriptor.features.timedWaitAnyEnable = true;
 var _instance = wgpu::CreateInstance(&instanceDescriptor);

//获取适配器和设备;

    wgpu::RequestAdapterOptions  options;
//默认设置为独显;
    options.powerPreference = wgpu::PowerPreference::HighPerformance;
//设置后端程序为D3D12
    options.backendType = wgpu::BackendType::D3D12;

//获取适配器;
wgpu::Adapter _adapter
    _instance.WaitAny(
        _instance.RequestAdapter(
            &options, wgpu::CallbackMode::WaitAnyOnly,
            [this](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message) {
                if (status != wgpu::RequestAdapterStatus::Success) {
                    return;
                }
                _adapter = std::move(adapter);
            }),
        UINT64_MAX);

    wgpu::ChainedStruct* togglesChain = nullptr;
 

//获取设备;
    wgpu::DeviceDescriptor deviceDesc = {};
//设置错误回调;
    deviceDesc.SetUncapturedErrorCallback(
        [](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView message) {


        });
    _instance.WaitAny(
        _adapter.RequestDevice(
            &deviceDesc, wgpu::CallbackMode::WaitAnyOnly,
            [this](wgpu::RequestDeviceStatus status, wgpu::Device device, wgpu::StringView message) {
                if (status != wgpu::RequestDeviceStatus::Success) {
                  
                    return;
                }
                _device= std::move(device);
            }),
        UINT64_MAX);
}

将Qt窗口绑定到webgpu的surface中
std::unique_ptr<wgpu::ChainedStruct, void (*)(wgpu::ChainedStruct*)>
SetupWindowAndGetSurfaceDescriptor(void* window) {
    wgpu::SurfaceSourceWindowsHWND* desc = new wgpu::SurfaceSourceWindowsHWND();
    desc->hwnd = window;
    desc->hinstance = GetModuleHandle(nullptr);
    return { desc, [](wgpu::ChainedStruct* desc) {
                delete reinterpret_cast<wgpu::SurfaceSourceWindowsHWND*>(desc);
            } };
 
}
//指定Qt窗口的句柄;
wgpu::Surface CreateSurfaceForWindow(wgpu::Instance instance, void* window) {
    wgpu::SurfaceDescriptor temp_descriptor;
    auto desc=SetupWindowAndGetSurfaceDescriptor(window);
    temp_descriptor.nextInChain = desc.get();
    wgpu::Surface surface = instance.CreateSurface(&temp_descriptor);

    return surface;
}
窗口大小调整响应
void Renderer::onResize()
{ 
    RECT rect;
    GetWindowRect((HWND)_impl->_window_handle, &rect);
    int width= rect.right - rect.left;
    int height= rect.bottom - rect.top;
    wgpu::SurfaceConfiguration config;
    config.width = width;
    config.height = height;
    config.format = wgpu::TextureFormat::BGRA8Unorm;
 
    config.device =_device;
    config.presentMode = wgpu::PresentMode::Fifo;
    config.usage = wgpu::TextureUsage::RenderAttachment;
    _impl->_surface.Configure(&config);
    
}
主帧渲染函数
 auto device = GlobalInstance::instance()->device();

 wgpu::RenderPassColorAttachment attachment = {};
  

 
if (v == 0)
 {
   
    int time = clock();
     _impl->_surface.GetCurrentTexture(&surface_texture);
     v = 0;
     int end=clock()-time;
     std::cout << "texture time:" << end << std::endl;
 }
text_View = surface_texture.texture.CreateView();
 
 attachment.view = text_View;
 attachment.loadOp = wgpu::LoadOp::Clear;
 attachment.storeOp = wgpu::StoreOp::Store;
 //设置背景色;
 attachment.clearValue=wgpu::Color{0.0f,0.0f,0.0f,1.0f};
 attachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;

 wgpu::RenderPassDescriptor renderpass;
  
 renderpass.colorAttachmentCount = 1;
 
 renderpass.colorAttachments = &attachment;
      



    float* mat = glm::value_ptr(_mat);
  
   device.GetQueue().WriteBuffer(_batch->impl()->_matrix_buffer, 0, mat, sizeof(glm::mat4));


     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
     wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderpass);

     //pass.setViewport(0, 0, 500, 500,0,1 );
     pass.SetPipeline(_batch->impl()->_pipeline);
     pass.SetViewport(0, 0, _impl->_width, _impl->_height, 0, 1);
     pass.SetScissorRect(0, 0, _impl->_width, _impl->_height);
   
    pass.SetBindGroup(0, _batch->impl()->_bind_group);

     pass.SetVertexBuffer(0, _batch->impl()->_vertex_buffer,0, _batch->impl()->_vertex_buffer.GetSize());
     pass.SetVertexBuffer(1, _batch->impl()->_color_buffer);
     pass.SetIndexBuffer(_batch->impl()->_index_buffer, wgpu::IndexFormat::Uint32);
     pass.DrawIndexed(_batch->impl()->_index_buffer.GetSize()/4);
     pass.End();

     wgpu::CommandBuffer commands = encoder.Finish();
 
     device.GetQueue().Submit(1,&commands);
   
     _impl->_surface.Present();
QWidget 窗口设置
class CenterWidget :public QWidget
{
	
public:
	CenterWidget()
	{
		this->setAttribute(Qt::WA_PaintOnScreen, true);
		this->setAttribute(Qt::WA_NativeWindow, true);
		this->setUpdatesEnabled(false);
	}
	virtual QPaintEngine* paintEngine() const override
	{
		return nullptr;
	}
	void resizeEvent(QResizeEvent* event)
	{
		if (_renderer != nullptr)
		{
			_renderer->onResize();
		}

	}
	void frame()
	{
		QTime tm;
		tm.start();
        //调用的render的渲染方法,具体如何渲染不在本文章中.
		_renderer->render();
		int aa = tm.elapsed();
		qApp->processEvents();

		std::cout << "frame time:" << aa << std::endl;
	}
}
测试

重复渲染100万个三角形,3060独立显卡,将所有数据放在一个顶点缓冲中,并使用索引绘制的结果。基本上需要耗时60ms。


http://www.kler.cn/a/398100.html

相关文章:

  • 【Linux】Ubuntu中muduo库的编译环境安装
  • HBase压测 ycsb
  • 深入理解Flutter生命周期函数之StatefulWidget(一)
  • Chrome 浏览器开启打印模式
  • 创建vue+electron项目流程
  • 高级计算机算法的8道题(贪心、动态规划)
  • github算法
  • 241113.学习日志——[CSDIY] [ByteDance] 后端训练营 [02]
  • 实验06for与do~while循环---7-01 验证一个著名数学猜想
  • 循环矩阵和BCCB矩阵与向量乘积的快速计算——矩阵向量乘积与频域乘积之间的转换
  • 7、ARM_栈
  • 【日常记录-Git】git log
  • 传奇996_24——变量lua
  • Kafka常见问题及处理
  • 如何用python将pdf转换为json格式
  • 假设一棵平衡二叉树的每个结点都表明了平衡因子b,试设计一个算法,求平衡二叉树的高度。
  • ChatGPT 搜索 vs Google 搜索
  • stm32学习之路——LED闪烁实验
  • SSH隧道连接(基于linux)
  • 【366】基于springboot的高校物品捐赠管理系统
  • Python常用魔术方法 (学习笔记)
  • Prometheus面试内容整理-PromQL 查询语言
  • 【软件测试】设计测试用例的万能公式
  • git简介和本地仓库创建,并提交修改。git config init status add commit
  • 开启鸿蒙开发之旅:交互——点击事件
  • 领夹麦克风哪个品牌好,手机领夹麦克风哪个牌子好,选购推荐