龙书D3D11章节习题答案(第四章)

下面答案仅供參考,有错欢迎留言


Chapter 4:Direct3D Initialzation


  

1. Modify the previous exercise solution by disabling the ALT-ENTER functionality to switch between full screen and windowed mode;  use the IDXGIFactory::MakeWindowAssociation method and specify the DXGI_MWA_NO_WINDOW_CHANGES flag so that DXGI does not monitor the message queue. Note that the IDXGIFactory::MakeWindowAssociation method needs to be called after IDXGIFactory::CreateSwapChain is called.

 

意思是禁用框架代码提供的ALT-ENTER键功能,即全屏和窗体模式间的切换。

按要求加入代码(注意加入在创建交换链之后)



DXGI应该是利用Hook窗体消息处理过程,监听ALT+ENTER按键,来实现自己主动的在窗体模式和全屏模式切换。而用DXGI_MWA_NO_WINDOW_CHANGES能够指定取消监听程序消息队列。来"取消"此功能。

为了满足好奇心能够用VS工具菜单下的Spy++来检測ALT-ENTER所发送的窗体消息:


过滤掉全部已知的消息= =。剩下的未知消息应该会包括发送给DXGI的消息吧(我自己的推測...)

这个窗体正常执行时会一直SendMessage和return一个标识为0x00AE的消息。

而在按下ALT+ENTER切换全屏时。则有额外的0x0093、0x0094消息...

所以93、94消息即为DXGI所监听的消息。

然后呢,我们调用DXGIFactory::MakeWindowAssociation以后再用spy++看看...

这次怎么按ALT-ENTER都不会出现93、94消息了,而仅仅是一直在发送、返回AE消息(= =, 真不知道是干嘛的。

)...


2. Some systems have more than one adapter (video card), and the application may wish to let the user choose which one to use, instead of always using the default adapter. Use the IDXGIFactory::EnumAdapters method to determine how many adapters are on your system.

意思是说有些系统有多块显卡。让你用DXGI接口给的EnumAdapters来看看究竟是哪几块= =

	// 列出全部找到的显卡设备的信息
	UINT i = 0;
	IDXGIAdapter* pAdapter;
	DXGI_ADAPTER_DESC desc;      
        ZeroMemory ( &desc, sizeof(desc));
	WCHAR adapterInfo[3][256];

	// MS Basic Render Driver?
	std::vector<IDXGIAdapter*> vAdapters; 
	while(dxgiFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND)
	{
		vAdapters.push_back(pAdapter);
		pAdapter->GetDesc(&desc);

		swprintf_s(adapterInfo[i], L"-----------------\n***显卡名称:%s\n***厂商ID:%u\n***设备ID:%u\n***子系统ID:%u\n***专有显存:%uB\n***专有系统内存:%uB\n***共享的系统内存:%uB\n***LUID:%u%u\n",
			desc.Description,desc.VendorId,desc.DeviceId,desc.SubSysId,desc.DedicatedVideoMemory,desc.DedicatedSystemMemory,desc.SharedSystemMemory,desc.AdapterLuid.HighPart,desc.AdapterLuid.LowPart);
		OutputDebugStringW(adapterInfo[i]);
		++i;
	}

考虑到大多数电脑最多也就是双显卡。

。所以存储显卡相关信息的数组仅仅定义了[3][256]。。处理的时候使用的是Unicode字符集,所以字符数组用的是WCHAR。而用于格式化生成输出字符串的sprintf换成了swprintf。加个_s帮忙在越界时提示信息;在调试窗体程序时输出信息到VS的输出窗体最为方便(和MessageBox相比不会影响程序正常执行),所以用OutputDebugStringW来完毕此操作。

显存输出的单位是B,即byte,我的独立显卡是2G显存的,这里正好是2*10^9 B,符合~

唯一有点疑惑的是MS Basic Render Driver这个adapter,显然这不是一块真实存在的显卡。。或许是做软件模拟的?。。

