mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Merge branch '12.0-development' into metal
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "Buffer.h"
|
||||
#include "common/Data.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user