Compare commits

...

6 Commits

Author SHA1 Message Date
Bjorn f3cae5f80e
Merge pull request #748 from bjornbytes/rm-msaa-textures
Remove Multisample Textures
2024-02-23 12:38:23 -08:00
Bjorn bad3d8b78a
Merge pull request #747 from bjornbytes/changelog
Changelog
2024-02-23 12:38:12 -08:00
Bjorn f1158b2159
Merge pull request #745 from bjornbytes/xr-swapchain-colorspace
Fix OpenXR Swapchain Colorspaces
2024-02-23 12:37:54 -08:00
bjorn 114109ab54 rm multisample texture objects; 2024-02-22 14:40:32 -08:00
bjorn b65fa0d1f6 Add changelog; 2024-02-22 14:16:54 -08:00
bjorn 0bf09ca108 Rearrange the way sRGB textures work (again); 2024-02-16 12:45:35 -08:00
8 changed files with 1225 additions and 51 deletions

1202
CHANGES.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -726,7 +726,6 @@ static int l_lovrGraphicsNewTexture(lua_State* L) {
.format = FORMAT_RGBA8,
.layers = 1,
.mipmaps = ~0u,
.samples = 1,
.usage = TEXTURE_SAMPLE,
.srgb = true
};
@ -815,10 +814,6 @@ static int l_lovrGraphicsNewTexture(lua_State* L) {
lua_getfield(L, index, "format");
info.format = lua_isnil(L, -1) ? info.format : (uint32_t) luax_checkenum(L, -1, TextureFormat, NULL);
lua_pop(L, 1);
lua_getfield(L, index, "samples");
info.samples = lua_isnil(L, -1) ? info.samples : luax_checku32(L, -1);
lua_pop(L, 1);
}
lua_getfield(L, index, "linear");
@ -832,7 +827,7 @@ static int l_lovrGraphicsNewTexture(lua_State* L) {
} else if (!lua_isnil(L, -1)) {
info.mipmaps = lua_toboolean(L, -1) ? ~0u : 1;
} else {
info.mipmaps = (info.samples > 1 || info.imageCount == 0 || !mipmappable) ? 1 : ~0u;
info.mipmaps = (info.imageCount == 0 || !mipmappable) ? 1 : ~0u;
}
lovrCheck(info.imageCount == 0 || info.mipmaps == 1 || mipmappable, "This texture format does not support blitting, which is required for mipmap generation");
lua_pop(L, 1);
@ -1092,7 +1087,6 @@ static Texture* luax_opttexture(lua_State* L, int index) {
.height = lovrImageGetHeight(image, 0),
.layers = 1,
.mipmaps = ~0u,
.samples = 1,
.usage = TEXTURE_SAMPLE,
.srgb = lovrImageIsSRGB(image),
.imageCount = 1,

View File

@ -91,10 +91,8 @@ static int l_lovrTextureGetMipmapCount(lua_State* L) {
return 1;
}
static int l_lovrTextureGetSampleCount(lua_State* L) {
Texture* texture = luax_checktype(L, 1, Texture);
const TextureInfo* info = lovrTextureGetInfo(texture);
lua_pushinteger(L, info->samples);
static int l_lovrTextureGetSampleCount(lua_State* L) { // Deprecated
lua_pushinteger(L, 1);
return 1;
}
@ -246,7 +244,7 @@ const luaL_Reg lovrTexture[] = {
{ "getLayerCount", l_lovrTextureGetLayerCount },
{ "getDimensions", l_lovrTextureGetDimensions },
{ "getMipmapCount", l_lovrTextureGetMipmapCount },
{ "getSampleCount", l_lovrTextureGetSampleCount },
{ "getSampleCount", l_lovrTextureGetSampleCount }, // Deprecated
{ "hasUsage", l_lovrTextureHasUsage },
{ "newReadback", l_lovrTextureNewReadback },
{ "getPixels", l_lovrTextureGetPixels },

View File

@ -436,20 +436,22 @@ bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info) {
return gpu_texture_init_view(texture, &viewInfo);
}
bool mutableFormat = info->srgb && (info->usage & GPU_TEXTURE_STORAGE);
VkImageCreateInfo imageInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.flags =
(info->type == GPU_TEXTURE_3D ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT : 0) |
(info->type == GPU_TEXTURE_CUBE ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0) |
(info->srgb ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0),
(mutableFormat ? (VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) : 0),
.imageType = imageTypes[info->type],
.format = convertFormat(texture->format, LINEAR),
.format = convertFormat(texture->format, info->srgb),
.extent.width = info->size[0],
.extent.height = info->size[1],
.extent.depth = texture->layers ? 1 : info->size[2],
.mipLevels = info->mipmaps,
.arrayLayers = texture->layers ? texture->layers : 1,
.samples = info->samples,
.samples = info->samples ? info->samples : 1,
.usage =
(((info->usage & GPU_TEXTURE_RENDER) && texture->aspect == VK_IMAGE_ASPECT_COLOR_BIT) ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
(((info->usage & GPU_TEXTURE_RENDER) && texture->aspect != VK_IMAGE_ASPECT_COLOR_BIT) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0) |
@ -464,7 +466,7 @@ bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info) {
VkFormat formats[2];
VkImageFormatListCreateInfo imageFormatList;
if (info->srgb && state.extensions.formatList) {
if (mutableFormat && state.extensions.formatList) {
imageFormatList = (VkImageFormatListCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
.viewFormatCount = COUNTOF(formats),
@ -472,12 +474,9 @@ bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info) {
};
formats[0] = imageInfo.format;
formats[1] = convertFormat(texture->format, SRGB);
if (formats[0] != formats[1]) {
imageFormatList.pNext = imageInfo.pNext;
imageInfo.pNext = &imageFormatList;
}
formats[1] = convertFormat(texture->format, LINEAR);
imageFormatList.pNext = imageInfo.pNext;
imageInfo.pNext = &imageFormatList;
}
VK(vkCreateImage(state.device, &imageInfo, NULL, &texture->handle), "Could not create texture") return false;
@ -505,10 +504,7 @@ bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info) {
return false;
}
bool needsView = info->usage & (GPU_TEXTURE_RENDER | GPU_TEXTURE_SAMPLE | GPU_TEXTURE_STORAGE);
if (info->usage == GPU_TEXTURE_STORAGE && info->srgb) needsView = false;
if (needsView && !gpu_texture_init_view(texture, &viewInfo)) {
if (!gpu_texture_init_view(texture, &viewInfo)) {
vkDestroyImage(state.device, texture->handle, NULL);
gpu_release(memory);
return false;
@ -650,6 +646,11 @@ bool gpu_texture_init_view(gpu_texture* texture, gpu_texture_view_info* info) {
((info->usage & GPU_TEXTURE_STORAGE) && !texture->srgb ? VK_IMAGE_USAGE_STORAGE_BIT : 0)
};
if (usage.usage == 0) {
texture->view = VK_NULL_HANDLE;
return true;
}
VkImageViewCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &usage,
@ -2201,7 +2202,6 @@ bool gpu_init(gpu_config* config) {
{ "VK_KHR_portability_enumeration", true, &state.extensions.portability },
{ "VK_EXT_debug_utils", config->debug, &state.extensions.debug },
{ "VK_EXT_swapchain_colorspace", true, &state.extensions.colorspace },
{ "VK_KHR_image_format_list", true, &state.extensions.formatList },
{ "VK_KHR_surface", true, &state.extensions.surface },
#if defined(_WIN32)
{ "VK_KHR_win32_surface", true, &state.extensions.surfaceOS },
@ -2436,6 +2436,7 @@ bool gpu_init(gpu_config* config) {
{ "VK_KHR_portability_subset", true, &state.extensions.portability },
{ "VK_KHR_depth_stencil_resolve", true, &state.extensions.depthResolve },
{ "VK_KHR_shader_non_semantic_info", config->debug, &state.extensions.shaderDebug },
{ "VK_KHR_image_format_list", true, &state.extensions.formatList },
{ "VK_KHR_synchronization2", true, NULL }
};

View File

@ -739,7 +739,6 @@ bool lovrGraphicsInit(GraphicsConfig* config) {
.height = 4,
.layers = 1,
.mipmaps = 1,
.samples = 1,
.srgb = false,
.imageCount = 1,
.images = &image,
@ -2013,7 +2012,6 @@ Texture* lovrGraphicsGetWindowTexture(void) {
.height = height,
.layers = 1,
.mipmaps = 1,
.samples = 1,
.usage = TEXTURE_RENDER,
.srgb = true
};
@ -2090,11 +2088,6 @@ Texture* lovrTextureCreate(const TextureInfo* info) {
lovrCheck(info->layers % 6 == 0 || info->type != TEXTURE_CUBE, "Cubemap layer count must be a multiple of 6");
lovrCheck(info->width == info->height || info->type != TEXTURE_CUBE, "Cubemaps must be square");
lovrCheck(measureTexture(info->format, info->width, info->height, info->layers) < 1 << 30, "Memory for a Texture can not exceed 1GB"); // TODO mip?
lovrCheck(info->samples == 1 || info->samples == 4, "Texture multisample count must be 1 or 4...for now");
lovrCheck(info->samples == 1 || info->type != TEXTURE_CUBE, "Cubemaps can not be multisampled");
lovrCheck(info->samples == 1 || info->type != TEXTURE_3D, "3D textures can not be multisampled");
lovrCheck(info->samples == 1 || ~info->usage & TEXTURE_STORAGE, "Textures with the 'storage' flag can not be multisampled...for now");
lovrCheck(info->samples == 1 || mipmaps == 1, "Multisampled textures can only have 1 mipmap");
lovrCheck(~info->usage & TEXTURE_SAMPLE || (supports & GPU_FEATURE_SAMPLE), "GPU does not support the 'sample' flag for this texture format/encoding");
lovrCheck(~info->usage & TEXTURE_RENDER || (supports & GPU_FEATURE_RENDER), "GPU does not support the 'render' flag for this texture format/encoding");
lovrCheck(~info->usage & TEXTURE_STORAGE || (linearSupports & GPU_FEATURE_STORAGE), "GPU does not support the 'storage' flag for this texture format");
@ -2157,7 +2150,6 @@ Texture* lovrTextureCreate(const TextureInfo* info) {
.format = (gpu_texture_format) info->format,
.size = { info->width, info->height, info->layers },
.mipmaps = texture->info.mipmaps,
.samples = MAX(info->samples, 1),
.usage =
((info->usage & TEXTURE_SAMPLE) ? GPU_TEXTURE_SAMPLE : 0) |
((info->usage & TEXTURE_RENDER) ? GPU_TEXTURE_RENDER : 0) |
@ -2334,7 +2326,6 @@ Image* lovrTextureGetPixels(Texture* texture, uint32_t offset[4], uint32_t exten
lovrCheck(extent[2] == 1, "Currently only a single layer can be read from a Texture");
lovrCheck(texture->info.usage & TEXTURE_TRANSFER, "Texture must be created with the 'transfer' usage to read from it");
lovrCheck(!texture->info.parent, "Texture views can not be read");
lovrCheck(texture->info.samples == 1, "Multisampled Textures can not be read");
checkTextureBounds(&texture->info, offset, extent);
gpu_barrier barrier = syncTransfer(&texture->sync, GPU_PHASE_COPY, GPU_CACHE_TRANSFER_READ);
@ -2359,7 +2350,6 @@ void lovrTextureSetPixels(Texture* texture, Image* image, uint32_t srcOffset[4],
if (extent[2] == ~0u) extent[2] = MIN(texture->info.layers - dstOffset[2], lovrImageGetLayerCount(image) - srcOffset[2]);
lovrCheck(texture->info.usage & TEXTURE_TRANSFER, "Texture must be created with the 'transfer' usage to copy to it");
lovrCheck(!texture->info.parent, "Texture views can not be written to");
lovrCheck(texture->info.samples == 1, "Multisampled Textures can not be written to");
lovrCheck(lovrImageGetFormat(image) == texture->info.format, "Image and Texture formats must match");
lovrCheck(srcOffset[0] + extent[0] <= lovrImageGetWidth(image, srcOffset[3]), "Image copy region exceeds its %s", "width");
lovrCheck(srcOffset[1] + extent[1] <= lovrImageGetHeight(image, srcOffset[3]), "Image copy region exceeds its %s", "height");
@ -2395,7 +2385,6 @@ void lovrTextureCopy(Texture* src, Texture* dst, uint32_t srcOffset[4], uint32_t
lovrCheck(dst->info.usage & TEXTURE_TRANSFER, "Texture must be created with the 'transfer' usage to copy %s it", "to");
lovrCheck(!src->info.parent && !dst->info.parent, "Can not copy texture views");
lovrCheck(src->info.format == dst->info.format, "Copying between Textures requires them to have the same format");
lovrCheck(src->info.samples == dst->info.samples, "Texture sample counts must match to copy between them");
checkTextureBounds(&src->info, srcOffset, extent);
checkTextureBounds(&dst->info, dstOffset, extent);
gpu_barrier barriers[2];
@ -2415,7 +2404,6 @@ void lovrTextureBlit(Texture* src, Texture* dst, uint32_t srcOffset[4], uint32_t
if (dstExtent[2] == ~0u) dstExtent[2] = dst->info.layers - dstOffset[2];
uint32_t supports = state.features.formats[src->info.format][src->info.srgb];
lovrCheck(!src->info.parent && !dst->info.parent, "Can not blit Texture views");
lovrCheck(src->info.samples == 1 && dst->info.samples == 1, "Multisampled textures can not be used for blits");
lovrCheck(src->info.usage & TEXTURE_TRANSFER, "Texture must be created with the 'transfer' usage to blit %s it", "from");
lovrCheck(dst->info.usage & TEXTURE_TRANSFER, "Texture must be created with the 'transfer' usage to blit %s it", "to");
lovrCheck(supports & GPU_FEATURE_BLIT, "This GPU does not support blitting this texture format/encoding");
@ -2449,7 +2437,6 @@ void lovrTextureGenerateMipmaps(Texture* texture, uint32_t base, uint32_t count)
if (count == ~0u) count = texture->info.mipmaps - (base + 1);
uint32_t supports = state.features.formats[texture->info.format][texture->info.srgb];
lovrCheck(!texture->info.parent, "Can not mipmap a Texture view");
lovrCheck(texture->info.samples == 1, "Can not mipmap a multisampled texture");
lovrCheck(texture->info.usage & TEXTURE_TRANSFER, "Texture must be created with the 'transfer' usage to mipmap it");
lovrCheck(supports & GPU_FEATURE_BLIT, "This GPU does not support mipmapping this texture format/encoding");
lovrCheck(base + count < texture->info.mipmaps, "Trying to generate too many mipmaps");
@ -3493,7 +3480,6 @@ static Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint, bool* resized) {
.height = font->atlasHeight,
.layers = 1,
.mipmaps = 1,
.samples = 1,
.usage = TEXTURE_SAMPLE | TEXTURE_TRANSFER,
.label = "Font Atlas"
});
@ -4203,7 +4189,6 @@ Model* lovrModelCreate(const ModelInfo* info) {
.height = lovrImageGetHeight(data->images[index], 0),
.layers = 1,
.mipmaps = info->mipmaps || lovrImageGetLevelCount(data->images[index]) > 1 ? ~0u : 1,
.samples = 1,
.srgb = texture == &material.texture || texture == &material.glowTexture,
.images = &data->images[index],
.imageCount = 1
@ -4936,7 +4921,6 @@ Readback* lovrReadbackCreateTexture(Texture* texture, uint32_t offset[4], uint32
if (extent[1] == ~0u) extent[1] = texture->info.height - offset[1];
lovrCheck(extent[2] == 1, "Currently, only one layer can be read from a Texture");
lovrCheck(!texture->info.parent, "Can not read from a Texture view");
lovrCheck(texture->info.samples == 1, "Can not read from a multisampled texture");
lovrCheck(texture->info.usage & TEXTURE_TRANSFER, "Texture must be created with the 'transfer' usage to read from it");
checkTextureBounds(&texture->info, offset, extent);
Readback* readback = lovrReadbackCreate(READBACK_TEXTURE);
@ -5229,8 +5213,8 @@ void lovrPassSetCanvas(Pass* pass, Texture* textures[4], Texture* depthTexture,
lovrCheck(t->height <= state.limits.renderSize[1], "Pass canvas height (%d) exceeds the renderSize limit of this GPU (%d)", t->height, state.limits.renderSize[1]);
lovrCheck(t->layers <= state.limits.renderSize[2], "Pass canvas layer count (%d) exceeds the renderSize limit of this GPU (%d)", t->layers, state.limits.renderSize[2]);
lovrCheck(samples == 1 || samples == 4, "Currently MSAA must be 1 or 4");
canvas->samples = t->samples > 1 ? t->samples : samples;
canvas->resolve = t->samples == 1 && samples > 1;
canvas->samples = samples;
canvas->resolve = samples > 1;
} else {
memset(canvas, 0, sizeof(Canvas));
}
@ -5244,7 +5228,6 @@ void lovrPassSetCanvas(Pass* pass, Texture* textures[4], Texture* depthTexture,
lovrCheck(texture->width == t->width, "Canvas texture sizes must match");
lovrCheck(texture->height == t->height, "Canvas texture sizes must match");
lovrCheck(texture->layers == t->layers, "Canvas texture layer counts must match");
lovrCheck(texture->samples == t->samples, "Canvas texture sample counts must match");
canvas->color[i].texture = textures[i];
lovrRetain(textures[i]);
}
@ -5256,8 +5239,7 @@ void lovrPassSetCanvas(Pass* pass, Texture* textures[4], Texture* depthTexture,
lovrCheck(texture->width == t->width, "Canvas texture sizes must match");
lovrCheck(texture->height == t->height, "Canvas texture sizes must match");
lovrCheck(texture->layers == t->layers, "Canvas texture layer counts must match");
lovrCheck(texture->samples == t->samples, "Canvas texture sample counts must match");
lovrCheck(texture->samples == samples || state.features.depthResolve, "This GPU does not support resolving depth textures, MSAA should be set to 1");
lovrCheck(samples == 1 || state.features.depthResolve, "This GPU does not support resolving depth textures, MSAA should be set to 1");
canvas->depth.texture = depthTexture;
canvas->depth.format = texture->format;
lovrRetain(depthTexture);

View File

@ -218,7 +218,6 @@ typedef struct {
uint32_t height;
uint32_t layers;
uint32_t mipmaps;
uint32_t samples;
uint32_t usage;
bool srgb;
bool xr;

View File

@ -466,7 +466,6 @@ static void swapchain_init(Swapchain* swapchain, uint32_t width, uint32_t height
.height = height,
.layers = 1 << stereo,
.mipmaps = 1,
.samples = 1,
.usage = TEXTURE_RENDER | (depth ? 0 : TEXTURE_SAMPLE),
.handle = (uintptr_t) images[i].image,
.label = "OpenXR Swapchain",

View File

@ -382,7 +382,6 @@ static Pass* simulator_getPass(void) {
.height = height,
.layers = 1,
.mipmaps = 1,
.samples = 1,
.usage = TEXTURE_RENDER | TEXTURE_SAMPLE,
});