至于ADAPTER_DESC里面的LUID(Local Unique IDentifier)我非常外行,输出的时候组合highpart在前,lowpart在后。不知道对不正确。。


3. For each adapter the system possesses, IDXGIFactory::EnumAdapters outputs a pointer to a filled out IDXGIAdapter interface. This interface can be used to query information about the adapter. Use the IDXGIAdapter::CheckInterfaceSupport method to see if the adapters on your system support Direct3D 11.

	// CheckInterfaceSupport如今失效了...详见MSDN SDK说明
	for(std::vector<IDXGIAdapter*>::iterator it=vAdapters.begin(); it!=vAdapters.end(); ++it)
	{	
		if((*it)->CheckInterfaceSupport(__uuidof(ID3D11Device), NULL) == DXGI_ERROR_UNSUPPORTED)
		{
			OutputDebugStringW(L"11.x版本号如今不能用CheckInterfaceSupport检測~\n");
		}
	}

经个人測试,我的明明支持dx11的显卡(这一点能够window+R键执行dxdiag看看),检測ID3D11Device时总是会return DXGI_ERROR_UNSUPPORTED,官方的最新说明表示这种方法如今仅仅能Check 10.x了,所以如今请不要用这种方法检測是否支持11.x。如今呢,你要检查显卡是否支持某个特定的接口必须试试看去创建它。。

也就是说。一项一项的检測= =。。想调用融合相关接口那就要去试试ID3D11Device::CreateBlendState是不是返回成功,假设失败就证明不支持。。

这真是个坏消息...


4. An adapter has outputs associated with it (e.g., a monitor). You can use the IDXGIAdapter::EnumOutputs method to enumerate the outputs for a particular adapter. Use this method to determine the number of outputs for the default adapter.

5. Each output has a list of supported display modes (DXGI_MODE_DESC) for a given pixel format. For each output(IDXGIOutput), show the width, height, and refresh rate of each display mode the output supports for theDXGI_FORMAT_R8G8B8A8_UNORM format using the IDXGIOutput::GetDisplayModeList method.


意思是显卡(adater)之所以能正确输出到显示器上(monitor)。是由于显卡有支持这块屏幕相应的宽、高、格式等属性,即显卡关联(associated with)显示器。

试着用IDXGIAdapter::EnumOutputs去输出显卡所支持的属性表(Outputs)以及其支持属性的数量(the num of outputs)。

	// 列出全部显卡对本机连接上的显示器的output信息表
	IDXGIOutput *pOutput;
	WCHAR outputInfo[256];
	UINT numScreens = 0;
	for(std::vector<IDXGIAdapter*>::iterator it=vAdapters.begin(); it!=vAdapters.end(); ++it)
	{	
		while((*it)->EnumOutputs(numScreens++, &pOutput) != DXGI_ERROR_NOT_FOUND)
		{
		   UINT numOutputs = 0;
		   pOutput->GetDisplayModeList( DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numOutputs, 0);
		   DXGI_MODE_DESC* pDescs = new DXGI_MODE_DESC[numOutputs];
	       pOutput->GetDisplayModeList( DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numOutputs, pDescs);

		   swprintf_s(outputInfo,L"%u\n",numOutputs);
		   OutputDebugStringW(outputInfo);

		   for(int i=0; i<numOutputs; i++)
		   {
			  swprintf_s(outputInfo,L"\n***Width:   %u  Height:  %u\  Format: %u\  RefreshRate:  %u",
				(pDescs[i]).Width,(pDescs[i]).Height, (pDescs[i]).Format, (pDescs[i]).RefreshRate);
		      OutputDebugStringW(outputInfo);
		   }
		}
	}

在本机測试总共输出了107条支持信息。从320*200一直到1920*1080格式。




今天又一次看了下写的东西:

上图输出的刷新率非常不正常,原来RefreshRate并不能直接输出,由于其是一个DXGI_RATIONAL结构体,

