73 lines
2.8 KiB
C++
73 lines
2.8 KiB
C++
|
|
//SPDX-License-Identifier: LGPL-3.0-only
|
||
|
|
//SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||
|
|
|
||
|
|
// VulkanBuffer::Create asks for a device address only for buffers whose
|
||
|
|
// usage includes SHADER_DEVICE_ADDRESS. It used to request the
|
||
|
|
// DEVICE_ADDRESS allocation flag and call vkGetBufferDeviceAddress for every
|
||
|
|
// buffer, which is invalid usage for the others
|
||
|
|
// (VUID-VkBufferDeviceAddressInfo-buffer-02601), so every caller had to add
|
||
|
|
// the usage bit whether it wanted an address or not. A buffer without the bit
|
||
|
|
// now reports address 0; one with it still gets a real address. A UI
|
||
|
|
// buffer slot points at the buffer by its address, so RegisterBuffer refuses
|
||
|
|
// a buffer without one rather than registering address 0.
|
||
|
|
//
|
||
|
|
// Needs a Vulkan device; the validation check only means something with
|
||
|
|
// CRAFTER_GRAPHICS_VALIDATION set.
|
||
|
|
|
||
|
|
#include <cstdlib>
|
||
|
|
#include "vulkan/vulkan.h"
|
||
|
|
|
||
|
|
import Crafter.Graphics;
|
||
|
|
import std;
|
||
|
|
using namespace Crafter;
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
int failures = 0;
|
||
|
|
|
||
|
|
void Check(bool ok, std::string_view what) {
|
||
|
|
std::println("{} {}", ok ? "PASS" : "FAIL", what);
|
||
|
|
if (!ok) ++failures;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
int main() {
|
||
|
|
Device::Initialize();
|
||
|
|
Device::validationErrorCount = 0;
|
||
|
|
|
||
|
|
VulkanBuffer<std::uint32_t, true> staging;
|
||
|
|
staging.Create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 16);
|
||
|
|
Check(staging.address == 0, std::format("a buffer without SHADER_DEVICE_ADDRESS has no address (got {:#x})", staging.address));
|
||
|
|
|
||
|
|
VulkanBuffer<std::uint32_t, false> resized;
|
||
|
|
resized.Resize(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 16);
|
||
|
|
resized.Resize(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 64);
|
||
|
|
Check(resized.address == 0, "nor after growing through Resize");
|
||
|
|
|
||
|
|
VulkanBuffer<std::uint32_t, false> addressable;
|
||
|
|
addressable.Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 16);
|
||
|
|
Check(addressable.address != 0, "a buffer with SHADER_DEVICE_ADDRESS has one");
|
||
|
|
|
||
|
|
// Refused before it touches the renderer, so an uninitialised one does.
|
||
|
|
UIRenderer ui;
|
||
|
|
bool refused = false;
|
||
|
|
try {
|
||
|
|
(void)ui.RegisterBuffer(staging);
|
||
|
|
} catch (const std::invalid_argument&) {
|
||
|
|
refused = true;
|
||
|
|
}
|
||
|
|
Check(refused, "RegisterBuffer refuses a buffer without a device address");
|
||
|
|
|
||
|
|
if (std::getenv("CRAFTER_GRAPHICS_VALIDATION") != nullptr) {
|
||
|
|
Check(Device::validationErrorCount == 0,
|
||
|
|
std::format("no Vulkan validation errors ({} seen)", Device::validationErrorCount));
|
||
|
|
}
|
||
|
|
|
||
|
|
staging.Clear();
|
||
|
|
resized.Clear();
|
||
|
|
addressable.Clear();
|
||
|
|
std::println("{}", failures == 0 ? "all checks passed" : "check(s) failed");
|
||
|
|
return failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||
|
|
}
|