mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
vulkan: fix uniform vec3 array alignment
This commit is contained in:
@@ -1478,6 +1478,43 @@ void Shader::handleUnknownUniformName(const char */*name*/)
|
|||||||
// TODO: do something here?
|
// TODO: do something here?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::copyToUniformBuffer(const UniformInfo *info, const void *src, void *dst, int count) const
|
||||||
|
{
|
||||||
|
count = std::min(count, info->count);
|
||||||
|
|
||||||
|
size_t elementsize = info->components * 4;
|
||||||
|
if (info->baseType == UNIFORM_MATRIX)
|
||||||
|
elementsize = info->matrix.columns * info->matrix.rows * 4;
|
||||||
|
|
||||||
|
// Assuming std140 packing rules, the source data can only be direct-copied
|
||||||
|
// to the uniform buffer in certain cases because it's tightly packed whereas
|
||||||
|
// the buffer's data isn't.
|
||||||
|
if (elementsize * info->count == info->dataSize || (count == 1 && info->baseType != UNIFORM_MATRIX))
|
||||||
|
{
|
||||||
|
memcpy(dst, src, elementsize * count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int veccount = count;
|
||||||
|
int comp = info->components;
|
||||||
|
|
||||||
|
if (info->baseType == UNIFORM_MATRIX)
|
||||||
|
{
|
||||||
|
veccount *= info->matrix.rows;
|
||||||
|
comp = info->matrix.columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int *isrc = (const int *) src;
|
||||||
|
int *idst = (int *) dst;
|
||||||
|
|
||||||
|
for (int i = 0; i < veccount; i++)
|
||||||
|
{
|
||||||
|
for (int c = 0; c < comp; c++)
|
||||||
|
idst[i * 4 + c] = isrc[i * comp + c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Shader::initialize()
|
bool Shader::initialize()
|
||||||
{
|
{
|
||||||
bool success = glslang::InitializeProcess();
|
bool success = glslang::InitializeProcess();
|
||||||
|
|||||||
@@ -307,6 +307,9 @@ protected:
|
|||||||
|
|
||||||
void handleUnknownUniformName(const char *name);
|
void handleUnknownUniformName(const char *name);
|
||||||
|
|
||||||
|
// std140 uniform buffer alignment-aware copy.
|
||||||
|
void copyToUniformBuffer(const UniformInfo *info, const void *src, void *dst, int count) const;
|
||||||
|
|
||||||
static std::string canonicaliizeUniformName(const std::string &name);
|
static std::string canonicaliizeUniformName(const std::string &name);
|
||||||
static bool validateInternal(StrongRef<ShaderStage> stages[], std::string& err, Reflection &reflection);
|
static bool validateInternal(StrongRef<ShaderStage> stages[], std::string& err, Reflection &reflection);
|
||||||
static DataBaseType getDataBaseType(PixelFormat format);
|
static DataBaseType getDataBaseType(PixelFormat format);
|
||||||
|
|||||||
@@ -708,40 +708,10 @@ void Shader::updateUniform(const UniformInfo *info, int count)
|
|||||||
|
|
||||||
count = std::min(count, info->count);
|
count = std::min(count, info->count);
|
||||||
|
|
||||||
// TODO: store some of this in UniformInfo.
|
|
||||||
size_t elementsize = info->components * 4;
|
|
||||||
if (info->baseType == UNIFORM_MATRIX)
|
|
||||||
elementsize = info->matrix.columns * info->matrix.rows * 4;
|
|
||||||
|
|
||||||
size_t offset = (const uint8 *)info->data - localUniformStagingData;
|
size_t offset = (const uint8 *)info->data - localUniformStagingData;
|
||||||
|
uint8 *dst = localUniformBufferData + offset;
|
||||||
|
|
||||||
// Assuming std140 packing rules, the source data can only be direct-copied
|
copyToUniformBuffer(info, info->data, dst, count);
|
||||||
// to the uniform buffer in certain cases because it's tightly packed whereas
|
|
||||||
// the buffer's data isn't.
|
|
||||||
if (elementsize * info->count == info->dataSize || (count == 1 && info->baseType != UNIFORM_MATRIX))
|
|
||||||
{
|
|
||||||
memcpy(localUniformBufferData + offset, info->data, elementsize * count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int veccount = count;
|
|
||||||
int comp = info->components;
|
|
||||||
|
|
||||||
if (info->baseType == UNIFORM_MATRIX)
|
|
||||||
{
|
|
||||||
veccount *= info->matrix.rows;
|
|
||||||
comp = info->matrix.columns;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int *src = info->ints;
|
|
||||||
int *dst = (int *) (localUniformBufferData + offset);
|
|
||||||
|
|
||||||
for (int i = 0; i < veccount; i++)
|
|
||||||
{
|
|
||||||
for (int c = 0; c < comp; c++)
|
|
||||||
dst[i * 4 + c] = src[i * comp + c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count)
|
void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count)
|
||||||
|
|||||||
@@ -358,8 +358,14 @@ void Shader::updateUniform(const UniformInfo *info, int count)
|
|||||||
if (current == this)
|
if (current == this)
|
||||||
Graphics::flushBatchedDrawsGlobal();
|
Graphics::flushBatchedDrawsGlobal();
|
||||||
|
|
||||||
if (usesLocalUniformData(info))
|
count = std::min(count, info->count);
|
||||||
memcpy(localUniformData.data(), localUniformStagingData.data(), localUniformStagingData.size());
|
|
||||||
|
if (info->data != nullptr)
|
||||||
|
{
|
||||||
|
size_t offset = (const uint8*)info->data - localUniformStagingData.data();
|
||||||
|
uint8 *dst = localUniformData.data() + offset;
|
||||||
|
copyToUniformBuffer(info, info->data, dst, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count)
|
void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count)
|
||||||
@@ -453,10 +459,15 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::
|
|||||||
{
|
{
|
||||||
const auto &values = valuesit->second;
|
const auto &values = valuesit->second;
|
||||||
if (!values.empty())
|
if (!values.empty())
|
||||||
|
{
|
||||||
memcpy(
|
memcpy(
|
||||||
u.data,
|
u.data,
|
||||||
values.data(),
|
values.data(),
|
||||||
std::min(u.dataSize, values.size() * sizeof(LocalUniformValue)));
|
std::min(u.dataSize, values.size() * sizeof(LocalUniformValue)));
|
||||||
|
|
||||||
|
uint8 *dst = localUniformData.data() + offset;
|
||||||
|
copyToUniformBuffer(&u, u.data, dst, u.count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
|
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
|
||||||
@@ -588,8 +599,6 @@ void Shader::compileShaders()
|
|||||||
|
|
||||||
std::string basename("");
|
std::string basename("");
|
||||||
buildLocalUniforms(comp, type, 0, basename);
|
buildLocalUniforms(comp, type, 0, basename);
|
||||||
|
|
||||||
memcpy(localUniformData.data(), localUniformStagingData.data(), localUniformStagingData.size());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw love::Exception("unimplemented: non default uniform blocks.");
|
throw love::Exception("unimplemented: non default uniform blocks.");
|
||||||
|
|||||||
Reference in New Issue
Block a user