节习题答案(第四章)

Posted 独饮月色的猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了节习题答案(第四章)相关的知识,希望对你有一定的参考价值。

以下答案仅供参考,有错欢迎留言


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啊什么的来试试











以上是关于节习题答案(第四章)的主要内容,如果未能解决你的问题,请参考以下文章

高等数学 本科少学时类型 第4版 上册 课后习题 答案 同济大学数学系

《计算机网络·自顶向下方法》第七版 第四章 课后习题与问题 答案

数据的表示和运算-第四节2:本节习题

管理信息系统(第六版)课后题答案 黄梯云 李一军

当代中国经济——第三种声音龚 刚课后答案

第四章习题答案