Files
marfrit a4e7d8ab90 initial seed: retrofit campaign lineage from local working trees
panvk-bifrost campaigns (r1..r4 Vulkan compositor + r5.video1 Vulkan
video decode) shipped before this repo existed; the deliverable
patches live in marfrit-packages, but the reasoning chain, phase docs,
and source-state evidence lived only in local working trees on the
development host.

This retrofit imports:
- mesa-panvk-bifrost/   — r1..r4 era phase docs (iter1..iter18)
                          (libmali stub blobs at iter18/blob/ excluded
                          — 109MB of RE artifacts replaced with a README
                          pointer)
- mesa-panvk-bifrost-video/ — sibling campaign phase docs + probe
- evidence/             — frozen .tgz source snapshots at each milestone
                          (basis for the 0005 patch diff generation)

Future iterations should branch off here from day one, so each iter is
a commit rather than a snapshot. See [[feedback-session-local-process-pins]]
for the process drift this retrofit closes.

Total: 1.9 MB across 124 files.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 05:25:37 +02:00

129 lines
5.1 KiB
C

/*
* panvk-bifrost-video — Phase 3 regression probe.
*
* Enumerates Vulkan device extensions + queue families on every physical
* device. Emits structured PASS/FAIL lines for the four conditions Phase 1
* of the campaign must flip from FAIL to PASS:
*
* 1. extension VK_KHR_video_queue present
* 2. extension VK_KHR_video_decode_queue present
* 3. extension VK_KHR_video_decode_h264 present
* 4. queue family with VK_QUEUE_VIDEO_DECODE_BIT_KHR (advertising
* videoCodecOperations & VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR)
*
* Build: gcc -O2 -Wall probe_vkvideo.c -lvulkan -o probe_vkvideo
* Run: VK_ICD_FILENAMES=/usr/lib/panvk-bifrost/icd.json \
* PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1 \
* ./probe_vkvideo
*
* Phase 3 baseline (panvk-bifrost r4): all 4 → FAIL.
* Phase 4 commit 1 target: all 4 → PASS (no functionality, just enumeration).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <vulkan/vulkan.h>
#define FAIL(fmt, ...) do { fprintf(stderr, "[fail] " fmt "\n", ##__VA_ARGS__); return 1; } while (0)
#define INFO(fmt, ...) printf("[info] " fmt "\n", ##__VA_ARGS__)
static void report(bool ok, const char *name) {
printf("[%s] %s\n", ok ? "PASS" : "FAIL", name);
}
static bool has_ext(const VkExtensionProperties *exts, uint32_t n, const char *name) {
for (uint32_t i = 0; i < n; i++)
if (strcmp(exts[i].extensionName, name) == 0) return true;
return false;
}
int main(void) {
VkResult r;
VkInstance inst;
const VkApplicationInfo app = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = "panvk-bifrost-video-probe",
.apiVersion = VK_API_VERSION_1_3,
};
const VkInstanceCreateInfo ici = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &app,
};
r = vkCreateInstance(&ici, NULL, &inst);
if (r != VK_SUCCESS) FAIL("vkCreateInstance => %d", r);
uint32_t n_phys = 0;
r = vkEnumeratePhysicalDevices(inst, &n_phys, NULL);
if (r != VK_SUCCESS) FAIL("vkEnumeratePhysicalDevices count => %d", r);
if (n_phys == 0) FAIL("no physical devices");
VkPhysicalDevice *phys = calloc(n_phys, sizeof(*phys));
r = vkEnumeratePhysicalDevices(inst, &n_phys, phys);
if (r != VK_SUCCESS) FAIL("vkEnumeratePhysicalDevices fill => %d", r);
int overall_pass = 0;
for (uint32_t pi = 0; pi < n_phys; pi++) {
VkPhysicalDeviceProperties p;
vkGetPhysicalDeviceProperties(phys[pi], &p);
INFO("device[%u]: %s (vendor=%04x device=%08x)", pi, p.deviceName, p.vendorID, p.deviceID);
uint32_t n_ext = 0;
vkEnumerateDeviceExtensionProperties(phys[pi], NULL, &n_ext, NULL);
VkExtensionProperties *exts = calloc(n_ext, sizeof(*exts));
vkEnumerateDeviceExtensionProperties(phys[pi], NULL, &n_ext, exts);
bool e_queue = has_ext(exts, n_ext, "VK_KHR_video_queue");
bool e_decode = has_ext(exts, n_ext, "VK_KHR_video_decode_queue");
bool e_h264 = has_ext(exts, n_ext, "VK_KHR_video_decode_h264");
report(e_queue, "VK_KHR_video_queue");
report(e_decode, "VK_KHR_video_decode_queue");
report(e_h264, "VK_KHR_video_decode_h264");
/* Queue family enumeration with video-properties pNext walk.
* If VK_KHR_video_queue isn't advertised, this still works but
* VkQueueFamilyVideoPropertiesKHR fields stay zero. */
uint32_t n_qf = 0;
vkGetPhysicalDeviceQueueFamilyProperties2(phys[pi], &n_qf, NULL);
VkQueueFamilyProperties2 *qfp = calloc(n_qf, sizeof(*qfp));
VkQueueFamilyVideoPropertiesKHR *vp = calloc(n_qf, sizeof(*vp));
for (uint32_t i = 0; i < n_qf; i++) {
qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
qfp[i].pNext = e_queue ? &vp[i] : NULL;
vp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
}
vkGetPhysicalDeviceQueueFamilyProperties2(phys[pi], &n_qf, qfp);
bool qf_has_video = false;
bool qf_has_h264 = false;
for (uint32_t i = 0; i < n_qf; i++) {
INFO(" qf[%u]: flags=0x%08x count=%u",
i, qfp[i].queueFamilyProperties.queueFlags,
qfp[i].queueFamilyProperties.queueCount);
if (qfp[i].queueFamilyProperties.queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
qf_has_video = true;
if (vp[i].videoCodecOperations & VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR)
qf_has_h264 = true;
}
}
report(qf_has_video, "queue family with VK_QUEUE_VIDEO_DECODE_BIT_KHR");
report(qf_has_h264, "queue family advertising DECODE_H264 codec op");
if (e_queue && e_decode && e_h264 && qf_has_video && qf_has_h264)
overall_pass = 1;
free(qfp); free(vp); free(exts);
}
free(phys);
vkDestroyInstance(inst, NULL);
printf("\n=== OVERALL: %s ===\n", overall_pass ? "PASS" : "FAIL (Phase 3 baseline expected)");
return overall_pass ? 0 : 2; /* exit 2 distinguishes "ran cleanly, baseline-fail" from build/run errors */
}