typedef struct DXGI_RATIONAL {
  UINT Numerator;
  UINT Denominator;
} DXGI_RATIONAL;
所以输出的时候须要分子/分母(Numerator/Denominator)。

    swprintf_s(outputInfo,L"\n***Width:   %u  Height:  %u\  Format: %d\  RefreshRate:  %f",
    (pDescs[i]).Width,(pDescs[i]).Height, (pDescs[i]).Format, (float)(pDescs[i]).RefreshRate.Numerator/(pDescs[i]).RefreshRate.Denominator);




由于我还有块HDMI接口的显示屏外接笔记本所以。。正好測试下会不会输出两份信息~

开启双屏...


双显卡的电脑对同一块显示器不会有两份outputs的原因应该是:双显卡在执行某个程序时并不会两块显卡同一时候火力全开。。而是须要节能时开集成显卡作为主显卡。须要高性能时开独立显卡作为主显卡。

双显卡技术不是太了解= =。至少我还没想通为什么我的双显卡单开独显fps非常低。而开了集显和独显以后fps是仅仅开集显的两倍以上。。或许是我打开方式有问题。。


6. Experiment with modifying the viewport settings to draw the scene into a subrectangle of the back buffer. For example, try:....

按要求改动下d3dAPP::OnResize()里面md3dImmediateContext->RSSetViewports(1, &mScreenViewport)所调用的mScreenViewport属性就能够了,注意至少要画个物体才干观察到变化。。

