《dx12 龙书》第四部分学习笔记——预备知识(下)

7、多重采样技术的原理

 由于屏幕中显示的像素不可能是无穷小的,所以并不是任意一条直线都能在显示器上“平滑”而完美地呈现出来。即为以像素矩阵 (matrix of pixels, 可以理解为“像素2D数组”)逼近直线的方法所产生的“阶梯” (aliasing, 锯齿状走样)效果。类似地,显示器中呈现的三角形之边也存在着不同程度的锯齿效应。
 通过提高显示器的分辨率就能够缩小像素的大小,继而使上述问题得到显著地改善,使阶梯效应在很大程度上不易被用户所察觉。
 在不能提升显示器分辨率,或在显示器分辨率受限的情况下,我们就可以运用各种反走样(antialiasing, 也有译作抗锯齿、反锯齿、反失真等)技术。有一种名为超级采样(supersampling, 可简记作SSAA,即Super Sample Anti-Aliasing)的反走样技术,它使用4倍于屏幕分辨率大小的后台缓冲区和深度缓冲区。3D场景将以这种更大的分辨率渲染到后台缓冲区中。当数据要从后台缓冲区调往屏幕显示的时候,会将后台缓冲区按4个像素一组进行解析(resolve, 或称降采样,downsample。把放大的采样点数降低回原采样点数):每组用求平均值的方法得到一组相对平滑的像素颜色。因此,超级采样实际上是通过软件的方式提升了画面的分辨率。
 超级采样是一种开销高昂的操作,因为它将像素的处理数量和占用的内存大小都增加到之前的4倍。
 对此,Direct3D还支持一种在性能于效果等方面都较为折中的反走样技术,叫做多重采样(multisampling, 可简记作MSAA,即MultiSample Anti-Aliasing)。这种技术通过跨子像素共享一些计算信息,从而使它比超级采样的开销更低。现假设采用4X多重采样(即每个像素都有4个子像素),并同样使用4倍于屏幕分辨率的后台缓冲区和深度缓冲区。值得注意的是,这种技术并不需要对每一个子像素都进行计算,而是仅计算一次像素中心处的颜色,再基于可视性(每个子像素经深度/模板测试的结果)和覆盖性(子像素的中心在多边形的里面还是外面?)将得到的颜色信息分享给其子像素。下图展示了一个多重采样的实例。
多重采样实例注意:
 超级采样和多重采样的关键区别是显而易见的。对于超级采样来说,图像颜色要根据每一个子像素来计算,因此每个子像素都可能各具不同的颜色。而以多重采样的方式来求取图像颜色时,每个像素只需计算一次,最后,再将得到的颜色数据复制到多边形覆盖的所有可见子像素之中。由于计算图像颜色是图形流水线中开销最大的步骤之一,所以用多重采样来代替超级采样对节省资源而言意义非凡。但是,超级采样的精准度确实更高一筹。
 上图所示的是一种将每个像素都以均匀栅格划分为4个子像素的反锯齿采样模式。实际上,每家硬件厂商所采用的模式(即选定的子像素位置,可以说决定了采样的位置)可能会各不相同,而Direct3D也并没有定义子像素的具体布局。在各种特定的情况下,不同的布局模式各有千秋。

8、利用Direct3D进行多重采样

typedef struct DXGI_SAMPLE_DESC
{UINT Count; UINT Quality;
}DXGI_SAMPLE_DESC;

 Count成员指定了每个像素的采样次数,Quality成员则用于指示用户期望的图像质量级别。采样数量越多或质量级别越高,其渲染操作的代价也就会愈发高昂,所以需要在质量与速度之间做出利弊权衡。至于质量级别的范围,则要取决于纹理格式和每个像素的采样数量。
 根据给定的纹理格式和采样数量,我们就能用ID3D12Device::CheckFeatureSupport方法查询到对应的质量级别:

typedef struct D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS{DXGI_FORMAT Format;UINT SampleCount;D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS Flags;UINT NumQualityLevels;
}D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS;D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msQualityLevels;
msQualityLevels.Format = mBackBufferFormat;
msQualityLevels.SampleCount = 4;
msQualityLevels.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE;
msQualityLevels.NumQualityLevels = 0;
ThrowIfFailed(md3dDevice->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,&msQualityLevels,sizeof(msQualityLevels)));

 注意,此方法的第二个参数兼具输入和输出的属性。当它作为输入参数时,我们必须指定纹理格式、采样数量以及希望查询的多重采样所支持的标志。接着,待函数执行后便会填写图像质量级别作为输出。对于某种纹理格式和采样数量的组合来讲,其质量级别的有效范围为0至NumQualityLevels-1。
 每个像素的最大采样数量被定义为:
 #define D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT(32)
 但是,考虑到多重采样会占用内存资源,又为了保证程序性能等原因,通常会把采样数量设定为4或8。如果不希望使用多重采样,则可将采样数量设置为1,并令质量级别为0。其实在所有支持Direct3D11的设备上,就已经可以对所有的渲染目标格式用用4X多重采样了。
