Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 5a4bbd0

Browse files
author
Jonah Williams
authored
[impeller] combine sampler and texture maps. (#44990)
Simplify command encoding and reduce binding size by placing all texture/sampler data in a single map instead of 3. We don't currently (nor do we plan to) support separate textures and samplers. The vulkan backend is particularly bad, because there are 3 map lookups to pull all of the texture and sampler data out of the bindings. Also see [go/impeller-vulkan-cmd-recording-performance](http://goto.google.com/impeller-vulkan-cmd-recording-performance)
1 parent f9264f0 commit 5a4bbd0

File tree

10 files changed

+72
-192
lines changed

10 files changed

+72
-192
lines changed

impeller/core/resource_binder.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,6 @@ struct ResourceBinder {
3232
const ShaderMetadata& metadata,
3333
const BufferView& view) = 0;
3434

35-
virtual bool BindResource(ShaderStage stage,
36-
const SampledImageSlot& slot,
37-
const ShaderMetadata& metadata,
38-
const std::shared_ptr<const Texture>& texture) = 0;
39-
40-
virtual bool BindResource(ShaderStage stage,
41-
const SampledImageSlot& slot,
42-
const ShaderMetadata& metadata,
43-
const std::shared_ptr<const Sampler>& sampler) = 0;
44-
4535
virtual bool BindResource(ShaderStage stage,
4636
const SampledImageSlot& slot,
4737
const ShaderMetadata& metadata,

impeller/renderer/backend/gles/buffer_bindings_gles.cc

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -305,15 +305,15 @@ bool BufferBindingsGLES::BindTextures(const ProcTableGLES& gl,
305305
const Bindings& bindings,
306306
ShaderStage stage) const {
307307
size_t active_index = 0;
308-
for (const auto& texture : bindings.textures) {
309-
const auto& texture_gles = TextureGLES::Cast(*texture.second.resource);
310-
if (texture.second.GetMetadata() == nullptr) {
308+
for (const auto& data : bindings.sampled_images) {
309+
const auto& texture_gles = TextureGLES::Cast(*data.second.texture.resource);
310+
if (data.second.texture.GetMetadata() == nullptr) {
311311
VALIDATION_LOG << "No metadata found for texture binding.";
312312
return false;
313313
}
314314

315315
const auto uniform_key =
316-
CreateUniformMemberKey(texture.second.GetMetadata()->name);
316+
CreateUniformMemberKey(data.second.texture.GetMetadata()->name);
317317
auto uniform = uniform_locations_.find(uniform_key);
318318
if (uniform == uniform_locations_.end()) {
319319
VALIDATION_LOG << "Could not find uniform for key: " << uniform_key;
@@ -341,12 +341,9 @@ bool BufferBindingsGLES::BindTextures(const ProcTableGLES& gl,
341341
/// If there is a sampler for the texture at the same index, configure the
342342
/// bound texture using that sampler.
343343
///
344-
auto sampler = bindings.samplers.find(texture.first);
345-
if (sampler != bindings.samplers.end()) {
346-
const auto& sampler_gles = SamplerGLES::Cast(*sampler->second.resource);
347-
if (!sampler_gles.ConfigureBoundTexture(texture_gles, gl)) {
348-
return false;
349-
}
344+
const auto& sampler_gles = SamplerGLES::Cast(*data.second.sampler.resource);
345+
if (!sampler_gles.ConfigureBoundTexture(texture_gles, gl)) {
346+
return false;
350347
}
351348

352349
//--------------------------------------------------------------------------

impeller/renderer/backend/metal/compute_pass_mtl.mm

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -187,22 +187,13 @@ static bool Bind(ComputePassBindingsCache& pass,
187187

188188
static bool Bind(ComputePassBindingsCache& pass,
189189
size_t bind_index,
190+
const Sampler& sampler,
190191
const Texture& texture) {
191-
if (!texture.IsValid()) {
192+
if (!sampler.IsValid() || !texture.IsValid()) {
192193
return false;
193194
}
194195

195196
pass.SetTexture(bind_index, TextureMTL::Cast(texture).GetMTLTexture());
196-
return true;
197-
}
198-
199-
static bool Bind(ComputePassBindingsCache& pass,
200-
size_t bind_index,
201-
const Sampler& sampler) {
202-
if (!sampler.IsValid()) {
203-
return false;
204-
}
205-
206197
pass.SetSampler(bind_index, SamplerMTL::Cast(sampler).GetMTLSamplerState());
207198
return true;
208199
}
@@ -239,16 +230,13 @@ static bool Bind(ComputePassBindingsCache& pass,
239230
}
240231
}
241232

242-
for (const auto& texture : command.bindings.textures) {
243-
if (!Bind(pass_bindings, texture.first, *texture.second.resource)) {
244-
return false;
245-
}
246-
}
247-
for (const auto& sampler : command.bindings.samplers) {
248-
if (!Bind(pass_bindings, sampler.first, *sampler.second.resource)) {
233+
for (const auto& data : command.bindings.sampled_images) {
234+
if (!Bind(pass_bindings, data.first, *data.second.sampler.resource,
235+
*data.second.texture.resource)) {
249236
return false;
250237
}
251238
}
239+
252240
// TODO(dnfield): use feature detection to support non-uniform threadgroup
253241
// sizes.
254242
// https://github.com/flutter/flutter/issues/110619

impeller/renderer/backend/metal/render_pass_mtl.mm

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,9 @@ static bool Bind(PassBindingsCache& pass,
379379
static bool Bind(PassBindingsCache& pass,
380380
ShaderStage stage,
381381
size_t bind_index,
382+
const Sampler& sampler,
382383
const Texture& texture) {
383-
if (!texture.IsValid()) {
384+
if (!sampler.IsValid() || !texture.IsValid()) {
384385
return false;
385386
}
386387

@@ -395,18 +396,8 @@ static bool Bind(PassBindingsCache& pass,
395396
}
396397

397398
return pass.SetTexture(stage, bind_index,
398-
TextureMTL::Cast(texture).GetMTLTexture());
399-
}
400-
401-
static bool Bind(PassBindingsCache& pass,
402-
ShaderStage stage,
403-
size_t bind_index,
404-
const Sampler& sampler) {
405-
if (!sampler.IsValid()) {
406-
return false;
407-
}
408-
409-
return pass.SetSampler(stage, bind_index,
399+
TextureMTL::Cast(texture).GetMTLTexture()) &&
400+
pass.SetSampler(stage, bind_index,
410401
SamplerMTL::Cast(sampler).GetMTLSamplerState());
411402
}
412403

@@ -422,15 +413,9 @@ static bool Bind(PassBindingsCache& pass,
422413
return false;
423414
}
424415
}
425-
for (const auto& texture : bindings.textures) {
426-
if (!Bind(pass_bindings, stage, texture.first,
427-
*texture.second.resource)) {
428-
return false;
429-
}
430-
}
431-
for (const auto& sampler : bindings.samplers) {
432-
if (!Bind(pass_bindings, stage, sampler.first,
433-
*sampler.second.resource)) {
416+
for (const auto& data : bindings.sampled_images) {
417+
if (!Bind(pass_bindings, stage, data.first, *data.second.sampler.resource,
418+
*data.second.texture.resource)) {
434419
return false;
435420
}
436421
}

impeller/renderer/backend/vulkan/compute_pass_vk.cc

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ static bool UpdateBindingLayouts(const Bindings& bindings,
4343

4444
barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
4545

46-
for (const auto& [_, texture] : bindings.textures) {
47-
if (!TextureVK::Cast(*texture.resource).SetLayout(barrier)) {
46+
for (const auto& [_, data] : bindings.sampled_images) {
47+
if (!TextureVK::Cast(*data.texture.resource).SetLayout(barrier)) {
4848
return false;
4949
}
5050
}
@@ -88,21 +88,17 @@ static bool AllocateAndBindDescriptorSets(const ContextVK& context,
8888
&writes, //
8989
&vk_desc_set //
9090
](const Bindings& bindings) -> bool {
91-
for (const auto& [index, sampler_handle] : bindings.samplers) {
92-
if (bindings.textures.find(index) == bindings.textures.end()) {
93-
return false;
94-
}
95-
96-
auto texture = bindings.textures.at(index).resource;
91+
for (const auto& [index, data] : bindings.sampled_images) {
92+
auto texture = data.texture.resource;
9793
const auto& texture_vk = TextureVK::Cast(*texture);
98-
const SamplerVK& sampler = SamplerVK::Cast(*sampler_handle.resource);
94+
const SamplerVK& sampler = SamplerVK::Cast(*data.sampler.resource);
9995

10096
if (!encoder.Track(texture) ||
10197
!encoder.Track(sampler.GetSharedSampler())) {
10298
return false;
10399
}
104100

105-
const SampledImageSlot& slot = bindings.sampled_images.at(index);
101+
const SampledImageSlot& slot = data.slot;
106102

107103
vk::DescriptorImageInfo image_info;
108104
image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;

impeller/renderer/backend/vulkan/render_pass_vk.cc

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ static bool UpdateBindingLayouts(const Bindings& bindings,
283283

284284
barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
285285

286-
for (const auto& [_, texture] : bindings.textures) {
287-
if (!TextureVK::Cast(*texture.resource).SetLayout(barrier)) {
286+
for (const auto& [_, data] : bindings.sampled_images) {
287+
if (!TextureVK::Cast(*data.texture.resource).SetLayout(barrier)) {
288288
return false;
289289
}
290290
}
@@ -331,21 +331,17 @@ static bool AllocateAndBindDescriptorSets(const ContextVK& context,
331331
&writes, //
332332
&vk_desc_set //
333333
](const Bindings& bindings) -> bool {
334-
for (const auto& [index, sampler_handle] : bindings.samplers) {
335-
if (bindings.textures.find(index) == bindings.textures.end()) {
336-
return false;
337-
}
338-
339-
auto texture = bindings.textures.at(index).resource;
334+
for (const auto& [index, data] : bindings.sampled_images) {
335+
auto texture = data.texture.resource;
340336
const auto& texture_vk = TextureVK::Cast(*texture);
341-
const SamplerVK& sampler = SamplerVK::Cast(*sampler_handle.resource);
337+
const SamplerVK& sampler = SamplerVK::Cast(*data.sampler.resource);
342338

343339
if (!encoder.Track(texture) ||
344340
!encoder.Track(sampler.GetSharedSampler())) {
345341
return false;
346342
}
347343

348-
const SampledImageSlot& slot = bindings.sampled_images.at(index);
344+
const SampledImageSlot& slot = data.slot;
349345

350346
vk::DescriptorImageInfo image_info;
351347
image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;

impeller/renderer/command.cc

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -83,53 +83,32 @@ bool Command::DoBindResource(ShaderStage stage,
8383
bool Command::BindResource(ShaderStage stage,
8484
const SampledImageSlot& slot,
8585
const ShaderMetadata& metadata,
86-
const std::shared_ptr<const Texture>& texture) {
87-
if (!texture || !texture->IsValid()) {
88-
return false;
89-
}
90-
91-
if (!slot.HasTexture()) {
92-
return true;
93-
}
94-
95-
switch (stage) {
96-
case ShaderStage::kVertex:
97-
vertex_bindings.textures[slot.texture_index] = {&metadata, texture};
98-
return true;
99-
case ShaderStage::kFragment:
100-
fragment_bindings.textures[slot.texture_index] = {&metadata, texture};
101-
return true;
102-
case ShaderStage::kCompute:
103-
VALIDATION_LOG << "Use ComputeCommands for compute shader stages.";
104-
case ShaderStage::kTessellationControl:
105-
case ShaderStage::kTessellationEvaluation:
106-
case ShaderStage::kUnknown:
107-
return false;
108-
}
109-
110-
return false;
111-
}
112-
113-
bool Command::BindResource(ShaderStage stage,
114-
const SampledImageSlot& slot,
115-
const ShaderMetadata& metadata,
86+
const std::shared_ptr<const Texture>& texture,
11687
const std::shared_ptr<const Sampler>& sampler) {
11788
if (!sampler || !sampler->IsValid()) {
11889
return false;
11990
}
120-
121-
if (!slot.HasSampler()) {
91+
if (!texture || !texture->IsValid()) {
92+
return false;
93+
}
94+
if (!slot.HasSampler() || !slot.HasTexture()) {
12295
return true;
12396
}
12497

12598
switch (stage) {
12699
case ShaderStage::kVertex:
127-
vertex_bindings.samplers[slot.sampler_index] = {&metadata, sampler};
128-
vertex_bindings.sampled_images[slot.sampler_index] = slot;
100+
vertex_bindings.sampled_images[slot.sampler_index] = TextureAndSampler{
101+
.slot = slot,
102+
.texture = {&metadata, texture},
103+
.sampler = {&metadata, sampler},
104+
};
129105
return true;
130106
case ShaderStage::kFragment:
131-
fragment_bindings.samplers[slot.sampler_index] = {&metadata, sampler};
132-
fragment_bindings.sampled_images[slot.sampler_index] = slot;
107+
fragment_bindings.sampled_images[slot.sampler_index] = TextureAndSampler{
108+
.slot = slot,
109+
.texture = {&metadata, texture},
110+
.sampler = {&metadata, sampler},
111+
};
133112
return true;
134113
case ShaderStage::kCompute:
135114
VALIDATION_LOG << "Use ComputeCommands for compute shader stages.";
@@ -142,13 +121,4 @@ bool Command::BindResource(ShaderStage stage,
142121
return false;
143122
}
144123

145-
bool Command::BindResource(ShaderStage stage,
146-
const SampledImageSlot& slot,
147-
const ShaderMetadata& metadata,
148-
const std::shared_ptr<const Texture>& texture,
149-
const std::shared_ptr<const Sampler>& sampler) {
150-
return BindResource(stage, slot, metadata, texture) &&
151-
BindResource(stage, slot, metadata, sampler);
152-
}
153-
154124
} // namespace impeller

impeller/renderer/command.h

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,17 @@ using BufferResource = Resource<BufferView>;
6161
using TextureResource = Resource<std::shared_ptr<const Texture>>;
6262
using SamplerResource = Resource<std::shared_ptr<const Sampler>>;
6363

64+
/// @brief combines the texture, sampler and sampler slot information.
65+
struct TextureAndSampler {
66+
SampledImageSlot slot;
67+
TextureResource texture;
68+
SamplerResource sampler;
69+
};
70+
6471
struct Bindings {
6572
std::map<size_t, ShaderUniformSlot> uniforms;
66-
std::map<size_t, SampledImageSlot> sampled_images;
73+
std::map<size_t, TextureAndSampler> sampled_images;
6774
std::map<size_t, BufferResource> buffers;
68-
std::map<size_t, TextureResource> textures;
69-
std::map<size_t, SamplerResource> samplers;
7075
};
7176

7277
//------------------------------------------------------------------------------
@@ -184,18 +189,6 @@ struct Command : public ResourceBinder {
184189
const std::shared_ptr<const ShaderMetadata>& metadata,
185190
const BufferView& view);
186191

187-
// |ResourceBinder|
188-
bool BindResource(ShaderStage stage,
189-
const SampledImageSlot& slot,
190-
const ShaderMetadata& metadata,
191-
const std::shared_ptr<const Texture>& texture) override;
192-
193-
// |ResourceBinder|
194-
bool BindResource(ShaderStage stage,
195-
const SampledImageSlot& slot,
196-
const ShaderMetadata& metadata,
197-
const std::shared_ptr<const Sampler>& sampler) override;
198-
199192
// |ResourceBinder|
200193
bool BindResource(ShaderStage stage,
201194
const SampledImageSlot& slot,
@@ -205,7 +198,9 @@ struct Command : public ResourceBinder {
205198

206199
BufferView GetVertexBuffer() const;
207200

208-
constexpr operator bool() const { return pipeline && pipeline->IsValid(); }
201+
constexpr explicit operator bool() const {
202+
return pipeline && pipeline->IsValid();
203+
}
209204

210205
private:
211206
template <class T>

0 commit comments

Comments
 (0)