light position debug pipeline, keyboard camera movement

This commit is contained in:
Zack Buhman 2026-07-26 19:15:25 -05:00
parent ed2160a935
commit 4526aaa2c5
19 changed files with 7695 additions and 1189 deletions

View File

@ -79,7 +79,7 @@ fn lighting(position: vec3f, normal: vec3f) -> vec3f
{ {
let d = 0.9; let d = 0.9;
let eyePosition = vec3f(d, d / 2, d); let eyePosition = vec3f(d, d / 2, d);
let lightPosition = vec3f(1, 1, 1); let lightPosition = vec3f(100, 100, 100);
let lightVector = normalize(lightPosition - position); let lightVector = normalize(lightPosition - position);
let ndotl = max(dot(lightVector, normal), 0.0); let ndotl = max(dot(lightVector, normal), 0.0);
let intensity = (ndotl + 0.3) / 1.3; let intensity = (ndotl + 0.3) / 1.3;
@ -95,5 +95,5 @@ fn fragmentMain(input: FragmentInput) -> @location(0) vec4f
let intensity = lighting(input.positionWorld, normalize(input.normal)); let intensity = lighting(input.positionWorld, normalize(input.normal));
let color = textureSample(colorTexture, linearSampler, input.texture); let color = textureSample(colorTexture, linearSampler, input.texture);
return vec4(color.xyz, 1.0); return vec4(color.xyz * intensity, 1.0);
} }

143
index.js
View File

@ -1,5 +1,6 @@
import { getPath } from "./common.js"; import { getPath } from "./common.js";
import { loadGltf } from "./index2.js"; import { loadGltf } from "./index2.js";
import { loadLight } from "./light.js";
if (!navigator.gpu) { if (!navigator.gpu) {
throw new Error("WebGPU not supported on this browser."); throw new Error("WebGPU not supported on this browser.");
@ -441,18 +442,150 @@ function render()
} }
//requestAnimationFrame(render); //requestAnimationFrame(render);
const gltfRenderer = await loadGltf(device, canvasFormat, memory2, module); const matrixSize = 4 * 4 * 4;
const float4Size = 4 * 4;
const float3Size = 4 * 3;
const viewUniformBufferSize = (matrixSize * 2) + (float4Size * 1);
const viewUniformBuffer = device.createBuffer({
label: "view uniform buffer",
size: viewUniformBufferSize,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});
const cameraStateSize = (float3Size * 3) + (4 * 3) + (float3Size * 1);
const viewStateAddress = module.instance.exports.mem_alloc(viewUniformBufferSize);
const cameraStateAddress = module.instance.exports.mem_alloc(cameraStateSize);
module.instance.exports.camera_init(cameraStateAddress);
const gltfRenderer = await loadGltf(device, canvasFormat, viewUniformBuffer, memory2, module);
const lightRenderer = await loadLight(device, canvasFormat, viewUniformBuffer);
const KEY = {
A: 65,
B: 66,
C: 67,
D: 68,
E: 69,
F: 70,
G: 71,
H: 72,
I: 73,
J: 74,
K: 75,
L: 76,
M: 77,
N: 78,
O: 79,
P: 80,
Q: 81,
R: 82,
S: 83,
T: 84,
U: 85,
V: 86,
W: 87,
X: 88,
Y: 89,
Z: 90,
Left: 37,
Up: 38,
Right: 39,
Down: 40,
};
const keyCodes = new Set(Object.values(KEY));
const keyState = {};
for (const code of Object.values(KEY)) {
keyState[code] = false;
}
function handleKeydown(e)
{
//console.log(e.keyCode);
if (keyCodes.has(e.keyCode)) {
keyState[e.keyCode] = true;
}
}
function handleKeyup(e)
{
if (keyCodes.has(e.keyCode)) {
keyState[e.keyCode] = false;
}
}
window.addEventListener('keydown', handleKeydown, false);
window.addEventListener('keyup', handleKeyup, false);
function updateView()
{
const lu = keyState[KEY.W] === true;
const ll = keyState[KEY.A] === true;
const ld = keyState[KEY.S] === true;
const lr = keyState[KEY.D] === true;
const lal = keyState[KEY.Q] === true;
const lar = keyState[KEY.E] === true;
const ru = keyState[KEY.Up] === true;
const rl = keyState[KEY.Left] === true;
const rd = keyState[KEY.Down] === true;
const rr = keyState[KEY.Right] === true;
module.instance.exports.camera_move(cameraStateAddress,
lu, ll, ld, lr,
lal, lar,
ru, rl, rd, rr);
const aspect = canvas.width / canvas.height;
module.instance.exports.camera_view_projection(cameraStateAddress,
viewStateAddress,
aspect);
device.queue.writeBuffer(viewUniformBuffer, 0,
memory2.buffer, viewStateAddress,
viewUniformBufferSize);
}
function render2() function render2()
{ {
recreateDepth(); recreateDepth();
const colorView = context.getCurrentTexture().createView(); const colorView = context.getCurrentTexture().createView();
const aspect = canvas.width / canvas.height; updateView();
rotate.instance.exports.rotate(tick * 0.01, aspect, 0);
device.queue.writeBuffer(gltfRenderer.uniformBuffer, 0, uniformArray, 0, gltfRenderer.uniformBufferSize / 4); {
const encoder = device.createCommandEncoder();
const renderPass = encoder.beginRenderPass({
colorAttachments: [{
view: colorView,
loadOp: "clear",
clearValue: { r: 0.2, g: 0.2, b: 0.4, a: 1 },
storeOp: "store",
}],
depthStencilAttachment: {
view: depthTexture.createView(),
depthClearValue: 1.0,
depthLoadOp: 'clear',
depthStoreOp: 'store',
},
});
gltfRenderer.render(renderPass);
lightRenderer.render(renderPass);
renderPass.end();
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
}
gltfRenderer.render(device, colorView, depthTexture);
requestAnimationFrame(render2); requestAnimationFrame(render2);
} }
requestAnimationFrame(render2); requestAnimationFrame(render2);

View File

