Chrome keep printing this warning: "Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true.". I checked the code, where the warning triggers, and you can see I set the willReadFrequently attribute to true. What could be the problem? There was this warning in other places, but there the willReadFrequently attribute solved it.
The problem in Chrome 104-108 exists for sure. Btw, I am in a WebWorker. Could this be a chrome bug?
const offdesireCtx = offDesire.getContext("2d", { willReadFrequently: true });
if (!offdesireCtx) {
throw new Error("Desired OffscrenCanvas ctx undefined");
}
const offGetCtx = offGet.getContext("2d", { willReadFrequently: true });
if (!offGetCtx) {
throw new Error("Get OffscrenCanvas ctx undefined");
}
var imgd = offdesireCtx.getImageData(0, 0, tileSize, tileSize), pix = imgd.data; //Warning triggers
var imgdGet = offGetCtx.getImageData(0, 0, tileSize, tileSize), pixGet = imgdGet.data; //Warning triggers
As MDN says about willReadFrequently
:
This will force the use of a software (instead of hardware accelerated) 2D canvas and can save memory when calling getImageData() frequently.
This means the canvas must be created, drawn to, and read from entirely on the CPU. Calling getContext
provides a handle to the canvas buffer on the GPU by default, and if that call ever occurs with this canvas earlier on, that data is already on the GPU and it would have to be copied back to the CPU, defeating the goal of the performance warning.
I found in my case, I was creating the canvas and writing to it in one function, then returning the canvas. Later in my code, the result of that function call took the same canvas and created another context. It applied the
{ willReadFrequently: true }
options argument to that call, but that was the second time getContext
was called for this canvas. That means the texture buffer was already living on the GPU by this point and the second getContext
call was ignoring the willReadFrequently
suggestion as the data was already on the GPU.
So you need to trace back to where your canvas is first created, and then where its first getContext
is called and drawn to. Subsequent canvas.getContext("2d", { willReadFrequently: true })
calls are too late to matter (and are likely even fine to omit the option). Think about when the texture buffer is being created and trace through your data flow to make sure it all lives on the CPU since its inception.