注意:
 在创建交换链缓冲区和深度缓冲区时都需要填写DXGI_SAMPLE_DESC结构体。当创建后台缓冲区和深度缓冲区时,多重采样的有关设置一定要相同。

9、功能级别

 举例以下参数大致对应于Direct3D9到Direct3D11之间的各种版本:

enum D3D_FEATURE_LEVEL
{D3D_FEATURE_LEVEL_9_1	  = 0x9100,D3D_FEATURE_LEVEL_9_2	  = 0x9200,D3D_FEATURE_LEVEL_9_3	  = 0x9300,D3D_FEATURE_LEVEL_10_0	= 0xa000,D3D_FEATURE_LEVEL_10_1	= 0xa100,D3D_FEATURE_LEVEL_11_0	= 0xb000,D3D_FEATURE_LEVEL_11_1	= 0xb100,
}D3D_FEATURE_LEVEL;

 “功能级别”为不同级别所支持的功能进行了严格的界定(每个功能级别所支持的特定功能可参见SDK文档)。
 例,一款支持功能级别11的GPU,除了个别特例之外,必须支持完整的Direct3D11功能集。
 功能集使程序员的开发工作更加便捷——只要了解所支持的功能集,就能知道有哪些Direct3D功能可供使用。
 如果用户的硬件不支持某特定功能级别,应用程序理当回退至版本更低的功能级别。在现实的应用程序中,我们往往需要考虑支持稍旧的硬件,以获得更多的用户。

10、DirectX图形基础结构

 DirectX图形基础结构(DirectX Graphics Infrastructure,DXGI,也有译作DirectX图形基础设施)是一种与Direct3D配合使用的API设计DXGI的基本理念是使多种图形API中所共有的底层任务能借助一组通用API来进行处理。例如,为了保证动画的流畅性,2D渲染与3D渲染两组API都要用到交换链和页面翻转功能,这里所用的交换链接口IDXGISwapChain实际上就属于DXGI API。DXGI还用于处理一些其他常用的图形功能,如切换全屏模式,枚举显示适配器、显示设备及其支持的显示模式(分辨率、刷新率等)等这类图形系统信息。除此之外,它还定义了Direct3D支持的各种表面格式信息(DXGI_FORMAT)。
 我们刚刚简单地叙述了DXGI的概念,下面来介绍一些在Direct3D初始化时会用到的相关接口。IDXGIFactory是DXGI中的关键接口之一。通常来说,显示适配器(display adapter) 是一种硬件设备(如独立显卡),然而系统也可以用软件显示适配器来模拟硬件的图形处理功能。一个系统中可能会存在数个适配器(比如装有数块显卡)。适配器用接口IDXGIAdapter来表示。我们可以用下面的代码来枚举一个系统中的所有适配器:

void D3DApp::LogAdapters()
{UINT i = 0;IDXGIAdapter* adapter = nullptr;std::vector<IDXGIAdapter*> adapterList;while (mdxgiFactory->EnumAdapters(i, &adapter) !=DXGI_ERROR_NOT_FOUND){DXGI_ADAPTER_DESC desc;adapter->GetDesc(&desc);std::wstring text = L"***Adapter: ";text += desc.Description;text += L”\n”;OutputDebugString(text.c_str());adapterList.push_back(adapter);++i;}for (size_t i = 0; i < adapterList.size(); ++i){LogAdapterOutputs(adapterList[i]);ReleaseCom(adapterList[i]);}
}

注: D3DAPP类后续会讲到,这里先写着,暂时不介绍
 另外,一个系统也可能装有数个显示设备。我们称每一台显示设备都是一个显示输出(display output, 有的文档也作adapter output, 适配器输出)实例,用IDXGIOutput接口来表示。每个适配器都与一组显示输出相关联。
 每种显示设备都有一系列它所支持的显示模式,可以用下列DXGI_MODE_DESC结构体中的数据成员来加以表示:

#include <minwindef.h>
#include <Dxgiformat.h>
typedef struct DXGI_MODE_DESC
{UINT Width;  //分辨率宽UINT Height;  //分辨率高度DXGI_RATIONAL RefreshRate;  //刷新率,单位为赫兹HzDXGI_FORMAT Format;  //显示格式DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;  //逐行扫描vs.隔行扫描DXGI_MODE_SCALING Scaling;  //图像相对于屏幕的拉伸
} DXGI_MODE_DESC;typedef struct DXGI_RATIONAL
{UINT Numerator;UINT Denominator;
} DXGI_RATIONAL;typedef enum DXGI_MODE_SCANLINE_ORDER
{DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED = 0,DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE = 1,DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST = 2,DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST = 3
} DXGI_MODE_SCANLINE_ORDER;typedef enum DXGI_MODE_SCALING
{DXGI_MODE_SCALING_UNSPECIFIED = 0,DXGI_MODE_SCALING_CENTERED = 1,//不做缩放,将图像显示在屏幕中DXGI_MODE_SCALING_STRETCHED = 2//根据屏幕分辨率对图像进行拉伸
} DXGI_MODE_SCALING;

 一旦确定了显示模式的具体格式(DXGI_FORMAT),我们就能通过下列代码,获得某个显示输出对此格式所支持的全部显示模式:

void D3DApp::LogOutputDisplayModes(IDXGIOutput*output, DXGI_FORMAT format)
{UINT count = 0;UINT flags = 0;// 以nullptr作为参数调用此函数来获取符合条件的显示模式个数output->GetDisplayModeList(format, flags, &count, nullptr);std::vector<DXGI_MODE_DESC> modeList(count);output->GetDisplayModeList(format, flags, &count,&modeList[0]);for (auto& x : modeList){UINT n = x.RefreshRate.Numerator;UINT d = x.RefreshRate.Denominator;std::wstring text =L”Width =+ std::to_wstring(x.Width) + L” ” +L”Height =+ std::to_wstring(x.Height) + L” ”+L”Refresh =+ std::to_wstring(n) + L” /+std::to_wstring(d) +L”\n”;::OutputDebugString(text.c_str());}
}

注: D3DAPP类后续会讲到,这里先写着,暂时不介绍
 在进入全屏模式之时,枚举显示模式就显得尤为重要。为了获得最优的全屏性能,我们所指定的显示模式(包括刷新率)一定要与显示器支持的显示模式完全匹配。根据枚举出来的显示模式进行选定,便可以保证这一点。

11、功能支持的检测

 我们已经通过ID3D12Device::CheckFeatureSupport方法,检测了当前图形驱动对多重采样的支持。然而,这只是此函数对功能支持检测的冰山一角。这个方法的原型为:

#include <winError.h>
#include <minwindef.h>
#include <d3d12.h>HRESULT ID3D12Device::CheckFeatureSupport(D3D12_FEATURE Feature,void *pFeatureSupportData,UINT fEATUREsUPPORTdATASize
);

 1.Feature:枚举类型D3D12_FEATURE中的成员之一,用于指定我们希望检测的功能支持类型。

D3D12_FEATURE_D3D12_OPTIONS  //检测当前图形驱动对Direct3D 12各种功能的支持情况
D3D12_FEATURE_ARCHITECTURE  //检测图形适配器中GPU的硬件体系架构特性
D3D12_FEATURE_FEATURE_LEVELS  //检测对功能级别的支持情况
D3D12_FEATURE_FORMAT_SUPPORT  //检测对给定纹理格式的支持情况(例,指定的格式能否用于渲染目标?或,指定的格式能否用于混合技术?)
D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS  //检测对多重采样功能的支持情况

 2.pFeatureSupportData:指向某种数据结构的指针,该结构中存有检索到的特定功能支持的信息。此结构体的具体类型取决于Feature参数。

Feature参数指定为D3D12_FEATURE_D3D12_OPTIONS传回的是一个D3D12_FEATURE_DATA_D3D12_OPTIONS实例。
Feature参数指定为D3D12_FEATURE_ARCHITECTURE传回的是一个D3D12_FEATURE_DATA_ARCHITECTURE实例。
Feature参数指定为D3D12_FEATURE_FEATURE_LEVELS传回的是一个D3D12_FEATURE_DATA_FEATURE_LEVELS实例。
Feature参数指定为D3D12_FEATURE_FORMAT_SUPPORT传回的是一个D3D12_FEATURE_DATA_FORMAT_SUPPORT实例。
Feature参数指定为D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS传回的是一个D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS实例。

 3.FeatureSupportDataSize:传回pFeatureSupportData参数中的数据结构的大小。
 举例,如何对功能级别的支持情况进行检测:

#include <d3d12.h>typedef struct D3D12_FEATURE_DATA_FEATURE_LEVELS {UINT NumFeatureLevels;const D3D_FEATURE_LEVEL* pFeatureLevelsRequested;D3D_FEATURE_LEVEL MaxSupportedFeatureLevel;
} D3D12_FEATURE_DATA_FEATURE_LEVELS;D3D_FEATURE_LEVEL featureLevels[3] =
{D3D_FEATURE_LEVEL_11_0,  // 首先检测是否支持D3D 11D3D_FEATURE_LEVEL_10_0,  // 其次检测是否支持D3D 10D3D_FEATURE_LEVEL_9_3    // 最后检测是否支持D3D 9.3
};int main()
{D3D12_FEATURE_DATA_FEATURE_LEVELS featureLevelsInfo;featureLevelsInfo.NumFeatureLevels = 3;featureLevelsInfo.pFeatureLevelsRequested = featureLevels;md3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,&featureLevelsInfo,sizeof(featureLevelsInfo));
}

注意:
 CheckFeatureSupport方法的第二个参数兼有输入和输出的属性。作为输入的时候,先要指定功能级别数组中元素的个数,再令指针指向功能级别数组,其中应包括我们希望检测的一系列硬件支持功能级别。最后,此函数将用MaxSupportedFeatureLevel字段返回当前硬件可支持的最高功能级别。

12、资源驻留

 复杂的游戏会运用大量纹理和3D网格(3d mesh)等资源,但是其中的大多数并不需要总是置于显存中供GPU使用。
 在Direct3D 12中,应用程序通过控制资源在显存中的去留,主动管理资源的驻留情况。该技术的基本思路为使应用程序占用最小的显存空间。这是因为现存的空间有限,很可能不足以容下整个游戏的所有资源,或者用户还有运行中的程序也在同时使用显存。性能优化提示:程序应当避免在短时间内于显存中交换进出相同的资源,这会引起过高的开销。最理想的情况使,所清出的资源在短时间内不会再次使用。

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

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

相关文章

EDM营销平台哪个好?推荐的邮件营销平台?

EDM邮件营销平台有哪些&#xff1f;外贸EDM邮件营销平台有哪些&#xff1f; EDM营销平台已成为企业推广产品和服务的重要工具。但是&#xff0c;面对市场上众多的EDM营销平台&#xff0c;究竟哪个更好呢&#xff1f;下面&#xff0c;蜂邮EDM将从平台功能、用户体验、数据分析和…

Matlab使用点云工具箱进行点云配准

一、代码 source_pc pcread(bun_zipper.ply); target_pc pcread(bun_zipper2.ply); % 下采样 gridStep 0.001; ptCloudA pcdownsample(source_pc,gridAverage,gridStep); ptCloudB pcdownsample(target_pc,gridAverage,gridStep); % 初始变换矩阵 tform_initial affine3…

C语言笔试题之实现C库函数 pow()(递归的思想)

实例要求&#xff1a; 1、请你实现C库函数 pow()&#xff08;stdio.h & math.h&#xff09; &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即x^n &#xff09;&#xff1b;2、函数声明&#xff1a;double myPow(double x, int n)&#xff1b;参数&#xff1a;1、x …

YOLOv8改进 更换轻量级网络结构

一、GhostNet论文 论文地址:1911.11907.pdf (arxiv.org) 二、 GhostNet结构 GhostNet是一种高效的目标检测网络,具有较低的计算复杂度和较高的准确性。该网络采用了轻量级的架构,可以在计算资源有限的设备上运行,并能够快速地实时检测图像中的目标物体。 GhostNet基于Mo…

AI大模型开发架构设计(9)——AI 编程架构刨析和业务应用实战案例

文章目录 AI 编程架构刨析和业务应用实战案例1 AI编程代码生成模型剖析编程方式的发展代码自动生成基于大模型的AI编程工具——Github Copilot以 CodeGeeX 为例-发展过程以 CodeGeeX 为例-训练过程以 CodeGeeX 为例-大规模代码数据处理以 CodeGeeX 为例-模型结构以 CodeGeeX 为…

[设计模式Java实现附plantuml源码~行为型]请求的链式处理——职责链模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

JWT令牌 | 一个区别于cookie/session的更安全的校验技术

目录 1、简介 2、组成成分 3、应用场景 4、生成和校验 5、登录下发令牌 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅长web应用开发、数据结构和算法&#xff0c;初步涉猎Pyth…

洛谷C++简单题小练习day9—[AHOI2017]寻找探监点

