1#include "TexturesWebGPU.h"
3#include "FormatsWebGPU.h"
4#include "GraphicsDeviceWebGPU.h"
5#include "Foundation/Logging/Logger.h"
7#include "Foundation/StringView.h"
9#include <glm/gtc/color_space.hpp>
10#include <glm/detail/func_packing.inl>
15 void textures_error_callback(WGPUPopErrorScopeStatus status, WGPUErrorType type, WGPUStringView message,
void* userdata1,
void* userdata2)
21 if(status == WGPUPopErrorScopeStatus_CallbackCancelled){
22 LOG_ERROR(logger,
"WebGPU textures err status: Cancelled");
24 if(status == WGPUPopErrorScopeStatus_Error){
25 LOG_ERROR(logger,
"WebGPU textures err status: Error");
27 if(message.data && message.length){
28 LOG_ERROR(logger,
"WebGPU textures err (%d) %.*s", type, WGPUStringViewFormat(message));
35 case Cogs::SamplerState::ComparisonFunction::Never:
36 return WGPUCompareFunction_Never;
37 case Cogs::SamplerState::ComparisonFunction::Less:
38 return WGPUCompareFunction_Less;
39 case Cogs::SamplerState::ComparisonFunction::Equal:
40 return WGPUCompareFunction_Equal;
41 case Cogs::SamplerState::ComparisonFunction::LessEqual:
42 return WGPUCompareFunction_LessEqual;
43 case Cogs::SamplerState::ComparisonFunction::Greater:
44 return WGPUCompareFunction_Greater;
45 case Cogs::SamplerState::ComparisonFunction::NotEqual:
46 return WGPUCompareFunction_NotEqual;
47 case Cogs::SamplerState::ComparisonFunction::GreaterEqual:
48 return WGPUCompareFunction_GreaterEqual;
49 case Cogs::SamplerState::ComparisonFunction::Always:
50 return WGPUCompareFunction_Always;
51 case Cogs::SamplerState::ComparisonFunction::ComparisonFunction_Size:
55 return WGPUCompareFunction_Undefined;
62 return WGPUAddressMode_ClampToEdge;
64 return WGPUAddressMode_Repeat;
66 return WGPUAddressMode_MirrorRepeat;
68 LOG_WARNING_ONCE(logger,
"WebGPU backend does not support SamplerState::AddressMode::Border.");
69 return WGPUAddressMode_ClampToEdge;
70 case Cogs::SamplerState::AddressMode::AddressMode_Size:
74 return WGPUAddressMode_Repeat;
80 void TexturesWebGPU::initialize(
class GraphicsDeviceWebGPU *device)
82 graphicsDevice = device;
88 wgpuTextureSetLabel(texture.texture, {name.data(), name.length()});
91 static void writeMipLevelToGPU(
GraphicsDeviceWebGPU *graphicsDevice, WGPUTexture *destinationTexture,
void *data, uint32_t cubeFace, uint32_t arrayLayer, uint32_t mipLevel,
Cogs::TextureExtent textureExtent,
size_t levelSize, uint32_t bytesPerPixel)
93 WGPUTexelCopyBufferLayout layout = WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT;
95 layout.bytesPerRow = bytesPerPixel * textureExtent.width;
96 layout.rowsPerImage = textureExtent.height;
98 WGPUTexelCopyTextureInfo destination = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT;
99 destination.texture = *destinationTexture;
100 destination.aspect = WGPUTextureAspect_All;
101 destination.origin = { 0, 0,
static_cast<uint32_t
>(arrayLayer + cubeFace) };
102 destination.mipLevel =
static_cast<uint32_t
>(mipLevel);
103 WGPUExtent3D sizeExtent = { textureExtent.width, textureExtent.height, textureExtent.depth };
104 wgpuQueueWriteTexture(graphicsDevice->queue, &destination, data, levelSize, &layout, &sizeExtent);
107 template <
typename T>
108 static void convertMiplevelDataToFloatData(
float *out, T *data,
size_t nPixels, uint32_t channels,
bool isSigned,
bool isFloat,
bool isHalfFloat,
bool isSRGB,
bool hasAlpha)
110 float valRange = std::powf(2, 8 *
sizeof(T)) - 1.0f;
112 memcpy(out, data,
static_cast<size_t>(isFloat) * nPixels * channels *
sizeof(
float));
114 for(
size_t pixel = 0; pixel < nPixels * static_cast<size_t>(!isFloat); pixel++) {
115 for(
size_t channel = 0; channel < channels; channel++) {
116 T channelData = data[(pixel * channels) + channel];
117 size_t isSignBitSet =
static_cast<size_t>(isSigned) & (
static_cast<size_t>(channelData) >> ((
sizeof(T) * 8) - 1));
120 T channelDataShifted = channelData +
static_cast<T
>((
static_cast<size_t>(!isHalfFloat) * isSignBitSet * (
static_cast<size_t>(valRange) >> 1)));
122 glm::vec2 halfFloatToFloatVec = glm::unpackHalf2x16(
static_cast<uint32_t
>(channelDataShifted));
123 float halfFloatToFloat = halfFloatToFloatVec.x;
125 float channelDataAsFloat = (
static_cast<size_t>(!isHalfFloat) *
static_cast<float>(channelDataShifted) / valRange) + (
static_cast<float>(
static_cast<size_t>(isHalfFloat)) * halfFloatToFloat);
126 channelDataAsFloat -= 1.0f * isSignBitSet *
static_cast<size_t>(!isHalfFloat);
128 size_t isNotAlphaChannel =
static_cast<size_t>(!hasAlpha) + (
static_cast<size_t>(hasAlpha) *
static_cast<size_t>((channel < (channels-1))));
129 size_t isAlphaChannel =
static_cast<size_t>(hasAlpha) *
static_cast<size_t>((channel == (channels-1)));
131 glm::vec3 channelDataVecGamma = glm::convertSRGBToLinear(glm::vec3(channelDataAsFloat, 0.0f, 0.0f));
132 float channelDataGamma = channelDataVecGamma.r;
134 float dataSRGBToLinear =
static_cast<size_t>(isSRGB) * ((isNotAlphaChannel * channelDataGamma) + (isAlphaChannel * channelDataAsFloat));
136 channelDataAsFloat = (
static_cast<size_t>(!isSRGB) * channelDataAsFloat) + (
static_cast<size_t>(isSRGB) * dataSRGBToLinear);
138 out[(pixel * channels) + channel] = channelDataAsFloat;
143 template <
typename T>
144 static void nextMiplevelFromFloatData(T *nativeTypeOut,
float *data,
Cogs::TextureExtent textureExtent, uint32_t channels,
bool isSigned,
bool isFloat,
bool isHalfFloat,
bool isSRGB,
bool hasAlpha)
146 float valRange = std::powf(2, 8 *
sizeof(T)) - 1.0f;
148 for (
size_t y = 0; y < textureExtent.height; y++)
150 for (
size_t x = 0; x < textureExtent.width; x++)
152 float *writeFloat = &data[channels * (y * textureExtent.width + x)];
153 T *write = &nativeTypeOut[channels * (y * textureExtent.width + x)];
155 float *s0 = &data[channels * ((2 * y + 0) * (2 * textureExtent.width) + (2 * x + 0))];
156 float *s1 = &data[channels * ((2 * y + 0) * (2 * textureExtent.width) + (2 * x + 1))];
157 float *s2 = &data[channels * ((2 * y + 1) * (2 * textureExtent.width) + (2 * x + 0))];
158 float *s3 = &data[channels * ((2 * y + 1) * (2 * textureExtent.width) + (2 * x + 1))];
160 for (
size_t channel = 0; channel < channels; channel++) {
161 float channelDataFloat = (s0[channel] + s1[channel] + s2[channel] + s3[channel]) / 4.0f;
163 writeFloat[channel] = channelDataFloat;
165 size_t isSignBitSet =
static_cast<size_t>(isSigned) & (
static_cast<size_t>(channelDataFloat) >> ((
sizeof(T) * 8) - 1));
167 float channelDataFloatShifted = channelDataFloat + 1.0f *
static_cast<float>(
static_cast<size_t>(!isHalfFloat)) *
static_cast<float>(isSignBitSet) *
static_cast<float>(
static_cast<size_t>(!isFloat));
169 size_t isNotAlphaChannel =
static_cast<size_t>(!hasAlpha) + (
static_cast<size_t>(hasAlpha) *
static_cast<size_t>((channel < (channels-1))));
170 size_t isAlphaChannel =
static_cast<size_t>(hasAlpha) *
static_cast<size_t>((channel == (channels-1)));
172 glm::vec3 channelDataVecGamma = glm::convertLinearToSRGB(glm::vec3(channelDataFloatShifted, 0.0f, 0.0f));
173 float channelDataGamma = channelDataVecGamma.r;
175 float channelDataLinearToSRGB =
static_cast<size_t>(isSRGB) * ((isNotAlphaChannel * channelDataGamma) + (isAlphaChannel * channelDataFloatShifted));
177 channelDataFloatShifted = (
static_cast<size_t>(!isSRGB) * channelDataFloatShifted) + (
static_cast<size_t>(isSRGB) * channelDataLinearToSRGB);
179 uint16_t floatToHalfFloat =
static_cast<uint16_t
>(glm::packHalf2x16(glm::vec2(channelDataFloat, 0.0f)));
181 T channelData =
static_cast<T
>((
static_cast<size_t>(!isFloat) *
static_cast<size_t>(!isHalfFloat) * channelDataFloatShifted * valRange) + (
static_cast<size_t>(isFloat) * channelDataFloat) + (
static_cast<size_t>(isHalfFloat) * floatToHalfFloat));
183 write[channel] = channelData;
189 template <
typename T>
190 static void generateMipmapsInternal(GraphicsDeviceWebGPU *graphicsDevice, WGPUTexture *destinationTexture,
const TextureData *data, uint32_t faces, uint32_t layers, uint32_t levels, uint32_t bytesPerChannel, uint32_t channels,
bool isSigned,
bool isFloat,
bool isHalfFloat,
bool isSRGB,
bool hasAlpha)
192 uint32_t bytesPerPixel = bytesPerChannel * channels;
193 size_t nPixels = data->getLevelSize(0) / bytesPerPixel;
195 size_t levelSize = data->getLevelSize(0);
197 std::vector<T> currLevelData(levelSize);
198 std::vector<T> prevLevelData(nPixels * channels);
199 std::vector<float> prevLevelDataFloat(nPixels * channels);
203 for (uint32_t f = 0; f < faces; ++f) {
204 for (uint32_t a = 0; a < layers; ++a) {
205 textureExtent = data->getExtent(0);
207 T* tmpLevelData =
reinterpret_cast<T*
>(
const_cast<void*
>(data->getData(a, f, 0)));
208 memcpy(prevLevelData.data(), tmpLevelData, levelSize);
210 writeMipLevelToGPU(graphicsDevice, destinationTexture, prevLevelData.data(), f, a, 0, textureExtent, levelSize, bytesPerPixel);
212 convertMiplevelDataToFloatData<T>(prevLevelDataFloat.data(), prevLevelData.data(), nPixels, channels, isSigned, isFloat, isHalfFloat, isSRGB, hasAlpha);
214 for (uint32_t m = 1; m < levels; ++m) {
215 textureExtent = data->getExtent(m);
216 size_t currentLevelSize = data->getLevelSize(m);
218 nextMiplevelFromFloatData(currLevelData.data(), prevLevelDataFloat.data(), textureExtent, channels, isSigned, isFloat, isHalfFloat, isSRGB, hasAlpha);
220 writeMipLevelToGPU(graphicsDevice, destinationTexture, currLevelData.data(), f, a, m, textureExtent, currentLevelSize, bytesPerPixel);
230 WGPUDevice device = graphicsDevice->device;
232 if(graphicsDevice->use_error_scope){
233 wgpuDevicePushErrorScope(graphicsDevice->device, graphicsDevice->filter);
237 texture.estimatedByteSize = uint32_t(td.estimateMemorySize());
239 WGPUTextureFormat format = TextureFormatsWebGPU[(size_t)td.format];
243 WGPUTextureFormat view_formats[] = {format};
245 uint32_t mipLevelCount = td.levels;
248 WGPUTextureDescriptor desc = WGPU_TEXTURE_DESCRIPTOR_INIT;
250 desc.usage = WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding;
251 desc.usage |= WGPUTextureUsage_CopySrc;
254 desc.usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst | WGPUTextureUsage_CopySrc;
257 desc.usage |= WGPUTextureUsage_StorageBinding;
259 if(td.target == ResourceDimensions::Texture1D ||
260 td.target == ResourceDimensions::Texture1DArray){
261 desc.dimension = WGPUTextureDimension_1D;
263 else if(td.target == ResourceDimensions::Texture3D ||
264 td.target == ResourceDimensions::Texture3DArray){
265 desc.dimension = WGPUTextureDimension_3D;
268 desc.dimension = WGPUTextureDimension_2D;
272 bool compressedFormat =
278 if(compressedFormat) {
279 LOG_WARNING_ONCE(logger,
"Generating mips for compressed textures is not supported.");
281 size_t max = glm::max(td.width, td.height);
291 desc.size = {td.width, td.height, td.depth*td.faces*td.layers };
292 desc.format = format;
293 desc.mipLevelCount = mipLevelCount;
295 desc.sampleCount = td.samples > 1 ? 4 : 1;
296 desc.viewFormatCount =
sizeof(view_formats)/
sizeof(view_formats[0]);
297 desc.viewFormats = view_formats;
299#ifndef __EMSCRIPTEN__
300 wgpuDeviceValidateTextureDescriptor(device, &desc);
304 assert(data !=
nullptr && data->externalHandle != 0);
305 if (mipLevelCount != 1) {
306 LOG_WARNING_ONCE(logger,
"External WebGPU textures currently only support 1 mip level; mipmap generation is deferred.");
308 desc.mipLevelCount = 1;
310 texture.texture =
reinterpret_cast<WGPUTexture
>(data->externalHandle);
312 texture.texture = wgpuDeviceCreateTexture(device, &desc);
317 texture.view_format = desc.format;
318 texture.format = td.format;
319 if(td.target == ResourceDimensions::Texture1D ||
320 td.target == ResourceDimensions::Texture1DArray){
321 texture.view_dimension = WGPUTextureViewDimension_1D;
323 else if(td.target == ResourceDimensions::Texture2D ||
324 td.target == ResourceDimensions::Texture2DMS){
325 texture.view_dimension = WGPUTextureViewDimension_2D;
327 else if(td.target == ResourceDimensions::Texture2DArray ||
328 td.target == ResourceDimensions::Texture2DMSArray){
329 texture.view_dimension = WGPUTextureViewDimension_2DArray;
331 else if(td.target == ResourceDimensions::Texture3D ||
332 td.target == ResourceDimensions::Texture3DArray){
333 texture.view_dimension = WGPUTextureViewDimension_3D;
335 else if(td.target == ResourceDimensions::TextureCube){
336 texture.view_dimension = WGPUTextureViewDimension_Cube;
338 else if(td.target == ResourceDimensions::TextureCubeArray){
339 texture.view_dimension = WGPUTextureViewDimension_CubeArray;
345 WGPUTextureViewDescriptor view_desc = WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT;
346 view_desc.label = {
"DefaultTextureView", WGPU_STRLEN};
347 view_desc.format = format;
348 view_desc.dimension = texture.view_dimension;
349 view_desc.baseMipLevel = 0;
350 view_desc.mipLevelCount = mipLevelCount;
351 view_desc.baseArrayLayer = 0;
352 view_desc.arrayLayerCount = td.faces*td.layers;
353 view_desc.aspect = WGPUTextureAspect_All;
354 texture.texture_view = wgpuTextureCreateView(texture.texture, &view_desc);
355 counters.texture_view++;
357 texture.width = td.width;
358 texture.height = td.height;
359 texture.samples = desc.sampleCount;
360 texture.flags = td.flags;
364 uint32_t faces = std::min(td.faces,
static_cast<uint32_t
>(data->faces));
365 uint32_t layers = std::min(td.layers,
static_cast<uint32_t
>(data->layers));
366 uint32_t levels = mipLevelCount;
368 if(generateMips && !compressedFormat) {
370 Cogs::DataFormat formatType = parseDataFormat(textureFormat->
name);
372 switch (formatType) {
373 case(Cogs::DataFormat::R8_UNORM):
374 case(Cogs::DataFormat::R8G8_UNORM):
375 case(Cogs::DataFormat::R8G8B8_UNORM):
376 case(Cogs::DataFormat::R8G8B8A8_UNORM):
378 generateMipmapsInternal<uint8_t>(
394 case(Cogs::DataFormat::R8_SNORM):
395 case(Cogs::DataFormat::R8G8_SNORM):
396 case(Cogs::DataFormat::R8G8B8_SNORM):
397 case(Cogs::DataFormat::R8G8B8A8_SNORM):
399 generateMipmapsInternal<uint8_t>(
415 case(Cogs::DataFormat::R16_UNORM):
416 case(Cogs::DataFormat::R16G16_UNORM):
417 case(Cogs::DataFormat::R16G16B16_UNORM):
418 case(Cogs::DataFormat::R16G16B16A16_UNORM):
420 generateMipmapsInternal<uint16_t>(
436 case(Cogs::DataFormat::R16_SNORM):
437 case(Cogs::DataFormat::R16G16_SNORM):
438 case(Cogs::DataFormat::R16G16B16_SNORM):
439 case(Cogs::DataFormat::R16G16B16A16_SNORM):
441 generateMipmapsInternal<uint16_t>(
457 case(Cogs::DataFormat::R16_FLOAT):
458 case(Cogs::DataFormat::R16G16_FLOAT):
459 case(Cogs::DataFormat::R16G16B16_FLOAT):
460 case(Cogs::DataFormat::R16G16B16A16_FLOAT):
462 generateMipmapsInternal<uint16_t>(
478 case(Cogs::DataFormat::R32_FLOAT):
479 case(Cogs::DataFormat::R32G32_FLOAT):
480 case(Cogs::DataFormat::R32G32B32_FLOAT):
481 case(Cogs::DataFormat::R32G32B32A32_FLOAT):
483 generateMipmapsInternal<float>(
499 case(Cogs::DataFormat::R8G8B8_UNORM_SRGB):
501 generateMipmapsInternal<uint8_t>(
517 case(Cogs::DataFormat::R8G8B8A8_UNORM_SRGB):
519 generateMipmapsInternal<uint8_t>(
540 for (
size_t f = 0; f < faces; ++f) {
541 for (
size_t a = 0; a < layers; ++a) {
542 for (
size_t m = 0; m < mipLevelCount; ++m) {
544 const void* ptr = data->getData(a, f, m);
545 const size_t ptr_size = data->getLevelSize(m);
547 if ((extent.width % data->blockExtent.width) != 0) {
548 extent.width = (extent.width / data->blockExtent.width + 1) * data->blockExtent.width;
550 if ((extent.height % data->blockExtent.height) != 0) {
551 extent.height = (extent.height / data->blockExtent.height + 1) * data->blockExtent.height;
554 WGPUTexelCopyTextureInfo dst = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT;
555 dst.texture = texture.texture;
556 dst.mipLevel = (uint32_t)m;
557 dst.origin = { 0, 0, (uint32_t)(a + f) };
558 dst.aspect = WGPUTextureAspect_All;
560 WGPUTexelCopyBufferLayout layout = WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT;
562 layout.bytesPerRow = (uint32_t)data->getPitch(m);
563 layout.rowsPerImage = extent.height;
564 WGPUExtent3D size = { extent.width, extent.height, extent.depth };
565 wgpuQueueWriteTexture(graphicsDevice->queue, &dst, ptr, ptr_size, &layout, &size);
572 textureMemoryConsumption += texture.estimatedByteSize;
574 if(graphicsDevice->use_error_scope){
575 WGPUPopErrorScopeCallbackInfo info = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT;
576 info.mode = WGPUCallbackMode_AllowSpontaneous;
577 info.callback = textures_error_callback;
578 info.userdata1 =
this;
579 info.userdata2 = graphicsDevice;
580 WGPUFuture future = wgpuDevicePopErrorScope(graphicsDevice->device, info);
584 return textures.addResource(std::move(texture));
590 if(!HandleIsValid(handle))
return;
594 wgpuTextureViewRelease(texture.texture_view);
595 counters.texture_view--;
596 if ((texture.flags & TextureFlags::NoDelete) == 0 &&
597 (texture.flags & TextureFlags::ExternalTexture) == 0) {
598 wgpuTextureDestroy(texture.texture);
599 wgpuTextureRelease(texture.texture);
602 textureMemoryConsumption -= texture.estimatedByteSize;
604 textures.removeResource(handle);
607 void TexturesWebGPU::releaseNativeTexture(TextureNativeHandle nativeHandle)
609 WGPUTexture texture =
reinterpret_cast<WGPUTexture
>(nativeHandle);
610 wgpuTextureDestroy(texture);
611 wgpuTextureRelease(texture);
619 if(graphicsDevice->use_error_scope){
620 wgpuDevicePushErrorScope(graphicsDevice->device, graphicsDevice->filter);
625 WGPUTextureViewDescriptor desc = WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT;
627 desc.format = texture.view_format;
628 desc.dimension = texture.view_dimension;
630 switch(desc.dimension){
631 case WGPUTextureViewDimension_2DArray:
632 desc.dimension = WGPUTextureViewDimension_2D;
634 case WGPUTextureViewDimension_CubeArray:
635 desc.dimension = WGPUTextureViewDimension_Cube;
645 desc.aspect = WGPUTextureAspect_All;
646 texture_view.texture_view = wgpuTextureCreateView(texture.texture, &desc);
647 counters.texture_view++;
649 if(graphicsDevice->use_error_scope){
650 WGPUPopErrorScopeCallbackInfo info = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT;
651 info.mode = WGPUCallbackMode_AllowSpontaneous;
652 info.callback = textures_error_callback;
653 info.userdata1 =
this;
654 info.userdata2 = graphicsDevice;
655 WGPUFuture future = wgpuDevicePopErrorScope(graphicsDevice->device, info);
659 return textureViews.addResource(std::move(texture_view));
664 if(!HandleIsValid(handle))
return;
668 wgpuTextureViewRelease(texture_view.texture_view);
669 counters.texture_view--;
671 textureViews.removeResource(handle);
677 WGPUDevice device = graphicsDevice->device;
679 if(graphicsDevice->use_error_scope){
680 wgpuDevicePushErrorScope(graphicsDevice->device, graphicsDevice->filter);
685 WGPUSamplerDescriptor desc = WGPU_SAMPLER_DESCRIPTOR_INIT;
691 case SamplerState::FilterMode::MinMagMipPoint:
692 desc.magFilter = WGPUFilterMode_Nearest;
693 desc.minFilter = WGPUFilterMode_Nearest;
694 desc.mipmapFilter = WGPUMipmapFilterMode_Nearest;
695 desc.compare = WGPUCompareFunction_Undefined;
697 case SamplerState::FilterMode::MinMagMipLinear:
698 desc.magFilter = WGPUFilterMode_Linear;
699 desc.minFilter = WGPUFilterMode_Linear;
700 desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
701 desc.compare = WGPUCompareFunction_Undefined;
703 case SamplerState::FilterMode::ComparisonMinMagMipPoint:
704 desc.magFilter = WGPUFilterMode_Nearest;
705 desc.minFilter = WGPUFilterMode_Nearest;
706 desc.mipmapFilter = WGPUMipmapFilterMode_Nearest;
709 case SamplerState::FilterMode::ComparisonMinMagMipLinear:
710 desc.magFilter = WGPUFilterMode_Linear;
711 desc.minFilter = WGPUFilterMode_Linear;
712 desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
719 desc.lodMinClamp = 0;
720 desc.lodMaxClamp = 32;
722 desc.maxAnisotropy = 1;
725 if ((desc.minFilter == WGPUFilterMode_Nearest || desc.magFilter == WGPUFilterMode_Nearest) && desc.maxAnisotropy > 1) {
726 LOG_WARNING(logger,
"Sampler with nearest filter must set maxAnisotropy = 1");
727 desc.maxAnisotropy = 1;
729 sampler.sampler = wgpuDeviceCreateSampler(device, &desc);
732 if(graphicsDevice->use_error_scope){
733 WGPUPopErrorScopeCallbackInfo info = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT;
734 info.mode = WGPUCallbackMode_AllowSpontaneous;
735 info.callback = textures_error_callback;
736 info.userdata1 =
this;
737 info.userdata2 = graphicsDevice;
738 WGPUFuture future = wgpuDevicePopErrorScope(graphicsDevice->device, info);
742 return samplerStates.addResource(std::move(sampler));
747 if(!HandleIsValid(handle))
return;
751 wgpuSamplerRelease(sampler.sampler);
754 samplerStates.removeResource(handle);
762 void TexturesWebGPU::releaseResources()
Log implementation class.
Provides a weakly referenced view over the contents of a string.
virtual void annotate(TextureHandle handle, const StringView &name) override
Associate a name with an object for use in graphics debugging.
virtual TextureHandle loadTexture(const TextureDescription &desc, const TextureData *data) override
Load a texture from the given description.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
Encapsulates state for texture sampling in a state object.
ComparisonFunction comparisonFunction
Specifies the comparison function to use when applying a comparison sampler.
unsigned int maxAnisotropy
Specifies the maximum number of anisotropic samples to use when sampling a texture.
AddressMode addressModeW
Specifies the addressing mode along the W axis in texture coordinate space.
ComparisonFunction
Comparison functions applied when sampling depth buffers using comparison filters.
AddressMode addressModeS
Specifies the addressing mode along the S axis in texture coordinate space.
AddressMode
Addressing modes to use when sampling textures.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
@ Border
Texture color is set to the border color when outside [0, 1] range.
@ Wrap
Texture coordinates automatically wrap around to [0, 1] range.
@ Mirror
Texture coordinates are mirrored when outside [0, 1] range.
FilterMode filter
Specifies the filter to use for texture sampling.
AddressMode addressModeT
Specifies the addressing mode along the T axis in texture coordinate space.
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
@ RenderTarget
The texture can be used as a render target and drawn into.
@ GenerateMipMaps
The texture supports automatic mipmap generation performed by the graphics device.
@ ReadWriteTexture
The texture can be used as a read/write texture. Can be used to output data from compute shaders.
Describes how to fetch data from a texture in shaders.
uint32_t layerIndex
Index of the first layer (if array) to fetch from.
uint32_t numLayers
Number of array layers available.
uint32_t numLevels
Number of mipmap levels available.
uint32_t levelIndex
First mipmap level to fetch data from.
TextureHandle texture
Texture.