Skip to content

Commit 16ce253

Browse files
SenorBlancoDawn LUCI CQ
authored and
Dawn LUCI CQ
committed
OpenGL: fix multiplanar external textures.
There are two problems with multiplanar textures in the OpenGL backend. 1) When the the multiplanar external texture transform runs, it splits a texture_external variable into two texture_2d variables. The Resolver then creates new texture/sampler pairs for the samplers with which the plane1 texture is used, and new binding points for those that bubble up to the global level. Since Dawn collects sampler/texture pairs from the Inspector before the transforms run, it doesn't know about these extra pairs, doesn't name them and doesn't bind anything to them. 2) The multiplanar transform also inserts calls to textureDimensions(), a texture-only builtin that doesn't require a sampler. In the CombineSamplers transform, since OpenGLES doesn't have the concept of a texture-only sampler2d, this necessitates the creation of new binding points for the texture with a "placeholder" sampler, which Dawn also doesn't know about, so it doesn't name them or bind anything to them. Fix #1 is on the Dawn side: when iterating over external texture bindings, create a map from plane0 texture -> plane1 texture. When iterating over the sampler/texture uses that the Tint inspector has discovered, if the texture is an external texture, add a new pair with the same sampler and the plane1 texture. Fix for #2 is on the Tint side: if a function contains both a texture-only reference and a texture/sampler reference to the same texture, use the latter and remove the former. Texture-only builtins won't use the sampler anyway. This is essentially an optimization, but it's one we know will run on the functions generated by the multiplanar transform, since it always calls textureDimensions() in a function also containing the textureSample() call on the same texture. Change-Id: I531ab09acdc47b435d72033aabd9eefa57f8f6e3 Bug: tint:1774 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/152660 Kokoro: Kokoro <[email protected]> Reviewed-by: Ben Clayton <[email protected]> Commit-Queue: Stephen White <[email protected]>
1 parent 243017b commit 16ce253

File tree

9 files changed

+157
-117
lines changed

9 files changed

+157
-117
lines changed

