window显示驱动开发—流输出阶段

流输出 (SO) 阶段可以在这些顶点到达光栅器之前将顶点流式传输到内存。 流输出的运行方式类似于管道中的点击。 即使数据继续向下流向光栅器,也可以打开此点击。 通过流输出发送的数据连接到缓冲区。 这些缓冲区可以在后续传递上作为管道输入进行循环。

流输出的一个约束是,它与几何着色器相关联,因为它们必须一起创建, (两者可以是“NULL”/“off”) 。 不过,流出到的特定内存缓冲区不会绑定到特定的几何着色器和流输出对。 仅描述要馈送给流输出的顶点数据部分与几何着色器相关联。

流输出可用于保存将重复使用的有序管道数据。 例如,一批顶点可以通过将顶点传入管道来“皮肤化”,就好像它们是独立的点 (只是) 访问所有这些点,对每个顶点应用“皮肤化”操作,并将结果流式传输到内存。 保存的“皮肤化”顶点随后可用作输入。

由于通过流输出写入的输出量是动态的,因此需要一种新型的 Draw ,DrawAuto 才能允许流输出缓冲区与输入汇编程序一起重复使用,而无需 CPU 参与来确定实际写入的数据量。 此外,需要查询来缓解流输出溢出,以及检索写入流输出缓冲区的数据量 (D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE和 D3D10DDI_QUERY_STREAMOUTPUTSTATS D3D10DDI_QUERY 枚举) 。

Direct3D 运行时调用以下驱动程序函数来创建和设置流输出:

  • CalcPrivateGeometryShaderWithStreamOutput
  • CreateGeometryShaderWithStreamOutput
  • SoSetTargets

 1. 核心功能与设计理念

流输出 (SO) 是 Direct3D 10 引入的数据回写机制,允许在几何着色器 (GS) 处理后,将顶点数据直接写入GPU缓冲区,而非仅传递到光栅化阶段。其核心特性包括:

  • 数据持久化:将处理后的顶点保存到缓冲区,供后续渲染循环使用。
  • GPU闭环:实现完全在GPU内部的数据复用(如粒子系统更新)。
  • 动态数据量:支持可变长度输出(需配合 DrawAuto 和查询机制)。

类比:SO 如同在渲染管线中插入一个“T型阀门”,既可流向光栅器,也可分流到内存。

2. 流输出与几何着色器的关系

  1. 强耦合性:SO 必须与 GS 同时创建(两者可同时为NULL关闭)。
  2. 分离绑定:
  • GS+SO创建时:定义哪些顶点属性输出到缓冲区(如仅位置+速度)。
  • 运行时绑定:实际缓冲区(D3D10DDI_HRESOURCE)通过 SoSetTargets 动态指定。

示例:创建带SO的GS:

D3D10DDIARG_STAGE_IO_SIGNATURES soSignatures;
soSignatures.NumEntries = 2;
soSignatures.pOutputSignature = { "POSITION", "VELOCITY" }; // 输出到缓冲区的属性pDeviceFuncs->CreateGeometryShaderWithStreamOutput(hDevice, pGSBytecode, &soSignatures, hGS, hRTGS
);

3. 关键驱动函数与实现

(1) 函数列表

函数职责
CalcPrivateGeometryShaderWithStreamOutput计算GS+SO私有数据所需内存。
CreateGeometryShaderWithStreamOutput创建带SO的GS对象,指定输出属性和格式。
SoSetTargets绑定SO目标缓冲区(支持多缓冲区,需匹配创建时的声明)。

(2) SoSetTargets 实现示例

