Refactor out access chain reads.

Prepare for matrix, array and struct loads.
This commit is contained in:
Hans-Kristian Arntzen 2017-08-15 10:12:08 +02:00
Родитель af2b233582
Коммит 4375aa3fd2
2 изменённых файлов: 59 добавлений и 37 удалений

Просмотреть файл

@ -17,6 +17,7 @@
#include "spirv_hlsl.hpp" #include "spirv_hlsl.hpp"
#include "GLSL.std.450.h" #include "GLSL.std.450.h"
#include <algorithm> #include <algorithm>
#include <assert.h>
using namespace spv; using namespace spv;
using namespace spirv_cross; using namespace spirv_cross;
@ -1849,6 +1850,49 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
} }
} }
string CompilerHLSL::read_access_chain(const SPIRAccessChain &chain)
{
auto &type = get<SPIRType>(chain.basetype);
SPIRType target_type;
target_type.basetype = SPIRType::UInt;
target_type.vecsize = type.vecsize;
target_type.columns = type.columns;
if (type.columns != 1)
SPIRV_CROSS_THROW("Reading matrices from ByteAddressBuffer not yet supported.");
if (type.basetype == SPIRType::Struct)
SPIRV_CROSS_THROW("Reading structs from ByteAddressBuffer not yet supported.");
if (type.width != 32)
SPIRV_CROSS_THROW("Reading types other than 32-bit from ByteAddressBuffer not yet supported.");
const char *load_op = nullptr;
switch (type.vecsize)
{
case 1:
load_op = "Load";
break;
case 2:
load_op = "Load2";
break;
case 3:
load_op = "Load3";
break;
case 4:
load_op = "Load4";
break;
default:
SPIRV_CROSS_THROW("Unknown vector size.");
}
auto load_expr = join(chain.base, ".", load_op, "(", chain.dynamic_index, chain.static_index, ")");
auto bitcast_op = bitcast_glsl_op(type, target_type);
if (!bitcast_op.empty())
load_expr = join(bitcast_op, "(", load_expr, ")");
return load_expr;
}
void CompilerHLSL::emit_load(const Instruction &instruction) void CompilerHLSL::emit_load(const Instruction &instruction)
{ {
auto ops = stream(instruction); auto ops = stream(instruction);
@ -1856,46 +1900,11 @@ void CompilerHLSL::emit_load(const Instruction &instruction)
auto *chain = maybe_get<SPIRAccessChain>(ops[2]); auto *chain = maybe_get<SPIRAccessChain>(ops[2]);
if (chain) if (chain)
{ {
auto &type = get<SPIRType>(chain->basetype);
uint32_t result_type = ops[0]; uint32_t result_type = ops[0];
uint32_t id = ops[1]; uint32_t id = ops[1];
uint32_t ptr = ops[2]; uint32_t ptr = ops[2];
SPIRType target_type; auto load_expr = read_access_chain(*chain);
target_type.basetype = SPIRType::UInt;
target_type.vecsize = type.vecsize;
target_type.columns = type.columns;
if (type.columns != 1)
SPIRV_CROSS_THROW("Reading matrices from ByteAddressBuffer not yet supported.");
if (type.basetype == SPIRType::Struct)
SPIRV_CROSS_THROW("Reading structs from ByteAddressBuffer not yet supported.");
if (type.width != 32)
SPIRV_CROSS_THROW("Reading types other than 32-bit from ByteAddressBuffer not yet supported.");
const char *load_op = nullptr;
switch (type.vecsize)
{
case 1:
load_op = "Load";
break;
case 2:
load_op = "Load2";
break;
case 3:
load_op = "Load3";
break;
case 4:
load_op = "Load4";
break;
default:
SPIRV_CROSS_THROW("Unknown vector size.");
}
auto load_expr = join(chain->base, ".", load_op, "(", chain->dynamic_index, chain->static_index, ")");
auto bitcast_op = bitcast_glsl_op(type, target_type);
if (!bitcast_op.empty())
load_expr = join(bitcast_op, "(", load_expr, ")");
bool forward = should_forward(ptr) && forced_temporaries.find(id) == end(forced_temporaries); bool forward = should_forward(ptr) && forced_temporaries.find(id) == end(forced_temporaries);
auto &e = emit_op(result_type, id, load_expr, forward, true); auto &e = emit_op(result_type, id, load_expr, forward, true);
@ -1994,8 +2003,20 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction)
base = to_expression(ops[2]); base = to_expression(ops[2]);
auto *basetype = &type; auto *basetype = &type;
// Start traversing type hierarchy at the proper non-pointer types.
while (basetype->pointer)
{
assert(basetype->parent_type);
basetype = &get<SPIRType>(basetype->parent_type);
}
// Traverse the type hierarchy down to the actual buffer types.
for (uint32_t i = 0; i < to_plain_buffer_length; i++) for (uint32_t i = 0; i < to_plain_buffer_length; i++)
basetype = &get<SPIRType>(type.parent_type); {
assert(basetype->parent_type);
basetype = &get<SPIRType>(basetype->parent_type);
}
uint32_t matrix_stride = 0; uint32_t matrix_stride = 0;
bool need_transpose = false; bool need_transpose = false;

Просмотреть файл

@ -90,6 +90,7 @@ private:
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override; void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
void emit_access_chain(const Instruction &instruction); void emit_access_chain(const Instruction &instruction);
void emit_load(const Instruction &instruction); void emit_load(const Instruction &instruction);
std::string read_access_chain(const SPIRAccessChain &chain);
void emit_store(const Instruction &instruction); void emit_store(const Instruction &instruction);
const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override; const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override;