src/dawn/native/opengl/ShaderModuleGL.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,26 @@ tint::glsl::writer::Version::Standard ToTintGLStandard(opengl::OpenGLVersion::St
5858

5959
using BindingMap = std::unordered_map<tint::BindingPoint, tint::BindingPoint>;
6060

61+
opengl::CombinedSampler* AppendCombinedSampler(opengl::CombinedSamplerInfo* info,
62+
tint::inspector::SamplerTexturePair pair,
63+
tint::BindingPoint placeholderBindingPoint) {
64+
info->emplace_back();
65+
opengl::CombinedSampler* combinedSampler = &info->back();
66+
combinedSampler->usePlaceholderSampler = pair.sampler_binding_point == placeholderBindingPoint;
67+
combinedSampler->samplerLocation.group = BindGroupIndex(pair.sampler_binding_point.group);
68+
combinedSampler->samplerLocation.binding = BindingNumber(pair.sampler_binding_point.binding);
69+
combinedSampler->textureLocation.group = BindGroupIndex(pair.texture_binding_point.group);
70+
combinedSampler->textureLocation.binding = BindingNumber(pair.texture_binding_point.binding);
71+
return combinedSampler;
72+
}
73+
6174
#define GLSL_COMPILATION_REQUEST_MEMBERS(X) \
6275
X(const tint::Program*, inputProgram) \
6376
X(std::string, entryPointName) \
6477
X(SingleShaderStage, stage) \
6578
X(tint::ExternalTextureOptions, externalTextureOptions) \
6679
X(BindingMap, glBindings) \
80+
X(BindingMap, externalTextureExpansionMap) \
6781
X(tint::TextureBuiltinsFromUniformOptions, textureBuiltinsFromUniform) \
6882
X(std::optional<tint::ast::transform::SubstituteOverride::Config>, substituteOverrideConfig) \
6983
X(LimitsForCompilationRequest, limits) \
@@ -164,16 +178,17 @@ ResultOrError<GLuint> ShaderModule::CompileShader(
164178
// variables to the 1D space.
165179
const BindingInfoArray& moduleBindingInfo =
166180
GetEntryPoint(programmableStage.entryPoint).bindings;
167-
std::unordered_map<BindingPoint, BindingPoint> glBindings;
181+
BindingMap glBindings;
182+
BindingMap externalTextureExpansionMap;
168183
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
184+
uint32_t groupAsInt = static_cast<uint32_t>(group);
169185
const BindGroupLayoutInternalBase* bgl = layout->GetBindGroupLayout(group);
170186
const auto& indices = layout->GetBindingIndexInfo()[group];
171187
const auto& groupBindingInfo = moduleBindingInfo[group];
172188
for (const auto& [bindingNumber, bindingInfo] : groupBindingInfo) {
173189
BindingIndex bindingIndex = bgl->GetBindingIndex(bindingNumber);
174190
GLuint shaderIndex = indices[bindingIndex];
175-
BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
176-
static_cast<uint32_t>(bindingNumber)};
191+
BindingPoint srcBindingPoint{groupAsInt, static_cast<uint32_t>(bindingNumber)};
177192
BindingPoint dstBindingPoint{0, shaderIndex};
178193
if (srcBindingPoint != dstBindingPoint) {
179194
glBindings.emplace(srcBindingPoint, dstBindingPoint);
@@ -183,12 +198,12 @@ ResultOrError<GLuint> ShaderModule::CompileShader(
183198
for (const auto& [_, expansion] : bgl->GetExternalTextureBindingExpansionMap()) {
184199
uint32_t plane1Slot = indices[bgl->GetBindingIndex(expansion.plane1)];
185200
uint32_t paramsSlot = indices[bgl->GetBindingIndex(expansion.params)];
186-
glBindings.emplace(
187-
BindingPoint{static_cast<uint32_t>(group), static_cast<uint32_t>(expansion.plane1)},
188-
BindingPoint{0u, plane1Slot});
189-
glBindings.emplace(
190-
BindingPoint{static_cast<uint32_t>(group), static_cast<uint32_t>(expansion.params)},
191-
BindingPoint{0u, paramsSlot});
201+
BindingPoint plane0{groupAsInt, static_cast<uint32_t>(expansion.plane0)};
202+
BindingPoint plane1{groupAsInt, static_cast<uint32_t>(expansion.plane1)};
203+
BindingPoint params{groupAsInt, static_cast<uint32_t>(expansion.params)};
204+
glBindings.emplace(plane1, BindingPoint{0u, plane1Slot});
205+
glBindings.emplace(params, BindingPoint{0u, paramsSlot});
206+
externalTextureExpansionMap[plane0] = plane1;
192207
}
193208
}
194209

@@ -213,6 +228,7 @@ ResultOrError<GLuint> ShaderModule::CompileShader(
213228
req.entryPointName = programmableStage.entryPoint;
214229
req.externalTextureOptions = BuildExternalTextureTransformBindings(layout);
215230
req.glBindings = std::move(glBindings);
231+
req.externalTextureExpansionMap = std::move(externalTextureExpansionMap);
216232
req.textureBuiltinsFromUniform = std::move(textureBuiltinsFromUniform);
217233
req.substituteOverrideConfig = std::move(substituteOverrideConfig);
218234
req.limits = LimitsForCompilationRequest::Create(limits.v1);
@@ -277,21 +293,26 @@ ResultOrError<GLuint> ShaderModule::CompileShader(
277293
auto uses = inspector.GetSamplerTextureUses(r.entryPointName, placeholderBindingPoint);
278294
CombinedSamplerInfo combinedSamplerInfo;
279295
for (const auto& use : uses) {
280-
combinedSamplerInfo.emplace_back();
296+
CombinedSampler* info =
297+
AppendCombinedSampler(&combinedSamplerInfo, use, placeholderBindingPoint);
281298

282-
CombinedSampler* info = &combinedSamplerInfo.back();
283-
if (use.sampler_binding_point == placeholderBindingPoint) {
284-
info->usePlaceholderSampler = true;
299+
if (info->usePlaceholderSampler) {
285300
needsPlaceholderSampler = true;
286301
tintOptions.placeholder_binding_point = placeholderBindingPoint;
287-
} else {
288-
info->usePlaceholderSampler = false;
289302
}
290-
info->samplerLocation.group = BindGroupIndex(use.sampler_binding_point.group);
291-
info->samplerLocation.binding = BindingNumber(use.sampler_binding_point.binding);
292-
info->textureLocation.group = BindGroupIndex(use.texture_binding_point.group);
293-
info->textureLocation.binding = BindingNumber(use.texture_binding_point.binding);
294303
tintOptions.binding_map[use] = info->GetName();
304+
305+
// If the texture has an associated plane1 texture (ie., it's an external texture),
306+
// append a new combined sampler with the same sampler and the plane1 texture.
307+
BindingMap::iterator plane1Texture =
308+
r.externalTextureExpansionMap.find(use.texture_binding_point);
309+
if (plane1Texture != r.externalTextureExpansionMap.end()) {
310+
tint::inspector::SamplerTexturePair plane1Use{use.sampler_binding_point,
311+
plane1Texture->second};
312+
CombinedSampler* plane1Info = AppendCombinedSampler(
313+
&combinedSamplerInfo, plane1Use, placeholderBindingPoint);
314+
tintOptions.binding_map[plane1Use] = plane1Info->GetName();
315+
}
295316
}
296317

297318
tintOptions.binding_remapper_options.binding_points = std::move(r.glBindings);

src/dawn/tests/end2end/ExternalTextureTests.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,6 @@ TEST_P(ExternalTextureTests, SampleExternalTexture) {
207207
}
208208

209209
TEST_P(ExternalTextureTests, SampleMultiplanarExternalTexture) {
210-
// TODO(crbug.com/tint/1774): Tint has an issue compiling shaders that use external textures on
211-
// OpenGL/OpenGLES.
212-
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
213-
214210
wgpu::Texture sampledTexturePlane0 =
215211
Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::R8Unorm,
216212
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
@@ -305,10 +301,6 @@ TEST_P(ExternalTextureTests, SampleMultiplanarExternalTexture) {
305301
TEST_P(ExternalTextureTests, SampleMultiplanarExternalTextureNorm16) {
306302
DAWN_TEST_UNSUPPORTED_IF(!IsNorm16TextureFormatsSupported());
307303

308-
// TODO(crbug.com/tint/1774): Tint has an issue compiling shaders that use external textures on
309-
// OpenGL/OpenGLES.
310-
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
311-
312304
wgpu::Texture sampledTexturePlane0 =
313305
Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::R16Unorm,
314306
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
@@ -560,10 +552,6 @@ TEST_P(ExternalTextureTests, RotateAndOrFlipSinglePlane) {
560552
// square in the lower left and a blue square in the lower right. The image is then sampled as an
561553
// external texture and rotated 0, 90, 180, and 270 degrees with and without the y-axis flipped.
562554
TEST_P(ExternalTextureTests, RotateAndOrFlipMultiplanar) {
563-
// TODO(crbug.com/tint/1774): Tint has an issue compiling shaders that use external textures on
564-
// OpenGL/OpenGLES.
565-
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
566-
567555
const wgpu::ShaderModule sourceTexturePlane0FsModule = utils::CreateShaderModule(device, R"(
568556
@fragment fn main(@builtin(position) FragCoord : vec4f)
569557
-> @location(0) vec4f {
@@ -906,10 +894,6 @@ TEST_P(ExternalTextureTests, CropSinglePlane) {
906894
// This test draws a 2x2 multi-colored square surrounded by a 1px black border. We test the external
907895
// texture crop functionality by cropping to specific ranges inside the texture.
908896
TEST_P(ExternalTextureTests, CropMultiplanar) {
909-
// TODO(crbug.com/tint/1774): Tint has an issue compiling shaders that use external textures on
910-
// OpenGL/OpenGLES.
911-
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
912-
913897
const wgpu::ShaderModule sourceTexturePlane0FsModule = utils::CreateShaderModule(device, R"(
914898
@fragment fn main(@builtin(position) FragCoord : vec4f)
915899
-> @location(0) vec4f {

src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,51 @@ struct CombineSamplers::State {
145145
}
146146
}
147147

148+
/// Insert a new texture/sampler pair into the combined samplers maps (global or local, as
149+
/// appropriate). If local, also add a function parameter to "params".
150+
/// @param pair the texture/sampler pair to insert
151+
/// @param fn the function scope in which to insert (if local)
152+
/// @param params the calling function's parameter list to modify (if local)
153+
void InsertPair(sem::VariablePair pair,
154+
const sem::Function* fn,
155+
tint::Vector<const ast::Parameter*, 8>* params) {
156+
const sem::Variable* texture_var = pair.first;
157+
const sem::Variable* sampler_var = pair.second;
158+
std::string name = texture_var->Declaration()->name->symbol.Name();
159+
if (sampler_var) {
160+
name += "_" + sampler_var->Declaration()->name->symbol.Name();
161+
}
162+
if (IsGlobal(pair)) {
163+
// Both texture and sampler are global; add a new global variable
164+
// to represent the combined sampler (if not already created).
165+
GetOrCreate(global_combined_texture_samplers_, pair,
166+
[&] { return CreateCombinedGlobal(texture_var, sampler_var, name); });
167+
} else {
168+
// Either texture or sampler (or both) is a function parameter;
169+
// add a new function parameter to represent the combined sampler.
170+
ast::Type type = CreateCombinedASTTypeFor(texture_var, sampler_var);
171+
auto* var = ctx.dst->Param(ctx.dst->Symbols().New(name), type);
172+
params->Push(var);
173+
function_combined_texture_samplers_[fn][pair] = var;
174+
}
175+
}
176+
177+
/// For a given texture, find any texture/sampler pair with a non-null sampler in the given
178+
/// function scope.
179+
/// @param texture_var the texture variable of interest
180+
/// @param fn the function scope in which to search
181+
/// @returns the full pair, if found
182+
const sem::VariablePair* FindFullTextureSamplerPair(const sem::Variable* texture_var,
183+
const sem::Function* fn) {
184+
for (auto pairIter = fn->TextureSamplerPairs().begin();
185+
pairIter != fn->TextureSamplerPairs().end(); pairIter++) {
186+
if (pairIter->first == texture_var && pairIter->second) {
187+
return pairIter;
188+
}
189+
}
190+
return nullptr;
191+
}
192+
148193
/// Runs the transform
149194
/// @returns the new program or SkipTransform if the transform is not required
150195
ApplyResult Run() {
@@ -177,25 +222,30 @@ struct CombineSamplers::State {
177222
}
178223
Vector<const ast::Parameter*, 8> params;
179224
for (auto pair : fn->TextureSamplerPairs()) {
180-
const sem::Variable* texture_var = pair.first;
181-
const sem::Variable* sampler_var = pair.second;
182-
std::string name = texture_var->Declaration()->name->symbol.Name();
183-
if (sampler_var) {
184-
name += "_" + sampler_var->Declaration()->name->symbol.Name();
225+
if (!pair.second) {
226+
continue;
185227
}
186-
if (IsGlobal(pair)) {
187-
// Both texture and sampler are global; add a new global variable
188-
// to represent the combined sampler (if not already created).
189-
GetOrCreate(global_combined_texture_samplers_, pair, [&] {
190-
return CreateCombinedGlobal(texture_var, sampler_var, name);
191-
});
228+
InsertPair(pair, fn, &params);
229+
}
230+
for (auto pair : fn->TextureSamplerPairs()) {
231+
if (pair.second) {
232+
continue;
233+
}
234+
// Look for another pair with a non-null sampler.
235+
// NOTE: this is O(N^2) in the number of pairs, since
236+
// FindFullTextureSamplerPair() also loops over all pairs. If this proves
237+
// problematic, it could be optimized.
238+
if (const sem::VariablePair* fullPair =
239+
FindFullTextureSamplerPair(pair.first, fn)) {
240+
if (IsGlobal(pair)) {
241+
global_combined_texture_samplers_[pair] =
242+
global_combined_texture_samplers_[*fullPair];
243+
} else {
244+
auto* var = function_combined_texture_samplers_[fn][*fullPair];
245+
function_combined_texture_samplers_[fn][pair] = var;
246+
}
192247
} else {
193-
// Either texture or sampler (or both) is a function parameter;
194-
// add a new function parameter to represent the combined sampler.
195-
ast::Type type = CreateCombinedASTTypeFor(texture_var, sampler_var);
196-
auto* var = ctx.dst->Param(ctx.dst->Symbols().New(name), type);
197-
params.Push(var);
198-
function_combined_texture_samplers_[fn][pair] = var;
248+
InsertPair(pair, fn, &params);
199249
}
200250
}
201251
// Filter out separate textures and samplers from the original
@@ -285,6 +335,12 @@ struct CombineSamplers::State {
285335
if (IsGlobal(pair)) {
286336
continue;
287337
}
338+
// Texture-only pairs do not require a function parameter if they've been
339+
// replaced by a real pair.
340+
if (!pair.second && FindFullTextureSamplerPair(pair.first, callee)) {
341+
continue;
342+
}
343+
288344
const sem::Variable* texture_var = pair.first;
289345
const sem::Variable* sampler_var = pair.second;
290346
if (auto* param = texture_var->As<sem::Parameter>()) {

src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -794,14 +794,12 @@ fn main() -> vec4<f32> {
794794
}
795795
)";
796796
auto* expect = R"(
797-
@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var fred : texture_2d<f32>;
798-
799797
@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var barney : texture_2d<f32>;
800798
801799
@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var placeholder_sampler : sampler;
802800
803801
fn main() -> vec4<f32> {
804-
return (textureLoad(fred, vec2<i32>(), 0) + textureSample(barney, placeholder_sampler, vec2<f32>()));
802+
return (textureLoad(barney, vec2<i32>(), 0) + textureSample(barney, placeholder_sampler, vec2<f32>()));
805803
}
806804
)";
807805

test/tint/bug/tint/942.wgsl.expected.glsl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ uint tint_div(uint lhs, uint rhs) {
2828
return (lhs / ((rhs == 0u) ? 1u : rhs));
2929
}
3030

31-
uniform highp sampler2D inputTex_1;
3231
uniform highp sampler2D inputTex_samp;
3332

3433
void tint_symbol(uvec3 WorkGroupID, uvec3 LocalInvocationID, uint local_invocation_index) {
@@ -41,7 +40,7 @@ void tint_symbol(uvec3 WorkGroupID, uvec3 LocalInvocationID, uint local_invocati
4140
}
4241
barrier();
4342
uint filterOffset = tint_div((params.inner.filterDim - 1u), 2u);
44-
uvec2 dims = uvec2(textureSize(inputTex_1, 0));
43+
uvec2 dims = uvec2(textureSize(inputTex_samp, 0));
4544
uvec2 baseIndex = (((WorkGroupID.xy * uvec2(params.inner.blockDim, 4u)) + (LocalInvocationID.xy * uvec2(4u, 1u))) - uvec2(filterOffset, 0u));
4645
{
4746
for(uint r = 0u; (r < 4u); r = (r + 1u)) {

0 commit comments

Comments
 (0)