day9--[AHOI2017]寻找探监点--2.7 习题概述 题目描述 一个nn 的网格图&#xff08;标号由 1,1 开始&#xff09;上有 m 个探测器&#xff0c;每个探测器有个探测半径 r &#xff0c;问这 nn 个点中有多少个点能被探测到。 输入格式 第一行 3 个整数 n,m,r。 接下来 m 行&…

黄金交易策略:heiken ashi smoothed与macd快慢指标协同工作

第2点应该是有很大的优化空间 推荐阅读&#xff1a;Nerve Knife.ex4黄金交易策略_黄金趋势ea-CSDN博客

Verilog刷题笔记23

题目: Suppose you’re building a circuit to process scancodes from a PS/2 keyboard for a game. Given the last two bytes of scancodes received, you need to indicate whether one of the arrow keys on the keyboard have been pressed. This involves a fairly simp…

2020年通信工程师初级专业实务真题

文章目录 一、第1章 现代通信网概述&#xff1a;信令网、同步网、管理网。第10章 通信业务&#xff1a;通信产业链&#xff0c;通信终端的分类&#xff0c;通信业务的定义及分类二、第3章 接入网&#xff1a;无线接入网的优点&#xff0c;接入网的接口&#xff08;UNI&#xff…

git rebase # |REBASE 1/1 #rebase in progress; onto

git 代码解决冲突之后会提示rebase in progress; onto 1 执行git rebase --abort 回到没有pull代码之前 2 git pull 3 解决冲突 4 git add . (不需要git commit) 5 git rebase --continue 6 git push

人工智能之大数定理和中心极限定理

大数定律 大数定律&#xff1a;是一种描述当试验次数很大时所呈现的概率性致的定律&#xff0c;由概率统计定义“频率收敛于概率”引申而来。换而言之&#xff0c;就是n个独立分布的随机变量其观察值的均值依概率收敛于这些随机变量所属分布的理论均值&#xff0c;也就是总体均…

拿捏循环链表

目录&#xff1a; 一&#xff1a;单链表&#xff08;不带头单向不循环&#xff09;与循环链表&#xff08;带头双向循环&#xff09;区别 二&#xff1a;循环链表初始化 三&#xff1a;循环链表头插 四&#xff1a;循环链表尾插 五&#xff1a;循环链表头删 六&#xff1…

kafka客户端生产者消费者kafka可视化工具(可生产和消费消息)

点击下载《kafka客户端生产者消费者kafka可视化工具&#xff08;可生产和消费消息&#xff09;》 1. 前言 因在工作中经常有用到kafka做消息的收发&#xff0c;每次调试过程中&#xff0c;经常需要查看接收的消息内容以及人为发送消息&#xff0c;从网上搜寻了一下&#xff0…

【C++航海王:追寻罗杰的编程之路】类与对象你学会了吗?(下)

目录 1 -> 再谈构造函数1.1 -> 构造函数体赋值1.2 -> 初始化列表1.3 -> explicit关键字 2 -> static成员2.1 -> 概念2.2 -> 特性 3 -> 友元3.1 -> 友元函数3.2 -> 友元类 4 -> 内部类5 -> 匿名对象6 -> 拷贝对象时的一些编译器优化 1 -…

K8s环境下rook-v1.13.3部署Ceph-v18.2.1集群

文章目录 1.K8s环境搭建2.Ceph集群部署2.1 部署Rook Operator2.2 镜像准备2.3 配置节点角色2.4 部署operator2.5 部署Ceph集群2.6 强制删除命名空间2.7 验证集群 3.Ceph界面 1.K8s环境搭建 参考&#xff1a;CentOS7搭建k8s-v1.28.6集群详情&#xff0c;把K8s集群完成搭建&…

基于高通滤波器的ECG信号滤波及心率统计matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 ECG信号简介 4.2 高通滤波器原理 4.3 心率统计 5.完整工程文件 1.课题概述 通过高通滤波器对ECG信号进行滤波&#xff0c;然后再统计其心率。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a…

如何用DT浏览器建立视频播放系统

在DT浏览器官方网站下载最新版软件&#xff0c;安装&#xff0c;在DT浏览器首页点视频直播&#xff0c;软件会自动检测手机相册里的视频并且显示出来&#xff0c;选择需要播放的视频在直播间里播放。如果要建立节目单&#xff0c;需要在服务器上把播放顺序&#xff0c;视频名称…

算法——前缀和算法

1. 什么是前缀和算法 前缀和算法&#xff08;Prefix Sum&#xff09;是一种用于快速计算数组元素之和的技术。它通过预先计算数组中每个位置前所有元素的累加和&#xff0c;将这些部分和存储在一个新的数组中&#xff0c;从而在需要计算某个区间的和时&#xff0c;可以通过简单…