mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Change the 'viewformats' texture setting field to be a list of pixel formats.
Replace Texture:hasViewFormats with Texture:getViewFormats.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user