UWP开发细节记录:DirectX::XMMATRIX 的坑
这两天写的代码概率性的崩溃在 XMMatrixMultiply() 函数,XMMatrixMultiply() 本身是 inline 函数可以看到崩溃处的代码:
vX = _mm_mul_ps(vX,M2.r[]);
经查,_mm_mul_ps 是 SSE2 指令要求内存地址 16 字节对齐。猜想可能是字节未对齐引发的问题,打印出矩阵参数的地址,果然,发生崩溃时都是未对齐到 16 字节的情况。
XMMATRIX 声明中指定了对齐到 16 字节,如下:
__declspec(align()) struct XMMATRIX
{
...
};
但是显然没起到效果,继续查发现是用到 XMMATRIX 变量被定义成了类成员变量,该类的实例是 new 出来的:
class MyClass
{
XMMATRIX matrix_;
}; MyClass* ptr= new MyClass(); // 这里应该有一个编译警告
而 new 操作符只保证对齐到不大于 alignof(std::max_align_t) 也就是 8 字节,导致成员变量 matrix_ 也只能对齐到 8 字节。 解决方法先将成员变量 martix_ 赋值给一个局部变量,然后通过局部变量调用 XMMatrixMultiply() 函数。直接使用 new 会有一条对象可能无法对齐到 16 字节的警告信息,但因为我是用 std::make_shared 直接生成智能指针,编译器没能给出这条警告——这也是个坑,最终导致了前面的崩溃问题。
注意 XMMatrixMultiply() 的声明,第一个参数是值传参,第二个是引用传参,问题就处在引用传参上:
typedef const XMMATRIX FXMMATRIX
typedef const XMMATRIX& CXMMATRIX; inline XMMATRIX XM_CALLCONV XMMatrixMultiply (FXMMATRIX M1, CXMMATRIX M2); //注意第二个参数是引用传参
MSDN 中对 XMMatrixMultiply 函数的声明和实际代码并不一致:
XMMATRIX XMMatrixMultiply(
[in] XMMATRIX M1,
[in] XMMATRIX M2
);
如果真的两个参数都是值传参也就没有字节对齐的问题了。
最终结论:XMMATRIX 结构体要求 16 字节对齐,只能用作局部变量或全局变量——在静态存储区或栈上分配内存可以确保 align(16) 声明有效,永远不要用 new 分配堆内存,也不要用作类成员变量;如果需要在成员变量中保存矩阵可以用 DirectX::XMFLOAT4X4 ,使用时再转换为 XMMATRIX 。
顺便吐槽一下,MSDN 以前被称为写得最好的开发文档是当之无愧的,现在只能呵呵了。最近两年新增的文档(比如 UWP 和 DX11 的文档)明显敷衍了事,函数说明经常一句话了事,看文档和直接对着函数声明猜用法都没什么区别了,这次居然还出现了函数声明不一致的情况,这样下去吃枣药丸哪。
UWP开发细节记录:DirectX::XMMATRIX 的坑的更多相关文章
- UWP开发细节记录:WRL::ComPtr 的坑
WRL::ComPtr 取原始指针的地址有两种方式: operator&() 先释放原指针再取地址 GetAddressOf() 直接得到原始指针的地址 显然,operator& ...
- UWP开发细节记录:加载图像文件到D2D位图和D3D纹理
在UWP中加载文件一般先创建 StorageFile 对象,然后调用StorageFile.OpenReadAsync 方法得到一个IRandomAccessStream 接口用来读取数据: Stor ...
- UWP开发细节记录:IStream 和 IRandomAccessStream^ 以及 IMFByteStream 互转
IStream 和 IRandomAccessStream^ 互转 IRandomAccessStream^ --> IStream: CreateStreamOverRandomAccess ...
- UWP开发细节记录:判断文件类型
StorageFile.ContentType 属性,是 string 类型,用来表示文件内容的 MIME 类型.例如,音乐文件可能有 "audio/mpeg" MIME 类型.( ...
- 记UWP开发——多线程操作/并发操作中的坑
一切都要从新版风车动漫UWP的图片缓存功能说起. 起因便是风车动漫官网的番剧更新都很慢,所以图片更新也非常慢.在开发新版的过程中,我很简单就想到了图片多次重复下载导致的资源浪费问题. 所以我给app加 ...
- PC客户端开发细节记录:保存GUID到VARIANT
有两个 API 可以实现保存 GUID 到 VARIANT InitVariantFromGUIDAsBuffer 以字节数组形式保存,保存类型为 VT_ARRAY | VT_UI1,相当于字节拷贝, ...
- java后台开发细节记录
1. ResultMap是程序员控制SQL查询结果和实体类的映射关系,而不是sql语句中字段的重命名,所以在sql语句中还是要按照原来字段的格式进行书写.
- 讲讲我在Windows10(uwp)开发中遇到的一些坑.
7月29日发布的Windows10正式版,当天安装好以后,在网络不太好的情况下,经过多次尝试终于装上了Visual Studio 2015和Windows 10 10240的SDK.这两周一直在开发U ...
- 领域驱动和MVVM应用于UWP开发的一些思考
领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...
随机推荐
- 五、CLR加载程序集代码时,JIT编译器对性能的产生的影响
1.CLR首次加载代码造成的性能损失 四.CLR执行程序集中代码介绍了CLR在首次执行一个类的时,会初始化一个内部结构,然后当目标方法被首次调用时,JITComplier函数(JIT编译器)会验证IL ...
- url最后的“/”是什么作用
多了个尾巴 有时候,当你尝试在地址栏输入https://123/demo的时候,会发现浏览器会重定向到https://123/demo/这个地址,也就是多了个/,发生了重定向.有图为证: 上面这个图是 ...
- 公共技术点(Android 动画基础)
转载地址:http://p.codekk.com/blogs/detail/559623d8d6459ae793499787 一 传统 View 动画(Tween/Frame) 1.1 Tween 动 ...
- Python -- 多媒体编程 -- 音乐播放
使用win32库的WMPlayer.OCX开发一个简易的音乐播放器 import sys from PyQt4 import QtGui, QtCore from win32com.client im ...
- slf4j 作用及logback概述
为什么要使用slf4j 现实场景: 我们自己的系统中使用了logback这个日志系统 我们的系统使用了A.jar,A.jar中使用的日志系统为log4j 我们的系统又使用了B.jar,B.jar中使用 ...
- Tomcat学习总结(10)——Tomcat多实例冗余部署
昨天在跟群友做技术交流的时候,了解到,有很多大公司都是采用了高可用的,分布式的,实例沉余1+台.但是在小公司的同学也很多,他们反映并不是所有公司都有那样的资源来供你调度.往往公司只会给你一台机器,因为 ...
- Java并发编程-synchronized指南
在多线程程序中,同步修饰符用来控制对临界区代码的访问.其中一种方式是用synchronized关键字来保证代码的线程安全性.在Java中,synchronized修饰的代码块或方法不会被多个线程并发访 ...
- cool--music
1.三年的赌注 2.非酋 3.Swan Song 4.Better Than A Hallelujah
- oracle 删除服务sc delete Oracle
oracle 删除服务sc delete OracleVssWriterorcl -----(oracle orcl vss writer service的服务名!)
- POJ 1679 The Unique MST(判断最小生成树是否唯一)
题目链接: http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its min ...