Refactor flattened_access_chain functions

Instead of filling a std::string buffer passed by reference return a new
string. This may be slightly slower in certain cases but they are pretty
rare and this matches the code style better.

Also streamline error handling in different branches and extract function
to generate vector swizzle.
This commit is contained in:
Arseny Kapoulkine 2017-01-17 18:07:56 -08:00
parent c5a821cdbf
commit 1ec6c1a029
2 changed files with 64 additions and 49 deletions

View File

@ -129,6 +129,23 @@ static uint32_t pls_format_to_components(PlsFormat format)
}
}
static const char* vector_swizzle(int vecsize, int index)
{
static const char* swizzle[4][4] =
{
{ ".x", ".y", ".z", ".w" },
{ ".xy", ".yz", ".zw" },
{ ".xyz", ".yzw" },
{ "" }
};
assert(vecsize >= 1 && vecsize <= 4);
assert(index >= 0 && index < 4);
assert(swizzle[vecsize - 1][index]);
return swizzle[vecsize - 1][index];
}
void CompilerGLSL::reset()
{
// We do some speculative optimizations which should pretty much always work out,
@ -3277,13 +3294,10 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
{
if (flattened_buffer_blocks.count(base))
{
std::string expr;
flattened_access_chain(expr, base, indices, count, target_type, 0);
if (need_transpose)
*need_transpose = false;
return expr;
return flattened_access_chain(base, indices, count, target_type, 0);
}
else
{
@ -3291,7 +3305,7 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
}
}
void CompilerGLSL::flattened_access_chain(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
std::string CompilerGLSL::flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
{
if (!target_type.array.empty())
{
@ -3299,20 +3313,22 @@ void CompilerGLSL::flattened_access_chain(std::string &expr, uint32_t base, cons
}
else if (target_type.basetype == SPIRType::Struct)
{
flattened_access_chain_struct(expr, base, indices, count, target_type, offset);
return flattened_access_chain_struct(base, indices, count, target_type, offset);
}
else if (target_type.columns > 1)
{
flattened_access_chain_matrix(expr, base, indices, count, target_type, offset);
return flattened_access_chain_matrix(base, indices, count, target_type, offset);
}
else
{
flattened_access_chain_vector_scalar(expr, base, indices, count, target_type, offset);
return flattened_access_chain_vector_scalar(base, indices, count, target_type, offset);
}
}
void CompilerGLSL::flattened_access_chain_struct(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
std::string CompilerGLSL::flattened_access_chain_struct(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
{
std::string expr;
expr += type_to_glsl(target_type);
expr += "(";
@ -3324,14 +3340,18 @@ void CompilerGLSL::flattened_access_chain_struct(std::string &expr, uint32_t bas
const SPIRType &member_type = get<SPIRType>(target_type.member_types[i]);
uint32_t member_offset = type_struct_member_offset(target_type, uint32_t(i));
flattened_access_chain(expr, base, indices, count, member_type, offset + member_offset);
expr += flattened_access_chain(base, indices, count, member_type, offset + member_offset);
}
expr += ")";
return expr;
}
void CompilerGLSL::flattened_access_chain_matrix(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
std::string CompilerGLSL::flattened_access_chain_matrix(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
{
std::string expr;
expr += type_to_glsl(target_type);
expr += "(";
@ -3340,45 +3360,40 @@ void CompilerGLSL::flattened_access_chain_matrix(std::string &expr, uint32_t bas
if (i != 0)
expr += ", ";
flattened_access_chain_vector_scalar(expr, base, indices, count, target_type, offset + i * 16);
expr += flattened_access_chain_vector_scalar(base, indices, count, target_type, offset + i * 16);
}
expr += ")";
return expr;
}
void CompilerGLSL::flattened_access_chain_vector_scalar(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
std::string CompilerGLSL::flattened_access_chain_vector_scalar(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset)
{
if (target_type.basetype != SPIRType::Float)
SPIRV_CROSS_THROW("Access chains that use non-floating-point base types can not be flattened");
auto result = flattened_access_chain_offset(base, indices, count, offset);
assert(result.second % 4 == 0);
uint32_t index = result.second / 4;
auto buffer_name = to_name(expression_type(base).self);
std::string expr;
expr += buffer_name;
expr += "[";
uint32_t result = flattened_access_chain_offset(expr, base, indices, count, offset);
assert(result % 4 == 0);
uint32_t index = result / 4;
expr += result.first; // this is a series of N1*k1+N2*k2+... that is either empty or ends with a +
expr += convert_to_string(index / 4);
expr += "]";
static const char* swizzle[4][4] =
{
{ ".x", ".y", ".z", ".w" },
{ ".xy", ".yz", ".zw" },
{ ".xyz", ".yzw" },
{ "" }
};
expr += vector_swizzle(target_type.vecsize, index % 4);
assert(target_type.vecsize >= 1 && target_type.vecsize <= 4);
assert(swizzle[target_type.vecsize - 1][index % 4]);
expr += swizzle[target_type.vecsize - 1][index % 4];
return expr;
}
uint32_t CompilerGLSL::flattened_access_chain_offset(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset)
std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset)
{
const auto *type = &expression_type(base);
uint32_t type_size = 0;
@ -3386,6 +3401,8 @@ uint32_t CompilerGLSL::flattened_access_chain_offset(std::string &expr, uint32_t
// For resolving array accesses, etc, keep a local copy for poking.
SPIRType temp;
std::string expr;
for (uint32_t i = 0; i < count; i++)
{
uint32_t index = indices[i];
@ -3431,14 +3448,13 @@ uint32_t CompilerGLSL::flattened_access_chain_offset(std::string &expr, uint32_t
// Matrix -> Vector
else if (type->columns > 1)
{
if (ids[index].get_type() == TypeConstant)
{
auto &c = get<SPIRConstant>(index);
offset += c.scalar() * 16;
}
else
if (ids[index].get_type() != TypeConstant)
SPIRV_CROSS_THROW("Cannot flatten dynamic matrix indexing!");
index = get<SPIRConstant>(index).scalar();
offset += index * 16;
// We have to modify the type, so keep a local copy.
if (&temp != type)
temp = *type;
@ -3448,14 +3464,13 @@ uint32_t CompilerGLSL::flattened_access_chain_offset(std::string &expr, uint32_t
// Vector -> Scalar
else if (type->vecsize > 1)
{
if (ids[index].get_type() == TypeConstant)
{
auto &c = get<SPIRConstant>(index);
offset += c.scalar() * 4;
}
else
if (ids[index].get_type() != TypeConstant)
SPIRV_CROSS_THROW("Cannot flatten dynamic vector indexing!");
index = get<SPIRConstant>(index).scalar();
offset += index * 4;
// We have to modify the type, so keep a local copy.
if (&temp != type)
temp = *type;
@ -3466,7 +3481,7 @@ uint32_t CompilerGLSL::flattened_access_chain_offset(std::string &expr, uint32_t
SPIRV_CROSS_THROW("Cannot subdivide a scalar value!");
}
return offset;
return std::make_pair(expr, offset);
}
bool CompilerGLSL::should_forward(uint32_t id)

View File

@ -317,11 +317,11 @@ protected:
bool chain_only = false, bool *need_transpose = nullptr);
std::string access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, bool *need_transpose);
void flattened_access_chain(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
void flattened_access_chain_struct(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
void flattened_access_chain_matrix(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
void flattened_access_chain_vector_scalar(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
uint32_t flattened_access_chain_offset(std::string &expr, uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset);
std::string flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::string flattened_access_chain_struct(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::string flattened_access_chain_matrix(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::string flattened_access_chain_vector_scalar(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::pair<std::string, uint32_t> flattened_access_chain_offset(uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset);
const char *index_to_swizzle(uint32_t index);
std::string remap_swizzle(uint32_t result_type, uint32_t input_components, uint32_t expr);