@ -1,7 +1,6 @@
import { getPath } from "./common.js"; import { getPath } from "./common.js";
import { parseGltfChunks, vertexBufferLayouts, primitiveAccessors, splitGltf } from "./gltf.js"; import { parseGltfChunks, vertexBufferLayouts, primitiveAccessors, splitGltf } from "./gltf.js";
function loadGltfNode(module, handle, gltf, nodeIndex) function loadGltfNode(module, handle, gltf, nodeIndex)
{ {
const node = gltf.json.nodes[nodeIndex]; const node = gltf.json.nodes[nodeIndex];
@ -37,7 +36,7 @@ function printMatrix(m, o)
} }
class GltfRenderer { class GltfRenderer {
constructor(device, canvasFormat, shaderModule, gltf, texture) constructor(device, canvasFormat, viewUniformBuffer, shaderModule, gltf, texture)
{ {
this.gltf = gltf; this.gltf = gltf;
@ -153,13 +152,6 @@ class GltfRenderer {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
const matrixSize = 4 * 4 * 4; const matrixSize = 4 * 4 * 4;
this.uniformBufferSize = matrixSize * 2;
this.uniformBuffer = device.createBuffer({
label: "gltf uniform 0",
size: this.uniformBufferSize,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});
this.nodeBufferSize = matrixSize * this.gltf.json.nodes.length; this.nodeBufferSize = matrixSize * this.gltf.json.nodes.length;
this.nodeBuffer = device.createBuffer({ this.nodeBuffer = device.createBuffer({
label: "gltf node buffer", label: "gltf node buffer",
@ -173,7 +165,7 @@ class GltfRenderer {
layout: bindGroupLayouts[0], layout: bindGroupLayouts[0],
entries: [{ entries: [{
binding: 0, binding: 0,
resource: { buffer: this.uniformBuffer }, resource: { buffer: viewUniformBuffer },
}, { }, {
binding: 1, binding: 1,
resource: { buffer: this.nodeBuffer }, resource: { buffer: this.nodeBuffer },
@ -235,33 +227,12 @@ class GltfRenderer {
return lastKey; return lastKey;
} }
render(device, colorView, depthTexture) render(renderPass)
{ {
const encoder = device.createCommandEncoder();
const renderPass = encoder.beginRenderPass({
colorAttachments: [{
view: colorView,
loadOp: "clear",
clearValue: { r: 0.2, g: 0.2, b: 0.4, a: 1 },
storeOp: "store",
}],
depthStencilAttachment: {
view: depthTexture.createView(),
depthClearValue: 1.0,
depthLoadOp: 'clear',
depthStoreOp: 'store',
},
});
var lastKey = undefined; var lastKey = undefined;
for (let nodeIndex of this.gltf.json.scenes[0].nodes) { for (let nodeIndex of this.gltf.json.scenes[0].nodes) {
lastKey = this.renderNode(renderPass, lastKey, nodeIndex); lastKey = this.renderNode(renderPass, lastKey, nodeIndex);
} }
renderPass.end();
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
} }
} }
@ -333,8 +304,14 @@ async function loadTextures(device, memory, module, gltf)
return textures; return textures;
} }
async function loadGltf(device, canvasFormat, memory, module) async function loadGltf(device, canvasFormat, viewUniformBuffer, memory, module)
{ {
const code = await getPath("gltf.wgsl");
const shaderModule = device.createShaderModule({
label: "gltf module",
code: await code,
});
const gltf = await splitGltf("gltf/lamp.gltf", "gltf/lamp.bin"); const gltf = await splitGltf("gltf/lamp.gltf", "gltf/lamp.bin");
const nodesHandle = loadGltfNodes(module, gltf); const nodesHandle = loadGltfNodes(module, gltf);
@ -348,13 +325,7 @@ async function loadGltf(device, canvasFormat, memory, module)
const textures = await loadTextures(device, memory, module, gltf); const textures = await loadTextures(device, memory, module, gltf);
const code = await getPath("gltf.wgsl"); const renderer = new GltfRenderer(device, canvasFormat, viewUniformBuffer, shaderModule, gltf, textures[2]);
const shaderModule = device.createShaderModule({
label: "gltf module",
code: await code,
});
const renderer = new GltfRenderer(device, canvasFormat, shaderModule, gltf, textures[0]);
console.log(renderer.nodeBuffer); console.log(renderer.nodeBuffer);
device.queue.writeBuffer(renderer.nodeBuffer, 0, device.queue.writeBuffer(renderer.nodeBuffer, 0,
memory.buffer, nodesHandle, (4 * 4 * 4) * gltf.json.nodes.length); memory.buffer, nodesHandle, (4 * 4 * 4) * gltf.json.nodes.length);

160
light.js Normal file
View File

@ -0,0 +1,160 @@
import { getPath } from "./common.js";
function parseHeader(buffer)
{
const array = new Uint32Array(buffer);
/*
console.log("index count", icosphereU32[0]);
console.log("index buffer offset", icosphereU32[1]);
console.log("index buffer size", icosphereU32[2]);
console.log("vertex buffer offset", icosphereU32[3]);
console.log("vertex buffer size", icosphereU32[4]);
*/
return {
indexCount: array[0],
indexOffset: array[1],
indexSize: array[2],
vertexOffset: array[3],
vertexSize: array[4],
};
}
class LightRenderer {
constructor(device, canvasFormat, viewUniformBuffer,
shaderModule, binBuffer, label)
{
//////////////////////////////////////////////////////////////////////
// buffer
//////////////////////////////////////////////////////////////////////
const header = parseHeader(binBuffer);
this.header = header;
this.buffer = device.createBuffer({
label: `${label} renderer buffer`,
size: header.indexSize + header.vertexSize,
usage: GPUBufferUsage.INDEX | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
this.indexOffset = 0;
this.vertexOffset = header.indexSize;
device.queue.writeBuffer(this.buffer, this.indexOffset,
binBuffer, header.indexOffset, header.indexSize);
device.queue.writeBuffer(this.buffer, this.vertexOffset,
binBuffer, header.vertexOffset, header.vertexSize);
//////////////////////////////////////////////////////////////////////
// pipeline
//////////////////////////////////////////////////////////////////////
const bindGroupLayouts = [
device.createBindGroupLayout({
label: `${label} view matrix bind group layout`,
entries: [{
binding: 0,
visibility: GPUShaderStage.VERTEX,
buffer: { type: "uniform" }
},/* {
binding: 1,
visibility: GPUShaderStage.VERTEX,
buffer: { type: "read-only-storage" }
}*/]
}),
];
const pipelineLayout = device.createPipelineLayout({
label: `${label} pipeline layout`,
bindGroupLayouts: bindGroupLayouts,
});
const vertexBufferLayouts = [{
arrayStride: 36,
attributes: [{
format: "float32x3",
offset: 0,
shaderLocation: 0,
}, {
format: "float32x2",
offset: 12,
shaderLocation: 1,
}, {
format: "float16x4",
offset: 20,
shaderLocation: 2,
}, {
format: "float16x4",
offset: 28,
shaderLocation: 3,
}],
stepMode: "vertex",
}];
this.renderPipeline = device.createRenderPipeline({
label: `${label} pipeline`,
layout: pipelineLayout,
vertex: {
module: shaderModule,
entryPoint: "vertexMain",
buffers: vertexBufferLayouts,
},
fragment: {
module: shaderModule,
entryPoint: "fragmentMain",
targets: [{
format: canvasFormat,
}]
},
primitive: {
topology: "triangle-list",
},
depthStencil: {
depthWriteEnabled: true,
depthCompare: "less",
format: "depth24plus",
},
});
//////////////////////////////////////////////////////////////////////
// bind group
//////////////////////////////////////////////////////////////////////
this.bindGroups = [
device.createBindGroup({
label: `${label} bind group`,
layout: bindGroupLayouts[0],
entries: [{
binding: 0,
resource: { buffer: viewUniformBuffer },
}],
}),
];
}
render(renderPass)
{
renderPass.setPipeline(this.renderPipeline);
renderPass.setVertexBuffer(0, this.buffer, this.vertexOffset, this.header.vertexSize);
renderPass.setIndexBuffer(this.buffer, "uint16", this.indexOffset, this.header.indexSize);
renderPass.setBindGroup(0, this.bindGroups[0]);
renderPass.drawIndexed(this.header.indexCount);
}
}
async function loadLight(device, canvasFormat, viewUniformBuffer)
{
const lightWgsl = getPath("light.wgsl");
const shaderModule = device.createShaderModule({
label: "light shader",
code: await lightWgsl,
});
const response = await fetch("obj/icosphere.bin");
const binBuffer = await response.arrayBuffer();
const renderer = new LightRenderer(device, canvasFormat, viewUniformBuffer,
shaderModule, binBuffer, "light");
return renderer;
}
export { loadLight };

35
light.wgsl Normal file
View File

@ -0,0 +1,35 @@
struct Configuration {
matrix: mat4x4f,
matrixWorld: mat4x4f,
};
@group(0) @binding(0) var<uniform> config: Configuration;
struct VertexInput {
@location(0) position: vec3f,
@location(1) texture: vec2f,
@location(2) normal: vec4f,
@location(3) tangent: vec4f,
};
struct VertexOutput {
@builtin(position) position: vec4f,
@location(0) texture: vec2f,
};
@vertex
fn vertexMain(input: VertexInput) -> VertexOutput
{
let position = vec4f(input.position, 1);
var output: VertexOutput;
output.position = config.matrix * position;
output.texture = input.texture;
return output;
}
@fragment
fn fragmentMain(input: VertexOutput) -> @location(0) vec4f
{
return vec4(1, 0, 0, 1.0);
}

BIN
obj/icosphere.bin Normal file

Binary file not shown.

269
obj/icosphere.obj Normal file
View File

@ -0,0 +1,269 @@
# Blender 5.2.0 LTS
# www.blender.org
o Icosphere
v 0.000000 -1.000000 0.000000
v 0.723607 -0.447220 0.525725
v -0.276388 -0.447220 0.850649
v -0.894426 -0.447216 0.000000
v -0.276388 -0.447220 -0.850649
v 0.723607 -0.447220 -0.525725
v 0.276388 0.447220 0.850649
v -0.723607 0.447220 0.525725
v -0.723607 0.447220 -0.525725
v 0.276388 0.447220 -0.850649
v 0.894426 0.447216 0.000000
v 0.000000 1.000000 0.000000
v -0.162456 -0.850654 0.499995
v 0.425323 -0.850654 0.309011
v 0.262869 -0.525738 0.809012
v 0.850648 -0.525736 0.000000
v 0.425323 -0.850654 -0.309011
v -0.525730 -0.850652 0.000000
v -0.688189 -0.525736 0.499997
v -0.162456 -0.850654 -0.499995
v -0.688189 -0.525736 -0.499997
v 0.262869 -0.525738 -0.809012
v 0.951058 0.000000 0.309013
v 0.951058 0.000000 -0.309013
v 0.000000 0.000000 1.000000
v 0.587786 0.000000 0.809017
v -0.951058 0.000000 0.309013
v -0.587786 0.000000 0.809017
v -0.587786 0.000000 -0.809017
v -0.951058 0.000000 -0.309013
v 0.587786 0.000000 -0.809017
v 0.000000 0.000000 -1.000000
v 0.688189 0.525736 0.499997
v -0.262869 0.525738 0.809012
v -0.850648 0.525736 0.000000
v -0.262869 0.525738 -0.809012
v 0.688189 0.525736 -0.499997
v 0.162456 0.850654 0.499995
v 0.525730 0.850652 0.000000
v -0.425323 0.850654 0.309011
v -0.425323 0.850654 -0.309011
v 0.162456 0.850654 -0.499995
vn 0.1024 -0.9435 0.3151
vn 0.7002 -0.6617 0.2680
vn -0.2680 -0.9435 0.1947
vn -0.2680 -0.9435 -0.1947
vn 0.1024 -0.9435 -0.3151
vn 0.9050 -0.3304 0.2680
vn 0.0247 -0.3304 0.9435
vn -0.8897 -0.3304 0.3151
vn -0.5746 -0.3304 -0.7488
vn 0.5346 -0.3304 -0.7779
vn 0.8026 -0.1256 0.5831
vn -0.3066 -0.1256 0.9435
vn -0.9921 -0.1256 -0.0000
vn -0.3066 -0.1256 -0.9435
vn 0.8026 -0.1256 -0.5831
vn 0.4089 0.6617 0.6284
vn -0.4713 0.6617 0.5831
vn -0.7002 0.6617 -0.2680
vn 0.0385 0.6617 -0.7488
vn 0.7240 0.6617 -0.1947
vn 0.2680 0.9435 -0.1947
vn 0.4911 0.7947 -0.3568
vn 0.4089 0.6617 -0.6284
vn -0.1024 0.9435 -0.3151
vn -0.1876 0.7947 -0.5773
vn -0.4713 0.6617 -0.5831
vn -0.3313 0.9435 -0.0000
vn -0.6071 0.7947 -0.0000
vn -0.7002 0.6617 0.2680
vn -0.1024 0.9435 0.3151
vn -0.1876 0.7947 0.5773
vn 0.0385 0.6617 0.7488
vn 0.2680 0.9435 0.1947
vn 0.4911 0.7947 0.3568
vn 0.7240 0.6617 0.1947
vn 0.8897 0.3304 -0.3151
vn 0.7947 0.1876 -0.5773
vn 0.5746 0.3304 -0.7488
vn -0.0247 0.3304 -0.9435
vn -0.3035 0.1876 -0.9342
vn -0.5346 0.3304 -0.7779
vn -0.9050 0.3304 -0.2680
vn -0.9822 0.1876 -0.0000
vn -0.9050 0.3304 0.2680
vn -0.5346 0.3304 0.7779
vn -0.3035 0.1876 0.9342
vn -0.0247 0.3304 0.9435
vn 0.5746 0.3304 0.7488
vn 0.7947 0.1876 0.5773
vn 0.8897 0.3304 0.3151
vn 0.3066 0.1256 -0.9435
vn 0.3035 -0.1876 -0.9342
vn 0.0247 -0.3304 -0.9435
vn -0.8026 0.1256 -0.5831
vn -0.7947 -0.1876 -0.5773
vn -0.8897 -0.3304 -0.3151
vn -0.8026 0.1256 0.5831
vn -0.7947 -0.1876 0.5773
vn -0.5746 -0.3304 0.7488
vn 0.3066 0.1256 0.9435
vn 0.3035 -0.1876 0.9342
vn 0.5346 -0.3304 0.7779
vn 0.9921 0.1256 -0.0000
vn 0.9822 -0.1876 -0.0000
vn 0.9050 -0.3304 -0.2680
vn 0.4713 -0.6617 -0.5831
vn 0.1876 -0.7947 -0.5773
vn -0.0385 -0.6617 -0.7488
vn -0.4089 -0.6617 -0.6284
vn -0.4911 -0.7947 -0.3568
vn -0.7240 -0.6617 -0.1947
vn -0.7240 -0.6617 0.1947
vn -0.4911 -0.7947 0.3568
vn -0.4089 -0.6617 0.6284
vn 0.7002 -0.6617 -0.2680
vn 0.6071 -0.7947 -0.0000
vn 0.3313 -0.9435 -0.0000
vn -0.0385 -0.6617 0.7488
vn 0.1876 -0.7947 0.5773
vn 0.4713 -0.6617 0.5831
vt 0.181819 0.000000
vt 0.227273 0.078731
vt 0.136365 0.078731
vt 0.272728 0.157461
vt 0.318182 0.078731
vt 0.363637 0.157461
vt 0.909091 0.000000
vt 0.954545 0.078731
vt 0.863636 0.078731
vt 0.727273 0.000000
vt 0.772727 0.078731
vt 0.681818 0.078731
vt 0.545455 0.000000
vt 0.590909 0.078731
vt 0.500000 0.078731
vt 0.318182 0.236191
vt 0.090910 0.157461
vt 0.181819 0.157461
vt 0.136365 0.236191
vt 0.818182 0.157461
vt 0.909091 0.157461
vt 0.863636 0.236191
vt 0.636364 0.157461
vt 0.727273 0.157461
vt 0.681818 0.236191
vt 0.454546 0.157461
vt 0.545455 0.157461
vt 0.500000 0.236191
vt 0.227273 0.236191
vt 0.045455 0.236191
vt 0.772727 0.236191
vt 0.590909 0.236191
vt 0.409092 0.236191
vt 0.181819 0.314921
vt 0.272728 0.314921
vt 0.227273 0.393651
vt 0.000000 0.314921
vt 0.090910 0.314921
vt 0.045455 0.393651
vt 0.727273 0.314921
vt 0.818182 0.314921
vt 0.772727 0.393651
vt 0.545455 0.314921
vt 0.636364 0.314921
vt 0.590909 0.393651
vt 0.363637 0.314921
vt 0.454546 0.314921
vt 0.409092 0.393651
vt 0.500000 0.393651
vt 0.454546 0.472382
vt 0.681818 0.393651
vt 0.636364 0.472382
vt 0.863636 0.393651
vt 0.818182 0.472382
vt 0.909091 0.314921
vt 0.136365 0.393651
vt 0.090910 0.472382
vt 0.318182 0.393651
vt 0.272728 0.472382
vt 0.954545 0.236191
vt 1.000000 0.157461
vt 0.409092 0.078731
vt 0.363637 0.000000
s 0
f 1/1/1 14/2/1 13/3/1
f 2/4/2 14/5/2 16/6/2
f 1/7/3 13/8/3 18/9/3
f 1/10/4 18/11/4 20/12/4
f 1/13/5 20/14/5 17/15/5
f 2/4/6 16/6/6 23/16/6
f 3/17/7 15/18/7 25/19/7
f 4/20/8 19/21/8 27/22/8
f 5/23/9 21/24/9 29/25/9
f 6/26/10 22/27/10 31/28/10
f 2/4/11 23/16/11 26/29/11
f 3/17/12 25/19/12 28/30/12
f 4/20/13 27/22/13 30/31/13
f 5/23/14 29/25/14 32/32/14
f 6/26/15 31/28/15 24/33/15
f 7/34/16 33/35/16 38/36/16
f 8/37/17 34/38/17 40/39/17
f 9/40/18 35/41/18 41/42/18
f 10/43/19 36/44/19 42/45/19
f 11/46/20 37/47/20 39/48/20
f 39/48/21 42/49/21 12/50/21
f 39/48/22 37/47/22 42/49/22
f 37/47/23 10/43/23 42/49/23
f 42/45/24 41/51/24 12/52/24
f 42/45/25 36/44/25 41/51/25
f 36/44/26 9/40/26 41/51/26
f 41/42/27 40/53/27 12/54/27
f 41/42/28 35/41/28 40/53/28
f 35/41/29 8/55/29 40/53/29
f 40/39/30 38/56/30 12/57/30
f 40/39/31 34/38/31 38/56/31
f 34/38/32 7/34/32 38/56/32
f 38/36/33 39/58/33 12/59/33
f 38/36/34 33/35/34 39/58/34
f 33/35/35 11/46/35 39/58/35
f 24/33/36 37/47/36 11/46/36
f 24/33/37 31/28/37 37/47/37
f 31/28/38 10/43/38 37/47/38
f 32/32/39 36/44/39 10/43/39
f 32/32/40 29/25/40 36/44/40
f 29/25/41 9/40/41 36/44/41
f 30/31/42 35/41/42 9/40/42
f 30/31/43 27/22/43 35/41/43
f 27/22/44 8/55/44 35/41/44
f 28/30/45 34/38/45 8/37/45
f 28/30/46 25/19/46 34/38/46
f 25/19/47 7/34/47 34/38/47
f 26/29/48 33/35/48 7/34/48
f 26/29/49 23/16/49 33/35/49
f 23/16/50 11/46/50 33/35/50
f 31/28/51 32/32/51 10/43/51
f 31/28/52 22/27/52 32/32/52
f 22/27/53 5/23/53 32/32/53
f 29/25/54 30/31/54 9/40/54
f 29/25/55 21/24/55 30/31/55
f 21/24/56 4/20/56 30/31/56
f 27/22/57 28/60/57 8/55/57
f 27/22/58 19/21/58 28/60/58
f 19/21/59 3/61/59 28/60/59
f 25/19/60 26/29/60 7/34/60
f 25/19/61 15/18/61 26/29/61
f 15/18/62 2/4/62 26/29/62
f 23/16/63 24/33/63 11/46/63
f 23/16/64 16/6/64 24/33/64
f 16/6/65 6/26/65 24/33/65
f 17/15/66 22/27/66 6/26/66
f 17/15/67 20/14/67 22/27/67
f 20/14/68 5/23/68 22/27/68
f 20/12/69 21/24/69 5/23/69
f 20/12/70 18/11/70 21/24/70
f 18/11/71 4/20/71 21/24/71
f 18/9/72 19/21/72 4/20/72
f 18/9/73 13/8/73 19/21/73
f 13/8/74 3/61/74 19/21/74
f 16/6/75 17/62/75 6/26/75
f 16/6/76 14/5/76 17/62/76
f 14/5/77 1/63/77 17/62/77
f 13/3/78 15/18/78 3/17/78
f 13/3/79 14/2/79 15/18/79
f 14/2/80 2/4/80 15/18/80

View File

@ -5,9 +5,9 @@ CFLAGS = \
-g \ -g \
-O3 \ -O3 \
-flto \ -flto \
-ffast-math \
-nostdlib \ -nostdlib \
-I$(MINIZ) \ -I$(MINIZ) \
-I.. \
-I. \ -I. \
-Werror \ -Werror \
-Wfatal-errors \ -Wfatal-errors \
@ -29,6 +29,9 @@ LDFLAGS = \
-Wl,--export=node_init_translation \ -Wl,--export=node_init_translation \
-Wl,--export=png_build_crc_table \ -Wl,--export=png_build_crc_table \
-Wl,--export=png_decode \ -Wl,--export=png_decode \
-Wl,--export=camera_move \
-Wl,--export=camera_init \
-Wl,--export=camera_view_projection \
-Wl,--import-undefined \ -Wl,--import-undefined \
-Wl,--print-map \ -Wl,--print-map \
-Wl,--import-memory \ -Wl,--import-memory \
@ -45,7 +48,8 @@ PNG_OBJ = \
stdlib.o \ stdlib.o \
$(MINIZ)/miniz_tinfl.o \ $(MINIZ)/miniz_tinfl.o \
memory.o \ memory.o \
node.o node.o \
camera.o
module.wasm: $(PNG_OBJ) module.wasm: $(PNG_OBJ)
clang++ $(CFLAGS) $(LDFLAGS) -o $@ $^ clang++ $(CFLAGS) $(LDFLAGS) -o $@ $^

138
src/camera.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "directxmath/DirectXMath.h"
#include "camera.h"
struct CameraState {
XMFLOAT3 eye;
XMFLOAT3 look;
XMFLOAT3 up;
float fov;
float pitch;
float yaw;
XMFLOAT3 light_position;
};
struct ViewState {
XMFLOAT4X4 viewProj;
XMFLOAT4X4 lightViewProj;
XMFLOAT4 lightPosition;
};
static inline XMMATRIX camera_view(CameraState const * state)
{
XMMATRIX view = XMMatrixLookToRH(XMLoadFloat3(&state->eye),
XMLoadFloat3(&state->look),
XMLoadFloat3(&state->up));
return view;
}
static inline XMMATRIX camera_projection(CameraState const * state, float aspect)
{
float near_z = 0.01;
float far_z = 1000.0;
XMMATRIX projection = XMMatrixPerspectiveFovRH(state->fov,
aspect,
near_z,
far_z);
return projection;
};
extern "C" void log(float x);
static inline float min(float a, float b)
{
return a < b ? a : b;
}
static inline float max(float a, float b)
{
return a > b ? a : b;
}
void camera_move(CameraState * state,
int lu, int ll, int ld, int lr,
int lal, int lar,
int ru, int rl, int rd, int rr)
{
const float linearSpeed = 0.1;
const float rotationalSpeed = 0.01;
XMFLOAT3 move = {0, 0, 0};
if (ll)
move.x -= 1.0;
if (lr)
move.x += 1.0;
if (lu)
move.z -= 1.0;
if (ld)
move.z += 1.0;
if (lal)
move.y += 1.0;
if (lar)
move.y -= 1.0;
//XMStoreFloat3(&move, XMVector3Normalize(XMLoadFloat3(&move)));
if (rl)
state->yaw += rotationalSpeed;
if (rr)
state->yaw -= rotationalSpeed;
if (ru)
state->pitch += rotationalSpeed;
if (rd)
state->pitch -= rotationalSpeed;
state->pitch = min(state->pitch, XM_PIDIV4);
state->pitch = max(state->pitch, -XM_PIDIV4);
float sinyaw;
float cosyaw;
XMScalarSinCos(&sinyaw, &cosyaw, state->yaw);
// eye
float x = move.x * -cosyaw - move.z * sinyaw;
float y = move.y;
float z = move.x * sinyaw - move.z * cosyaw;
state->eye.x += x * linearSpeed;
state->eye.y += y * linearSpeed;
state->eye.z += z * linearSpeed;
// look
float sinpitch;
float cospitch;
XMScalarSinCos(&sinpitch, &cospitch, state->pitch);
state->look.x = cospitch * sinyaw;
state->look.y = sinpitch;
state->look.z = cospitch * cosyaw;
}
void camera_init(CameraState * camera_state)
{
camera_state->fov = XMConvertToRadians(45 * 1.5);
camera_state->yaw = XM_PI;
camera_state->pitch = 0.0f;
camera_state->up = {0, 1, 0};
camera_state->look = {0, 0, -1};
camera_state->eye = {0, 0, 5};
camera_state->light_position = {1, 1, 1};
}
void camera_view_projection(CameraState const * camera_state,
ViewState * view_state,
float aspect)
{
XMMATRIX view = camera_view(camera_state);
XMMATRIX projection = camera_projection(camera_state, aspect);
XMMATRIX view_projection = view * projection;
XMMATRIX light_world = XMMatrixTranslationFromVector(XMLoadFloat3(&camera_state->light_position));
XMStoreFloat4x4(&view_state->viewProj, view_projection);
XMStoreFloat4x4(&view_state->lightViewProj, light_world * view_projection);
XMStoreFloat4(&view_state->lightPosition, XMLoadFloat3(&camera_state->light_position));
}

13
src/camera.h Normal file
View File

@ -0,0 +1,13 @@
struct CameraState;
struct ViewState;
extern "C" {
void camera_move(CameraState * camera_state,
int lu, int ll, int ld, int lr,
int lal, int lar,
int ru, int rl, int rd, int rr);
void camera_init(CameraState * camera_state);
void camera_view_projection(CameraState const * camera_state,
ViewState * view_state,
float aspect);
};

View File

@ -0,0 +1,369 @@
//-------------------------------------------------------------------------------------
// DirectXCollision.h -- C++ Collision Math library
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
// https://go.microsoft.com/fwlink/?LinkID=615560
//-------------------------------------------------------------------------------------
#pragma once
#include "DirectXMath.h"
namespace DirectX
{
enum ContainmentType
{
DISJOINT = 0,
INTERSECTS = 1,
CONTAINS = 2
};
enum PlaneIntersectionType
{
FRONT = 0,
INTERSECTING = 1,
BACK = 2
};
struct BoundingBox;
struct BoundingOrientedBox;
struct BoundingFrustum;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4324 4820)
// C4324: alignment padding warnings
// C4820: Off by default noise
#endif
//-------------------------------------------------------------------------------------
// Bounding sphere
//-------------------------------------------------------------------------------------
struct BoundingSphere
{
XMFLOAT3 Center; // Center of the sphere.
float Radius; // Radius of the sphere.
// Creators
BoundingSphere() noexcept : Center(0, 0, 0), Radius(1.f) {}
BoundingSphere(const BoundingSphere&) = default;
BoundingSphere& operator=(const BoundingSphere&) = default;
BoundingSphere(BoundingSphere&&) = default;
BoundingSphere& operator=(BoundingSphere&&) = default;
constexpr BoundingSphere(_In_ const XMFLOAT3& center, _In_ float radius) noexcept
: Center(center), Radius(radius) {}
// Methods
void XM_CALLCONV Transform(_Out_ BoundingSphere& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingSphere& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
// Transform the sphere
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sh) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-sphere test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-sphere test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-sphere test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test sphere against six planes (see BoundingFrustum::GetPlanes)
// Static methods
static void CreateMerged(_Out_ BoundingSphere& Out, _In_ const BoundingSphere& S1, _In_ const BoundingSphere& S2) noexcept;
static void CreateFromBoundingBox(_Out_ BoundingSphere& Out, _In_ const BoundingBox& box) noexcept;
static void CreateFromBoundingBox(_Out_ BoundingSphere& Out, _In_ const BoundingOrientedBox& box) noexcept;
static void CreateFromPoints(_Out_ BoundingSphere& Out, _In_ size_t Count,
_In_reads_bytes_(sizeof(XMFLOAT3) + Stride * (Count - 1)) const XMFLOAT3* pPoints, _In_ size_t Stride) noexcept;
static void CreateFromFrustum(_Out_ BoundingSphere& Out, _In_ const BoundingFrustum& fr) noexcept;
};
//-------------------------------------------------------------------------------------
// Axis-aligned bounding box
//-------------------------------------------------------------------------------------
struct BoundingBox
{
static constexpr size_t CORNER_COUNT = 8;
XMFLOAT3 Center; // Center of the box.
XMFLOAT3 Extents; // Distance from the center to each side.
// Creators
BoundingBox() noexcept : Center(0, 0, 0), Extents(1.f, 1.f, 1.f) {}
BoundingBox(const BoundingBox&) = default;
BoundingBox& operator=(const BoundingBox&) = default;
BoundingBox(BoundingBox&&) = default;
BoundingBox& operator=(BoundingBox&&) = default;
constexpr BoundingBox(_In_ const XMFLOAT3& center, _In_ const XMFLOAT3& extents) noexcept
: Center(center), Extents(extents) {}
// Methods
void XM_CALLCONV Transform(_Out_ BoundingBox& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingBox& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
void GetCorners(_Out_writes_(8) XMFLOAT3* Corners) const noexcept;
// Gets the 8 corners of the box
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sh) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-Box test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-box test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-Box test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test box against six planes (see BoundingFrustum::GetPlanes)
// Static methods
static void CreateMerged(_Out_ BoundingBox& Out, _In_ const BoundingBox& b1, _In_ const BoundingBox& b2) noexcept;
static void CreateFromSphere(_Out_ BoundingBox& Out, _In_ const BoundingSphere& sh) noexcept;
static void XM_CALLCONV CreateFromPoints(_Out_ BoundingBox& Out, _In_ FXMVECTOR pt1, _In_ FXMVECTOR pt2) noexcept;
static void CreateFromPoints(_Out_ BoundingBox& Out, _In_ size_t Count,
_In_reads_bytes_(sizeof(XMFLOAT3) + Stride * (Count - 1)) const XMFLOAT3* pPoints, _In_ size_t Stride) noexcept;
};
//-------------------------------------------------------------------------------------
// Oriented bounding box
//-------------------------------------------------------------------------------------
struct BoundingOrientedBox
{
static constexpr size_t CORNER_COUNT = 8;
XMFLOAT3 Center; // Center of the box.
XMFLOAT3 Extents; // Distance from the center to each side.
XMFLOAT4 Orientation; // Unit quaternion representing rotation (box -> world).
// Creators
BoundingOrientedBox() noexcept : Center(0, 0, 0), Extents(1.f, 1.f, 1.f), Orientation(0, 0, 0, 1.f) {}
BoundingOrientedBox(const BoundingOrientedBox&) = default;
BoundingOrientedBox& operator=(const BoundingOrientedBox&) = default;
BoundingOrientedBox(BoundingOrientedBox&&) = default;
BoundingOrientedBox& operator=(BoundingOrientedBox&&) = default;
constexpr BoundingOrientedBox(_In_ const XMFLOAT3& center, _In_ const XMFLOAT3& extents, _In_ const XMFLOAT4& orientation) noexcept
: Center(center), Extents(extents), Orientation(orientation) {}
// Methods
void XM_CALLCONV Transform(_Out_ BoundingOrientedBox& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingOrientedBox& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
void GetCorners(_Out_writes_(8) XMFLOAT3* Corners) const noexcept;
// Gets the 8 corners of the box
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sh) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-OrientedBox test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-OrientedBox test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-OrientedBox test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test OrientedBox against six planes (see BoundingFrustum::GetPlanes)
// Static methods
static void CreateFromBoundingBox(_Out_ BoundingOrientedBox& Out, _In_ const BoundingBox& box) noexcept;
static void CreateFromPoints(_Out_ BoundingOrientedBox& Out, _In_ size_t Count,
_In_reads_bytes_(sizeof(XMFLOAT3) + Stride * (Count - 1)) const XMFLOAT3* pPoints, _In_ size_t Stride) noexcept;
};
//-------------------------------------------------------------------------------------
// Bounding frustum
//-------------------------------------------------------------------------------------
struct BoundingFrustum
{
static constexpr size_t CORNER_COUNT = 8;
XMFLOAT3 Origin; // Origin of the frustum (and projection).
XMFLOAT4 Orientation; // Quaternion representing rotation.
float RightSlope; // Positive X (X/Z)
float LeftSlope; // Negative X
float TopSlope; // Positive Y (Y/Z)
float BottomSlope; // Negative Y
float Near, Far; // Z of the near plane and far plane.
// Creators
BoundingFrustum() noexcept :
Origin(0, 0, 0), Orientation(0, 0, 0, 1.f), RightSlope(1.f), LeftSlope(-1.f),
TopSlope(1.f), BottomSlope(-1.f), Near(0), Far(1.f) {}
BoundingFrustum(const BoundingFrustum&) = default;
BoundingFrustum& operator=(const BoundingFrustum&) = default;
BoundingFrustum(BoundingFrustum&&) = default;
BoundingFrustum& operator=(BoundingFrustum&&) = default;
constexpr BoundingFrustum(_In_ const XMFLOAT3& origin, _In_ const XMFLOAT4& orientation,
_In_ float rightSlope, _In_ float leftSlope, _In_ float topSlope, _In_ float bottomSlope,
_In_ float nearPlane, _In_ float farPlane) noexcept
: Origin(origin), Orientation(orientation),
RightSlope(rightSlope), LeftSlope(leftSlope), TopSlope(topSlope), BottomSlope(bottomSlope),
Near(nearPlane), Far(farPlane) {}
BoundingFrustum(_In_ CXMMATRIX Projection, bool rhcoords = false) noexcept;
// Methods
void XM_CALLCONV Transform(_Out_ BoundingFrustum& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingFrustum& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
void GetCorners(_Out_writes_(8) XMFLOAT3* Corners) const noexcept;
// Gets the 8 corners of the frustum
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sp) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
// Frustum-Frustum test
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-Frustum test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-Frustum test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR rayOrigin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-Frustum test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test frustum against six planes (see BoundingFrustum::GetPlanes)
void GetPlanes(_Out_opt_ XMVECTOR* NearPlane, _Out_opt_ XMVECTOR* FarPlane, _Out_opt_ XMVECTOR* RightPlane,
_Out_opt_ XMVECTOR* LeftPlane, _Out_opt_ XMVECTOR* TopPlane, _Out_opt_ XMVECTOR* BottomPlane) const noexcept;
// Create 6 Planes representation of Frustum
// Static methods
static void XM_CALLCONV CreateFromMatrix(_Out_ BoundingFrustum& Out, _In_ FXMMATRIX Projection, bool rhcoords = false) noexcept;
};
//-----------------------------------------------------------------------------
// Triangle intersection testing routines.
//-----------------------------------------------------------------------------
namespace TriangleTests
{
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _In_ FXMVECTOR V0, _In_ GXMVECTOR V1, _In_ HXMVECTOR V2, _Out_ float& Dist) noexcept;
// Ray-Triangle
bool XM_CALLCONV Intersects(_In_ FXMVECTOR A0, _In_ FXMVECTOR A1, _In_ FXMVECTOR A2, _In_ GXMVECTOR B0, _In_ HXMVECTOR B1, _In_ HXMVECTOR B2) noexcept;
// Triangle-Triangle
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2, _In_ GXMVECTOR Plane) noexcept;
// Plane-Triangle
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2,
_In_ GXMVECTOR Plane0, _In_ HXMVECTOR Plane1, _In_ HXMVECTOR Plane2,
_In_ CXMVECTOR Plane3, _In_ CXMVECTOR Plane4, _In_ CXMVECTOR Plane5) noexcept;
// Test a triangle against six planes at once (see BoundingFrustum::GetPlanes)
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
/****************************************************************************
*
* Implementation
*
****************************************************************************/
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4068 4365 4616 6001)
// C4068/4616: ignore unknown pragmas
// C4365: Off by default noise
// C6001: False positives
#endif
#ifdef _PREFAST_
#pragma prefast(push)
#pragma prefast(disable : 25000, "FXMVECTOR is 16 bytes")
#pragma prefast(disable : 26495, "Union initialization confuses /analyze")
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
#include "DirectXCollision.inl"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef _PREFAST_
#pragma prefast(pop)
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace DirectX

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,25 @@
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// DirectXMath.h -- SIMD C++ Math library // DirectXMath.h -- SIMD C++ Math library
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
// //
// http://go.microsoft.com/fwlink/?LinkID=615560 // https://go.microsoft.com/fwlink/?LinkID=615560
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#pragma once #pragma once
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
#ifndef __cplusplus #ifndef __cplusplus
#error DirectX Math requires C++ #error DirectX Math requires C++
#endif #endif
#define DIRECTX_MATH_VERSION 314 #define DIRECTX_MATH_VERSION 321
#if defined(_MSC_VER) && (_MSC_VER < 1910) #if defined(_MSC_VER) && (_MSC_VER < 1910)
#error DirectX Math requires Visual C++ 2017 or later. #error DirectX Math requires Visual C++ 2017 or later.
#endif #endif
#if defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(_M_HYBRID_X86_ARM64) && (!_MANAGED) && (!_M_CEE) && (!defined(_M_IX86_FP) || (_M_IX86_FP > 1)) && !defined(_XM_NO_INTRINSICS_) && !defined(_XM_VECTORCALL_) #if defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(_M_HYBRID_X86_ARM64) && !defined(_M_ARM64EC) && (!_MANAGED) && (!_M_CEE) && (!defined(_M_IX86_FP) || (_M_IX86_FP > 1)) && !defined(_XM_NO_INTRINSICS_) && !defined(_XM_VECTORCALL_)
#define _XM_VECTORCALL_ 1 #define _XM_VECTORCALL_ 1
#endif #endif
@ -37,7 +32,9 @@
#endif #endif
#ifndef XM_DEPRECATED #ifndef XM_DEPRECATED
#ifdef __GNUC__ #if (__cplusplus >= 201402L)
#define XM_DEPRECATED [[deprecated]]
#elif defined(__GNUC__)
#define XM_DEPRECATED __attribute__ ((deprecated)) #define XM_DEPRECATED __attribute__ ((deprecated))
#else #else
#define XM_DEPRECATED __declspec(deprecated("This is deprecated and will be removed in a future version.")) #define XM_DEPRECATED __declspec(deprecated("This is deprecated and will be removed in a future version."))
@ -85,25 +82,33 @@
#endif #endif
#if !defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if !defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
#if (defined(_M_IX86) || defined(_M_X64) || __i386__ || __x86_64__) && !defined(_M_HYBRID_X86_ARM64) #if (defined(_M_IX86) || defined(_M_X64) || __i386__ || __x86_64__ || __powerpc64__) && !defined(_M_HYBRID_X86_ARM64) && !defined(_M_ARM64EC)
#define _XM_SSE_INTRINSICS_ #define _XM_SSE_INTRINSICS_
#elif defined(_M_ARM) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || __arm__ || __aarch64__ #elif defined(_M_ARM) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __arm__ || __aarch64__
#define _XM_ARM_NEON_INTRINSICS_ #define _XM_ARM_NEON_INTRINSICS_
#elif !defined(_XM_NO_INTRINSICS_) #elif !defined(_XM_NO_INTRINSICS_)
#error DirectX Math does not support this target #error DirectX Math does not support this target
#endif #endif
#endif // !_XM_ARM_NEON_INTRINSICS_ && !_XM_SSE_INTRINSICS_ && !_XM_NO_INTRINSICS_ #endif // !_XM_ARM_NEON_INTRINSICS_ && !_XM_SSE_INTRINSICS_ && !_XM_NO_INTRINSICS_
#if !defined(_XM_NO_XMVECTOR_OVERLOADS_) && (defined(__clang__) || defined(__GNUC__)) #if defined(_XM_SSE_INTRINSICS_) && defined(_MSC_VER) && (_MSC_VER >= 1920) && !defined(__clang__) && !defined(_XM_SVML_INTRINSICS_) && !defined(_XM_DISABLE_INTEL_SVML_)
#define _XM_SVML_INTRINSICS_
#endif
#if !defined(_XM_NO_XMVECTOR_OVERLOADS_) && (defined(__clang__) || defined(__GNUC__)) && !defined(_XM_NO_INTRINSICS_)
#define _XM_NO_XMVECTOR_OVERLOADS_ #define _XM_NO_XMVECTOR_OVERLOADS_
#endif #endif
#ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4514 4820) #pragma warning(disable:4514 4820)
// C4514/4820: Off by default noise // C4514/4820: Off by default noise
#endif
//#include <math.h> //#include <math.h>
#include <float.h> #include <float.h>
#ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif
#ifndef _XM_NO_INTRINSICS_ #ifndef _XM_NO_INTRINSICS_
@ -111,11 +116,15 @@
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4987) #pragma warning(disable : 4987)
// C4987: Off by default noise // C4987: Off by default noise
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <intrin.h> #include <intrin.h>
#endif
#ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#if (defined(__clang__) || defined(__GNUC__)) && (__x86_64__ || __i386__) #if (defined(__clang__) || defined(__GNUC__)) && (__x86_64__ || __i386__) && !defined(__MINGW32__) && !defined(_MSC_VER)
#include <cpuid.h> #include <cpuid.h>
#endif #endif
@ -136,7 +145,7 @@
#endif #endif
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64)) #if defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC))
#include <arm64_neon.h> #include <arm64_neon.h>
#else #else
#include <arm_neon.h> #include <arm_neon.h>
@ -147,11 +156,14 @@
#include "sal.h" #include "sal.h"
//#include <assert.h> //#include <assert.h>
#define assert(x) #define assert(x)
#define isnan(x) __builtin_isnan(x) #define isnan(x) (false)
#define floorf(x) __builtin_floorf(x) #define floorf(x) __builtin_floorf(x)
#define sqrtf(x) __builtin_sqrtf(x) #define sqrtf(x) __builtin_sqrtf(x)
#define expf(x) __builtin_expf(x) #define expf(x) __builtin_expf(x)
#define exp2f(x) __builtin_exp2f(x)
#define logf(x) __builtin_logf(x) #define logf(x) __builtin_logf(x)
#define log2f(x) __builtin_log2f(x)
#define log10f(x) __builtin_log10f(x)
#define powf(x, y) __builtin_powf(x, y) #define powf(x, y) __builtin_powf(x, y)
#define fabsf(x) __builtin_fabsf(x) #define fabsf(x) __builtin_fabsf(x)
#define sinf(x) __builtin_sinf(x) #define sinf(x) __builtin_sinf(x)
@ -164,18 +176,25 @@
#define coshf(x) __builtin_coshf(x) #define coshf(x) __builtin_coshf(x)
#define atanf(x) __builtin_atanf(x) #define atanf(x) __builtin_atanf(x)
#define atan2f(x, y) __builtin_atan2f(x, y) #define atan2f(x, y) __builtin_atan2f(x, y)
#define isinf(x) __builtin_isinf(x) #define isinf(x) (false)
#define ceilf(x) __builtin_ceilf(x) #define ceilf(x) __builtin_ceilf(x)
#define modff(x, y) __builtin_modff(x, y) #define modff(x, y) __builtin_modff(x, y)
#include <stddef.h> #include <stddef.h>
#ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4005 4668) #pragma warning(disable : 4005 4668)
// C4005/4668: Old header issue // C4005/4668: Old header issue
#endif
#include <stdint.h> #include <stdint.h>
#ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif
#ifdef __GNUC__ #if (__cplusplus >= 201703L)
#define XM_ALIGNED_DATA(x) alignas(x)
#define XM_ALIGNED_STRUCT(x) struct alignas(x)
#elif defined(__GNUC__)
#define XM_ALIGNED_DATA(x) __attribute__ ((aligned(x))) #define XM_ALIGNED_DATA(x) __attribute__ ((aligned(x)))
#define XM_ALIGNED_STRUCT(x) struct __attribute__ ((aligned(x))) #define XM_ALIGNED_STRUCT(x) struct __attribute__ ((aligned(x)))
#else #else
@ -183,6 +202,10 @@
#define XM_ALIGNED_STRUCT(x) __declspec(align(x)) struct #define XM_ALIGNED_STRUCT(x) __declspec(align(x)) struct
#endif #endif
#if (__cplusplus >= 202002L)
#include <compare>
#endif
/**************************************************************************** /****************************************************************************
* *
* Conditional intrinsics * Conditional intrinsics
@ -215,11 +238,17 @@
#define XM_PERMUTE_PS( v, c ) _mm_shuffle_ps((v), (v), c ) #define XM_PERMUTE_PS( v, c ) _mm_shuffle_ps((v), (v), c )
#endif #endif
#if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 11)) || defined(__powerpc64__)
#define XM_LOADU_SI16( p ) _mm_cvtsi32_si128(*reinterpret_cast<unsigned short const*>(p))
#else
#define XM_LOADU_SI16( p ) _mm_loadu_si16(p)
#endif
#endif // _XM_SSE_INTRINSICS_ && !_XM_NO_INTRINSICS_ #endif // _XM_SSE_INTRINSICS_ && !_XM_NO_INTRINSICS_
#if defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
#if defined(__clang__) #if defined(__clang__) || defined(__GNUC__)
#define XM_PREFETCH( a ) __builtin_prefetch(a) #define XM_PREFETCH( a ) __builtin_prefetch(a)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#define XM_PREFETCH( a ) __prefetch(a) #define XM_PREFETCH( a ) __prefetch(a)
@ -291,7 +320,11 @@ namespace DirectX
constexpr uint32_t XM_CRMASK_CR6FALSE = 0x00000020; constexpr uint32_t XM_CRMASK_CR6FALSE = 0x00000020;
constexpr uint32_t XM_CRMASK_CR6BOUNDS = XM_CRMASK_CR6FALSE; constexpr uint32_t XM_CRMASK_CR6BOUNDS = XM_CRMASK_CR6FALSE;
#if defined(_M_ARM) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __arm__ || __aarch64__
constexpr size_t XM_CACHE_LINE_SIZE = 128;
#else
constexpr size_t XM_CACHE_LINE_SIZE = 64; constexpr size_t XM_CACHE_LINE_SIZE = 64;
#endif
/**************************************************************************** /****************************************************************************
@ -312,18 +345,18 @@ namespace DirectX
// Unit conversion // Unit conversion
inline constexpr float XMConvertToRadians(float fDegrees) noexcept { return fDegrees * (XM_PI / 180.0f); } constexpr float XMConvertToRadians(float fDegrees) noexcept { return fDegrees * (XM_PI / 180.0f); }
inline constexpr float XMConvertToDegrees(float fRadians) noexcept { return fRadians * (180.0f / XM_PI); } constexpr float XMConvertToDegrees(float fRadians) noexcept { return fRadians * (180.0f / XM_PI); }
// Condition register evaluation proceeding a recording (R) comparison // Condition register evaluation proceeding a recording (R) comparison
inline constexpr bool XMComparisonAllTrue(uint32_t CR) noexcept { return (((CR)&XM_CRMASK_CR6TRUE) == XM_CRMASK_CR6TRUE); } constexpr bool XMComparisonAllTrue(uint32_t CR) noexcept { return (CR & XM_CRMASK_CR6TRUE) == XM_CRMASK_CR6TRUE; }
inline constexpr bool XMComparisonAnyTrue(uint32_t CR) noexcept { return (((CR)&XM_CRMASK_CR6FALSE) != XM_CRMASK_CR6FALSE); } constexpr bool XMComparisonAnyTrue(uint32_t CR) noexcept { return (CR & XM_CRMASK_CR6FALSE) != XM_CRMASK_CR6FALSE; }
inline constexpr bool XMComparisonAllFalse(uint32_t CR) noexcept { return (((CR)&XM_CRMASK_CR6FALSE) == XM_CRMASK_CR6FALSE); } constexpr bool XMComparisonAllFalse(uint32_t CR) noexcept { return (CR & XM_CRMASK_CR6FALSE) == XM_CRMASK_CR6FALSE; }
inline constexpr bool XMComparisonAnyFalse(uint32_t CR) noexcept { return (((CR)&XM_CRMASK_CR6TRUE) != XM_CRMASK_CR6TRUE); } constexpr bool XMComparisonAnyFalse(uint32_t CR) noexcept { return (CR & XM_CRMASK_CR6TRUE) != XM_CRMASK_CR6TRUE; }
inline constexpr bool XMComparisonMixed(uint32_t CR) noexcept { return (((CR)&XM_CRMASK_CR6) == 0); } constexpr bool XMComparisonMixed(uint32_t CR) noexcept { return (CR & XM_CRMASK_CR6) == 0; }
inline constexpr bool XMComparisonAllInBounds(uint32_t CR) noexcept { return (((CR)&XM_CRMASK_CR6BOUNDS) == XM_CRMASK_CR6BOUNDS); } constexpr bool XMComparisonAllInBounds(uint32_t CR) noexcept { return (CR & XM_CRMASK_CR6BOUNDS) == XM_CRMASK_CR6BOUNDS; }
inline constexpr bool XMComparisonAnyOutOfBounds(uint32_t CR) noexcept { return (((CR)&XM_CRMASK_CR6BOUNDS) != XM_CRMASK_CR6BOUNDS); } constexpr bool XMComparisonAnyOutOfBounds(uint32_t CR) noexcept { return (CR & XM_CRMASK_CR6BOUNDS) != XM_CRMASK_CR6BOUNDS; }
/**************************************************************************** /****************************************************************************
@ -332,12 +365,14 @@ namespace DirectX
* *
****************************************************************************/ ****************************************************************************/
#ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4068 4201 4365 4324 4820) #pragma warning(disable:4068 4201 4365 4324 4820)
// C4068: ignore unknown pragmas // C4068: ignore unknown pragmas
// C4201: nonstandard extension used : nameless struct/union // C4201: nonstandard extension used : nameless struct/union
// C4365: Off by default noise // C4365: Off by default noise
// C4324/4820: padding warnings // C4324/4820: padding warnings
#endif
#ifdef _PREFAST_ #ifdef _PREFAST_
#pragma prefast(push) #pragma prefast(push)
@ -360,11 +395,11 @@ namespace DirectX
// Vector intrinsic: Four 32 bit floating point components aligned on a 16 byte // Vector intrinsic: Four 32 bit floating point components aligned on a 16 byte
// boundary and mapped to hardware vector registers // boundary and mapped to hardware vector registers
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
typedef __m128 XMVECTOR; using XMVECTOR = __m128;
#elif defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
typedef float32x4_t XMVECTOR; using XMVECTOR = float32x4_t;
#else #else
typedef __vector4 XMVECTOR; using XMVECTOR = __vector4;
#endif #endif
// Fix-up for (1st-3rd) XMVECTOR parameters that are pass-in-register for x86, ARM, ARM64, and vector call; by reference otherwise // Fix-up for (1st-3rd) XMVECTOR parameters that are pass-in-register for x86, ARM, ARM64, and vector call; by reference otherwise
@ -374,15 +409,15 @@ namespace DirectX
typedef const XMVECTOR& FXMVECTOR; typedef const XMVECTOR& FXMVECTOR;
#endif #endif
// Fix-up for (4th) XMVECTOR parameter to pass in-register for ARM, ARM64, and x64 vector call; by reference otherwise // Fix-up for (4th) XMVECTOR parameter to pass in-register for ARM, ARM64, and vector call; by reference otherwise
#if ( defined(_M_ARM) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || (_XM_VECTORCALL_ && !defined(_M_IX86) ) || __arm__ || __aarch64__ ) && !defined(_XM_NO_INTRINSICS_) #if ( defined(_M_ARM) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || _XM_VECTORCALL_ || __arm__ || __aarch64__ ) && !defined(_XM_NO_INTRINSICS_)
typedef const XMVECTOR GXMVECTOR; typedef const XMVECTOR GXMVECTOR;
#else #else
typedef const XMVECTOR& GXMVECTOR; typedef const XMVECTOR& GXMVECTOR;
#endif #endif
// Fix-up for (5th & 6th) XMVECTOR parameter to pass in-register for ARM64 and vector call; by reference otherwise // Fix-up for (5th & 6th) XMVECTOR parameter to pass in-register for ARM64 and vector call; by reference otherwise
#if ( defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || _XM_VECTORCALL_ || __aarch64__ ) && !defined(_XM_NO_INTRINSICS_) #if ( defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || _XM_VECTORCALL_ || __aarch64__ ) && !defined(_XM_NO_INTRINSICS_)
typedef const XMVECTOR HXMVECTOR; typedef const XMVECTOR HXMVECTOR;
#else #else
typedef const XMVECTOR& HXMVECTOR; typedef const XMVECTOR& HXMVECTOR;
@ -403,9 +438,13 @@ namespace DirectX
inline operator XMVECTOR() const noexcept { return v; } inline operator XMVECTOR() const noexcept { return v; }
inline operator const float* () const noexcept { return f; } inline operator const float* () const noexcept { return f; }
#if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SSE_INTRINSICS_) #ifdef _XM_NO_INTRINSICS_
#elif defined(_XM_SSE_INTRINSICS_)
inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128i() const noexcept { return _mm_castps_si128(v); }
inline operator __m128d() const noexcept { return _mm_castps_pd(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); }
#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES))
inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); }
inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); }
#endif #endif
}; };
@ -418,9 +457,13 @@ namespace DirectX
}; };
inline operator XMVECTOR() const noexcept { return v; } inline operator XMVECTOR() const noexcept { return v; }
#if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SSE_INTRINSICS_) #ifdef _XM_NO_INTRINSICS_
#elif defined(_XM_SSE_INTRINSICS_)
inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128i() const noexcept { return _mm_castps_si128(v); }
inline operator __m128d() const noexcept { return _mm_castps_pd(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); }
#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES))
inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); }
inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); }
#endif #endif
}; };
@ -433,9 +476,13 @@ namespace DirectX
}; };
inline operator XMVECTOR() const noexcept { return v; } inline operator XMVECTOR() const noexcept { return v; }
#if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SSE_INTRINSICS_) #ifdef _XM_NO_INTRINSICS_
#elif defined(_XM_SSE_INTRINSICS_)
inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128i() const noexcept { return _mm_castps_si128(v); }
inline operator __m128d() const noexcept { return _mm_castps_pd(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); }
#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES))
inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); }
inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); }
#endif #endif
}; };
@ -448,9 +495,13 @@ namespace DirectX
}; };
inline operator XMVECTOR() const noexcept { return v; } inline operator XMVECTOR() const noexcept { return v; }
#if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SSE_INTRINSICS_) #ifdef _XM_NO_INTRINSICS_
#elif defined(_XM_SSE_INTRINSICS_)
inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128i() const noexcept { return _mm_castps_si128(v); }
inline operator __m128d() const noexcept { return _mm_castps_pd(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); }
#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES))
inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); }
inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); }
#endif #endif
}; };
@ -485,7 +536,7 @@ namespace DirectX
struct XMMATRIX; struct XMMATRIX;
// Fix-up for (1st) XMMATRIX parameter to pass in-register for ARM64 and vector call; by reference otherwise // Fix-up for (1st) XMMATRIX parameter to pass in-register for ARM64 and vector call; by reference otherwise
#if ( defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || _XM_VECTORCALL_ || __aarch64__ ) && !defined(_XM_NO_INTRINSICS_) #if ( defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || _XM_VECTORCALL_ || __aarch64__ ) && !defined(_XM_NO_INTRINSICS_)
typedef const XMMATRIX FXMMATRIX; typedef const XMMATRIX FXMMATRIX;
#else #else
typedef const XMMATRIX& FXMMATRIX; typedef const XMMATRIX& FXMMATRIX;
@ -577,21 +628,17 @@ namespace DirectX
constexpr XMFLOAT2(float _x, float _y) noexcept : x(_x), y(_y) {} constexpr XMFLOAT2(float _x, float _y) noexcept : x(_x), y(_y) {}
explicit XMFLOAT2(_In_reads_(2) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]) {} explicit XMFLOAT2(_In_reads_(2) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMFLOAT2&) const = default;
auto operator <=> (const XMFLOAT2&) const = default;
#endif
}; };
// 2D Vector; 32 bit floating point components aligned on a 16 byte boundary // 2D Vector; 32 bit floating point components aligned on a 16 byte boundary
XM_ALIGNED_STRUCT(16) XMFLOAT2A : public XMFLOAT2 XM_ALIGNED_STRUCT(16) XMFLOAT2A : public XMFLOAT2
{ {
XMFLOAT2A() = default; using XMFLOAT2::XMFLOAT2;
XMFLOAT2A(const XMFLOAT2A&) = default;
XMFLOAT2A& operator=(const XMFLOAT2A&) = default;
XMFLOAT2A(XMFLOAT2A&&) = default;
XMFLOAT2A& operator=(XMFLOAT2A&&) = default;
constexpr XMFLOAT2A(float _x, float _y) noexcept : XMFLOAT2(_x, _y) {}
explicit XMFLOAT2A(_In_reads_(2) const float* pArray) noexcept : XMFLOAT2(pArray) {}
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -611,6 +658,11 @@ namespace DirectX
constexpr XMINT2(int32_t _x, int32_t _y) noexcept : x(_x), y(_y) {} constexpr XMINT2(int32_t _x, int32_t _y) noexcept : x(_x), y(_y) {}
explicit XMINT2(_In_reads_(2) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]) {} explicit XMINT2(_In_reads_(2) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMINT2&) const = default;
auto operator <=> (const XMINT2&) const = default;
#endif
}; };
// 2D Vector; 32 bit unsigned integer components // 2D Vector; 32 bit unsigned integer components
@ -629,6 +681,11 @@ namespace DirectX
constexpr XMUINT2(uint32_t _x, uint32_t _y) noexcept : x(_x), y(_y) {} constexpr XMUINT2(uint32_t _x, uint32_t _y) noexcept : x(_x), y(_y) {}
explicit XMUINT2(_In_reads_(2) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]) {} explicit XMUINT2(_In_reads_(2) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMUINT2&) const = default;
auto operator <=> (const XMUINT2&) const = default;
#endif
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -649,21 +706,17 @@ namespace DirectX
constexpr XMFLOAT3(float _x, float _y, float _z) noexcept : x(_x), y(_y), z(_z) {} constexpr XMFLOAT3(float _x, float _y, float _z) noexcept : x(_x), y(_y), z(_z) {}
explicit XMFLOAT3(_In_reads_(3) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {} explicit XMFLOAT3(_In_reads_(3) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMFLOAT3&) const = default;
auto operator <=> (const XMFLOAT3&) const = default;
#endif
}; };
// 3D Vector; 32 bit floating point components aligned on a 16 byte boundary // 3D Vector; 32 bit floating point components aligned on a 16 byte boundary
XM_ALIGNED_STRUCT(16) XMFLOAT3A : public XMFLOAT3 XM_ALIGNED_STRUCT(16) XMFLOAT3A : public XMFLOAT3
{ {
XMFLOAT3A() = default; using XMFLOAT3::XMFLOAT3;
XMFLOAT3A(const XMFLOAT3A&) = default;
XMFLOAT3A& operator=(const XMFLOAT3A&) = default;
XMFLOAT3A(XMFLOAT3A&&) = default;
XMFLOAT3A& operator=(XMFLOAT3A&&) = default;
constexpr XMFLOAT3A(float _x, float _y, float _z) noexcept : XMFLOAT3(_x, _y, _z) {}
explicit XMFLOAT3A(_In_reads_(3) const float* pArray) noexcept : XMFLOAT3(pArray) {}
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -684,6 +737,11 @@ namespace DirectX
constexpr XMINT3(int32_t _x, int32_t _y, int32_t _z) noexcept : x(_x), y(_y), z(_z) {} constexpr XMINT3(int32_t _x, int32_t _y, int32_t _z) noexcept : x(_x), y(_y), z(_z) {}
explicit XMINT3(_In_reads_(3) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {} explicit XMINT3(_In_reads_(3) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMINT3&) const = default;
auto operator <=> (const XMINT3&) const = default;
#endif
}; };
// 3D Vector; 32 bit unsigned integer components // 3D Vector; 32 bit unsigned integer components
@ -703,6 +761,11 @@ namespace DirectX
constexpr XMUINT3(uint32_t _x, uint32_t _y, uint32_t _z) noexcept : x(_x), y(_y), z(_z) {} constexpr XMUINT3(uint32_t _x, uint32_t _y, uint32_t _z) noexcept : x(_x), y(_y), z(_z) {}
explicit XMUINT3(_In_reads_(3) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {} explicit XMUINT3(_In_reads_(3) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMUINT3&) const = default;
auto operator <=> (const XMUINT3&) const = default;
#endif
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -724,21 +787,17 @@ namespace DirectX
constexpr XMFLOAT4(float _x, float _y, float _z, float _w) noexcept : x(_x), y(_y), z(_z), w(_w) {} constexpr XMFLOAT4(float _x, float _y, float _z, float _w) noexcept : x(_x), y(_y), z(_z), w(_w) {}
explicit XMFLOAT4(_In_reads_(4) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {} explicit XMFLOAT4(_In_reads_(4) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMFLOAT4&) const = default;
auto operator <=> (const XMFLOAT4&) const = default;
#endif
}; };
// 4D Vector; 32 bit floating point components aligned on a 16 byte boundary // 4D Vector; 32 bit floating point components aligned on a 16 byte boundary
XM_ALIGNED_STRUCT(16) XMFLOAT4A : public XMFLOAT4 XM_ALIGNED_STRUCT(16) XMFLOAT4A : public XMFLOAT4
{ {
XMFLOAT4A() = default; using XMFLOAT4::XMFLOAT4;
XMFLOAT4A(const XMFLOAT4A&) = default;
XMFLOAT4A& operator=(const XMFLOAT4A&) = default;
XMFLOAT4A(XMFLOAT4A&&) = default;
XMFLOAT4A& operator=(XMFLOAT4A&&) = default;
constexpr XMFLOAT4A(float _x, float _y, float _z, float _w) noexcept : XMFLOAT4(_x, _y, _z, _w) {}
explicit XMFLOAT4A(_In_reads_(4) const float* pArray) noexcept : XMFLOAT4(pArray) {}
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -760,6 +819,11 @@ namespace DirectX
constexpr XMINT4(int32_t _x, int32_t _y, int32_t _z, int32_t _w) noexcept : x(_x), y(_y), z(_z), w(_w) {} constexpr XMINT4(int32_t _x, int32_t _y, int32_t _z, int32_t _w) noexcept : x(_x), y(_y), z(_z), w(_w) {}
explicit XMINT4(_In_reads_(4) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {} explicit XMINT4(_In_reads_(4) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMINT4&) const = default;
auto operator <=> (const XMINT4&) const = default;
#endif
}; };
// 4D Vector; 32 bit unsigned integer components // 4D Vector; 32 bit unsigned integer components
@ -780,12 +844,19 @@ namespace DirectX
constexpr XMUINT4(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w) noexcept : x(_x), y(_y), z(_z), w(_w) {} constexpr XMUINT4(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w) noexcept : x(_x), y(_y), z(_z), w(_w) {}
explicit XMUINT4(_In_reads_(4) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {} explicit XMUINT4(_In_reads_(4) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {}
#if (__cplusplus >= 202002L)
bool operator == (const XMUINT4&) const = default;
auto operator <=> (const XMUINT4&) const = default;
#endif
}; };
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-anonymous-struct" #pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
#pragma clang diagnostic ignored "-Wnested-anon-types" #pragma clang diagnostic ignored "-Wnested-anon-types"
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif #endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -816,11 +887,34 @@ namespace DirectX
float m20, float m21, float m22) noexcept float m20, float m21, float m22) noexcept
: _11(m00), _12(m01), _13(m02), : _11(m00), _12(m01), _13(m02),
_21(m10), _22(m11), _23(m12), _21(m10), _22(m11), _23(m12),
_31(m20), _32(m21), _33(m22) {} _31(m20), _32(m21), _33(m22)
{}
explicit XMFLOAT3X3(_In_reads_(9) const float* pArray) noexcept; explicit XMFLOAT3X3(_In_reads_(9) const float* pArray) noexcept;
float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; }
float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; }
#if (__cplusplus >= 202002L)
constexpr bool operator == (const XMFLOAT3X3& M) const noexcept
{
return _11 == M._11 && _12 == M._12 && _13 == M._13
&& _21 == M._21 && _22 == M._22 && _23 == M._23
&& _31 == M._31 && _32 == M._32 && _33 == M._33;
}
constexpr auto operator <=> (const XMFLOAT3X3& M) const noexcept
{
if (auto cmp = _11 <=> M._11; cmp != 0) return cmp;
if (auto cmp = _12 <=> M._12; cmp != 0) return cmp;
if (auto cmp = _13 <=> M._13; cmp != 0) return cmp;
if (auto cmp = _21 <=> M._21; cmp != 0) return cmp;
if (auto cmp = _22 <=> M._22; cmp != 0) return cmp;
if (auto cmp = _23 <=> M._23; cmp != 0) return cmp;
if (auto cmp = _31 <=> M._31; cmp != 0) return cmp;
if (auto cmp = _32 <=> M._32; cmp != 0) return cmp;
return _33 <=> M._33;
}
#endif
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -855,30 +949,44 @@ namespace DirectX
: _11(m00), _12(m01), _13(m02), : _11(m00), _12(m01), _13(m02),
_21(m10), _22(m11), _23(m12), _21(m10), _22(m11), _23(m12),
_31(m20), _32(m21), _33(m22), _31(m20), _32(m21), _33(m22),
_41(m30), _42(m31), _43(m32) {} _41(m30), _42(m31), _43(m32)
{}
explicit XMFLOAT4X3(_In_reads_(12) const float* pArray) noexcept; explicit XMFLOAT4X3(_In_reads_(12) const float* pArray) noexcept;
float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; }
float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; }
#if (__cplusplus >= 202002L)
constexpr bool operator == (const XMFLOAT4X3& M) const noexcept
{
return _11 == M._11 && _12 == M._12 && _13 == M._13
&& _21 == M._21 && _22 == M._22 && _23 == M._23
&& _31 == M._31 && _32 == M._32 && _33 == M._33
&& _41 == M._41 && _42 == M._42 && _43 == M._43;
}
constexpr auto operator <=> (const XMFLOAT4X3& M) const noexcept
{
if (auto cmp = _11 <=> M._11; cmp != 0) return cmp;
if (auto cmp = _12 <=> M._12; cmp != 0) return cmp;
if (auto cmp = _13 <=> M._13; cmp != 0) return cmp;
if (auto cmp = _21 <=> M._21; cmp != 0) return cmp;
if (auto cmp = _22 <=> M._22; cmp != 0) return cmp;
if (auto cmp = _23 <=> M._23; cmp != 0) return cmp;
if (auto cmp = _31 <=> M._31; cmp != 0) return cmp;
if (auto cmp = _32 <=> M._32; cmp != 0) return cmp;
if (auto cmp = _33 <=> M._33; cmp != 0) return cmp;
if (auto cmp = _41 <=> M._41; cmp != 0) return cmp;
if (auto cmp = _42 <=> M._42; cmp != 0) return cmp;
return _43 <=> M._43;
}
#endif
}; };
// 4x3 Row-major Matrix: 32 bit floating point components aligned on a 16 byte boundary // 4x3 Row-major Matrix: 32 bit floating point components aligned on a 16 byte boundary
XM_ALIGNED_STRUCT(16) XMFLOAT4X3A : public XMFLOAT4X3 XM_ALIGNED_STRUCT(16) XMFLOAT4X3A : public XMFLOAT4X3
{ {
XMFLOAT4X3A() = default; using XMFLOAT4X3::XMFLOAT4X3;
XMFLOAT4X3A(const XMFLOAT4X3A&) = default;
XMFLOAT4X3A& operator=(const XMFLOAT4X3A&) = default;
XMFLOAT4X3A(XMFLOAT4X3A&&) = default;
XMFLOAT4X3A& operator=(XMFLOAT4X3A&&) = default;
constexpr XMFLOAT4X3A(float m00, float m01, float m02,
float m10, float m11, float m12,
float m20, float m21, float m22,
float m30, float m31, float m32) noexcept :
XMFLOAT4X3(m00, m01, m02, m10, m11, m12, m20, m21, m22, m30, m31, m32) {}
explicit XMFLOAT4X3A(_In_reads_(12) const float* pArray) noexcept : XMFLOAT4X3(pArray) {}
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -910,29 +1018,43 @@ namespace DirectX
float m20, float m21, float m22, float m23) noexcept float m20, float m21, float m22, float m23) noexcept
: _11(m00), _12(m01), _13(m02), _14(m03), : _11(m00), _12(m01), _13(m02), _14(m03),
_21(m10), _22(m11), _23(m12), _24(m13), _21(m10), _22(m11), _23(m12), _24(m13),
_31(m20), _32(m21), _33(m22), _34(m23) {} _31(m20), _32(m21), _33(m22), _34(m23)
{}
explicit XMFLOAT3X4(_In_reads_(12) const float* pArray) noexcept; explicit XMFLOAT3X4(_In_reads_(12) const float* pArray) noexcept;
float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; }
float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; }
#if (__cplusplus >= 202002L)
constexpr bool operator == (const XMFLOAT3X4& M) const noexcept
{
return _11 == M._11 && _12 == M._12 && _13 == M._13 && _14 == M._14
&& _21 == M._21 && _22 == M._22 && _23 == M._23 && _24 == M._24
&& _31 == M._31 && _32 == M._32 && _33 == M._33 && _34 == M._34;
}
constexpr auto operator <=> (const XMFLOAT3X4& M) const noexcept
{
if (auto cmp = _11 <=> M._11; cmp != 0) return cmp;
if (auto cmp = _12 <=> M._12; cmp != 0) return cmp;
if (auto cmp = _13 <=> M._13; cmp != 0) return cmp;
if (auto cmp = _14 <=> M._14; cmp != 0) return cmp;
if (auto cmp = _21 <=> M._21; cmp != 0) return cmp;
if (auto cmp = _22 <=> M._22; cmp != 0) return cmp;
if (auto cmp = _23 <=> M._23; cmp != 0) return cmp;
if (auto cmp = _24 <=> M._24; cmp != 0) return cmp;
if (auto cmp = _31 <=> M._31; cmp != 0) return cmp;
if (auto cmp = _32 <=> M._32; cmp != 0) return cmp;
if (auto cmp = _33 <=> M._33; cmp != 0) return cmp;
return _34 <=> M._34;
}
#endif
}; };
// 3x4 Column-major Matrix: 32 bit floating point components aligned on a 16 byte boundary // 3x4 Column-major Matrix: 32 bit floating point components aligned on a 16 byte boundary
XM_ALIGNED_STRUCT(16) XMFLOAT3X4A : public XMFLOAT3X4 XM_ALIGNED_STRUCT(16) XMFLOAT3X4A : public XMFLOAT3X4
{ {
XMFLOAT3X4A() = default; using XMFLOAT3X4::XMFLOAT3X4;
XMFLOAT3X4A(const XMFLOAT3X4A&) = default;
XMFLOAT3X4A& operator=(const XMFLOAT3X4A&) = default;
XMFLOAT3X4A(XMFLOAT3X4A&&) = default;
XMFLOAT3X4A& operator=(XMFLOAT3X4A&&) = default;
constexpr XMFLOAT3X4A(float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23) noexcept :
XMFLOAT3X4(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23) {}
explicit XMFLOAT3X4A(_In_reads_(12) const float* pArray) noexcept : XMFLOAT3X4(pArray) {}
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -966,30 +1088,48 @@ namespace DirectX
: _11(m00), _12(m01), _13(m02), _14(m03), : _11(m00), _12(m01), _13(m02), _14(m03),
_21(m10), _22(m11), _23(m12), _24(m13), _21(m10), _22(m11), _23(m12), _24(m13),
_31(m20), _32(m21), _33(m22), _34(m23), _31(m20), _32(m21), _33(m22), _34(m23),
_41(m30), _42(m31), _43(m32), _44(m33) {} _41(m30), _42(m31), _43(m32), _44(m33)
{}
explicit XMFLOAT4X4(_In_reads_(16) const float* pArray) noexcept; explicit XMFLOAT4X4(_In_reads_(16) const float* pArray) noexcept;
float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; }
float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; }
#if (__cplusplus >= 202002L)
constexpr bool operator == (const XMFLOAT4X4& M) const noexcept
{
return _11 == M._11 && _12 == M._12 && _13 == M._13 && _14 == M._14
&& _21 == M._21 && _22 == M._22 && _23 == M._23 && _24 == M._24
&& _31 == M._31 && _32 == M._32 && _33 == M._33 && _34 == M._34
&& _41 == M._41 && _42 == M._42 && _43 == M._43 && _44 == M._44;
}
constexpr auto operator <=> (const XMFLOAT4X4& M) const noexcept
{
if (auto cmp = _11 <=> M._11; cmp != 0) return cmp;
if (auto cmp = _12 <=> M._12; cmp != 0) return cmp;
if (auto cmp = _13 <=> M._13; cmp != 0) return cmp;
if (auto cmp = _14 <=> M._14; cmp != 0) return cmp;
if (auto cmp = _21 <=> M._21; cmp != 0) return cmp;
if (auto cmp = _22 <=> M._22; cmp != 0) return cmp;
if (auto cmp = _23 <=> M._23; cmp != 0) return cmp;
if (auto cmp = _24 <=> M._24; cmp != 0) return cmp;
if (auto cmp = _31 <=> M._31; cmp != 0) return cmp;
if (auto cmp = _32 <=> M._32; cmp != 0) return cmp;
if (auto cmp = _33 <=> M._33; cmp != 0) return cmp;
if (auto cmp = _34 <=> M._34; cmp != 0) return cmp;
if (auto cmp = _41 <=> M._41; cmp != 0) return cmp;
if (auto cmp = _42 <=> M._42; cmp != 0) return cmp;
if (auto cmp = _43 <=> M._43; cmp != 0) return cmp;
return _44 <=> M._44;
}
#endif
}; };
// 4x4 Matrix: 32 bit floating point components aligned on a 16 byte boundary // 4x4 Matrix: 32 bit floating point components aligned on a 16 byte boundary
XM_ALIGNED_STRUCT(16) XMFLOAT4X4A : public XMFLOAT4X4 XM_ALIGNED_STRUCT(16) XMFLOAT4X4A : public XMFLOAT4X4
{ {
XMFLOAT4X4A() = default; using XMFLOAT4X4::XMFLOAT4X4;
XMFLOAT4X4A(const XMFLOAT4X4A&) = default;
XMFLOAT4X4A& operator=(const XMFLOAT4X4A&) = default;
XMFLOAT4X4A(XMFLOAT4X4A&&) = default;
XMFLOAT4X4A& operator=(XMFLOAT4X4A&&) = default;
constexpr XMFLOAT4X4A(float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33) noexcept
: XMFLOAT4X4(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {}
explicit XMFLOAT4X4A(_In_reads_(16) const float* pArray) noexcept : XMFLOAT4X4(pArray) {}
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -997,12 +1137,12 @@ namespace DirectX
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
#ifdef _PREFAST_ #ifdef _PREFAST_
#pragma prefast(pop) #pragma prefast(pop)
#endif #endif
#ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif
/**************************************************************************** /****************************************************************************
* *
@ -1250,9 +1390,11 @@ namespace DirectX
XMVECTOR XM_CALLCONV XMVectorReciprocalSqrtEst(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorReciprocalSqrtEst(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorReciprocalSqrt(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorReciprocalSqrt(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorExp2(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorExp2(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorExp10(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorExpE(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorExpE(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorExp(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorExp(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorLog2(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorLog2(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorLog10(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorLogE(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorLogE(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorLog(FXMVECTOR V) noexcept; XMVECTOR XM_CALLCONV XMVectorLog(FXMVECTOR V) noexcept;
XMVECTOR XM_CALLCONV XMVectorPow(FXMVECTOR V1, FXMVECTOR V2) noexcept; XMVECTOR XM_CALLCONV XMVectorPow(FXMVECTOR V1, FXMVECTOR V2) noexcept;
@ -1505,8 +1647,13 @@ namespace DirectX
XMMATRIX XM_CALLCONV XMMatrixRotationX(float Angle) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationX(float Angle) noexcept;
XMMATRIX XM_CALLCONV XMMatrixRotationY(float Angle) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationY(float Angle) noexcept;
XMMATRIX XM_CALLCONV XMMatrixRotationZ(float Angle) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationZ(float Angle) noexcept;
// Rotates about y-axis (Yaw), then x-axis (Pitch), then z-axis (Roll)
XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYaw(float Pitch, float Yaw, float Roll) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYaw(float Pitch, float Yaw, float Roll) noexcept;
// Rotates about y-axis (Angles.y), then x-axis (Angles.x), then z-axis (Angles.z)
XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYawFromVector(FXMVECTOR Angles) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYawFromVector(FXMVECTOR Angles) noexcept;
XMMATRIX XM_CALLCONV XMMatrixRotationNormal(FXMVECTOR NormalAxis, float Angle) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationNormal(FXMVECTOR NormalAxis, float Angle) noexcept;
XMMATRIX XM_CALLCONV XMMatrixRotationAxis(FXMVECTOR Axis, float Angle) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationAxis(FXMVECTOR Axis, float Angle) noexcept;
XMMATRIX XM_CALLCONV XMMatrixRotationQuaternion(FXMVECTOR Quaternion) noexcept; XMMATRIX XM_CALLCONV XMMatrixRotationQuaternion(FXMVECTOR Quaternion) noexcept;
@ -1568,8 +1715,13 @@ namespace DirectX
XMVECTOR XM_CALLCONV XMQuaternionBaryCentricV(FXMVECTOR Q0, FXMVECTOR Q1, FXMVECTOR Q2, GXMVECTOR F, HXMVECTOR G) noexcept; XMVECTOR XM_CALLCONV XMQuaternionBaryCentricV(FXMVECTOR Q0, FXMVECTOR Q1, FXMVECTOR Q2, GXMVECTOR F, HXMVECTOR G) noexcept;
XMVECTOR XM_CALLCONV XMQuaternionIdentity() noexcept; XMVECTOR XM_CALLCONV XMQuaternionIdentity() noexcept;
// Rotates about y-axis (Yaw), then x-axis (Pitch), then z-axis (Roll)
XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYaw(float Pitch, float Yaw, float Roll) noexcept; XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYaw(float Pitch, float Yaw, float Roll) noexcept;
// Rotates about y-axis (Angles.y), then x-axis (Angles.x), then z-axis (Angles.z)
XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYawFromVector(FXMVECTOR Angles) noexcept; XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYawFromVector(FXMVECTOR Angles) noexcept;
XMVECTOR XM_CALLCONV XMQuaternionRotationNormal(FXMVECTOR NormalAxis, float Angle) noexcept; XMVECTOR XM_CALLCONV XMQuaternionRotationNormal(FXMVECTOR NormalAxis, float Angle) noexcept;
XMVECTOR XM_CALLCONV XMQuaternionRotationAxis(FXMVECTOR Axis, float Angle) noexcept; XMVECTOR XM_CALLCONV XMQuaternionRotationAxis(FXMVECTOR Axis, float Angle) noexcept;
XMVECTOR XM_CALLCONV XMQuaternionRotationMatrix(FXMMATRIX M) noexcept; XMVECTOR XM_CALLCONV XMQuaternionRotationMatrix(FXMMATRIX M) noexcept;
@ -1596,11 +1748,15 @@ namespace DirectX
XMVECTOR XM_CALLCONV XMPlaneNormalize(FXMVECTOR P) noexcept; XMVECTOR XM_CALLCONV XMPlaneNormalize(FXMVECTOR P) noexcept;
XMVECTOR XM_CALLCONV XMPlaneIntersectLine(FXMVECTOR P, FXMVECTOR LinePoint1, FXMVECTOR LinePoint2) noexcept; XMVECTOR XM_CALLCONV XMPlaneIntersectLine(FXMVECTOR P, FXMVECTOR LinePoint1, FXMVECTOR LinePoint2) noexcept;
void XM_CALLCONV XMPlaneIntersectPlane(_Out_ XMVECTOR* pLinePoint1, _Out_ XMVECTOR* pLinePoint2, _In_ FXMVECTOR P1, _In_ FXMVECTOR P2) noexcept; void XM_CALLCONV XMPlaneIntersectPlane(_Out_ XMVECTOR* pLinePoint1, _Out_ XMVECTOR* pLinePoint2, _In_ FXMVECTOR P1, _In_ FXMVECTOR P2) noexcept;
XMVECTOR XM_CALLCONV XMPlaneTransform(FXMVECTOR P, FXMMATRIX M) noexcept;
// Transforms a plane given an inverse transpose matrix
XMVECTOR XM_CALLCONV XMPlaneTransform(FXMVECTOR P, FXMMATRIX ITM) noexcept;
// Transforms an array of planes given an inverse transpose matrix
XMFLOAT4* XM_CALLCONV XMPlaneTransformStream(_Out_writes_bytes_(sizeof(XMFLOAT4) + OutputStride * (PlaneCount - 1)) XMFLOAT4* pOutputStream, XMFLOAT4* XM_CALLCONV XMPlaneTransformStream(_Out_writes_bytes_(sizeof(XMFLOAT4) + OutputStride * (PlaneCount - 1)) XMFLOAT4* pOutputStream,
_In_ size_t OutputStride, _In_ size_t OutputStride,
_In_reads_bytes_(sizeof(XMFLOAT4) + InputStride * (PlaneCount - 1)) const XMFLOAT4* pInputStream, _In_reads_bytes_(sizeof(XMFLOAT4) + InputStride * (PlaneCount - 1)) const XMFLOAT4* pInputStream,
_In_ size_t InputStride, _In_ size_t PlaneCount, _In_ FXMMATRIX M) noexcept; _In_ size_t InputStride, _In_ size_t PlaneCount, _In_ FXMMATRIX ITM) noexcept;
XMVECTOR XM_CALLCONV XMPlaneFromPointNormal(FXMVECTOR Point, FXMVECTOR Normal) noexcept; XMVECTOR XM_CALLCONV XMPlaneFromPointNormal(FXMVECTOR Point, FXMVECTOR Normal) noexcept;
XMVECTOR XM_CALLCONV XMPlaneFromPoints(FXMVECTOR Point1, FXMVECTOR Point2, FXMVECTOR Point3) noexcept; XMVECTOR XM_CALLCONV XMPlaneFromPoints(FXMVECTOR Point1, FXMVECTOR Point2, FXMVECTOR Point3) noexcept;
@ -1638,6 +1794,9 @@ namespace DirectX
XMVECTOR XM_CALLCONV XMColorRGBToYUV_HD(FXMVECTOR rgb) noexcept; XMVECTOR XM_CALLCONV XMColorRGBToYUV_HD(FXMVECTOR rgb) noexcept;
XMVECTOR XM_CALLCONV XMColorYUVToRGB_HD(FXMVECTOR yuv) noexcept; XMVECTOR XM_CALLCONV XMColorYUVToRGB_HD(FXMVECTOR yuv) noexcept;
XMVECTOR XM_CALLCONV XMColorRGBToYUV_UHD(FXMVECTOR rgb) noexcept;
XMVECTOR XM_CALLCONV XMColorYUVToRGB_UHD(FXMVECTOR yuv) noexcept;
XMVECTOR XM_CALLCONV XMColorRGBToXYZ(FXMVECTOR rgb) noexcept; XMVECTOR XM_CALLCONV XMColorRGBToXYZ(FXMVECTOR rgb) noexcept;
XMVECTOR XM_CALLCONV XMColorXYZToRGB(FXMVECTOR xyz) noexcept; XMVECTOR XM_CALLCONV XMColorXYZToRGB(FXMVECTOR xyz) noexcept;
@ -1687,15 +1846,15 @@ namespace DirectX
#undef XMMax #undef XMMax
#endif #endif
template<class T> inline T XMMin(T a, T b) { return (a < b) ? a : b; } template<class T> inline T XMMin(T a, T b) noexcept { return (a < b) ? a : b; }
template<class T> inline T XMMax(T a, T b) { return (a > b) ? a : b; } template<class T> inline T XMMax(T a, T b) noexcept { return (a > b) ? a : b; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
// PermuteHelper internal template (SSE only) // PermuteHelper internal template (SSE only)
namespace Internal namespace MathInternal
{ {
// Slow path fallback for permutes that do not map to a single SSE shuffle opcode. // Slow path fallback for permutes that do not map to a single SSE shuffle opcode.
template<uint32_t Shuffle, bool WhichX, bool WhichY, bool WhichZ, bool WhichW> struct PermuteHelper template<uint32_t Shuffle, bool WhichX, bool WhichY, bool WhichZ, bool WhichW> struct PermuteHelper
@ -1757,14 +1916,14 @@ namespace DirectX
static_assert(PermuteW <= 7, "PermuteW template parameter out of range"); static_assert(PermuteW <= 7, "PermuteW template parameter out of range");
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
const uint32_t Shuffle = _MM_SHUFFLE(PermuteW & 3, PermuteZ & 3, PermuteY & 3, PermuteX & 3); constexpr uint32_t Shuffle = _MM_SHUFFLE(PermuteW & 3, PermuteZ & 3, PermuteY & 3, PermuteX & 3);
const bool WhichX = PermuteX > 3; constexpr bool WhichX = PermuteX > 3;
const bool WhichY = PermuteY > 3; constexpr bool WhichY = PermuteY > 3;
const bool WhichZ = PermuteZ > 3; constexpr bool WhichZ = PermuteZ > 3;
const bool WhichW = PermuteW > 3; constexpr bool WhichW = PermuteW > 3;
return Internal::PermuteHelper<Shuffle, WhichX, WhichY, WhichZ, WhichW>::Permute(V1, V2); return MathInternal::PermuteHelper<Shuffle, WhichX, WhichY, WhichZ, WhichW>::Permute(V1, V2);
#else #else
return XMVectorPermute(V1, V2, PermuteX, PermuteY, PermuteZ, PermuteW); return XMVectorPermute(V1, V2, PermuteX, PermuteY, PermuteZ, PermuteW);
@ -1773,8 +1932,8 @@ namespace DirectX
} }
// Special-case permute templates // Special-case permute templates
template<> inline XMVECTOR XM_CALLCONV XMVectorPermute<0, 1, 2, 3>(FXMVECTOR V1, FXMVECTOR) noexcept { return V1; } template<> constexpr XMVECTOR XM_CALLCONV XMVectorPermute<0, 1, 2, 3>(FXMVECTOR V1, FXMVECTOR) noexcept { return V1; }
template<> inline XMVECTOR XM_CALLCONV XMVectorPermute<4, 5, 6, 7>(FXMVECTOR, FXMVECTOR V2) noexcept { return V2; } template<> constexpr XMVECTOR XM_CALLCONV XMVectorPermute<4, 5, 6, 7>(FXMVECTOR, FXMVECTOR V2) noexcept { return V2; }
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
template<> inline XMVECTOR XM_CALLCONV XMVectorPermute<0, 1, 4, 5>(FXMVECTOR V1, FXMVECTOR V2) noexcept { return _mm_movelh_ps(V1, V2); } template<> inline XMVECTOR XM_CALLCONV XMVectorPermute<0, 1, 4, 5>(FXMVECTOR V1, FXMVECTOR V2) noexcept { return _mm_movelh_ps(V1, V2); }
@ -1862,7 +2021,7 @@ namespace DirectX
} }
// Specialized swizzles // Specialized swizzles
template<> inline XMVECTOR XM_CALLCONV XMVectorSwizzle<0, 1, 2, 3>(FXMVECTOR V) noexcept { return V; } template<> constexpr XMVECTOR XM_CALLCONV XMVectorSwizzle<0, 1, 2, 3>(FXMVECTOR V) noexcept { return V; }
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
template<> inline XMVECTOR XM_CALLCONV XMVectorSwizzle<0, 1, 0, 1>(FXMVECTOR V) noexcept { return _mm_movelh_ps(V, V); } template<> inline XMVECTOR XM_CALLCONV XMVectorSwizzle<0, 1, 0, 1>(FXMVECTOR V) noexcept { return _mm_movelh_ps(V, V); }
@ -1960,7 +2119,9 @@ namespace DirectX
// separate math routine it would be reloaded. // separate math routine it would be reloaded.
#ifndef XMGLOBALCONST #ifndef XMGLOBALCONST
#if defined(__GNUC__) && !defined(__MINGW32__) #if __cplusplus >= 201703L
#define XMGLOBALCONST inline constexpr
#elif defined(__GNUC__) && !defined(__MINGW32__)
#define XMGLOBALCONST extern const __attribute__((weak)) #define XMGLOBALCONST extern const __attribute__((weak))
#else #else
#define XMGLOBALCONST extern const __declspec(selectany) #define XMGLOBALCONST extern const __declspec(selectany)
@ -2101,6 +2262,8 @@ namespace DirectX
XMGLOBALCONST XMVECTORF32 g_XMLogEst7 = { { { -0.010578f, -0.010578f, -0.010578f, -0.010578f } } }; XMGLOBALCONST XMVECTORF32 g_XMLogEst7 = { { { -0.010578f, -0.010578f, -0.010578f, -0.010578f } } };
XMGLOBALCONST XMVECTORF32 g_XMLgE = { { { +1.442695f, +1.442695f, +1.442695f, +1.442695f } } }; XMGLOBALCONST XMVECTORF32 g_XMLgE = { { { +1.442695f, +1.442695f, +1.442695f, +1.442695f } } };
XMGLOBALCONST XMVECTORF32 g_XMInvLgE = { { { +6.93147182e-1f, +6.93147182e-1f, +6.93147182e-1f, +6.93147182e-1f } } }; XMGLOBALCONST XMVECTORF32 g_XMInvLgE = { { { +6.93147182e-1f, +6.93147182e-1f, +6.93147182e-1f, +6.93147182e-1f } } };
XMGLOBALCONST XMVECTORF32 g_XMLg10 = { { { +3.321928f, +3.321928f, +3.321928f, +3.321928f } } };
XMGLOBALCONST XMVECTORF32 g_XMInvLg10 = { { { +3.010299956e-1f, +3.010299956e-1f, +3.010299956e-1f, +3.010299956e-1f } } };
XMGLOBALCONST XMVECTORF32 g_UByteMax = { { { 255.0f, 255.0f, 255.0f, 255.0f } } }; XMGLOBALCONST XMVECTORF32 g_UByteMax = { { { 255.0f, 255.0f, 255.0f, 255.0f } } };
XMGLOBALCONST XMVECTORF32 g_ByteMin = { { { -127.0f, -127.0f, -127.0f, -127.0f } } }; XMGLOBALCONST XMVECTORF32 g_ByteMin = { { { -127.0f, -127.0f, -127.0f, -127.0f } } };
XMGLOBALCONST XMVECTORF32 g_ByteMax = { { { 127.0f, 127.0f, 127.0f, 127.0f } } }; XMGLOBALCONST XMVECTORF32 g_ByteMax = { { { 127.0f, 127.0f, 127.0f, 127.0f } } };
@ -2114,12 +2277,14 @@ namespace DirectX
* *
****************************************************************************/ ****************************************************************************/
#ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4068 4214 4204 4365 4616 4640 6001 6101) #pragma warning(disable:4068 4214 4204 4365 4616 4640 6001 6101)
// C4068/4616: ignore unknown pragmas // C4068/4616: ignore unknown pragmas
// C4214/4204: nonstandard extension used // C4214/4204: nonstandard extension used
// C4365/4640: Off by default noise // C4365/4640: Off by default noise
// C6001/6101: False positives // C6001/6101: False positives
#endif
#ifdef _PREFAST_ #ifdef _PREFAST_
#pragma prefast(push) #pragma prefast(push)
@ -2129,7 +2294,10 @@ namespace DirectX
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wundefined-reinterpret-cast" #pragma clang diagnostic ignored "-Wundefined-reinterpret-cast"
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif #endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -2185,7 +2353,7 @@ namespace DirectX
// Convert DivExponent into 1.0f/(1<<DivExponent) // Convert DivExponent into 1.0f/(1<<DivExponent)
uint32_t uScale = 0x3F800000U - (DivExponent << 23); uint32_t uScale = 0x3F800000U - (DivExponent << 23);
// Splat the scalar value (It's really a float) // Splat the scalar value (It's really a float)
vScale = vdupq_n_u32(uScale); vScale = vreinterpretq_s32_u32(vdupq_n_u32(uScale));
// Multiply by the reciprocal (Perform a right shift by DivExponent) // Multiply by the reciprocal (Perform a right shift by DivExponent)
vResult = vmulq_f32(vResult, reinterpret_cast<const float32x4_t*>(&vScale)[0]); vResult = vmulq_f32(vResult, reinterpret_cast<const float32x4_t*>(&vScale)[0]);
return vResult; return vResult;
@ -2223,25 +2391,21 @@ namespace DirectX
#endif #endif
} }
#include "directxmath/directxmathconvert.inl" #include "DirectXMathConvert.inl"
#include "directxmath/directxmathvector.inl" #include "DirectXMathVector.inl"
#include "directxmath/directxmathmatrix.inl" #include "DirectXMathMatrix.inl"
#include "directxmath/directxmathmisc.inl" #include "DirectXMathMisc.inl"
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
#ifdef _PREFAST_ #ifdef _PREFAST_
#pragma prefast(pop) #pragma prefast(pop)
#endif #endif
#ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif
} // namespace DirectX } // namespace DirectX
using namespace DirectX; using namespace DirectX;
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

