-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Make interleaved layout (more) explicit in generated headers. #42628
Changes from all commits
d5acf20
bce747d
3237c3c
7cd9792
f5b6627
0e251f7
9cc0bc5
154b63b
4235ecf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -226,8 +226,9 @@ std::optional<nlohmann::json> Reflector::GenerateTemplateArguments() const { | |
|
||
{ | ||
auto& stage_inputs = root["stage_inputs"] = nlohmann::json::array_t{}; | ||
if (auto stage_inputs_json = | ||
ReflectResources(shader_resources.stage_inputs); | ||
if (auto stage_inputs_json = ReflectResources( | ||
shader_resources.stage_inputs, | ||
/*compute_offsets=*/execution_model == spv::ExecutionModelVertex); | ||
stage_inputs_json.has_value()) { | ||
stage_inputs = std::move(stage_inputs_json.value()); | ||
} else { | ||
|
@@ -402,8 +403,36 @@ std::shared_ptr<fml::Mapping> Reflector::InflateTemplate( | |
inflated_template->size(), [inflated_template](auto, auto) {}); | ||
} | ||
|
||
std::vector<size_t> Reflector::ComputeOffsets( | ||
const spirv_cross::SmallVector<spirv_cross::Resource>& resources) const { | ||
std::vector<size_t> offsets(resources.size(), 0); | ||
if (resources.size() == 0) { | ||
return offsets; | ||
} | ||
for (const auto& resource : resources) { | ||
const auto type = compiler_->get_type(resource.type_id); | ||
auto location = compiler_->get_decoration( | ||
resource.id, spv::Decoration::DecorationLocation); | ||
// Malformed shader, will be caught later on. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not have some kind of VALIDATION_LOG here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this happens with invalid inputs, there is already a validation log that fires and exit that happens, so we'd either need to perform all of that work twice (since this code only runs on vertex shaders), or we do what I did here and let the later stage catch it. |
||
if (location >= resources.size() || location < 0) { | ||
location = 0; | ||
} | ||
offsets[location] = (type.width * type.vecsize) / 8; | ||
} | ||
for (size_t i = 1; i < resources.size(); i++) { | ||
offsets[i] += offsets[i - 1]; | ||
} | ||
for (size_t i = resources.size() - 1; i > 0; i--) { | ||
offsets[i] = offsets[i - 1]; | ||
} | ||
offsets[0] = 0; | ||
|
||
return offsets; | ||
} | ||
|
||
std::optional<nlohmann::json::object_t> Reflector::ReflectResource( | ||
const spirv_cross::Resource& resource) const { | ||
const spirv_cross::Resource& resource, | ||
std::optional<size_t> offset) const { | ||
nlohmann::json::object_t result; | ||
|
||
result["name"] = resource.name; | ||
|
@@ -426,6 +455,7 @@ std::optional<nlohmann::json::object_t> Reflector::ReflectResource( | |
return std::nullopt; | ||
} | ||
result["type"] = std::move(type.value()); | ||
result["offset"] = offset.value_or(0u); | ||
return result; | ||
} | ||
|
||
|
@@ -462,11 +492,23 @@ std::optional<nlohmann::json::object_t> Reflector::ReflectType( | |
} | ||
|
||
std::optional<nlohmann::json::array_t> Reflector::ReflectResources( | ||
const spirv_cross::SmallVector<spirv_cross::Resource>& resources) const { | ||
const spirv_cross::SmallVector<spirv_cross::Resource>& resources, | ||
bool compute_offsets) const { | ||
nlohmann::json::array_t result; | ||
result.reserve(resources.size()); | ||
std::vector<size_t> offsets; | ||
if (compute_offsets) { | ||
offsets = ComputeOffsets(resources); | ||
} | ||
for (const auto& resource : resources) { | ||
if (auto reflected = ReflectResource(resource); reflected.has_value()) { | ||
std::optional<size_t> maybe_offset = std::nullopt; | ||
if (compute_offsets) { | ||
auto location = compiler_->get_decoration( | ||
resource.id, spv::Decoration::DecorationLocation); | ||
maybe_offset = offsets[location]; | ||
} | ||
if (auto reflected = ReflectResource(resource, maybe_offset); | ||
reflected.has_value()) { | ||
result.emplace_back(std::move(reflected.value())); | ||
} else { | ||
return std::nullopt; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,17 +23,12 @@ BufferBindingsGLES::~BufferBindingsGLES() = default; | |
|
||
bool BufferBindingsGLES::RegisterVertexStageInput( | ||
const ProcTableGLES& gl, | ||
const std::vector<ShaderStageIOSlot>& p_inputs) { | ||
// Attrib locations have to be iterated over in order of location because we | ||
// will be calculating offsets later. | ||
auto inputs = p_inputs; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't need to sort, offsets must already be computed |
||
std::sort(inputs.begin(), inputs.end(), [](const auto& lhs, const auto& rhs) { | ||
return lhs.location < rhs.location; | ||
}); | ||
|
||
const std::vector<ShaderStageIOSlot>& p_inputs, | ||
const std::vector<ShaderStageBufferLayout>& layouts) { | ||
std::vector<VertexAttribPointer> vertex_attrib_arrays; | ||
size_t offset = 0u; | ||
for (const auto& input : inputs) { | ||
for (auto i = 0u; i < p_inputs.size(); i++) { | ||
const auto& input = p_inputs[i]; | ||
const auto& layout = layouts[input.binding]; | ||
VertexAttribPointer attrib; | ||
attrib.index = input.location; | ||
// Component counts must be 1, 2, 3 or 4. Do that validation now. | ||
|
@@ -47,13 +42,10 @@ bool BufferBindingsGLES::RegisterVertexStageInput( | |
} | ||
attrib.type = type.value(); | ||
attrib.normalized = GL_FALSE; | ||
attrib.offset = offset; | ||
offset += (input.bit_width * input.vec_size) / 8; | ||
attrib.offset = input.offset; | ||
attrib.stride = layout.stride; | ||
vertex_attrib_arrays.emplace_back(attrib); | ||
} | ||
for (auto& array : vertex_attrib_arrays) { | ||
array.stride = offset; | ||
} | ||
vertex_attrib_arrays_ = std::move(vertex_attrib_arrays); | ||
return true; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,27 +20,14 @@ class VertexDescriptorMTL { | |
|
||
~VertexDescriptorMTL(); | ||
|
||
bool SetStageInputs(const std::vector<ShaderStageIOSlot>& inputs); | ||
bool SetStageInputsAndLayout( | ||
const std::vector<ShaderStageIOSlot>& inputs, | ||
const std::vector<ShaderStageBufferLayout>& layouts); | ||
|
||
MTLVertexDescriptor* GetMTLVertexDescriptor() const; | ||
|
||
private: | ||
struct StageInput { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't need to sort, offsets must already be computed |
||
size_t location; | ||
MTLVertexFormat format; | ||
size_t length; | ||
|
||
StageInput(size_t p_location, MTLVertexFormat p_format, size_t p_length) | ||
: location(p_location), format(p_format), length(p_length) {} | ||
|
||
struct Compare { | ||
constexpr bool operator()(const StageInput& lhs, | ||
const StageInput& rhs) const { | ||
return lhs.location < rhs.location; | ||
} | ||
}; | ||
}; | ||
std::set<StageInput, StageInput::Compare> stage_inputs_; | ||
MTLVertexDescriptor* descriptor_; | ||
|
||
FML_DISALLOW_COPY_AND_ASSIGN(VertexDescriptorMTL); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Essentially the addtions here are:
We may need more info but this is good enough for now. TBD weirdness about stride in GLES