2024-01-01 21:11:32 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2024-04-10 02:43:44 +00:00
|
|
|
// This module is browser compatible.
|
2023-12-12 04:33:07 +00:00
|
|
|
|
|
|
|
/** Return value for {@linkcode getRowPadding}. */
|
|
|
|
export interface Padding {
|
|
|
|
/** The number of bytes per row without padding calculated. */
|
|
|
|
unpadded: number;
|
|
|
|
/** The number of bytes per row with padding calculated. */
|
|
|
|
padded: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Buffer-Texture copies must have [`bytes_per_row`] aligned to this number. */
|
|
|
|
export const COPY_BYTES_PER_ROW_ALIGNMENT = 256;
|
|
|
|
|
|
|
|
/** Number of bytes per pixel. */
|
|
|
|
export const BYTES_PER_PIXEL = 4;
|
|
|
|
|
|
|
|
/**
|
2024-06-03 04:10:27 +00:00
|
|
|
* Calculates the number of bytes including necessary padding when passing a
|
|
|
|
* {@linkcode GPUImageCopyBuffer}.
|
2023-12-12 04:33:07 +00:00
|
|
|
*
|
|
|
|
* Ref: https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding
|
|
|
|
*
|
2024-05-22 05:08:36 +00:00
|
|
|
* @example Usage
|
2023-12-12 04:33:07 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { getRowPadding } from "@std/webgpu/row-padding";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2023-12-12 04:33:07 +00:00
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* assertEquals(getRowPadding(1), { unpadded: 4, padded: 256 });
|
2023-12-12 04:33:07 +00:00
|
|
|
* ```
|
2024-05-21 17:33:10 +00:00
|
|
|
*
|
|
|
|
* @param width The width to get the padding for
|
|
|
|
* @returns The padded and unpadded values
|
2023-12-12 04:33:07 +00:00
|
|
|
*/
|
|
|
|
export function getRowPadding(width: number): Padding {
|
|
|
|
// It is a WebGPU requirement that
|
|
|
|
// GPUImageCopyBuffer.layout.bytesPerRow % COPY_BYTES_PER_ROW_ALIGNMENT == 0
|
|
|
|
// So we calculate paddedBytesPerRow by rounding unpaddedBytesPerRow
|
|
|
|
// up to the next multiple of COPY_BYTES_PER_ROW_ALIGNMENT.
|
|
|
|
|
|
|
|
const unpaddedBytesPerRow = width * BYTES_PER_PIXEL;
|
|
|
|
const paddedBytesPerRowPadding = (COPY_BYTES_PER_ROW_ALIGNMENT -
|
|
|
|
(unpaddedBytesPerRow % COPY_BYTES_PER_ROW_ALIGNMENT)) %
|
|
|
|
COPY_BYTES_PER_ROW_ALIGNMENT;
|
|
|
|
const paddedBytesPerRow = unpaddedBytesPerRow + paddedBytesPerRowPadding;
|
|
|
|
|
|
|
|
return {
|
|
|
|
unpadded: unpaddedBytesPerRow,
|
|
|
|
padded: paddedBytesPerRow,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new buffer while removing any unnecessary empty bytes.
|
|
|
|
* Useful for when wanting to save an image as a specific format.
|
|
|
|
*
|
2024-05-22 05:08:36 +00:00
|
|
|
* @example Usage
|
2023-12-12 04:33:07 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { resliceBufferWithPadding } from "@std/webgpu/row-padding";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2023-12-12 04:33:07 +00:00
|
|
|
*
|
|
|
|
* const input = new Uint8Array([0, 255, 0, 255, 120, 120, 120]);
|
2024-06-03 04:10:27 +00:00
|
|
|
* const result = resliceBufferWithPadding(input, 1, 1);
|
|
|
|
*
|
|
|
|
* assertEquals(result, new Uint8Array([0, 255, 0, 255]));
|
2023-12-12 04:33:07 +00:00
|
|
|
* ```
|
2024-05-21 17:33:10 +00:00
|
|
|
*
|
|
|
|
* @param buffer The buffer to reslice.
|
|
|
|
* @param width The width of the output buffer.
|
|
|
|
* @param height The height of the output buffer.
|
|
|
|
* @returns The resliced buffer.
|
2023-12-12 04:33:07 +00:00
|
|
|
*/
|
|
|
|
export function resliceBufferWithPadding(
|
|
|
|
buffer: Uint8Array,
|
|
|
|
width: number,
|
|
|
|
height: number,
|
|
|
|
): Uint8Array {
|
|
|
|
const { padded, unpadded } = getRowPadding(width);
|
|
|
|
const outputBuffer = new Uint8Array(unpadded * height);
|
|
|
|
|
|
|
|
for (let i = 0; i < height; i++) {
|
|
|
|
const slice = buffer
|
|
|
|
.slice(i * padded, (i + 1) * padded)
|
|
|
|
.slice(0, unpadded);
|
|
|
|
|
|
|
|
outputBuffer.set(slice, i * unpadded);
|
|
|
|
}
|
|
|
|
|
|
|
|
return outputBuffer;
|
|
|
|
}
|