void APIENTRY SoSetTargets(D3D10DDI_HDEVICE hDevice,UINT NumBuffers,const D3D10DDI_HRESOURCE* phBuffers,  // SO缓冲区资源句柄const UINT* pOffsets                  // 各缓冲区的写入起始偏移
) {MyDeviceContext* pCtx = (MyDeviceContext*)hDevice.pDrvPrivate;for (UINT i = 0; i < NumBuffers; ++i) {pCtx->soBuffers[i] = phBuffers[i];pCtx->soOffsets[i] = pOffsets ? pOffsets[i] : 0;// 标记SO缓冲区为脏(需GPU同步)pCtx->dirtyFlags |= SO_TARGETS_DIRTY;}
}

4. 数据流控制与高级特性

(1) 流输出工作流程

  • GS处理顶点:输出到SO缓冲区的属性由创建时的签名定义。

数据写入缓冲区:

  • 每个顶点按声明顺序写入绑定的缓冲区。
  • 支持多缓冲区交错写入(如位置和速度分开存储)。

后续渲染循环:

  • 绑定SO缓冲区作为输入装配器 (IA) 的输入(需兼容格式)。
  • 使用 DrawAuto 自动确定绘制数量。

(2) DrawAuto 机制

  • 用途:在不知道SO输出数据量的情况下,自动绘制所有有效顶点。
  • 驱动实现:

需内部记录SO写入的顶点数,并在 DrawAuto 时回传给IA。

void APIENTRY DrawAuto(D3D10DDI_HDEVICE hDevice) {MyDeviceContext* pCtx = (MyDeviceContext*)hDevice.pDrvPrivate;UINT vertexCount = pCtx->soStats.NumPrimitivesWritten * 3; // 假设三角形列表pDeviceFuncs->Draw(hDevice, vertexCount, 0);
}

(3) 溢出查询与统计
通过查询对象监测SO状态:

查询类型用途
D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE检测SO缓冲区是否溢出(返回TRUE/FALSE)。
D3D10DDI_QUERY_STREAMOUTPUTSTATS获取写入的图元/顶点数(用于调试或逻辑控制)。

示例:检查溢出:

BOOL overflow = FALSE;
pDeviceFuncs->QueryGetData(hQuery, &overflow, sizeof(BOOL));
if (overflow) {// 处理缓冲区扩容或数据截断
}

5. 典型应用场景

(1) GPU粒子系统

  • 初始化:创建带SO的GS,输出位置+速度。

更新循环:

  • 绑定SO缓冲区,用GS计算粒子运动。
  • 通过 DrawAuto 绘制更新后的粒子。
  • 渲染循环将SO缓冲区作为IA输入,渲染粒子。

(2) 几何变形缓存

  • 预处理:使用GS+SO将复杂变形(如曲面细分)结果存入缓冲区。
  • 复用数据:后续帧直接读取缓存,跳过重复计算。

6. 性能优化与注意事项

(1) 优化建议

  • 缓冲区复用:使用双缓冲或环形缓冲避免GPU停滞。
  • 对齐写入:确保SO输出格式符合硬件要求(如4字节对齐)。
  • 查询最小化:仅在必要时检查 STREAMOVERFLOWPREDICATE。

(2) 限制与兼容性

限制解决方案
SO缓冲区必须绑定为无序访问视图 (UAV)创建资源时指定 D3D10_DDI_BIND_STREAM_OUTPUT
输出数据量不可预测预分配足够大的缓冲区,或动态调整。
仅支持顶点数据(非结构化)需通过GS组织输出结构。

7. 驱动调试与验证

  • 验证SO签名匹配:确保 CreateGeometryShaderWithStreamOutput 声明的输出格式与 SoSetTargets 绑定的缓冲区兼容。
  • 检查溢出查询:在复杂场景中强制触发溢出,验证驱动正确处理。
  • 性能分析:使用GPU Profiler(如PIX)监测SO带宽占用。

总结

流输出 (SO) 是 Direct3D 10 实现 GPU数据闭环 的关键技术,其核心价值包括:

  • 数据持久化:避免CPU-GPU通信开销。
  • 动态处理:支持可变长度输出与自动绘制(DrawAuto)。
  • 高效复用:适用于粒子系统、几何变形等场景。

开发者需关注:

  • GS与SO的协同设计:明确定义输出属性。
  • 缓冲区管理:防止溢出并优化内存访问。
  • 查询机制:确保动态数据量可控。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87335.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

备份docker desktop中的opengauss数据库

文章目录 备份docker desktop中的opengauss数据库一、前提条件二、备份步骤三、注意事项四、自动化备份&#xff08;可选&#xff09;五、验证备份 备份docker desktop中的opengauss数据库 ​ 以下是在 Docker Desktop 中备份 OpenGauss 数据库&#xff08;以你的环境为例&…

实时中值滤波 + 低通滤波 示例程序(STM32环境)

一、功能概述 本示例实现两个滤波器&#xff1a; 中值滤波器&#xff08;Median Filter&#xff09;&#xff1a;对短期异常值&#xff08;如尖峰噪声&#xff09;有良好的抑制能力&#xff1b;低通滤波器&#xff08;Low-Pass Filter&#xff09;&#xff1a;对数据进行平滑…

AtCoder Beginner Contest 409 题解

本文为AtCoder Beginner Contest 409 的详细题解 目录 题目A: 题目大意: 解题思路: 代码(C): 题目B: 题目大意: 解题思路: 代码(C): 题目C: 题目大意: 解题思路: 代码(C): 题目D: 题目大意: 解题思路: 代码(C): 题目E: 题目大意: 解题思路: 代码(C): 题目A…

Spring @Environment 典型用法

简单说&#xff1a;Spring 里没有直接叫 Environment 的注解&#xff0c;更准确说常用的是 Autowired 注入 Environment 对象&#xff0c;或者结合 Value 配合 Environment 读取配置 。 支持从以下来源读取&#xff1a; 1、application.properties / .yaml 2、JVM 参数&#xf…

【集合与结构体】5.2(课本题)总结代码

ds老师产物&#xff0c;纯为期末复习&#xff0c;自用。 题目1 编写程序&#xff0c;将一个整型变量右移 4 位&#xff0c;并以二进制数形式输出该整数在移位前和移位后的数值。 //观察系统填补空缺的数位情况 代码解答 #include <iostream>//编写程序&#xff0c;将一个…

16.max/min最大最小值函数

1.基本使用 max/min函数返回满足where条件的一列的最大/最小值。 select max(column_name)|min(column_name) from table_namewhere where_definition 示例&#xff1a; ①求班级总分的最高分 #求班级总分的最高分 SELECT MAX(math_scorechinese_scoreenglish_score)AS 总分…

需要做一款小程序,用来发券,后端如何进行设计能够保证足够安全?

温馨提示&#xff1a;本文由ai生成&#xff0c;请辨别阅读&#xff0c;本文仅提供一种思考的方式和设计思路 设计一个安全的后端系统&#xff0c;用于发放优惠券的小程序&#xff0c;需要考虑多个安全层面&#xff0c;包括身份验证、数据安全、API 安全、以及防止常见攻击&…

ACM设计平台-核心模块解析-赵家康

负责模块解析-赵家康 一、Login.vue 功能逻辑、数据绑定、表单验证、与后端交互 Vue 登录页面的代码设计 代码功能概览 代码实现了一个典型的登录页功能&#xff0c;核心包括&#xff1a; 表单输入&#xff08;学号、用户名、密码、验证码&#xff09; 验证码生成与校验 勾…

在 VMware (WM) 虚拟机上安装的 Ubuntu 22.04 分配了 20GB 磁盘,但仅使用 10GB 就显示 “空间已满“

可能原因及解决方案 虚拟机磁盘未实际扩容&#xff08;仅调整了虚拟大小&#xff09; 现象&#xff1a;在 VMware 里调整了磁盘大小&#xff08;如 20GB → 50GB&#xff09;&#xff0c;但 Ubuntu 内部仍只识别 10GB。 原因&#xff1a;VMware 调整的是虚拟磁盘上限&#xf…

初学STM32全功能按键非阻塞式实现和强化

其实笔者以前学51的时候按键功能就包含非阻塞式的&#xff0c;而且还包括矩阵按键的非组塞式按键实现。开关的长短键功能笔者在之前的51博文中笔者自己尝试写过&#xff0c;功能是有了但写的其实很混乱&#xff0c;几乎没有移植的价值。这次江科大刚好出了新的教程&#xff0c;…

【网络原理】网络原理简单认识 —— 内含网络通信基础、五元组、网络协议(OSI 七层协议、TCP/IP 五层(或四层)协议)、封装和分用

目录 1. 网络互连 1.1 局域网LAN 1.2 广域网WAN 2 网络通信基础 2.1 IP地址 2.2 端口号 2.3 网络协议 3. 五元组 4. 协议分层 4.1 OSI 七层网络模型 4.2 TCP/IP 五层&#xff08;或四层&#xff09;网络模型 4.3 网络设备所在分层(经典笔试题) 5. 网络数据传输的基…

嵌入式之硬件学习(三)通信方式、串口通信

目录 一、通信种类 1、并行通信 2、串行通信 3、单工模式(Simplex Communication) 4、半双工通信(Half-Duplex Communication) 5、全双工通信(Full-Duplex Communication) 6、串行的异步通信与同步通信 &#xff08;1&#xff09;异步通信 &#xff08;2&#xff09;同…

【微信小程序】3、SpringBoot整合WxJava发送订阅消息

1、创建消息模板 在公共模板库里面选择符合自己业务场景的消息模板&#xff0c;例如&#xff1a; 每个消息模板最多选择5项&#xff0c;可根据自己业务需求自行选择&#xff0c;顺序也可以自己决定。提交后&#xff0c;我们就得到了属于自己的消息模板ID 2、文档阅读 官方文…

Flask 快速精通:从入门到实战的轻量级 Web 框架指南

Flask 作为 Python 生态中最受欢迎的轻量级 Web 框架&#xff0c;以其简洁灵活的设计理念赢得了开发者的青睐。本文将系统梳理 Flask 的核心概念与实战技巧&#xff0c;帮助你快速掌握这一强大框架。 一、Flask 框架概述 1.1 轻量级框架的核心特性 Flask 诞生于 2010 年&…

Python爬取豆瓣短评并生成词云分析

一、项目概述 本项目的目标是爬取豆瓣上某部电影的短评数据&#xff0c;并生成词云进行情感分析。我们将使用Python编程语言&#xff0c;借助爬虫技术获取数据&#xff0c;并利用自然语言处理和数据可视化工具进行分析。具体步骤包括&#xff1a; 爬取豆瓣短评数据。数据清洗…

Controller Area Network (CAN) 通信机制简介

目录 1. CAN 概述 2. 物理结构与传输机制 3. 消息格式与仲裁机制 4. 错误检测与总线状态 5. 工业用 CAN 接口 6. 本讲总结 1. CAN 概述 CAN&#xff08;Controller Area Network&#xff09;是由德国博世&#xff08;Bosch&#xff09;公司于 1983 年提出的串行通信协议…

我有一个想法

我有一个想法 我想为家乡做点事情&#xff0c;但是又不知道从哪里开始。 也许为家乡的教育做点事情是比较靠谱的。 于是&#xff0c;我就想到了&#xff0c;是不是可以在高中学校&#xff0c;设立一个“鸿鹄”奖学金&#xff1f; 这个奖学金怎么使用呢&#xff1f; 在每年9月份…

【Pandas】pandas DataFrame stack

Pandas2.2 DataFrame Reshaping sorting transposing 方法描述DataFrame.droplevel(level[, axis])用于**从 DataFrame 的索引&#xff08;行或列&#xff09;中删除指定层级&#xff08;level&#xff09;**的方法DataFrame.pivot(*, columns[, index, values])用于重塑 Dat…

Java 自动关闭资源语法糖 - try-with-resources

文章目录 Java 自动关闭资源语法糖 - try-with-resources前言优势1、自动资源管理2、处理多重资源3、异常处理更健壮4、适用条件 总结 Java 自动关闭资源语法糖 - try-with-resources 前言 日常开发中&#xff0c;我们经常会看到如下代码&#xff1a; try (InputStream is …

MyBatis中的动态SQL是什么?

大家好&#xff0c;我是锋哥。今天分享关于【MyBatis中的动态SQL是什么&#xff1f;】面试题。希望对大家有帮助&#xff1b; MyBatis中的动态SQL是什么&#xff1f; 超硬核AI学习资料&#xff0c;现在永久免费了&#xff01; MyBatis中的动态SQL指的是根据不同的条件&#x…