Skip to content

Commit

Permalink
Change the 'viewformats' texture setting field to be a list of pixel …
Browse files Browse the repository at this point in the history
…formats.

Replace Texture:hasViewFormats with Texture:getViewFormats.
  • Loading branch information
slime73 committed Feb 25, 2024
1 parent 42812ad commit e20f018
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 32 deletions.
46 changes: 25 additions & 21 deletions src/modules/graphics/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 6 additions & 3 deletions src/modules/graphics/Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

// C
#include <stddef.h>
#include <vector>

namespace love
{
Expand Down Expand Up @@ -195,7 +196,7 @@ class Texture : public Drawable, public Resource
int msaa = 1;
bool renderTarget = false;
bool computeWrite = false;
bool viewFormats = false;
std::vector<PixelFormat> viewFormats;
OptionalBool readable;
std::string debugName;
};
Expand Down Expand Up @@ -279,7 +280,8 @@ class Texture : public Drawable, public Resource
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;
Expand Down Expand Up @@ -353,9 +355,10 @@ class Texture : public Drawable, public Resource
PixelFormat format;
bool renderTarget;
bool computeWrite;
bool viewFormats;
bool readable;

std::vector<PixelFormat> viewFormats;

MipmapsMode mipmapsMode;

int width;
Expand Down
11 changes: 9 additions & 2 deletions src/modules/graphics/metal/Texture.mm
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,15 @@ static MTLTextureType getMTLTextureType(TextureType type, int msaa)
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];

Expand Down
2 changes: 2 additions & 0 deletions src/modules/graphics/vulkan/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ class Graphics final : public love::graphics::Graphics
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;
Expand Down
23 changes: 21 additions & 2 deletions src/modules/graphics/vulkan/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down
20 changes: 19 additions & 1 deletion src/modules/graphics/wrap_Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
17 changes: 14 additions & 3 deletions src/modules/graphics/wrap_Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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 },
Expand Down

0 comments on commit e20f018

Please sign in to comment.