View File

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// DirectXMathConvert.inl -- SIMD C++ Math library // DirectXMathConvert.inl -- SIMD C++ Math library
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
// //
// http://go.microsoft.com/fwlink/?LinkID=615560 // https://go.microsoft.com/fwlink/?LinkID=615560
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#pragma once #pragma once
@ -17,9 +17,11 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4701) #pragma warning(disable:4701)
// C4701: false positives // C4701: false positives
#endif
inline XMVECTOR XM_CALLCONV XMConvertVectorIntToFloat inline XMVECTOR XM_CALLCONV XMConvertVectorIntToFloat
( (
@ -32,14 +34,16 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorIntToFloat
float fScale = 1.0f / static_cast<float>(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
auto iTemp = static_cast<int32_t>(VInt.vector4_u32[ElementIndex]); auto iTemp = static_cast<int32_t>(VInt.vector4_u32[ElementIndex]);
Result.vector4_f32[ElementIndex] = static_cast<float>(iTemp)* fScale; Result.vector4_f32[ElementIndex] = static_cast<float>(iTemp)* fScale;
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fScale = 1.0f / (float)(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
float32x4_t vResult = vcvtq_f32_s32(VInt); float32x4_t vResult = vcvtq_f32_s32(vreinterpretq_s32_f32(VInt));
return vmulq_n_f32(vResult, fScale); return vmulq_n_f32(vResult, fScale);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
// Convert to floats // Convert to floats
@ -67,7 +71,8 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToInt
auto fScale = static_cast<float>(1U << MulExponent); auto fScale = static_cast<float>(1U << MulExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
int32_t iResult; int32_t iResult;
float fTemp = VFloat.vector4_f32[ElementIndex] * fScale; float fTemp = VFloat.vector4_f32[ElementIndex] * fScale;
if (fTemp <= -(65536.0f * 32768.0f)) if (fTemp <= -(65536.0f * 32768.0f))
@ -78,23 +83,25 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToInt
{ {
iResult = 0x7FFFFFFF; iResult = 0x7FFFFFFF;
} }
else { else
{
iResult = static_cast<int32_t>(fTemp); iResult = static_cast<int32_t>(fTemp);
} }
Result.vector4_u32[ElementIndex] = static_cast<uint32_t>(iResult); Result.vector4_u32[ElementIndex] = static_cast<uint32_t>(iResult);
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x4_t vResult = vmulq_n_f32(VFloat, (float)(1U << MulExponent)); float32x4_t vResult = vmulq_n_f32(VFloat, static_cast<float>(1U << MulExponent));
// In case of positive overflow, detect it // In case of positive overflow, detect it
uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxInt); uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxInt);
// Float to int conversion // Float to int conversion
int32x4_t vResulti = vcvtq_s32_f32(vResult); int32x4_t vResulti = vcvtq_s32_f32(vResult);
// If there was positive overflow, set to 0x7FFFFFFF // If there was positive overflow, set to 0x7FFFFFFF
vResult = vandq_u32(vOverflow, g_XMAbsMask); vResult = vreinterpretq_f32_u32(vandq_u32(vOverflow, g_XMAbsMask));
vOverflow = vbicq_u32(vResulti, vOverflow); vOverflow = vbicq_u32(vreinterpretq_u32_s32(vResulti), vOverflow);
vOverflow = vorrq_u32(vOverflow, vResult); vOverflow = vorrq_u32(vOverflow, vreinterpretq_u32_f32(vResult));
return vOverflow; return vreinterpretq_f32_u32(vOverflow);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent)); XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent));
vResult = _mm_mul_ps(vResult, VFloat); vResult = _mm_mul_ps(vResult, VFloat);
@ -123,13 +130,15 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorUIntToFloat
float fScale = 1.0f / static_cast<float>(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
Result.vector4_f32[ElementIndex] = static_cast<float>(VUInt.vector4_u32[ElementIndex])* fScale; Result.vector4_f32[ElementIndex] = static_cast<float>(VUInt.vector4_u32[ElementIndex])* fScale;
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fScale = 1.0f / (float)(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
float32x4_t vResult = vcvtq_f32_u32(VUInt); float32x4_t vResult = vcvtq_f32_u32(vreinterpretq_u32_f32(VUInt));
return vmulq_n_f32(vResult, fScale); return vmulq_n_f32(vResult, fScale);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
// For the values that are higher than 0x7FFFFFFF, a fixup is needed // For the values that are higher than 0x7FFFFFFF, a fixup is needed
@ -167,7 +176,8 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt
auto fScale = static_cast<float>(1U << MulExponent); auto fScale = static_cast<float>(1U << MulExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
uint32_t uResult; uint32_t uResult;
float fTemp = VFloat.vector4_f32[ElementIndex] * fScale; float fTemp = VFloat.vector4_f32[ElementIndex] * fScale;
if (fTemp <= 0.0f) if (fTemp <= 0.0f)
@ -178,22 +188,24 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt
{ {
uResult = 0xFFFFFFFFU; uResult = 0xFFFFFFFFU;
} }
else { else
{
uResult = static_cast<uint32_t>(fTemp); uResult = static_cast<uint32_t>(fTemp);
} }
Result.vector4_u32[ElementIndex] = uResult; Result.vector4_u32[ElementIndex] = uResult;
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x4_t vResult = vmulq_n_f32(VFloat, (float)(1U << MulExponent)); float32x4_t vResult = vmulq_n_f32(VFloat, static_cast<float>(1U << MulExponent));
// In case of overflow, detect it // In case of overflow, detect it
uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxUInt); uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxUInt);
// Float to int conversion // Float to int conversion
uint32x4_t vResulti = vcvtq_u32_f32(vResult); uint32x4_t vResulti = vcvtq_u32_f32(vResult);
// If there was overflow, set to 0xFFFFFFFFU // If there was overflow, set to 0xFFFFFFFFU
vResult = vbicq_u32(vResulti, vOverflow); vResult = vreinterpretq_f32_u32(vbicq_u32(vResulti, vOverflow));
vOverflow = vorrq_u32(vOverflow, vResult); vOverflow = vorrq_u32(vOverflow, vreinterpretq_u32_f32(vResult));
return vOverflow; return vreinterpretq_f32_u32(vOverflow);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent)); XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent));
vResult = _mm_mul_ps(vResult, VFloat); vResult = _mm_mul_ps(vResult, VFloat);
@ -218,7 +230,9 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt
#endif #endif
} }
#ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif
/**************************************************************************** /****************************************************************************
* *
@ -240,7 +254,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt(const uint32_t* pSource) noexcept
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x4_t zero = vdupq_n_u32(0); uint32x4_t zero = vdupq_n_u32(0);
return vld1q_lane_u32(pSource, zero, 0); return vreinterpretq_f32_u32(vld1q_lane_u32(pSource, zero, 0));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
return _mm_load_ss(reinterpret_cast<const float*>(pSource)); return _mm_load_ss(reinterpret_cast<const float*>(pSource));
#endif #endif
@ -281,7 +295,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt2(const uint32_t* pSource) noexcept
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t x = vld1_u32(pSource); uint32x2_t x = vld1_u32(pSource);
uint32x2_t zero = vdup_n_u32(0); uint32x2_t zero = vdup_n_u32(0);
return vcombine_u32(x, zero); return vreinterpretq_f32_u32(vcombine_u32(x, zero));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
#endif #endif
@ -301,13 +315,13 @@ inline XMVECTOR XM_CALLCONV XMLoadInt2A(const uint32_t* pSource) noexcept
V.vector4_u32[3] = 0; V.vector4_u32[3] = 0;
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
uint32x2_t x = vld1_u32_ex(pSource, 64); uint32x2_t x = vld1_u32_ex(pSource, 64);
#else #else
uint32x2_t x = vld1_u32(pSource); uint32x2_t x = vld1_u32(pSource);
#endif #endif
uint32x2_t zero = vdup_n_u32(0); uint32x2_t zero = vdup_n_u32(0);
return vcombine_u32(x, zero); return vreinterpretq_f32_u32(vcombine_u32(x, zero));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
#endif #endif
@ -348,7 +362,7 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat2A(const XMFLOAT2A* pSource) noexcept
V.vector4_f32[3] = 0.f; V.vector4_f32[3] = 0.f;
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x2_t x = vld1_f32_ex(reinterpret_cast<const float*>(pSource), 64); float32x2_t x = vld1_f32_ex(reinterpret_cast<const float*>(pSource), 64);
#else #else
float32x2_t x = vld1_f32(reinterpret_cast<const float*>(pSource)); float32x2_t x = vld1_f32(reinterpret_cast<const float*>(pSource));
@ -434,7 +448,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt3(const uint32_t* pSource) noexcept
uint32x2_t x = vld1_u32(pSource); uint32x2_t x = vld1_u32(pSource);
uint32x2_t zero = vdup_n_u32(0); uint32x2_t zero = vdup_n_u32(0);
uint32x2_t y = vld1_lane_u32(pSource + 2, zero, 0); uint32x2_t y = vld1_lane_u32(pSource + 2, zero, 0);
return vcombine_u32(x, y); return vreinterpretq_f32_u32(vcombine_u32(x, y));
#elif defined(_XM_SSE4_INTRINSICS_) #elif defined(_XM_SSE4_INTRINSICS_)
__m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); __m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
__m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2)); __m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2));
@ -461,12 +475,12 @@ inline XMVECTOR XM_CALLCONV XMLoadInt3A(const uint32_t* pSource) noexcept
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Reads an extra integer which is zero'd // Reads an extra integer which is zero'd
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
uint32x4_t V = vld1q_u32_ex(pSource, 128); uint32x4_t V = vld1q_u32_ex(pSource, 128);
#else #else
uint32x4_t V = vld1q_u32(pSource); uint32x4_t V = vld1q_u32(pSource);
#endif #endif
return vsetq_lane_u32(0, V, 3); return vreinterpretq_f32_u32(vsetq_lane_u32(0, V, 3));
#elif defined(_XM_SSE4_INTRINSICS_) #elif defined(_XM_SSE4_INTRINSICS_)
__m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); __m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
__m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2)); __m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2));
@ -521,12 +535,16 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat3A(const XMFLOAT3A* pSource) noexcept
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Reads an extra float which is zero'd // Reads an extra float which is zero'd
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x4_t V = vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128); float32x4_t V = vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128);
#else #else
float32x4_t V = vld1q_f32(reinterpret_cast<const float*>(pSource)); float32x4_t V = vld1q_f32(reinterpret_cast<const float*>(pSource));
#endif #endif
return vsetq_lane_f32(0, V, 3); return vsetq_lane_f32(0, V, 3);
#elif defined(_XM_SSE4_INTRINSICS_)
// Reads an extra float which is zero'd
__m128 V = _mm_load_ps(&pSource->x);
return _mm_blend_ps(_mm_setzero_ps(), V, 0x7);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Reads an extra float which is zero'd // Reads an extra float which is zero'd
__m128 V = _mm_load_ps(&pSource->x); __m128 V = _mm_load_ps(&pSource->x);
@ -614,7 +632,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt4(const uint32_t* pSource) noexcept
V.vector4_u32[3] = pSource[3]; V.vector4_u32[3] = pSource[3];
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
return vld1q_u32(pSource); return vreinterpretq_f32_u32(vld1q_u32(pSource));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
__m128i V = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pSource)); __m128i V = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pSource));
return _mm_castsi128_ps(V); return _mm_castsi128_ps(V);
@ -635,10 +653,10 @@ inline XMVECTOR XM_CALLCONV XMLoadInt4A(const uint32_t* pSource) noexcept
V.vector4_u32[3] = pSource[3]; V.vector4_u32[3] = pSource[3];
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
return vld1q_u32_ex(pSource, 128); return vld1q_u32_ex(pSource, 128);
#else #else
return vld1q_u32(pSource); return vreinterpretq_f32_u32(vld1q_u32(pSource));
#endif #endif
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
__m128i V = _mm_load_si128(reinterpret_cast<const __m128i*>(pSource)); __m128i V = _mm_load_si128(reinterpret_cast<const __m128i*>(pSource));
@ -679,7 +697,7 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat4A(const XMFLOAT4A* pSource) noexcept
V.vector4_f32[3] = pSource->w; V.vector4_f32[3] = pSource->w;
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
return vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128); return vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128);
#else #else
return vld1q_f32(reinterpret_cast<const float*>(pSource)); return vld1q_f32(reinterpret_cast<const float*>(pSource));
@ -780,8 +798,8 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x3(const XMFLOAT3X3* pSource) noexcept
float32x4_t T = vextq_f32(v0, v1, 3); float32x4_t T = vextq_f32(v0, v1, 3);
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(v0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(v0), g_XMMask3));
M.r[1] = vandq_u32(T, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T), g_XMMask3));
M.r[2] = vcombine_f32(vget_high_f32(v1), v2); M.r[2] = vcombine_f32(vget_high_f32(v1), v2);
M.r[3] = g_XMIdentityR3; M.r[3] = g_XMIdentityR3;
return M; return M;
@ -846,9 +864,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3(const XMFLOAT4X3* pSource) noexcept
float32x4_t T3 = vextq_f32(v2, v2, 1); float32x4_t T3 = vextq_f32(v2, v2, 1);
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(v0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(v0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -867,11 +885,18 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3(const XMFLOAT4X3* pSource) noexcept
// vTemp2 = x2,y2,z2,z2 // vTemp2 = x2,y2,z2,z2
vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2)); vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2));
// vTemp1 = x1,y1,z1,0 // vTemp1 = x1,y1,z1,0
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
// vTemp2 = x2,y2,z2,0 // vTemp2 = x2,y2,z2,0
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
// vTemp3 = x3,y3,z3,0 // vTemp3 = x3,y3,z3,0
#ifdef _XM_SSE4_INTRINSICS_
XMVECTOR zero = _mm_setzero_ps();
vTemp1 = _mm_blend_ps(zero, vTemp1, 0x7);
vTemp2 = _mm_blend_ps(zero, vTemp2, 0x7);
vTemp3 = _mm_blend_ps(zero, vTemp3, 0x7);
#else
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
vTemp3 = _mm_and_ps(vTemp3, g_XMMask3); vTemp3 = _mm_and_ps(vTemp3, g_XMMask3);
#endif
// vTemp4i = x4,y4,z4,0 // vTemp4i = x4,y4,z4,0
__m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8); __m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8);
// vTemp4i = x4,y4,z4,1.0f // vTemp4i = x4,y4,z4,1.0f
@ -915,7 +940,7 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3A(const XMFLOAT4X3A* pSource) noexcept
return M; return M;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x4_t v0 = vld1q_f32_ex(&pSource->m[0][0], 128); float32x4_t v0 = vld1q_f32_ex(&pSource->m[0][0], 128);
float32x4_t v1 = vld1q_f32_ex(&pSource->m[1][1], 128); float32x4_t v1 = vld1q_f32_ex(&pSource->m[1][1], 128);
float32x4_t v2 = vld1q_f32_ex(&pSource->m[2][2], 128); float32x4_t v2 = vld1q_f32_ex(&pSource->m[2][2], 128);
@ -930,9 +955,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3A(const XMFLOAT4X3A* pSource) noexcept
float32x4_t T3 = vextq_f32(v2, v2, 1); float32x4_t T3 = vextq_f32(v2, v2, 1);
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(v0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(v0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -951,11 +976,18 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3A(const XMFLOAT4X3A* pSource) noexcept
// vTemp2 = x2,y2,z2,z2 // vTemp2 = x2,y2,z2,z2
vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2)); vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2));
// vTemp1 = x1,y1,z1,0 // vTemp1 = x1,y1,z1,0
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
// vTemp2 = x2,y2,z2,0 // vTemp2 = x2,y2,z2,0
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
// vTemp3 = x3,y3,z3,0 // vTemp3 = x3,y3,z3,0
#ifdef _XM_SSE4_INTRINSICS_
XMVECTOR zero = _mm_setzero_ps();
vTemp1 = _mm_blend_ps(zero, vTemp1, 0x7);
vTemp2 = _mm_blend_ps(zero, vTemp2, 0x7);
vTemp3 = _mm_blend_ps(zero, vTemp3, 0x7);
#else
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
vTemp3 = _mm_and_ps(vTemp3, g_XMMask3); vTemp3 = _mm_and_ps(vTemp3, g_XMMask3);
#endif
// vTemp4i = x4,y4,z4,0 // vTemp4i = x4,y4,z4,0
__m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8); __m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8);
// vTemp4i = x4,y4,z4,1.0f // vTemp4i = x4,y4,z4,1.0f
@ -1012,9 +1044,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x4(const XMFLOAT3X4* pSource) noexcept
float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh); float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh);
XMMATRIX M = {}; XMMATRIX M = {};
M.r[0] = vandq_u32(T0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1077,7 +1109,7 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x4A(const XMFLOAT3X4A* pSource) noexcept
return M; return M;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x2x4_t vTemp0 = vld4_f32_ex(&pSource->_11, 128); float32x2x4_t vTemp0 = vld4_f32_ex(&pSource->_11, 128);
float32x4_t vTemp1 = vld1q_f32_ex(&pSource->_31, 128); float32x4_t vTemp1 = vld1q_f32_ex(&pSource->_31, 128);
#else #else
@ -1096,9 +1128,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x4A(const XMFLOAT3X4A* pSource) noexcept
float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh); float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh);
XMMATRIX M = {}; XMMATRIX M = {};
M.r[0] = vandq_u32(T0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1208,7 +1240,7 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x4A(const XMFLOAT4X4A* pSource) noexcept
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMMATRIX M; XMMATRIX M;
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
M.r[0] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_11), 128); M.r[0] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_11), 128);
M.r[1] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_21), 128); M.r[1] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_21), 128);
M.r[2] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_31), 128); M.r[2] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_31), 128);
@ -1283,7 +1315,7 @@ inline void XM_CALLCONV XMStoreInt2
pDestination[0] = V.vector4_u32[0]; pDestination[0] = V.vector4_u32[0];
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
_mm_store_sd(reinterpret_cast<double*>(pDestination), _mm_castps_pd(V)); _mm_store_sd(reinterpret_cast<double*>(pDestination), _mm_castps_pd(V));
@ -1304,8 +1336,8 @@ inline void XM_CALLCONV XMStoreInt2A
pDestination[0] = V.vector4_u32[0]; pDestination[0] = V.vector4_u32[0];
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_u32_ex(pDestination, VL, 64); vst1_u32_ex(pDestination, VL, 64);
#else #else
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
@ -1350,7 +1382,7 @@ inline void XM_CALLCONV XMStoreFloat2A
pDestination->y = V.vector4_f32[1]; pDestination->y = V.vector4_f32[1];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x2_t VL = vget_low_f32(V); float32x2_t VL = vget_low_f32(V);
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64); vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64);
#else #else
vst1_f32(reinterpret_cast<float*>(pDestination), VL); vst1_f32(reinterpret_cast<float*>(pDestination), VL);
@ -1373,9 +1405,9 @@ inline void XM_CALLCONV XMStoreSInt2
pDestination->x = static_cast<int32_t>(V.vector4_f32[0]); pDestination->x = static_cast<int32_t>(V.vector4_f32[0]);
pDestination->y = static_cast<int32_t>(V.vector4_f32[1]); pDestination->y = static_cast<int32_t>(V.vector4_f32[1]);
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
int32x2_t v = vget_low_s32(V); float32x2_t v = vget_low_f32(V);
v = vcvt_s32_f32(v); int32x2_t iv = vcvt_s32_f32(v);
vst1_s32(reinterpret_cast<int32_t*>(pDestination), v); vst1_s32(reinterpret_cast<int32_t*>(pDestination), iv);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// In case of positive overflow, detect it // In case of positive overflow, detect it
XMVECTOR vOverflow = _mm_cmpgt_ps(V, g_XMMaxInt); XMVECTOR vOverflow = _mm_cmpgt_ps(V, g_XMMaxInt);
@ -1443,7 +1475,7 @@ inline void XM_CALLCONV XMStoreInt3
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
vst1q_lane_u32(pDestination + 2, *reinterpret_cast<const uint32x4_t*>(&V), 2); vst1q_lane_u32(pDestination + 2, *reinterpret_cast<const uint32x4_t*>(&V), 2);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1468,8 +1500,8 @@ inline void XM_CALLCONV XMStoreInt3A
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_u32_ex(pDestination, VL, 64); vst1_u32_ex(pDestination, VL, 64);
#else #else
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
@ -1526,7 +1558,7 @@ inline void XM_CALLCONV XMStoreFloat3A
pDestination->z = V.vector4_f32[2]; pDestination->z = V.vector4_f32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x2_t VL = vget_low_f32(V); float32x2_t VL = vget_low_f32(V);
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64); vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64);
#else #else
vst1_f32(reinterpret_cast<float*>(pDestination), VL); vst1_f32(reinterpret_cast<float*>(pDestination), VL);
@ -1634,7 +1666,7 @@ inline void XM_CALLCONV XMStoreInt4
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
pDestination[3] = V.vector4_u32[3]; pDestination[3] = V.vector4_u32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
vst1q_u32(pDestination, V); vst1q_u32(pDestination, vreinterpretq_u32_f32(V));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
_mm_storeu_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V)); _mm_storeu_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V));
#endif #endif
@ -1656,10 +1688,10 @@ inline void XM_CALLCONV XMStoreInt4A
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
pDestination[3] = V.vector4_u32[3]; pDestination[3] = V.vector4_u32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_u32_ex(pDestination, V, 128); vst1q_u32_ex(pDestination, V, 128);
#else #else
vst1q_u32(pDestination, V); vst1q_u32(pDestination, vreinterpretq_u32_f32(V));
#endif #endif
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
_mm_store_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V)); _mm_store_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V));
@ -1703,7 +1735,7 @@ inline void XM_CALLCONV XMStoreFloat4A
pDestination->z = V.vector4_f32[2]; pDestination->z = V.vector4_f32[2];
pDestination->w = V.vector4_f32[3]; pDestination->w = V.vector4_f32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_f32_ex(reinterpret_cast<float*>(pDestination), V, 128); vst1q_f32_ex(reinterpret_cast<float*>(pDestination), V, 128);
#else #else
vst1q_f32(reinterpret_cast<float*>(pDestination), V); vst1q_f32(reinterpret_cast<float*>(pDestination), V);
@ -1913,7 +1945,7 @@ inline void XM_CALLCONV XMStoreFloat4x3A
pDestination->m[3][2] = M.r[3].vector4_f32[2]; pDestination->m[3][2] = M.r[3].vector4_f32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x4_t T1 = vextq_f32(M.r[0], M.r[1], 1); float32x4_t T1 = vextq_f32(M.r[0], M.r[1], 1);
float32x4_t T2 = vbslq_f32(g_XMMask3, M.r[0], T1); float32x4_t T2 = vbslq_f32(g_XMMask3, M.r[0], T1);
vst1q_f32_ex(&pDestination->m[0][0], T2, 128); vst1q_f32_ex(&pDestination->m[0][0], T2, 128);
@ -2057,7 +2089,7 @@ inline void XM_CALLCONV XMStoreFloat3x4A
float32x4x2_t T0 = vzipq_f32(P0.val[0], P1.val[0]); float32x4x2_t T0 = vzipq_f32(P0.val[0], P1.val[0]);
float32x4x2_t T1 = vzipq_f32(P0.val[1], P1.val[1]); float32x4x2_t T1 = vzipq_f32(P0.val[1], P1.val[1]);
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_f32_ex(&pDestination->m[0][0], T0.val[0], 128); vst1q_f32_ex(&pDestination->m[0][0], T0.val[0], 128);
vst1q_f32_ex(&pDestination->m[1][0], T0.val[1], 128); vst1q_f32_ex(&pDestination->m[1][0], T0.val[1], 128);
vst1q_f32_ex(&pDestination->m[2][0], T1.val[0], 128); vst1q_f32_ex(&pDestination->m[2][0], T1.val[0], 128);
@ -2166,7 +2198,7 @@ inline void XM_CALLCONV XMStoreFloat4x4A
pDestination->m[3][3] = M.r[3].vector4_f32[3]; pDestination->m[3][3] = M.r[3].vector4_f32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_11), M.r[0], 128); vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_11), M.r[0], 128);
vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_21), M.r[1], 128); vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_21), M.r[1], 128);
vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_31), M.r[2], 128); vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_31), M.r[2], 128);

View File

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// DirectXMathMatrix.inl -- SIMD C++ Math library // DirectXMathMatrix.inl -- SIMD C++ Math library
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
// //
// http://go.microsoft.com/fwlink/?LinkID=615560 // https://go.microsoft.com/fwlink/?LinkID=615560
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#pragma once #pragma once
@ -21,7 +21,7 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) #if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma float_control(push) #pragma float_control(push)
#pragma float_control(precise, on) #pragma float_control(precise, on)
#endif #endif
@ -32,7 +32,8 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept
#if defined(_XM_NO_INTRINSICS_) #if defined(_XM_NO_INTRINSICS_)
size_t i = 16; size_t i = 16;
auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]); auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]);
do { do
{
// Fetch value into integer unit // Fetch value into integer unit
uint32_t uTest = pWork[0]; uint32_t uTest = pWork[0];
// Remove sign // Remove sign
@ -44,27 +45,30 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept
break; // NaN found break; // NaN found
} }
++pWork; // Next entry ++pWork; // Next entry
} while (--i); }
while (--i);
return (i != 0); // i == 0 if nothing matched return (i != 0); // i == 0 if nothing matched
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Load in registers // Load in registers
XMVECTOR vX = M.r[0]; float32x4_t vX = M.r[0];
XMVECTOR vY = M.r[1]; float32x4_t vY = M.r[1];
XMVECTOR vZ = M.r[2]; float32x4_t vZ = M.r[2];
XMVECTOR vW = M.r[3]; float32x4_t vW = M.r[3];
// Test themselves to check for NaN // Test themselves to check for NaN
vX = vmvnq_u32(vceqq_f32(vX, vX)); uint32x4_t xmask = vmvnq_u32(vceqq_f32(vX, vX));
vY = vmvnq_u32(vceqq_f32(vY, vY)); uint32x4_t ymask = vmvnq_u32(vceqq_f32(vY, vY));
vZ = vmvnq_u32(vceqq_f32(vZ, vZ)); uint32x4_t zmask = vmvnq_u32(vceqq_f32(vZ, vZ));
vW = vmvnq_u32(vceqq_f32(vW, vW)); uint32x4_t wmask = vmvnq_u32(vceqq_f32(vW, vW));
// Or all the results // Or all the results
vX = vorrq_u32(vX, vZ); xmask = vorrq_u32(xmask, zmask);
vY = vorrq_u32(vY, vW); ymask = vorrq_u32(ymask, wmask);
vX = vorrq_u32(vX, vY); xmask = vorrq_u32(xmask, ymask);
// If any tested true, return true // If any tested true, return true
uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vX), vget_high_u8(vX)); uint8x8x2_t vTemp = vzip_u8(
uint16x4x2_t vTemp2 = vzip_u16(vTemp.val[0], vTemp.val[1]); vget_low_u8(vreinterpretq_u8_u32(xmask)),
uint32_t r = vget_lane_u32(vTemp2.val[1], 1); vget_high_u8(vreinterpretq_u8_u32(xmask)));
uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1]));
uint32_t r = vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1);
return (r != 0); return (r != 0);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Load in registers // Load in registers
@ -87,7 +91,7 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept
#endif #endif
} }
#if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) #if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma float_control(pop) #pragma float_control(pop)
#endif #endif
@ -99,7 +103,8 @@ inline bool XM_CALLCONV XMMatrixIsInfinite(FXMMATRIX M) noexcept
#if defined(_XM_NO_INTRINSICS_) #if defined(_XM_NO_INTRINSICS_)
size_t i = 16; size_t i = 16;
auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]); auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]);
do { do
{
// Fetch value into integer unit // Fetch value into integer unit
uint32_t uTest = pWork[0]; uint32_t uTest = pWork[0];
// Remove sign // Remove sign
@ -110,27 +115,35 @@ inline bool XM_CALLCONV XMMatrixIsInfinite(FXMMATRIX M) noexcept
break; // INF found break; // INF found
} }
++pWork; // Next entry ++pWork; // Next entry
} while (--i); }
while (--i);
return (i != 0); // i == 0 if nothing matched return (i != 0); // i == 0 if nothing matched
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Load in registers
float32x4_t vX = M.r[0];
float32x4_t vY = M.r[1];
float32x4_t vZ = M.r[2];
float32x4_t vW = M.r[3];
// Mask off the sign bits // Mask off the sign bits
XMVECTOR vTemp1 = vandq_u32(M.r[0], g_XMAbsMask); vX = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vX), g_XMAbsMask));
XMVECTOR vTemp2 = vandq_u32(M.r[1], g_XMAbsMask); vY = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vY), g_XMAbsMask));
XMVECTOR vTemp3 = vandq_u32(M.r[2], g_XMAbsMask); vZ = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vZ), g_XMAbsMask));
XMVECTOR vTemp4 = vandq_u32(M.r[3], g_XMAbsMask); vW = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vW), g_XMAbsMask));
// Compare to infinity // Compare to infinity
vTemp1 = vceqq_f32(vTemp1, g_XMInfinity); uint32x4_t xmask = vceqq_f32(vX, g_XMInfinity);
vTemp2 = vceqq_f32(vTemp2, g_XMInfinity); uint32x4_t ymask = vceqq_f32(vY, g_XMInfinity);
vTemp3 = vceqq_f32(vTemp3, g_XMInfinity); uint32x4_t zmask = vceqq_f32(vZ, g_XMInfinity);
vTemp4 = vceqq_f32(vTemp4, g_XMInfinity); uint32x4_t wmask = vceqq_f32(vW, g_XMInfinity);
// Or the answers together // Or the answers together
vTemp1 = vorrq_u32(vTemp1, vTemp2); xmask = vorrq_u32(xmask, zmask);
vTemp3 = vorrq_u32(vTemp3, vTemp4); ymask = vorrq_u32(ymask, wmask);
vTemp1 = vorrq_u32(vTemp1, vTemp3); xmask = vorrq_u32(xmask, ymask);
// If any are infinity, the signs are true. // If any tested true, return true
uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vTemp1), vget_high_u8(vTemp1)); uint8x8x2_t vTemp = vzip_u8(
uint16x4x2_t vTemp5 = vzip_u16(vTemp.val[0], vTemp.val[1]); vget_low_u8(vreinterpretq_u8_u32(xmask)),
uint32_t r = vget_lane_u32(vTemp5.val[1], 1); vget_high_u8(vreinterpretq_u8_u32(xmask)));
uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1]));
uint32_t r = vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1);
return (r != 0); return (r != 0);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Mask off the sign bits // Mask off the sign bits
@ -187,16 +200,16 @@ inline bool XM_CALLCONV XMMatrixIsIdentity(FXMMATRIX M) noexcept
uOne |= uZero; uOne |= uZero;
return (uOne == 0); return (uOne == 0);
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMVECTOR vTemp1 = vceqq_f32(M.r[0], g_XMIdentityR0); uint32x4_t xmask = vceqq_f32(M.r[0], g_XMIdentityR0);
XMVECTOR vTemp2 = vceqq_f32(M.r[1], g_XMIdentityR1); uint32x4_t ymask = vceqq_f32(M.r[1], g_XMIdentityR1);
XMVECTOR vTemp3 = vceqq_f32(M.r[2], g_XMIdentityR2); uint32x4_t zmask = vceqq_f32(M.r[2], g_XMIdentityR2);
XMVECTOR vTemp4 = vceqq_f32(M.r[3], g_XMIdentityR3); uint32x4_t wmask = vceqq_f32(M.r[3], g_XMIdentityR3);
vTemp1 = vandq_u32(vTemp1, vTemp2); xmask = vandq_u32(xmask, zmask);
vTemp3 = vandq_u32(vTemp3, vTemp4); ymask = vandq_u32(ymask, wmask);
vTemp1 = vandq_u32(vTemp1, vTemp3); xmask = vandq_u32(xmask, ymask);
uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vTemp1), vget_high_u8(vTemp1)); uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vreinterpretq_u8_u32(xmask)), vget_high_u8(vreinterpretq_u8_u32(xmask)));
uint16x4x2_t vTemp5 = vzip_u16(vTemp.val[0], vTemp.val[1]); uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1]));
uint32_t r = vget_lane_u32(vTemp5.val[1], 1); uint32_t r = vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1);
return (r == 0xFFFFFFFFU); return (r == 0xFFFFFFFFU);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
XMVECTOR vTemp1 = _mm_cmpeq_ps(M.r[0], g_XMIdentityR0); XMVECTOR vTemp1 = _mm_cmpeq_ps(M.r[0], g_XMIdentityR0);
@ -265,10 +278,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixMultiply
float32x2_t VL = vget_low_f32(M1.r[0]); float32x2_t VL = vget_low_f32(M1.r[0]);
float32x2_t VH = vget_high_f32(M1.r[0]); float32x2_t VH = vget_high_f32(M1.r[0]);
// Perform the operation on the first row // Perform the operation on the first row
XMVECTOR vX = vmulq_lane_f32(M2.r[0], VL, 0); float32x4_t vX = vmulq_lane_f32(M2.r[0], VL, 0);
XMVECTOR vY = vmulq_lane_f32(M2.r[1], VL, 1); float32x4_t vY = vmulq_lane_f32(M2.r[1], VL, 1);
XMVECTOR vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0); float32x4_t vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0);
XMVECTOR vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1); float32x4_t vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1);
mResult.r[0] = vaddq_f32(vZ, vW); mResult.r[0] = vaddq_f32(vZ, vW);
// Repeat for the other 3 rows // Repeat for the other 3 rows
VL = vget_low_f32(M1.r[1]); VL = vget_low_f32(M1.r[1]);
@ -478,10 +491,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixMultiplyTranspose
float32x2_t VL = vget_low_f32(M1.r[0]); float32x2_t VL = vget_low_f32(M1.r[0]);
float32x2_t VH = vget_high_f32(M1.r[0]); float32x2_t VH = vget_high_f32(M1.r[0]);
// Perform the operation on the first row // Perform the operation on the first row
XMVECTOR vX = vmulq_lane_f32(M2.r[0], VL, 0); float32x4_t vX = vmulq_lane_f32(M2.r[0], VL, 0);
XMVECTOR vY = vmulq_lane_f32(M2.r[1], VL, 1); float32x4_t vY = vmulq_lane_f32(M2.r[1], VL, 1);
XMVECTOR vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0); float32x4_t vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0);
XMVECTOR vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1); float32x4_t vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1);
float32x4_t r0 = vaddq_f32(vZ, vW); float32x4_t r0 = vaddq_f32(vZ, vW);
// Repeat for the other 3 rows // Repeat for the other 3 rows
VL = vget_low_f32(M1.r[1]); VL = vget_low_f32(M1.r[1]);
@ -1403,9 +1416,9 @@ inline XMMATRIX XM_CALLCONV XMMatrixScalingFromVector(FXMVECTOR Scale) noexcept
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(Scale, g_XMMaskX); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(Scale), g_XMMaskX));
M.r[1] = vandq_u32(Scale, g_XMMaskY); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(Scale), g_XMMaskY));
M.r[2] = vandq_u32(Scale, g_XMMaskZ); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(Scale), g_XMMaskZ));
M.r[3] = g_XMIdentityR3.v; M.r[3] = g_XMIdentityR3.v;
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1455,12 +1468,12 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationX(float Angle) noexcept
float fCosAngle; float fCosAngle;
XMScalarSinCos(&fSinAngle, &fCosAngle, Angle); XMScalarSinCos(&fSinAngle, &fCosAngle, Angle);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMVECTOR T1 = vsetq_lane_f32(fCosAngle, Zero, 1); float32x4_t T1 = vsetq_lane_f32(fCosAngle, Zero, 1);
T1 = vsetq_lane_f32(fSinAngle, T1, 2); T1 = vsetq_lane_f32(fSinAngle, T1, 2);
XMVECTOR T2 = vsetq_lane_f32(-fSinAngle, Zero, 1); float32x4_t T2 = vsetq_lane_f32(-fSinAngle, Zero, 1);
T2 = vsetq_lane_f32(fCosAngle, T2, 2); T2 = vsetq_lane_f32(fCosAngle, T2, 2);
XMMATRIX M; XMMATRIX M;
@ -1528,12 +1541,12 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationY(float Angle) noexcept
float fCosAngle; float fCosAngle;
XMScalarSinCos(&fSinAngle, &fCosAngle, Angle); XMScalarSinCos(&fSinAngle, &fCosAngle, Angle);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMVECTOR T0 = vsetq_lane_f32(fCosAngle, Zero, 0); float32x4_t T0 = vsetq_lane_f32(fCosAngle, Zero, 0);
T0 = vsetq_lane_f32(-fSinAngle, T0, 2); T0 = vsetq_lane_f32(-fSinAngle, T0, 2);
XMVECTOR T2 = vsetq_lane_f32(fSinAngle, Zero, 0); float32x4_t T2 = vsetq_lane_f32(fSinAngle, Zero, 0);
T2 = vsetq_lane_f32(fCosAngle, T2, 2); T2 = vsetq_lane_f32(fCosAngle, T2, 2);
XMMATRIX M; XMMATRIX M;
@ -1601,12 +1614,12 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationZ(float Angle) noexcept
float fCosAngle; float fCosAngle;
XMScalarSinCos(&fSinAngle, &fCosAngle, Angle); XMScalarSinCos(&fSinAngle, &fCosAngle, Angle);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMVECTOR T0 = vsetq_lane_f32(fCosAngle, Zero, 0); float32x4_t T0 = vsetq_lane_f32(fCosAngle, Zero, 0);
T0 = vsetq_lane_f32(fSinAngle, T0, 1); T0 = vsetq_lane_f32(fSinAngle, T0, 1);
XMVECTOR T1 = vsetq_lane_f32(-fSinAngle, Zero, 0); float32x4_t T1 = vsetq_lane_f32(-fSinAngle, Zero, 0);
T1 = vsetq_lane_f32(fCosAngle, T1, 1); T1 = vsetq_lane_f32(fCosAngle, T1, 1);
XMMATRIX M; XMMATRIX M;
@ -1646,8 +1659,41 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYaw
float Roll float Roll
) noexcept ) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_)
float cp = cosf(Pitch);
float sp = sinf(Pitch);
float cy = cosf(Yaw);
float sy = sinf(Yaw);
float cr = cosf(Roll);
float sr = sinf(Roll);
XMMATRIX M;
M.m[0][0] = cr * cy + sr * sp * sy;
M.m[0][1] = sr * cp;
M.m[0][2] = sr * sp * cy - cr * sy;
M.m[0][3] = 0.0f;
M.m[1][0] = cr * sp * sy - sr * cy;
M.m[1][1] = cr * cp;
M.m[1][2] = sr * sy + cr * sp * cy;
M.m[1][3] = 0.0f;
M.m[2][0] = cp * sy;
M.m[2][1] = -sp;
M.m[2][2] = cp * cy;
M.m[2][3] = 0.0f;
M.m[3][0] = 0.0f;
M.m[3][1] = 0.0f;
M.m[3][2] = 0.0f;
M.m[3][3] = 1.0f;
return M;
#else
XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f); XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f);
return XMMatrixRotationRollPitchYawFromVector(Angles); return XMMatrixRotationRollPitchYawFromVector(Angles);
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1657,8 +1703,69 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYawFromVector
FXMVECTOR Angles // <Pitch, Yaw, Roll, undefined> FXMVECTOR Angles // <Pitch, Yaw, Roll, undefined>
) noexcept ) noexcept
{ {
XMVECTOR Q = XMQuaternionRotationRollPitchYawFromVector(Angles); #if defined(_XM_NO_INTRINSICS_)
return XMMatrixRotationQuaternion(Q); float cp = cosf(Angles.vector4_f32[0]);
float sp = sinf(Angles.vector4_f32[0]);
float cy = cosf(Angles.vector4_f32[1]);
float sy = sinf(Angles.vector4_f32[1]);
float cr = cosf(Angles.vector4_f32[2]);
float sr = sinf(Angles.vector4_f32[2]);
XMMATRIX M;
M.m[0][0] = cr * cy + sr * sp * sy;
M.m[0][1] = sr * cp;
M.m[0][2] = sr * sp * cy - cr * sy;
M.m[0][3] = 0.0f;
M.m[1][0] = cr * sp * sy - sr * cy;
M.m[1][1] = cr * cp;
M.m[1][2] = sr * sy + cr * sp * cy;
M.m[1][3] = 0.0f;
M.m[2][0] = cp * sy;
M.m[2][1] = -sp;
M.m[2][2] = cp * cy;
M.m[2][3] = 0.0f;
M.m[3][0] = 0.0f;
M.m[3][1] = 0.0f;
M.m[3][2] = 0.0f;
M.m[3][3] = 1.0f;
return M;
#else
static const XMVECTORF32 Sign = { { { 1.0f, -1.0f, -1.0f, 1.0f } } };
XMVECTOR SinAngles, CosAngles;
XMVectorSinCos(&SinAngles, &CosAngles, Angles);
XMVECTOR P0 = XMVectorPermute<XM_PERMUTE_1X, XM_PERMUTE_0Z, XM_PERMUTE_1Z, XM_PERMUTE_1X>(SinAngles, CosAngles);
XMVECTOR Y0 = XMVectorPermute<XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_1X, XM_PERMUTE_1Y>(SinAngles, CosAngles);
XMVECTOR P1 = XMVectorPermute<XM_PERMUTE_1Z, XM_PERMUTE_0Z, XM_PERMUTE_1Z, XM_PERMUTE_0Z>(SinAngles, CosAngles);
XMVECTOR Y1 = XMVectorPermute<XM_PERMUTE_1Y, XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0Y>(SinAngles, CosAngles);
XMVECTOR P2 = XMVectorPermute<XM_PERMUTE_0Z, XM_PERMUTE_1Z, XM_PERMUTE_0Z, XM_PERMUTE_1Z>(SinAngles, CosAngles);
XMVECTOR P3 = XMVectorPermute<XM_PERMUTE_0Y, XM_PERMUTE_0Y, XM_PERMUTE_1Y, XM_PERMUTE_1Y>(SinAngles, CosAngles);
XMVECTOR Y2 = XMVectorSplatX(SinAngles);
XMVECTOR NS = XMVectorNegate(SinAngles);
XMVECTOR Q0 = XMVectorMultiply(P0, Y0);
XMVECTOR Q1 = XMVectorMultiply(P1, Sign.v);
Q1 = XMVectorMultiply(Q1, Y1);
XMVECTOR Q2 = XMVectorMultiply(P2, Y2);
Q2 = XMVectorMultiplyAdd(Q2, P3, Q1);
XMVECTOR V0 = XMVectorPermute<XM_PERMUTE_1X, XM_PERMUTE_0Y, XM_PERMUTE_1Z, XM_PERMUTE_0W>(Q0, Q2);
XMVECTOR V1 = XMVectorPermute<XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_1W, XM_PERMUTE_0W>(Q0, Q2);
XMVECTOR V2 = XMVectorPermute<XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_0W, XM_PERMUTE_0W>(Q0, NS);
XMMATRIX M;
M.r[0] = XMVectorSelect(g_XMZero, V0, g_XMSelect1110.v);
M.r[1] = XMVectorSelect(g_XMZero, V1, g_XMSelect1110.v);
M.r[2] = XMVectorSelect(g_XMZero, V2, g_XMSelect1110.v);
M.r[3] = g_XMIdentityR3;
return M;
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1770,8 +1877,42 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationAxis
inline XMMATRIX XM_CALLCONV XMMatrixRotationQuaternion(FXMVECTOR Quaternion) noexcept inline XMMATRIX XM_CALLCONV XMMatrixRotationQuaternion(FXMVECTOR Quaternion) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_) || defined(_XM_ARM_NEON_INTRINSICS_) #if defined(_XM_NO_INTRINSICS_)
float qx = Quaternion.vector4_f32[0];
float qxx = qx * qx;
float qy = Quaternion.vector4_f32[1];
float qyy = qy * qy;
float qz = Quaternion.vector4_f32[2];
float qzz = qz * qz;
float qw = Quaternion.vector4_f32[3];
XMMATRIX M;
M.m[0][0] = 1.f - 2.f * qyy - 2.f * qzz;
M.m[0][1] = 2.f * qx * qy + 2.f * qz * qw;
M.m[0][2] = 2.f * qx * qz - 2.f * qy * qw;
M.m[0][3] = 0.f;
M.m[1][0] = 2.f * qx * qy - 2.f * qz * qw;
M.m[1][1] = 1.f - 2.f * qxx - 2.f * qzz;
M.m[1][2] = 2.f * qy * qz + 2.f * qx * qw;
M.m[1][3] = 0.f;
M.m[2][0] = 2.f * qx * qz + 2.f * qy * qw;
M.m[2][1] = 2.f * qy * qz - 2.f * qx * qw;
M.m[2][2] = 1.f - 2.f * qxx - 2.f * qyy;
M.m[2][3] = 0.f;
M.m[3][0] = 0.f;
M.m[3][1] = 0.f;
M.m[3][2] = 0.f;
M.m[3][3] = 1.0f;
return M;
#elif defined(_XM_ARM_NEON_INTRINSICS_)
static const XMVECTORF32 Constant1110 = { { { 1.0f, 1.0f, 1.0f, 0.0f } } }; static const XMVECTORF32 Constant1110 = { { { 1.0f, 1.0f, 1.0f, 0.0f } } };
XMVECTOR Q0 = XMVectorAdd(Quaternion, Quaternion); XMVECTOR Q0 = XMVectorAdd(Quaternion, Quaternion);
@ -2166,7 +2307,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveLH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float TwoNearZ = NearZ + NearZ; float TwoNearZ = NearZ + NearZ;
float fRange = FarZ / (FarZ - NearZ); float fRange = FarZ / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(TwoNearZ / ViewHeight, Zero, 1); M.r[1] = vsetq_lane_f32(TwoNearZ / ViewHeight, Zero, 1);
@ -2253,7 +2394,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveRH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float TwoNearZ = NearZ + NearZ; float TwoNearZ = NearZ + NearZ;
float fRange = FarZ / (NearZ - FarZ); float fRange = FarZ / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0);
@ -2351,7 +2492,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovLH
float fRange = FarZ / (FarZ - NearZ); float fRange = FarZ / (FarZ - NearZ);
float Height = CosFov / SinFov; float Height = CosFov / SinFov;
float Width = Height / AspectRatio; float Width = Height / AspectRatio;
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(Width, Zero, 0); M.r[0] = vsetq_lane_f32(Width, Zero, 0);
@ -2378,10 +2519,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovLH
XMVECTOR vTemp = _mm_setzero_ps(); XMVECTOR vTemp = _mm_setzero_ps();
// Copy x only // Copy x only
vTemp = _mm_move_ss(vTemp, vValues); vTemp = _mm_move_ss(vTemp, vValues);
// CosFov / SinFov,0,0,0 // Height / AspectRatio,0,0,0
XMMATRIX M; XMMATRIX M;
M.r[0] = vTemp; M.r[0] = vTemp;
// 0,Height / AspectRatio,0,0 // 0,Height,0,0
vTemp = vValues; vTemp = vValues;
vTemp = _mm_and_ps(vTemp, g_XMMaskY); vTemp = _mm_and_ps(vTemp, g_XMMaskY);
M.r[1] = vTemp; M.r[1] = vTemp;
@ -2452,7 +2593,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovRH
float fRange = FarZ / (NearZ - FarZ); float fRange = FarZ / (NearZ - FarZ);
float Height = CosFov / SinFov; float Height = CosFov / SinFov;
float Width = Height / AspectRatio; float Width = Height / AspectRatio;
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(Width, Zero, 0); M.r[0] = vsetq_lane_f32(Width, Zero, 0);
@ -2478,10 +2619,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovRH
XMVECTOR vTemp = _mm_setzero_ps(); XMVECTOR vTemp = _mm_setzero_ps();
// Copy x only // Copy x only
vTemp = _mm_move_ss(vTemp, vValues); vTemp = _mm_move_ss(vTemp, vValues);
// CosFov / SinFov,0,0,0 // Height / AspectRatio,0,0,0
XMMATRIX M; XMMATRIX M;
M.r[0] = vTemp; M.r[0] = vTemp;
// 0,Height / AspectRatio,0,0 // 0,Height,0,0
vTemp = vValues; vTemp = vValues;
vTemp = _mm_and_ps(vTemp, g_XMMaskY); vTemp = _mm_and_ps(vTemp, g_XMMaskY);
M.r[1] = vTemp; M.r[1] = vTemp;
@ -2549,7 +2690,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveOffCenterLH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = FarZ / (FarZ - NearZ); float fRange = FarZ / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0);
@ -2647,7 +2788,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveOffCenterRH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = FarZ / (NearZ - FarZ); float fRange = FarZ / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0);
@ -2737,7 +2878,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicLH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fRange = 1.0f / (FarZ - NearZ); float fRange = 1.0f / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1); M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1);
@ -2821,7 +2962,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicRH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fRange = 1.0f / (NearZ - FarZ); float fRange = 1.0f / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1); M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1);
@ -2910,7 +3051,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicOffCenterLH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = 1.0f / (FarZ - NearZ); float fRange = 1.0f / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1); M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1);
@ -3010,7 +3151,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicOffCenterRH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = 1.0f / (NearZ - FarZ); float fRange = 1.0f / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1); M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1);
@ -3164,7 +3305,7 @@ inline XMMATRIX& XMMATRIX::operator/= (float S) noexcept
r[3] = XMVectorDivide(r[3], vS); r[3] = XMVectorDivide(r[3], vS);
return *this; return *this;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || __aarch64__ #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__
float32x4_t vS = vdupq_n_f32(S); float32x4_t vS = vdupq_n_f32(S);
r[0] = vdivq_f32(r[0], vS); r[0] = vdivq_f32(r[0], vS);
r[1] = vdivq_f32(r[1], vS); r[1] = vdivq_f32(r[1], vS);
@ -3178,7 +3319,7 @@ inline XMMATRIX& XMMATRIX::operator/= (float S) noexcept
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
S0 = vrecps_f32(R0, vS); S0 = vrecps_f32(R0, vS);
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
float32x4_t Reciprocal = vcombine_u32(R0, R0); float32x4_t Reciprocal = vcombine_f32(R0, R0);
r[0] = vmulq_f32(r[0], Reciprocal); r[0] = vmulq_f32(r[0], Reciprocal);
r[1] = vmulq_f32(r[1], Reciprocal); r[1] = vmulq_f32(r[1], Reciprocal);
r[2] = vmulq_f32(r[2], Reciprocal); r[2] = vmulq_f32(r[2], Reciprocal);
@ -3251,7 +3392,7 @@ inline XMMATRIX XMMATRIX::operator/ (float S) const noexcept
R.r[3] = XMVectorDivide(r[3], vS); R.r[3] = XMVectorDivide(r[3], vS);
return R; return R;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || __aarch64__ #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__
float32x4_t vS = vdupq_n_f32(S); float32x4_t vS = vdupq_n_f32(S);
XMMATRIX R; XMMATRIX R;
R.r[0] = vdivq_f32(r[0], vS); R.r[0] = vdivq_f32(r[0], vS);
@ -3266,7 +3407,7 @@ inline XMMATRIX XMMATRIX::operator/ (float S) const noexcept
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
S0 = vrecps_f32(R0, vS); S0 = vrecps_f32(R0, vS);
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
float32x4_t Reciprocal = vcombine_u32(R0, R0); float32x4_t Reciprocal = vcombine_f32(R0, R0);
XMMATRIX R; XMMATRIX R;
R.r[0] = vmulq_f32(r[0], Reciprocal); R.r[0] = vmulq_f32(r[0], Reciprocal);
R.r[1] = vmulq_f32(r[1], Reciprocal); R.r[1] = vmulq_f32(r[1], Reciprocal);

View File

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// DirectXMathMisc.inl -- SIMD C++ Math library // DirectXMathMisc.inl -- SIMD C++ Math library
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
// //
// http://go.microsoft.com/fwlink/?LinkID=615560 // https://go.microsoft.com/fwlink/?LinkID=615560
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#pragma once #pragma once
@ -120,12 +120,12 @@ inline XMVECTOR XM_CALLCONV XMQuaternionMultiply
vResult = vmlaq_f32(vResult, Q2X, ControlWZYX); vResult = vmlaq_f32(vResult, Q2X, ControlWZYX);
// Mul by Q1ZWXY // Mul by Q1ZWXY
vTemp = vrev64q_u32(vTemp); vTemp = vreinterpretq_f32_u32(vrev64q_u32(vreinterpretq_u32_f32(vTemp)));
Q2Y = vmulq_f32(Q2Y, vTemp); Q2Y = vmulq_f32(Q2Y, vTemp);
vResult = vmlaq_f32(vResult, Q2Y, ControlZWXY); vResult = vmlaq_f32(vResult, Q2Y, ControlZWXY);
// Mul by Q1YXWZ // Mul by Q1YXWZ
vTemp = vrev64q_u32(vTemp); vTemp = vreinterpretq_f32_u32(vrev64q_u32(vreinterpretq_u32_f32(vTemp)));
vTemp = vcombine_f32(vget_high_f32(vTemp), vget_low_f32(vTemp)); vTemp = vcombine_f32(vget_high_f32(vTemp), vget_low_f32(vTemp));
Q2Z = vmulq_f32(Q2Z, vTemp); Q2Z = vmulq_f32(Q2Z, vTemp);
vResult = vmlaq_f32(vResult, Q2Z, ControlYXWZ); vResult = vmlaq_f32(vResult, Q2Z, ControlYXWZ);
@ -228,8 +228,6 @@ inline XMVECTOR XM_CALLCONV XMQuaternionConjugate(FXMVECTOR Q) noexcept
inline XMVECTOR XM_CALLCONV XMQuaternionInverse(FXMVECTOR Q) noexcept inline XMVECTOR XM_CALLCONV XMQuaternionInverse(FXMVECTOR Q) noexcept
{ {
const XMVECTOR Zero = XMVectorZero();
XMVECTOR L = XMVector4LengthSq(Q); XMVECTOR L = XMVector4LengthSq(Q);
XMVECTOR Conjugate = XMQuaternionConjugate(Q); XMVECTOR Conjugate = XMQuaternionConjugate(Q);
@ -237,7 +235,7 @@ inline XMVECTOR XM_CALLCONV XMQuaternionInverse(FXMVECTOR Q) noexcept
XMVECTOR Result = XMVectorDivide(Conjugate, L); XMVECTOR Result = XMVectorDivide(Conjugate, L);
Result = XMVectorSelect(Result, Zero, Control); Result = XMVectorSelect(Result, g_XMZero, Control);
return Result; return Result;
} }
@ -582,9 +580,30 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYaw
float Roll float Roll
) noexcept ) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_)
const float halfpitch = Pitch * 0.5f;
float cp = cosf(halfpitch);
float sp = sinf(halfpitch);
const float halfyaw = Yaw * 0.5f;
float cy = cosf(halfyaw);
float sy = sinf(halfyaw);
const float halfroll = Roll * 0.5f;
float cr = cosf(halfroll);
float sr = sinf(halfroll);
XMVECTORF32 vResult = { { {
cr * sp * cy + sr * cp * sy,
cr * cp * sy - sr * sp * cy,
sr * cp * cy - cr * sp * sy,
cr * cp * cy + sr * sp * sy
} } };
return vResult;
#else
XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f); XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f);
XMVECTOR Q = XMQuaternionRotationRollPitchYawFromVector(Angles); return XMQuaternionRotationRollPitchYawFromVector(Angles);
return Q; #endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -594,6 +613,27 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYawFromVector
FXMVECTOR Angles // <Pitch, Yaw, Roll, 0> FXMVECTOR Angles // <Pitch, Yaw, Roll, 0>
) noexcept ) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_)
const float halfpitch = Angles.vector4_f32[0] * 0.5f;
float cp = cosf(halfpitch);
float sp = sinf(halfpitch);
const float halfyaw = Angles.vector4_f32[1] * 0.5f;
float cy = cosf(halfyaw);
float sy = sinf(halfyaw);
const float halfroll = Angles.vector4_f32[2] * 0.5f;
float cr = cosf(halfroll);
float sr = sinf(halfroll);
XMVECTORF32 vResult = { { {
cr * sp * cy + sr * cp * sy,
cr * cp * sy - sr * sp * cy,
sr * cp * cy - cr * sp * sy,
cr * cp * cy + sr * sp * sy
} } };
return vResult;
#else
static const XMVECTORF32 Sign = { { { 1.0f, -1.0f, -1.0f, 1.0f } } }; static const XMVECTORF32 Sign = { { { 1.0f, -1.0f, -1.0f, 1.0f } } };
XMVECTOR HalfAngles = XMVectorMultiply(Angles, g_XMOneHalf.v); XMVECTOR HalfAngles = XMVectorMultiply(Angles, g_XMOneHalf.v);
@ -615,6 +655,7 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYawFromVector
XMVECTOR Q = XMVectorMultiplyAdd(Q1, R1, Q0); XMVECTOR Q = XMVectorMultiplyAdd(Q1, R1, Q0);
return Q; return Q;
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -728,74 +769,74 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationMatrix(FXMMATRIX M) noexcept
static const XMVECTORU32 Select0110 = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_1, XM_SELECT_0 } } }; static const XMVECTORU32 Select0110 = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_1, XM_SELECT_0 } } };
static const XMVECTORU32 Select0010 = { { { XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 } } }; static const XMVECTORU32 Select0010 = { { { XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 } } };
XMVECTOR r0 = M.r[0]; float32x4_t r0 = M.r[0];
XMVECTOR r1 = M.r[1]; float32x4_t r1 = M.r[1];
XMVECTOR r2 = M.r[2]; float32x4_t r2 = M.r[2];
XMVECTOR r00 = vdupq_lane_f32(vget_low_f32(r0), 0); float32x4_t r00 = vdupq_lane_f32(vget_low_f32(r0), 0);
XMVECTOR r11 = vdupq_lane_f32(vget_low_f32(r1), 1); float32x4_t r11 = vdupq_lane_f32(vget_low_f32(r1), 1);
XMVECTOR r22 = vdupq_lane_f32(vget_high_f32(r2), 0); float32x4_t r22 = vdupq_lane_f32(vget_high_f32(r2), 0);
// x^2 >= y^2 equivalent to r11 - r00 <= 0 // x^2 >= y^2 equivalent to r11 - r00 <= 0
XMVECTOR r11mr00 = vsubq_f32(r11, r00); float32x4_t r11mr00 = vsubq_f32(r11, r00);
XMVECTOR x2gey2 = vcleq_f32(r11mr00, g_XMZero); uint32x4_t x2gey2 = vcleq_f32(r11mr00, g_XMZero);
// z^2 >= w^2 equivalent to r11 + r00 <= 0 // z^2 >= w^2 equivalent to r11 + r00 <= 0
XMVECTOR r11pr00 = vaddq_f32(r11, r00); float32x4_t r11pr00 = vaddq_f32(r11, r00);
XMVECTOR z2gew2 = vcleq_f32(r11pr00, g_XMZero); uint32x4_t z2gew2 = vcleq_f32(r11pr00, g_XMZero);
// x^2 + y^2 >= z^2 + w^2 equivalent to r22 <= 0 // x^2 + y^2 >= z^2 + w^2 equivalent to r22 <= 0
XMVECTOR x2py2gez2pw2 = vcleq_f32(r22, g_XMZero); uint32x4_t x2py2gez2pw2 = vcleq_f32(r22, g_XMZero);
// (4*x^2, 4*y^2, 4*z^2, 4*w^2) // (4*x^2, 4*y^2, 4*z^2, 4*w^2)
XMVECTOR t0 = vmulq_f32(XMPMMP, r00); float32x4_t t0 = vmulq_f32(XMPMMP, r00);
XMVECTOR x2y2z2w2 = vmlaq_f32(t0, XMMPMP, r11); float32x4_t x2y2z2w2 = vmlaq_f32(t0, XMMPMP, r11);
x2y2z2w2 = vmlaq_f32(x2y2z2w2, XMMMPP, r22); x2y2z2w2 = vmlaq_f32(x2y2z2w2, XMMMPP, r22);
x2y2z2w2 = vaddq_f32(x2y2z2w2, g_XMOne); x2y2z2w2 = vaddq_f32(x2y2z2w2, g_XMOne);
// (r01, r02, r12, r11) // (r01, r02, r12, r11)
t0 = vextq_f32(r0, r0, 1); t0 = vextq_f32(r0, r0, 1);
XMVECTOR t1 = vextq_f32(r1, r1, 1); float32x4_t t1 = vextq_f32(r1, r1, 1);
t0 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_low_f32(t1))); t0 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_low_f32(t1)));
// (r10, r20, r21, r10) // (r10, r20, r21, r10)
t1 = vextq_f32(r2, r2, 3); t1 = vextq_f32(r2, r2, 3);
XMVECTOR r10 = vdupq_lane_f32(vget_low_f32(r1), 0); float32x4_t r10 = vdupq_lane_f32(vget_low_f32(r1), 0);
t1 = vbslq_f32(Select0110, t1, r10); t1 = vbslq_f32(Select0110, t1, r10);
// (4*x*y, 4*x*z, 4*y*z, unused) // (4*x*y, 4*x*z, 4*y*z, unused)
XMVECTOR xyxzyz = vaddq_f32(t0, t1); float32x4_t xyxzyz = vaddq_f32(t0, t1);
// (r21, r20, r10, r10) // (r21, r20, r10, r10)
t0 = vcombine_f32(vrev64_f32(vget_low_f32(r2)), vget_low_f32(r10)); t0 = vcombine_f32(vrev64_f32(vget_low_f32(r2)), vget_low_f32(r10));
// (r12, r02, r01, r12) // (r12, r02, r01, r12)
XMVECTOR t2 = vcombine_f32(vrev64_f32(vget_high_f32(r0)), vrev64_f32(vget_low_f32(r0))); float32x4_t t2 = vcombine_f32(vrev64_f32(vget_high_f32(r0)), vrev64_f32(vget_low_f32(r0)));
XMVECTOR t3 = vdupq_lane_f32(vget_high_f32(r1), 0); float32x4_t t3 = vdupq_lane_f32(vget_high_f32(r1), 0);
t1 = vbslq_f32(Select0110, t2, t3); t1 = vbslq_f32(Select0110, t2, t3);
// (4*x*w, 4*y*w, 4*z*w, unused) // (4*x*w, 4*y*w, 4*z*w, unused)
XMVECTOR xwywzw = vsubq_f32(t0, t1); float32x4_t xwywzw = vsubq_f32(t0, t1);
xwywzw = vmulq_f32(XMMPMP, xwywzw); xwywzw = vmulq_f32(XMMPMP, xwywzw);
// (4*x*x, 4*x*y, 4*x*z, 4*x*w) // (4*x*x, 4*x*y, 4*x*z, 4*x*w)
t0 = vextq_f32(xyxzyz, xyxzyz, 3); t0 = vextq_f32(xyxzyz, xyxzyz, 3);
t1 = vbslq_f32(Select0110, t0, x2y2z2w2); t1 = vbslq_f32(Select0110, t0, x2y2z2w2);
t2 = vdupq_lane_f32(vget_low_f32(xwywzw), 0); t2 = vdupq_lane_f32(vget_low_f32(xwywzw), 0);
XMVECTOR tensor0 = vbslq_f32(g_XMSelect1110, t1, t2); float32x4_t tensor0 = vbslq_f32(g_XMSelect1110, t1, t2);
// (4*y*x, 4*y*y, 4*y*z, 4*y*w) // (4*y*x, 4*y*y, 4*y*z, 4*y*w)
t0 = vbslq_f32(g_XMSelect1011, xyxzyz, x2y2z2w2); t0 = vbslq_f32(g_XMSelect1011, xyxzyz, x2y2z2w2);
t1 = vdupq_lane_f32(vget_low_f32(xwywzw), 1); t1 = vdupq_lane_f32(vget_low_f32(xwywzw), 1);
XMVECTOR tensor1 = vbslq_f32(g_XMSelect1110, t0, t1); float32x4_t tensor1 = vbslq_f32(g_XMSelect1110, t0, t1);
// (4*z*x, 4*z*y, 4*z*z, 4*z*w) // (4*z*x, 4*z*y, 4*z*z, 4*z*w)
t0 = vextq_f32(xyxzyz, xyxzyz, 1); t0 = vextq_f32(xyxzyz, xyxzyz, 1);
t1 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_high_f32(xwywzw))); t1 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_high_f32(xwywzw)));
XMVECTOR tensor2 = vbslq_f32(Select0010, x2y2z2w2, t1); float32x4_t tensor2 = vbslq_f32(Select0010, x2y2z2w2, t1);
// (4*w*x, 4*w*y, 4*w*z, 4*w*w) // (4*w*x, 4*w*y, 4*w*z, 4*w*w)
XMVECTOR tensor3 = vbslq_f32(g_XMSelect1110, xwywzw, x2y2z2w2); float32x4_t tensor3 = vbslq_f32(g_XMSelect1110, xwywzw, x2y2z2w2);
// Select the row of the tensor-product matrix that has the largest // Select the row of the tensor-product matrix that has the largest
// magnitude. // magnitude.
@ -1176,7 +1217,7 @@ inline void XM_CALLCONV XMPlaneIntersectPlane
inline XMVECTOR XM_CALLCONV XMPlaneTransform inline XMVECTOR XM_CALLCONV XMPlaneTransform
( (
FXMVECTOR P, FXMVECTOR P,
FXMMATRIX M FXMMATRIX ITM
) noexcept ) noexcept
{ {
XMVECTOR W = XMVectorSplatW(P); XMVECTOR W = XMVectorSplatW(P);
@ -1184,10 +1225,10 @@ inline XMVECTOR XM_CALLCONV XMPlaneTransform
XMVECTOR Y = XMVectorSplatY(P); XMVECTOR Y = XMVectorSplatY(P);
XMVECTOR X = XMVectorSplatX(P); XMVECTOR X = XMVectorSplatX(P);
XMVECTOR Result = XMVectorMultiply(W, M.r[3]); XMVECTOR Result = XMVectorMultiply(W, ITM.r[3]);
Result = XMVectorMultiplyAdd(Z, M.r[2], Result); Result = XMVectorMultiplyAdd(Z, ITM.r[2], Result);
Result = XMVectorMultiplyAdd(Y, M.r[1], Result); Result = XMVectorMultiplyAdd(Y, ITM.r[1], Result);
Result = XMVectorMultiplyAdd(X, M.r[0], Result); Result = XMVectorMultiplyAdd(X, ITM.r[0], Result);
return Result; return Result;
} }
@ -1200,7 +1241,7 @@ inline XMFLOAT4* XM_CALLCONV XMPlaneTransformStream
const XMFLOAT4* pInputStream, const XMFLOAT4* pInputStream,
size_t InputStride, size_t InputStride,
size_t PlaneCount, size_t PlaneCount,
FXMMATRIX M FXMMATRIX ITM
) noexcept ) noexcept
{ {
return XMVector4TransformStream(pOutputStream, return XMVector4TransformStream(pOutputStream,
@ -1208,7 +1249,7 @@ inline XMFLOAT4* XM_CALLCONV XMPlaneTransformStream
pInputStream, pInputStream,
InputStride, InputStride,
PlaneCount, PlaneCount,
M); ITM);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1358,8 +1399,8 @@ inline XMVECTOR XM_CALLCONV XMColorNegative(FXMVECTOR vColor) noexcept
} } }; } } };
return vResult.v; return vResult.v;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMVECTOR vTemp = veorq_u32(vColor, g_XMNegate3); uint32x4_t vTemp = veorq_u32(vreinterpretq_u32_f32(vColor), g_XMNegate3);
return vaddq_f32(vTemp, g_XMOne3); return vaddq_f32(vreinterpretq_f32_u32(vTemp), g_XMOne3);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Negate only x,y and z. // Negate only x,y and z.
XMVECTOR vTemp = _mm_xor_ps(vColor, g_XMNegate3); XMVECTOR vTemp = _mm_xor_ps(vColor, g_XMNegate3);
@ -1520,7 +1561,7 @@ inline XMVECTOR XM_CALLCONV XMColorRGBToHSL(FXMVECTOR rgb) noexcept
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace Internal namespace MathInternal
{ {
inline XMVECTOR XM_CALLCONV XMColorHue2Clr(FXMVECTOR p, FXMVECTOR q, FXMVECTOR h) noexcept inline XMVECTOR XM_CALLCONV XMColorHue2Clr(FXMVECTOR p, FXMVECTOR q, FXMVECTOR h) noexcept
@ -1558,7 +1599,7 @@ namespace Internal
return p; return p;
} }
} // namespace Internal } // namespace MathInternal
inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept
{ {
@ -1588,9 +1629,9 @@ inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept
XMVECTOR p = XMVectorSubtract(XMVectorMultiply(g_XMTwo, l), q); XMVECTOR p = XMVectorSubtract(XMVectorMultiply(g_XMTwo, l), q);
XMVECTOR r = DirectX::Internal::XMColorHue2Clr(p, q, XMVectorAdd(h, oneThird)); XMVECTOR r = DirectX::MathInternal::XMColorHue2Clr(p, q, XMVectorAdd(h, oneThird));
XMVECTOR g = DirectX::Internal::XMColorHue2Clr(p, q, h); XMVECTOR g = DirectX::MathInternal::XMColorHue2Clr(p, q, h);
XMVECTOR b = DirectX::Internal::XMColorHue2Clr(p, q, XMVectorSubtract(h, oneThird)); XMVECTOR b = DirectX::MathInternal::XMColorHue2Clr(p, q, XMVectorSubtract(h, oneThird));
XMVECTOR rg = XMVectorSelect(g, r, g_XMSelect1000); XMVECTOR rg = XMVectorSelect(g, r, g_XMSelect1000);
XMVECTOR ba = XMVectorSelect(hsl, b, g_XMSelect1110); XMVECTOR ba = XMVectorSelect(hsl, b, g_XMSelect1110);
@ -1779,6 +1820,33 @@ inline XMVECTOR XM_CALLCONV XMColorYUVToRGB_HD(FXMVECTOR yuv) noexcept
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline XMVECTOR XM_CALLCONV XMColorRGBToYUV_UHD(FXMVECTOR rgb) noexcept
{
static const XMVECTORF32 Scale0 = { { { 0.2627f, -0.1215f, 0.6150f, 0.0f } } };
static const XMVECTORF32 Scale1 = { { { 0.6780f, -0.3136f, -0.5655f, 0.0f } } };
static const XMVECTORF32 Scale2 = { { { 0.0593f, 0.4351f, -0.0495f, 0.0f } } };
XMMATRIX M(Scale0, Scale1, Scale2, g_XMZero);
XMVECTOR clr = XMVector3Transform(rgb, M);
return XMVectorSelect(rgb, clr, g_XMSelect1110);
}
//------------------------------------------------------------------------------
inline XMVECTOR XM_CALLCONV XMColorYUVToRGB_UHD(FXMVECTOR yuv) noexcept
{
static const XMVECTORF32 Scale1 = { { { 0.0f, -0.1891f, 2.1620f, 0.0f } } };
static const XMVECTORF32 Scale2 = { { { 1.1989f, -0.4645f, 0.0f, 0.0f } } };
XMMATRIX M(g_XMOne, Scale1, Scale2, g_XMZero);
XMVECTOR clr = XMVector3Transform(yuv, M);
return XMVectorSelect(yuv, clr, g_XMSelect1110);
}
//------------------------------------------------------------------------------
inline XMVECTOR XM_CALLCONV XMColorRGBToXYZ(FXMVECTOR rgb) noexcept inline XMVECTOR XM_CALLCONV XMColorRGBToXYZ(FXMVECTOR rgb) noexcept
{ {
static const XMVECTORF32 Scale0 = { { { 0.4887180f, 0.1762044f, 0.0000000f, 0.0f } } }; static const XMVECTORF32 Scale0 = { { { 0.4887180f, 0.1762044f, 0.0000000f, 0.0f } } };
@ -1903,9 +1971,9 @@ inline XMVECTOR XM_CALLCONV XMColorSRGBToRGB(FXMVECTOR srgb) noexcept
inline bool XMVerifyCPUSupport() noexcept inline bool XMVerifyCPUSupport() noexcept
{ {
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_SSE_INTRINSICS_) && !defined(__powerpc64__) && !defined(_XM_NO_INTRINSICS_)
int CPUInfo[4] = { -1 }; int CPUInfo[4] = { -1 };
#if defined(__clang__) || defined(__GNUC__) #if (defined(__clang__) || defined(__GNUC__)) && !defined(_MSC_VER) && !defined(__MINGW32__)
__cpuid(0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); __cpuid(0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else #else
__cpuid(CPUInfo, 0); __cpuid(CPUInfo, 0);
@ -1919,7 +1987,7 @@ inline bool XMVerifyCPUSupport() noexcept
return false; return false;
#endif #endif
#if defined(__clang__) || defined(__GNUC__) #if (defined(__clang__) || defined(__GNUC__)) && !defined(_MSC_VER) && !defined(__MINGW32__)
__cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); __cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else #else
__cpuid(CPUInfo, 1); __cpuid(CPUInfo, 1);
@ -1954,7 +2022,7 @@ inline bool XMVerifyCPUSupport() noexcept
return false; // No SSE2/SSE support return false; // No SSE2/SSE support
#if defined(__AVX2__) || defined(_XM_AVX2_INTRINSICS_) #if defined(__AVX2__) || defined(_XM_AVX2_INTRINSICS_)
#if defined(__clang__) || defined(__GNUC__) #if (defined(__clang__) || defined(__GNUC__)) && !defined(_MSC_VER) && !defined(__MINGW32__)
__cpuid_count(7, 0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); __cpuid_count(7, 0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else #else
__cpuidex(CPUInfo, 7, 0); __cpuidex(CPUInfo, 7, 0);

View File

@ -3,7 +3,7 @@
#include "memory.h" #include "memory.h"
#include "node.h" #include "node.h"
#include "directxmath/directxmath.h" #include "directxmath/DirectXMath.h"
size_t node_alloc(int count) size_t node_alloc(int count)
{ {

View File