建议能够使用第六章的BoxDemo啊什么的来试试











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 译者序 前言 第1章 概论 1 1.1 为什么要用编译器 2 1.2 与编译器相关的程序 3 1.3 翻译步骤 5 1.4 编译器中的主要数据结构 8 1.5 编译器结构中的其他问题 10 1.6 自举与移植 12 1.7 TINY样本语言与编译器 14 1.7.1 TINY语言 15 1.7.2 TINY编译器 15 1.7.3 TM机 17 1.8 C-Minus:编译器项目的一种语言 18 练习 19 注意与参考 20 第2章 词法分析 21 2.1 扫描处理 21 2.2 正则表达式 23 2.2.1 正则表达式的定义 23 2.2.2 正则表达式的扩展 27 2.2.3 程序设计语言记号的正则表达式 29 2.3 有穷自动机 32 2.3.1 确定性有穷自动机的定义 32 2.3.2 先行、回溯和非确定性自动机 36 2.3.3 用代码实现有穷自动机 41 2.4 从正则表达式到DFA 45 2.4.1 从正则表达式到NFA 45 2.4.2 从NFA到DFA 48 2.4.3 利用子集构造模拟NFA 50 2.4.4 将DFA中的状态数最小化 51 2.5 TINY扫描程序的实现 52 2.5.1 为样本语言TINY实现一个扫描 程序 53 2.5.2 保留字与标识符 56 2.5.3 为标识符分配空间 57 2.6 利用Lex 自动生成扫描程序 57 2.6.1 正则表达式的Lex 约定 58 2.6.2 Lex输入文件的格式 59 2.6.3 使用Lex的TINY扫描程序 64 练习 65 编程练习 67 注意与参考 67 第3章 上下文无关文法及分析 69 3.1 分析过程 69 3.2 上下文无关文法 70 3.2.1 与正则表达式比较 70 3.2.2 上下文无关文法规则的说明 71 3.2.3 推导及由文法定义的语言 72 3.3 分析树与抽象语法树 77 3.3.1 分析树 77 3.3.2 抽象语法树 79 3.4 二义性 83 3.4.1 二义性文法 83 3.4.2 优先权和结合性 85 3.4.3 悬挂else问题 87 3.4.4 无关紧要的二义性 89 3.5 扩展的表示法:EBNF和语法图 89 3.5.1 EBNF表示法 89 3.5.2 语法图 91 3.6 上下文无关语言的形式特性 93 3.6.1 上下文无关语言的形式定义 93 3.6.2 文法规则和等式 94 3.6.3 乔姆斯基层次和作为上下文无关 规则的语法局限 95 3.7 TINY语言的语法 97 3.7.1 TINY的上下文无关文法 97 3.7.2 TINY编译器的语法树结构 98 练习 101 注意与参考 104 第4章 自顶向下的分析 105 4.1 使用递归下降分析算法进行自顶向下 的分析 105 4.1.1 递归下降分析的基本方法 105 4.1.2 重复和选择:使用EBNF 107 4.1.3 其他决定问题 112 4.2 LL(1)分析 113 4.2.1 LL(1)分析的基本方法 113 4.2.2 LL(1)分析与算法 114 4.2.3 消除左递归和提取左因子 117 4.2.4 在LL(1)分析中构造语法树 124 4.3 First集合和Follow集合 125 4.3.1 First 集合 125 4.3.2 Follow 集合 130 4.3.3 构造LL(1)分析表 134 4.3.4 再向前:LL(k)分析程序 135 4.4 TINY语言的递归下降分析程序 136 4.5 自顶向下分析程序中的错误校正 137 4.5.1 在递归下降分析程序中的错误 校正 138 4.5.2 在LL(1)分析程序中的错误校正 140 4.5.3 在TINY分析程序中的错误校正 141 练习 143 编程练习 146 注意与参考 148 第5章 自底向上的分析 150 5.1 自底向上分析概览 151 5.2 LR(0)项的有穷自动机与LR(0)分析 153 5.2.1 LR(0)项 153 5.2.2 项目的有穷自动机 154 5.2.3 LR(0)分析算法 157 5.3 SLR(1)分析 160 5.3.1 SLR(1)分析算法 160 5.3.2 用于分析冲突的消除二义性 规则 163 5.3.3 SLR(1)分析能力的局限性 164 5.3.4 SLR(k)文法 165 5.4 一般的LR(1)和LALR(1)分析 166 5.4.1 LR(1)项的有穷自动机 166
### 回答1: 编译原理龙书第四章主要讲述了词法分析器的设计与实现。词法分析器的主要作用是将源代码转化为一个词法单元序列。 在词法分析器的设计中,需要确定输入的文法,构造有限自动机(DFA)并最小化它,生成词法单元并将其输出。在实现中,可以采用手工编写DFA、使用生成器(如Lex和Flex)、使用正则表达式引擎(如PCRE)等不同方法。 本章中重点介绍了正则表达式的语法和特性,以及基于DFA的词法分析器生成器Flex的使用。在实现词法分析器时需要考虑错误处理和效率,同时保证正确性和完整性。 总体来说,词法分析器的设计与实现是编译器构建中的重要一环。掌握词法分析器的设计与实现可以提高编译器的开发效率和质量,也能够提高对编译原理的理解。 ### 回答2: 编译原理龙书第四章主要讲述了词法分析器的设计和实现。 词法分析器的任务是将源程序中的字符序列转换为单词序列,单词是指语言中的最小单元,包括关键字、标识符、常量、运算符等。词法分析器使用有限状态自动机(DFA)来识别单词,并将单词传递给语法分析器进一步分析。 第四章详细介绍了DFA的构造方法,包括正则表达式到NFA的转换以及NFA到DFA的子集构造法。同时也介绍了如何最小化DFA,以减少DFA中状态的数量,提高词法分析器的效率。 此外,第四章还讨论了错误处理和词法单元的表示方法。错误的检测和处理是词法分析器的重要任务之一,常用的处理方法包括返回错误信息、跳过错误单词或者将错误单词视为一个token进行处理。词法单元的表示方法也有多种选择,常见的是将token表示为一个结构体,包括单词的种类、属性、行号等信息。 总之,第四章是编译原理中非常重要的一章,词法分析器是编译器中的第一个组件,其正确性和效率对整个编译过程都具有决定性的影响。因此,认真学习和理解本章内容对编译原理学习有着重要的意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值