Change the 'viewformats' texture setting field to be a list of pixel formats.

Replace Texture:hasViewFormats with Texture:getViewFormats.
This commit is contained in:
Sasha Szpakowski
2024-02-24 23:42:28 -04:00
parent 42812ad521
commit e20f018272
7 changed files with 96 additions and 32 deletions
+25 -21
View File
@@ -287,6 +287,28 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
if (isCompressed() && renderTarget)
throw love::Exception("Compressed textures cannot be render targets.");
for (PixelFormat viewformat : viewFormats)
{
if (getLinearPixelFormat(viewformat) == getLinearPixelFormat(format))
continue;
if (isPixelFormatCompressed(format) || isPixelFormatCompressed(viewformat))
throw love::Exception("Compressed textures cannot use different pixel formats for texture views, aside from sRGB versus linear variants of the same pixel format.");
if (isPixelFormatColor(viewformat) != isPixelFormatColor(format))
throw love::Exception("Color-format textures cannot use depth/stencil pixel formats and vice versa, in texture views.");
// TODO: depth[24|32f]_stencil8 -> stencil8 can work.
if (isPixelFormatDepthStencil(viewformat))
throw love::Exception("Using different pixel formats for texture views is not currently supported for depth or stencil formats.");
size_t viewbytes = getPixelFormatBlockSize(viewformat);
size_t basebytes = getPixelFormatBlockSize(format);
if (viewbytes != basebytes)
throw love::Exception("Texture view pixel formats must have the same bits per pixel as the base texture's pixel format.");
}
validatePixelFormat(gfx);
if (!caps.textureTypes[texType])
@@ -409,28 +431,10 @@ Texture::Texture(Graphics *gfx, Texture *base, const ViewSettings &viewsettings)
throw love::Exception("Unknown texture type.");
}
auto baseformat = base->getPixelFormat();
if (format != baseformat)
if (format != base->getPixelFormat())
{
if (isPixelFormatCompressed(baseformat) || isPixelFormatCompressed(format))
throw love::Exception("Compressed textures cannot use a different pixel format in a texture view.");
if (isPixelFormatColor(baseformat) != isPixelFormatColor(format))
throw love::Exception("Color-format textures cannot use a depth/stencil pixel format and vice versa, in a texture view.");
// TODO: depth[24|32f]_stencil8 -> stencil8 can work.
if (isPixelFormatDepthStencil(baseformat))
throw love::Exception("Using a different pixel format in a texture view is not currently supported for depth or stencil formats.");
if (!viewFormats)
throw love::Exception("Using a different pixel format in a texture view requires the original texture to be created with the 'viewformats' setting set to true.");
size_t bytes = getPixelFormatBlockSize(format);
size_t basebytes = getPixelFormatBlockSize(baseformat);
if (bytes != basebytes)
throw love::Exception("Texture views must have the same bits per pixel as the original texture.");
if (std::find(viewFormats.begin(), viewFormats.end(), format) == viewFormats.end())
throw love::Exception("Using a different pixel format in a texture view requires the original texture to be created with a 'viewformats' setting that includes the given format in its list.");
}
const char *miperr = nullptr;
+6 -3
View File
@@ -39,6 +39,7 @@
// C
#include <stddef.h>
#include <vector>
namespace love
{
@@ -195,7 +196,7 @@ public:
int msaa = 1;
bool renderTarget = false;
bool computeWrite = false;
bool viewFormats = false;
std::vector<PixelFormat> viewFormats;
OptionalBool readable;
std::string debugName;
};
@@ -279,7 +280,8 @@ public:
bool isRenderTarget() const { return renderTarget; }
bool isComputeWritable() const { return computeWrite; }
bool isReadable() const { return readable; }
bool hasViewFormats() const { return viewFormats; }
const std::vector<PixelFormat> &getViewFormats() const { return viewFormats; }
bool isCompressed() const;
bool isFormatLinear() const;
@@ -353,9 +355,10 @@ protected:
PixelFormat format;
bool renderTarget;
bool computeWrite;
bool viewFormats;
bool readable;
std::vector<PixelFormat> viewFormats;
MipmapsMode mipmapsMode;
int width;
+9 -2
View File
@@ -76,8 +76,15 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id<MTLDevice> device, const
desc.usage |= MTLTextureUsageRenderTarget;
if (computeWrite)
desc.usage |= MTLTextureUsageShaderWrite;
if (viewFormats)
desc.usage |= MTLTextureUsagePixelFormatView;
for (PixelFormat viewformat : viewFormats)
{
if (getLinearPixelFormat(viewformat) != getLinearPixelFormat(format))
{
desc.usage |= MTLTextureUsagePixelFormatView;
break;
}
}
texture = [device newTextureWithDescriptor:desc];
+2
View File
@@ -326,6 +326,8 @@ public:
void setVsync(int vsync);
int getVsync() const;
uint32 getDeviceApiVersion() const { return deviceApiVersion; }
protected:
graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options) override;
+21 -2
View File
@@ -100,9 +100,17 @@ bool Texture::loadVolatile()
if (root)
{
VkImageCreateFlags createFlags = 0;
std::vector<VkFormat> vkviewformats;
if (viewFormats)
createFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
for (PixelFormat viewformat : viewFormats)
{
if (viewformat != format)
{
createFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
TextureFormat f = Vulkan::getTextureFormat(viewformat);
vkviewformats.push_back(f.internalFormat);
}
}
if (texType == TEXTURE_CUBE || texType == TEXTURE_2D_ARRAY)
createFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
@@ -125,6 +133,17 @@ bool Texture::loadVolatile()
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.samples = msaaSamples;
VkImageFormatListCreateInfo viewFormatsInfo{};
viewFormatsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO;
if (!vkviewformats.empty() && vgfx->getDeviceApiVersion() >= VK_API_VERSION_1_2)
{
viewFormatsInfo.viewFormatCount = (uint32)vkviewformats.size();
viewFormatsInfo.pViewFormats = vkviewformats.data();
imageInfo.pNext = &viewFormatsInfo;
}
VmaAllocationCreateInfo imageAllocationCreateInfo{};
if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS)
+19 -1
View File
@@ -830,7 +830,25 @@ static void luax_checktexturesettings(lua_State *L, int idx, bool opt, bool chec
s.msaa = luax_intflag(L, idx, Texture::getConstant(Texture::SETTING_MSAA), s.msaa);
s.computeWrite = luax_boolflag(L, idx, Texture::getConstant(Texture::SETTING_COMPUTE_WRITE), s.computeWrite);
s.viewFormats = luax_boolflag(L, idx, Texture::getConstant(Texture::SETTING_VIEW_FORMATS), s.viewFormats);
lua_getfield(L, idx, Texture::getConstant(Texture::SETTING_VIEW_FORMATS));
if (!lua_isnoneornil(L, -1))
{
if (lua_type(L, -1) != LUA_TTABLE)
luaL_argerror(L, idx, "expected field 'viewformats' to be a table type");
for (int i = 1; i <= luax_objlen(L, -1); i++)
{
lua_rawgeti(L, -1, i);
const char *str = luaL_checkstring(L, -1);
PixelFormat viewformat = PIXELFORMAT_UNKNOWN;
if (!getConstant(str, viewformat))
luax_enumerror(L, "pixel format", str);
s.viewFormats.push_back(viewformat);
lua_pop(L, 1);
}
}
lua_pop(L, 1);
lua_getfield(L, idx, Texture::getConstant(Texture::SETTING_READABLE));
if (!lua_isnoneornil(L, -1))
+14 -3
View File
@@ -300,10 +300,21 @@ int w_Texture_isReadable(lua_State *L)
return 1;
}
int w_Texture_hasViewFormats(lua_State *L)
int w_Texture_getViewFormats(lua_State *L)
{
Texture *t = luax_checktexture(L, 1);
luax_pushboolean(L, t->hasViewFormats());
const std::vector<PixelFormat> &viewformats = t->getViewFormats();
lua_createtable(L, (int) viewformats.size(), 0);
for (int i = 0; i < (int) viewformats.size(); i++)
{
const char *str = nullptr;
if (!getConstant(viewformats[i], str))
return luaL_error(L, "Unknown pixel format.");
lua_pushstring(L, str);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
@@ -518,7 +529,7 @@ const luaL_Reg w_Texture_functions[] =
{ "isCanvas", w_Texture_isCanvas },
{ "isComputeWritable", w_Texture_isComputeWritable },
{ "isReadable", w_Texture_isReadable },
{ "hasViewFormats", w_Texture_hasViewFormats },
{ "getViewFormats", w_Texture_getViewFormats },
{ "getMipmapMode", w_Texture_getMipmapMode },
{ "getDepthSampleMode", w_Texture_getDepthSampleMode },
{ "setDepthSampleMode", w_Texture_setDepthSampleMode },