TextureFormat::BGRA8Unorm is not supported by the adapter
Running the example, I get this error:
Error: 1 - message: Present mode (TextureFormat::BGRA8Unorm) is not supported by the adapter ([Adapter "NVIDIA GeForce GTX 1060 3GB"]) for this surface.
- While calling [Surface].Configure().
I tried to add DeviceDescriptor to request the device with the required feature. But still no luck:
void GetDevice(void (*callback)(wgpu::Device)) {
wgpu::DeviceDescriptor deviceDescriptor{};
wgpu::FeatureName requiredFeatures[] = {wgpu::FeatureName::BGRA8UnormStorage};
deviceDescriptor.requiredFeatures = requiredFeatures;
deviceDescriptor.requiredFeatureCount = 1;
adapter.RequestDevice(
&deviceDescriptor,
// TODO(https://bugs.chromium.org/p/dawn/issues/detail?id=1892): Use
// wgpu::RequestDeviceStatus and wgpu::Device.
[](WGPURequestDeviceStatus status, WGPUDevice cDevice,
const char* message, void* userdata) {
if (message) {
printf("RequestDevice: %s\n", message);
}
wgpu::Device device = wgpu::Device::Acquire(cDevice);
device.SetUncapturedErrorCallback(
[](WGPUErrorType type, const char* message, void* userdata) {
std::cout << "Error: " << type << " - message: " << message;
},
nullptr);
reinterpret_cast<void (*)(wgpu::Device)>(userdata)(device);
}, reinterpret_cast<void*>(callback));
}
The only way I could make this code work is to explicitly create the SwapChain object instead of surface configuration. I couldn't figure out what causes this issue, though. What's more interesting is that with the SwapChain method, I didn't even need to pass the DeviceDescriptor to RequestDevice.
I could have created a pull request out of the following code, but I was not sure whether surface configuration meant be done for this example or not.
#include <GLFW/glfw3.h>
#include <iostream>
#include <webgpu/webgpu_cpp.h>
#include <iostream>
#if defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#else
#include <webgpu/webgpu_glfw.h>
#endif
wgpu::Instance instance;
wgpu::Adapter adapter;
wgpu::Device device;
wgpu::RenderPipeline pipeline;
wgpu::SwapChain swapChain;
wgpu::Surface surface;
wgpu::TextureFormat format = wgpu::TextureFormat::BGRA8Unorm;
const uint32_t kWidth = 512;
const uint32_t kHeight = 512;
void ConfigureSwapChain() {
wgpu::SwapChainDescriptor swapChainDesc{};
swapChainDesc.usage = wgpu::TextureUsage::RenderAttachment;
swapChainDesc.format = format;
swapChainDesc.width = kWidth;
swapChainDesc.height = kHeight;
swapChainDesc.presentMode = wgpu::PresentMode::Fifo;
swapChain = device.CreateSwapChain(surface, &swapChainDesc);
}
void GetAdapter(void (*callback)(wgpu::Adapter)) {
instance.RequestAdapter(
nullptr,
// TODO(https://bugs.chromium.org/p/dawn/issues/detail?id=1892): Use
// wgpu::RequestAdapterStatus and wgpu::Adapter.
[](WGPURequestAdapterStatus status, WGPUAdapter cAdapter,
const char* message, void* userdata) {
if (message) {
printf("RequestAdapter: %s\n", message);
}
if (status != WGPURequestAdapterStatus_Success) {
exit(0);
}
wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
reinterpret_cast<void (*)(wgpu::Adapter)>(userdata)(adapter);
}, reinterpret_cast<void*>(callback));
}
void GetDevice(void (*callback)(wgpu::Device)) {
adapter.RequestDevice(
nullptr,
// TODO(https://bugs.chromium.org/p/dawn/issues/detail?id=1892): Use
// wgpu::RequestDeviceStatus and wgpu::Device.
[](WGPURequestDeviceStatus status, WGPUDevice cDevice,
const char* message, void* userdata) {
if (message) {
printf("RequestDevice: %s\n", message);
}
wgpu::Device device = wgpu::Device::Acquire(cDevice);
device.SetUncapturedErrorCallback(
[](WGPUErrorType type, const char* message, void* userdata) {
std::cout << "Error: " << type << " - message: " << message;
},
nullptr);
reinterpret_cast<void (*)(wgpu::Device)>(userdata)(device);
}, reinterpret_cast<void*>(callback));
}
const char shaderCode[] = R"(
@vertex fn vertexMain(@builtin(vertex_index) i : u32) ->
@builtin(position) vec4f {
const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));
return vec4f(pos[i], 0, 1);
}
@fragment fn fragmentMain() -> @location(0) vec4f {
return vec4f(1, 0, 0, 1);
}
)";
void CreateRenderPipeline() {
wgpu::ShaderModuleWGSLDescriptor wgslDesc{};
wgslDesc.code = shaderCode;
wgpu::ShaderModuleDescriptor shaderModuleDescriptor{
.nextInChain = &wgslDesc};
wgpu::ShaderModule shaderModule =
device.CreateShaderModule(&shaderModuleDescriptor);
wgpu::ColorTargetState colorTargetState{.format = format};
wgpu::FragmentState fragmentState{.module = shaderModule,
.targetCount = 1,
.targets = &colorTargetState};
wgpu::RenderPipelineDescriptor descriptor{
.vertex = {.module = shaderModule},
.fragment = &fragmentState};
pipeline = device.CreateRenderPipeline(&descriptor);
}
void Render() {
wgpu::TextureView backbuffer = swapChain.GetCurrentTextureView();
wgpu::RenderPassColorAttachment attachment{
.view = backbuffer,
.loadOp = wgpu::LoadOp::Clear,
.storeOp = wgpu::StoreOp::Store,
.clearValue = {0.3f, 0.3f, 0.3f, 1.0f}};
wgpu::RenderPassDescriptor renderpass{.colorAttachmentCount = 1,
.colorAttachments = &attachment};
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderpass);
pass.SetPipeline(pipeline);
pass.Draw(3);
pass.End();
wgpu::CommandBuffer commands = encoder.Finish();
device.GetQueue().Submit(1, &commands);
swapChain.Present();
}
void InitGraphics() {
ConfigureSwapChain();
CreateRenderPipeline();
}
void Start() {
if (!glfwInit()) {
return;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window =
glfwCreateWindow(kWidth, kHeight, "WebGPU window", nullptr, nullptr);
#if defined(__EMSCRIPTEN__)
wgpu::SurfaceDescriptorFromCanvasHTMLSelector canvasDesc{};
canvasDesc.selector = "#canvas";
wgpu::SurfaceDescriptor surfaceDesc{.nextInChain = &canvasDesc};
surface = instance.CreateSurface(&surfaceDesc);
#else
surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
#endif
InitGraphics();
#if defined(__EMSCRIPTEN__)
emscripten_set_main_loop(Render, 0, false);
#else
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
Render();
instance.ProcessEvents();
}
#endif
}
int main() {
instance = wgpu::CreateInstance();
GetAdapter([](wgpu::Adapter a) {
adapter = a;
GetDevice([](wgpu::Device d) {
device = d;
Start();
});
});
}
This is very strange, bgra8unorm should be the preferred format on everything except Android. (bgra8unorm-storage isn't relevant here, that's only needed if you use STORAGE usage, aka SSBO.) It sounds like a Dawn bug.
Could you please provide the chrome://gpu report from a Chromium browser on your system?
Sure. Here it is: about-gpu-2024-06-21T19-12-30-905Z.txt
Wait... I reread the error message and it doesn't make any sense.
Present mode (TextureFormat::BGRA8Unorm) is not supported by the adapter
BGRA8Unorm is not a present mode, it's a format. The error is erroneously printing the format when it should be printing the present mode.
Filed https://crbug.com/348590029 about that.
Anyway, I still don't know what the problem is because you are using Fifo and Fifo is supposed to be always supported. Maybe something weird is happening and Dawn is not actually receiving Fifo but some other present mode. You could try fixing the error messages in your Dawn checkout and see what it prints.
Thanks. Upvoted.
Yeah, I put Fifo after I got the error, and it doesn't make any changes.
I saw your filed bug, and I commented those three lines out of curiosity, and I rebuilt dawn. Of course, the original source worked like a charm!
// DAWN_INVALID_IF(presentModeIt == capabilities.presentModes.end(),
// "Present mode (%s) is not supported by the adapter (%s) for this surface.",
// config->format, config->device->GetAdapter());
Maybe, capabilities doesn't get populated correctly, or maybe the whole error checking is erroneous? 🤔
Maybe,
capabilitiesdoesn't get populated correctly
I think this is the most likely. Not sure why though.
Filed https://crbug.com/348699454 for that too.
Re: PresentMode::Fifo not being present, that mode is required to be supported in Vulkan and Dawn should translate it correctly. Can you provide the output of vulkaninfo?
@Kangz Sure: vulkaninfo.txt
Thank you!
GPU id : 0 (NVIDIA GeForce GTX 1060 3GB):
Surface types: count = 2
VK_KHR_xcb_surface
VK_KHR_xlib_surface
Formats: count = 2
SurfaceFormat[0]:
format = FORMAT_B8G8R8A8_UNORM
colorSpace = COLOR_SPACE_SRGB_NONLINEAR_KHR
SurfaceFormat[1]:
format = FORMAT_B8G8R8A8_SRGB
colorSpace = COLOR_SPACE_SRGB_NONLINEAR_KHR
Present Modes: count = 3
PRESENT_MODE_FIFO_KHR
PRESENT_MODE_FIFO_RELAXED_KHR
PRESENT_MODE_IMMEDIATE_KHR
VkSurfaceCapabilitiesKHR:
-------------------------
minImageCount = 2
maxImageCount = 8
currentExtent:
width = 256
height = 256
minImageExtent:
width = 256
height = 256
maxImageExtent:
width = 256
height = 256
maxImageArrayLayers = 1
supportedTransforms: count = 1
SURFACE_TRANSFORM_IDENTITY_BIT_KHR
currentTransform = SURFACE_TRANSFORM_IDENTITY_BIT_KHR
supportedCompositeAlpha: count = 1
COMPOSITE_ALPHA_OPAQUE_BIT_KHR
supportedUsageFlags: count = 6
IMAGE_USAGE_TRANSFER_SRC_BIT
IMAGE_USAGE_TRANSFER_DST_BIT
IMAGE_USAGE_SAMPLED_BIT
IMAGE_USAGE_STORAGE_BIT
IMAGE_USAGE_COLOR_ATTACHMENT_BIT
IMAGE_USAGE_INPUT_ATTACHMENT_BIT
VkSharedPresentSurfaceCapabilitiesKHR:
--------------------------------------
sharedPresentSupportedUsageFlags: count = 6
IMAGE_USAGE_TRANSFER_SRC_BIT
IMAGE_USAGE_TRANSFER_DST_BIT
IMAGE_USAGE_SAMPLED_BIT
IMAGE_USAGE_STORAGE_BIT
IMAGE_USAGE_COLOR_ATTACHMENT_BIT
IMAGE_USAGE_INPUT_ATTACHMENT_BIT
VkSurfaceProtectedCapabilitiesKHR:
----------------------------------
supportsProtected = false
and
GPU id : 1 (llvmpipe (LLVM 12.0.0, 256 bits)):
Surface types: count = 2
VK_KHR_xcb_surface
VK_KHR_xlib_surface
Formats: count = 2
SurfaceFormat[0]:
format = FORMAT_B8G8R8A8_SRGB
colorSpace = COLOR_SPACE_SRGB_NONLINEAR_KHR
SurfaceFormat[1]:
format = FORMAT_B8G8R8A8_UNORM
colorSpace = COLOR_SPACE_SRGB_NONLINEAR_KHR
Present Modes: count = 4
PRESENT_MODE_IMMEDIATE_KHR
PRESENT_MODE_MAILBOX_KHR
PRESENT_MODE_FIFO_KHR
PRESENT_MODE_FIFO_RELAXED_KHR
VkSurfaceCapabilitiesKHR:
-------------------------
minImageCount = 3
maxImageCount = 0
currentExtent:
width = 256
height = 256
minImageExtent:
width = 256
height = 256
maxImageExtent:
width = 256
height = 256
maxImageArrayLayers = 1
supportedTransforms: count = 1
SURFACE_TRANSFORM_IDENTITY_BIT_KHR
currentTransform = SURFACE_TRANSFORM_IDENTITY_BIT_KHR
supportedCompositeAlpha: count = 2
COMPOSITE_ALPHA_OPAQUE_BIT_KHR
COMPOSITE_ALPHA_INHERIT_BIT_KHR
supportedUsageFlags: count = 5
IMAGE_USAGE_TRANSFER_SRC_BIT
IMAGE_USAGE_TRANSFER_DST_BIT
IMAGE_USAGE_SAMPLED_BIT
IMAGE_USAGE_STORAGE_BIT
IMAGE_USAGE_COLOR_ATTACHMENT_BIT
VkSurfaceProtectedCapabilitiesKHR:
----------------------------------
supportsProtected = false
Fifo is indeed present. The code in Dawn should translate it correctly to wgpu::PresentMode::Fifo so I'm really not sure why the validation triggers.
@Kangz Thanks for the double check.
I checked out dawn to the main branch and tried without the fix:
// DAWN_INVALID_IF(presentModeIt == capabilities.presentModes.end(),
// "Present mode (%s) is not supported by the adapter (%s) for this surface.",
// config->format, config->device->GetAdapter());
And now there is no issue anymore. 🤔
Maybe the dawn branch should be updated in the .gitmodule then?
I use chromium/6478 branch in .gitmodule which is Chrome 126.
I now wonder which dawn change actually fixed the error you're seeing.