Merge branch '12.0-development' into metal

This commit is contained in:
Alex Szpakowski
2021-12-24 15:35:18 -04:00
61 changed files with 2101 additions and 2925 deletions
+23 -4
View File
@@ -147,11 +147,30 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataDe
// GLSL's std430 packing rules. We also assume all matrices are
// column-major.
if (info.isMatrix)
alignment = info.matrixRows * info.componentSize;
else
alignment = info.components * info.componentSize;
// https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf
// "If the member is a column-major matrix with C columns and R rows,
// the matrix is stored identically to an array of C column vectors
// with R components each".
// "If the member is a three-component vector with components
// consuming N basic machine units, the base alignment is 4N."
int c = info.isMatrix ? info.matrixRows : info.components;
alignment = c == 3 ? 4 * info.componentSize : c * info.componentSize;
// std430 will effectively turn a floatmat3x3 into a floatmat4x3
// because of its vec3 padding rules. For now we'd rather not
// support those formats at all, because it's not easy for users to
// deal with.
if (alignment != c * info.componentSize && (decl.arrayLength > 0 || info.isMatrix))
{
const char *fstr = "unknown";
getConstant(decl.format, fstr);
throw love::Exception("Data format %s%s is not currently supported in shader storage buffers.", fstr, decl.arrayLength > 0 ? " array" : "");
}
// "If the member is a structure, the base alignment of the structure
// is N, where N is the largest base alignment value of any of its
// members"
structurealignment = std::max(structurealignment, alignment);
memberoffset = alignUp(memberoffset, alignment);
+5 -8
View File
@@ -338,7 +338,7 @@ float Font::getKerning(uint32 leftglyph, uint32 rightglyph)
if (it != kerning.end())
return it->second;
float k = rasterizers[0]->getKerning(leftglyph, rightglyph) / dpiScale + 0.5f;
float k = floorf(rasterizers[0]->getKerning(leftglyph, rightglyph) / dpiScale + 0.5f);
for (const auto &r : rasterizers)
{
@@ -901,14 +901,11 @@ void Font::getWrap(const ColoredCodepoints &codepoints, float wraplimit, std::ve
}
// Push the last line.
if (!wline.cps.empty())
{
lines.push_back(wline);
lines.push_back(wline);
// Ignore the width of any trailing spaces, for individual lines.
if (linewidths)
linewidths->push_back(width - widthoftrailingspace);
}
// Ignore the width of any trailing spaces, for individual lines.
if (linewidths)
linewidths->push_back(width - widthoftrailingspace);
}
void Font::getWrap(const std::vector<ColoredString> &text, float wraplimit, std::vector<std::string> &lines, std::vector<int> *linewidths)
+3 -2
View File
@@ -1526,7 +1526,7 @@ void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h)
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry, int points)
{
if (rx == 0 || ry == 0)
if (rx <= 0 || ry <= 0)
{
rectangle(mode, x, y, w, h);
return;
@@ -1585,7 +1585,8 @@ void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, floa
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry)
{
rectangle(mode, x, y, w, h, rx, ry, calculateEllipsePoints(rx, ry));
int points = calculateEllipsePoints(std::min(rx, std::abs(w/2)), std::min(ry, std::abs(h/2)));
rectangle(mode, x, y, w, h, rx, ry, points);
}
void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)
+1 -1
View File
@@ -177,7 +177,7 @@ void ParticleSystem::resetOffset()
else
{
Quad::Viewport v = quads[0]->getViewport();
offset = love::Vector2(v.x*0.5f, v.y*0.5f);
offset = love::Vector2(v.w*0.5f, v.h*0.5f);
}
}
+4 -4
View File
@@ -896,14 +896,14 @@ bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err,
const glslang::TTypeList *structure = type->getStruct();
if (structure == nullptr || structure->size() != 1)
{
err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of structs.";
err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of base types or structs.";
return false;
}
const glslang::TType* structtype = (*structure)[0].type;
if (structtype == nullptr || structtype->getBasicType() != glslang::EbtStruct || !structtype->isUnsizedArray())
const glslang::TType* elementtype = (*structure)[0].type;
if (elementtype == nullptr || !elementtype->isUnsizedArray())
{
err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of structs.";
err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of base types or structs.";
return false;
}
+21 -2
View File
@@ -166,6 +166,12 @@ void Shader::mapActiveUniforms()
u.storageTextureFormat = reflectionit->second.format;
u.access = reflectionit->second.access;
}
else
{
// No reflection info - maybe glslang was better at detecting
// dead code than the driver's compiler?
continue;
}
StorageTextureBinding binding = {};
binding.gltexture = gl.getDefaultTexture(u.textureType, u.dataBaseType);
@@ -352,6 +358,7 @@ void Shader::mapActiveUniforms()
glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numstoragebuffers);
char namebuffer[2048] = { '\0' };
int nextstoragebufferbinding = 0;
for (int sindex = 0; sindex < numstoragebuffers; sindex++)
{
@@ -372,6 +379,12 @@ void Shader::mapActiveUniforms()
u.bufferMemberCount = reflectionit->second.memberCount;
u.access = reflectionit->second.access;
}
else
{
// No reflection info - maybe glslang was better at detecting
// dead code than the driver's compiler?
continue;
}
// Make sure previously set uniform data is preserved, and shader-
// initialized values are retrieved.
@@ -393,8 +406,11 @@ void Shader::mapActiveUniforms()
memset(u.buffers, 0, sizeof(Buffer*)* u.count);
}
GLenum props[] = { GL_BUFFER_BINDING };
glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, sindex, 1, props, 1, nullptr, u.ints);
// Unlike local uniforms and attributes, OpenGL doesn't auto-assign storage
// block bindings if they're unspecified in the shader. So we overwrite them
// regardless, here.
u.ints[0] = nextstoragebufferbinding++;
glShaderStorageBlockBinding(program, sindex, u.ints[0]);
BufferBinding binding;
binding.bindingindex = u.ints[0];
@@ -1074,6 +1090,9 @@ Shader::MatrixSize Shader::getMatrixSize(GLenum type) const
m.columns = 4;
m.rows = 3;
break;
default:
m.columns = m.rows = 0;
break;
}
return m;
+1 -1
View File
@@ -45,7 +45,7 @@ public:
struct StorageTextureBinding
{
Texture *texture = nullptr;
love::graphics::Texture *texture = nullptr;
GLuint gltexture = 0;
TextureType type = TEXTURE_2D;
GLenum access = GL_READ_ONLY;
+2
View File
@@ -22,6 +22,8 @@
#include "Buffer.h"
#include "common/Data.h"
#include <limits>
namespace love
{
namespace graphics
+1 -1
View File
@@ -3657,7 +3657,7 @@ extern "C" int luaopen_love_graphics(lua_State *L)
int n = luax_register_module(L, w);
if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "wrap_Graphics.lua") == 0)
if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "=[love \"wrap_Graphics.lua\"]") == 0)
lua_call(L, 0, 0);
else
lua_error(L);
+3 -9
View File
@@ -447,18 +447,12 @@ int w_Shader_send(lua_State *L)
const Shader::UniformInfo *info = shader->getUniformInfo(name);
if (info == nullptr)
{
luax_pushboolean(L, false);
return 1;
}
return luaL_error(L, "Shader uniform '%s' does not exist.\nA common error is to define but not use the variable.", name);
if (luax_istype(L, 3, Data::type) || (info->baseType == Shader::UNIFORM_MATRIX && luax_istype(L, 4, Data::type)))
w_Shader_sendData(L, 3, shader, info, false);
return w_Shader_sendData(L, 3, shader, info, false);
else
w_Shader_sendLuaValues(L, 3, shader, info, name);
luax_pushboolean(L, true);
return 1;
return w_Shader_sendLuaValues(L, 3, shader, info, name);
}
int w_Shader_sendColors(lua_State *L)
+1 -1
View File
@@ -168,7 +168,7 @@ int luaopen_video(lua_State *L)
{
int ret = luax_register_type(L, &Video::type, functions, nullptr);
luaL_loadbuffer(L, video_lua, sizeof(video_lua), "Video.lua");
luaL_loadbuffer(L, video_lua, sizeof(video_lua), "=[love \"Video.lua\"]");
luax_gettypemetatable(L, Video::type);
lua_call(L, 1, 0);