mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-21 08:58:10 +02:00
This commit allows you to dump different regions of memory related to bvh building. An additional script to decode the memory dump is also added, and you're able to view the built bvh in 3D view in html. See the included README.md for usage. Rework: - you can now view the actual child_coord in internalNode in html - change exponent to be int8_t in the interpreter - fix the actual coordinates using an updated formula - now you can have 3D view of the bvh - blockIncr could be 2 and vk_aabb should be first - Now, if any bvh dump is enabled, we will zero out tlas, to prevent gpu hang caused by incorrect tlas traversal - rootNodeOffset is back to the beginning - Add INTEL_DEBUG=bvh_no_build. - Fix type of dump_size - add assertion for a 4B alignment - when clearing out bvh, only clear out everything after (header+bvh_offset) - TODO: instead of dumping on destory, track in the command buffer Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31588>
394 lines
14 KiB
HTML
394 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>BVH Visualization</title>
|
|
</head>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
background-color: #f0f0f0;
|
|
margin: 0;
|
|
padding: 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
height: 100vh;
|
|
}
|
|
|
|
#container {
|
|
width: 100%;
|
|
height: 50%;
|
|
border: 2px solid #ccc;
|
|
background-color: #fff;
|
|
padding: 10px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.node circle {
|
|
fill: #999;
|
|
stroke: steelblue;
|
|
stroke-width: 1.5px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.node text {
|
|
font: 12px sans-serif;
|
|
}
|
|
|
|
.link {
|
|
fill: none;
|
|
stroke: #555;
|
|
stroke-opacity: 0.4;
|
|
stroke-width: 1.5px;
|
|
}
|
|
|
|
.tooltip {
|
|
position: absolute;
|
|
text-align: left;
|
|
width: 300px;
|
|
height: auto;
|
|
padding: 10px;
|
|
font: 12px sans-serif;
|
|
background: lightsteelblue;
|
|
border: 1px solid #333;
|
|
border-radius: 8px;
|
|
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
|
overflow-y: auto;
|
|
max-height: 400px;
|
|
visibility: hidden;
|
|
}
|
|
|
|
.tooltip h3 {
|
|
margin: 0;
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.tooltip p {
|
|
margin: 5px 0;
|
|
font-size: 12px;
|
|
word-wrap: break-word;
|
|
}
|
|
|
|
.tooltip .indent {
|
|
margin-left: 20px;
|
|
}
|
|
|
|
#header {
|
|
margin-bottom: 20px;
|
|
padding: 10px;
|
|
background-color: #e0e0e0;
|
|
border-radius: 8px;
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
#header h2 {
|
|
margin-top: 0;
|
|
color: #333;
|
|
}
|
|
|
|
#header p {
|
|
margin: 5px 0;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
#threeContainer {
|
|
width: 75%;
|
|
height: 100%;
|
|
}
|
|
|
|
#toggleControls {
|
|
width: 25%;
|
|
height: 100%;
|
|
overflow-y: auto;
|
|
margin-left: 20px;
|
|
border: 2px solid #ccc;
|
|
border-radius: 8px;
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
padding: 10px;
|
|
}
|
|
|
|
.toggle-container {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.toggle-container label {
|
|
font-size: 14px;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
#mainContainer {
|
|
display: flex;
|
|
width: 100%;
|
|
height: 50%;
|
|
justify-content: space-between;
|
|
margin-bottom: 20px;
|
|
}
|
|
</style>
|
|
<body>
|
|
<div id="header"></div>
|
|
<div id="container">
|
|
<div class="tooltip"></div>
|
|
<svg id="canvas"></svg>
|
|
</div>
|
|
<br></br>
|
|
<br></br>
|
|
<br></br>
|
|
<div id="mainContainer">
|
|
<div id="threeContainer"></div>
|
|
<div id="toggleControls"></div>
|
|
</div>
|
|
<br></br>
|
|
<br></br>
|
|
<br></br>
|
|
<script src="https://d3js.org/d3.v6.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.130.1/build/three.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.130.1/examples/js/controls/OrbitControls.js"></script>
|
|
<script>
|
|
function formatProperties(properties, depth = 0, maxDepth = 2, index = '') {
|
|
if (depth > maxDepth) {
|
|
return '<p><strong>...</strong></p>';
|
|
}
|
|
|
|
let html = '';
|
|
for (const [key, value] of Object.entries(properties)) {
|
|
const currentIndex = index ? `${index}.${key}` : key;
|
|
if (typeof value === 'object' && value !== null) {
|
|
html += `<p><strong>${currentIndex}:</strong><div class="indent">${formatProperties(value, depth + 1, maxDepth, currentIndex)}</div></p>`;
|
|
} else {
|
|
let displayValue = value;
|
|
if (typeof value === 'string' && value.length > 100) {
|
|
displayValue = value.substring(0, 100) + '...';
|
|
}
|
|
html += `<p><strong>${currentIndex}:</strong> ${displayValue}</p>`;
|
|
}
|
|
}
|
|
return html;
|
|
}
|
|
|
|
d3.json('bvh_dump.json').then(function(treeData) {
|
|
document.getElementById('header').innerHTML = `<h2>Header Information</h2>${formatProperties(treeData.header)}`;
|
|
|
|
var width = 1400,
|
|
height = 400; // Adjusted for half the height
|
|
|
|
var svg = d3.select("#canvas")
|
|
.attr("width", width)
|
|
.attr("height", height)
|
|
.call(d3.zoom().on("zoom", function (event) {
|
|
g.attr("transform", event.transform);
|
|
}))
|
|
.append("g");
|
|
|
|
var g = svg.append("g");
|
|
|
|
var root = d3.hierarchy(treeData.nodes.find(n => n.id === 0), function(d) {
|
|
return treeData.relationships[d.id].map(id => treeData.nodes.find(n => n.id === id));
|
|
});
|
|
|
|
var treeLayout = d3.tree().size([height, width - 250]);
|
|
|
|
treeLayout(root);
|
|
|
|
var link = g.selectAll(".link")
|
|
.data(root.links())
|
|
.enter().append("path")
|
|
.attr("class", "link")
|
|
.attr("d", d3.linkHorizontal()
|
|
.x(d => d.y)
|
|
.y(d => d.x));
|
|
|
|
var node = g.selectAll(".node")
|
|
.data(root.descendants())
|
|
.enter().append("g")
|
|
.attr("class", "node")
|
|
.attr("transform", d => `translate(${d.y},${d.x})`);
|
|
|
|
node.append("circle")
|
|
.attr("r", 10)
|
|
.on("click", function(event, d) {
|
|
const propertiesHtml = formatProperties(d.data.properties);
|
|
|
|
d3.select(".tooltip")
|
|
.html(`<h3>ID: ${d.data.id}</h3>${propertiesHtml}`)
|
|
.style("visibility", "visible")
|
|
.style("left", (event.pageX + 20) + "px")
|
|
.style("top", (event.pageY - 20) + "px");
|
|
d3.selectAll("circle").attr("r", 10);
|
|
d3.select(this).attr("r", 15);
|
|
});
|
|
|
|
node.append("text")
|
|
.attr("dy", 3)
|
|
.attr("x", d => d.children ? -12 : 12)
|
|
.style("text-anchor", d => d.children ? "end" : "start")
|
|
.text(d => d.data.type);
|
|
|
|
d3.select("body").on("click", function(event) {
|
|
if (!event.target.closest(".node")) {
|
|
d3.select(".tooltip").style("visibility", "hidden");
|
|
d3.selectAll("circle").attr("r", 10);
|
|
}
|
|
});
|
|
|
|
initThreeJs(treeData);
|
|
});
|
|
|
|
function initThreeJs(treeData) {
|
|
const scene = new THREE.Scene();
|
|
const camera = new THREE.PerspectiveCamera(75, window.innerWidth * 0.7 / 800, 0.1, 1000); // Adjusted for the new layout
|
|
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
renderer.setSize(window.innerWidth * 0.7, 800); // Adjusted for half the height
|
|
document.getElementById('threeContainer').appendChild(renderer.domElement);
|
|
|
|
// Add orbit controls for zoom and rotate
|
|
const controls = new THREE.OrbitControls(camera, renderer.domElement);
|
|
controls.enableDamping = true;
|
|
controls.dampingFactor = 0.25;
|
|
controls.screenSpacePanning = false;
|
|
controls.maxPolarAngle = Math.PI / 2;
|
|
|
|
// Add grid helper and axis helper for reference
|
|
const gridHelper = new THREE.GridHelper(10, 10);
|
|
scene.add(gridHelper);
|
|
|
|
const axesHelper = new THREE.AxesHelper(5);
|
|
scene.add(axesHelper);
|
|
|
|
const geometries = [];
|
|
|
|
function createBox(coord, color, id) {
|
|
const geometry = new THREE.BoxGeometry(
|
|
coord.x_upper - coord.x_lower,
|
|
coord.y_upper - coord.y_lower,
|
|
coord.z_upper - coord.z_lower
|
|
);
|
|
const edges = new THREE.EdgesGeometry(geometry);
|
|
const material = new THREE.LineBasicMaterial({ color: color });
|
|
const box = new THREE.LineSegments(edges, material);
|
|
box.position.set(
|
|
(coord.x_upper + coord.x_lower) / 2,
|
|
(coord.y_upper + coord.y_lower) / 2,
|
|
(coord.z_upper + coord.z_lower) / 2
|
|
);
|
|
|
|
scene.add(box);
|
|
geometries.push(box);
|
|
|
|
addToggleControl(box, id);
|
|
}
|
|
|
|
function createTriangle(vertices, leafColor, id) {
|
|
const geometry = new THREE.BufferGeometry();
|
|
const verticesArray = new Float32Array(vertices.flat());
|
|
geometry.setAttribute('position', new THREE.BufferAttribute(verticesArray, 3));
|
|
const material = new THREE.MeshBasicMaterial({ color: leafColor, side: THREE.DoubleSide, wireframe: true });
|
|
const triangle = new THREE.Mesh(geometry, material);
|
|
scene.add(triangle);
|
|
geometries.push(triangle);
|
|
|
|
addToggleControl(triangle, id);
|
|
}
|
|
|
|
function createInstance(instanceProperties, color, id) {
|
|
const geometry = new THREE.SphereGeometry(0.1, 32, 32); // Create a sphere geometry
|
|
const material = new THREE.MeshBasicMaterial({ color: color, wireframe: false }); // Create a material with wireframe
|
|
const sphere = new THREE.Mesh(geometry, material); // Create a mesh
|
|
|
|
const { obj2world_p } = instanceProperties.part0;
|
|
sphere.position.set(obj2world_p[0], obj2world_p[1], obj2world_p[2]);
|
|
|
|
scene.add(sphere);
|
|
geometries.push(sphere);
|
|
|
|
addToggleControl(sphere, id);
|
|
}
|
|
function addToggleControl(geometry, id) {
|
|
const toggleContainer = document.createElement('div');
|
|
toggleContainer.className = 'toggle-container';
|
|
|
|
const checkbox = document.createElement('input');
|
|
checkbox.type = 'checkbox';
|
|
checkbox.checked = true;
|
|
checkbox.addEventListener('change', () => {
|
|
geometry.visible = checkbox.checked;
|
|
});
|
|
|
|
const labelElement = document.createElement('label');
|
|
labelElement.textContent = `${id}`;
|
|
|
|
toggleContainer.appendChild(checkbox);
|
|
toggleContainer.appendChild(labelElement);
|
|
document.getElementById('toggleControls').appendChild(toggleContainer);
|
|
}
|
|
|
|
function handleNode(node, parentType) {
|
|
const leafColor = 0xffa500;
|
|
const internalColor = 0x00ff00;
|
|
if (node.type === 'AnvInternalNode') {
|
|
// Check if the internal node is a fatLeaf
|
|
const isFatProceduralLeaf = node.properties.node_type.nodeType === 0x3;
|
|
const isFatInstanceLeaf = node.properties.node_type.nodeType === 0x1;
|
|
node.properties.child_data.forEach((child, index) => {
|
|
if (child.blockIncr !== 1 && child.blockIncr !== 2) {
|
|
return;
|
|
}
|
|
const childIsProcedural = child.startPrim === 0x3 || isFatProceduralLeaf;
|
|
const childIsInstance = child.startPrim === 0x1 || isFatInstanceLeaf;
|
|
const color = (childIsProcedural || childIsInstance) ? leafColor : internalColor;
|
|
let label = node.id + "'s child box";
|
|
label += (childIsProcedural) ? " also a procedural leaf" : "";
|
|
label += (childIsInstance) ? " also a instance leaf" : "";
|
|
createBox(node.properties.actual_coords[index], color, label);
|
|
});
|
|
} else {
|
|
switch (node.type) {
|
|
case 'AnvQuadLeafNode':
|
|
createTriangle(node.properties.v, leafColor, `Triangle. NodeID=${node.id}`);
|
|
break;
|
|
case 'AnvInstanceLeaf':
|
|
// Skip. Already drawn by parents
|
|
break;
|
|
case 'AnvAabbLeafNode':
|
|
// Skip. Already drawn by parents
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw AABB from header
|
|
const headerAABB = treeData.header.aabb;
|
|
createBox({
|
|
x_lower: headerAABB.min_x,
|
|
x_upper: headerAABB.max_x,
|
|
y_lower: headerAABB.min_y,
|
|
y_upper: headerAABB.max_y,
|
|
z_lower: headerAABB.min_z,
|
|
z_upper: headerAABB.max_z
|
|
}, 0xff00ff, 'Root AABB');
|
|
|
|
// Draw nodes
|
|
treeData.nodes.forEach(node => {
|
|
handleNode(node, node.properties.node_type);
|
|
});
|
|
|
|
camera.position.z = 5;
|
|
|
|
function animate() {
|
|
requestAnimationFrame(animate);
|
|
controls.update();
|
|
renderer.render(scene, camera);
|
|
}
|
|
animate();
|
|
}
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|