1 // Copyright (c) 2019 Google LLC
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "source/fuzz/uniform_buffer_element_descriptor.h"
22 protobufs::UniformBufferElementDescriptor
MakeUniformBufferElementDescriptor(
23 uint32_t descriptor_set
, uint32_t binding
,
24 std::vector
<uint32_t>&& indices
) {
25 protobufs::UniformBufferElementDescriptor result
;
26 result
.set_descriptor_set(descriptor_set
);
27 result
.set_binding(binding
);
28 for (auto index
: indices
) {
29 result
.add_index(index
);
34 bool UniformBufferElementDescriptorEquals::operator()(
35 const protobufs::UniformBufferElementDescriptor
* first
,
36 const protobufs::UniformBufferElementDescriptor
* second
) const {
37 return first
->descriptor_set() == second
->descriptor_set() &&
38 first
->binding() == second
->binding() &&
39 first
->index().size() == second
->index().size() &&
40 std::equal(first
->index().begin(), first
->index().end(),
41 second
->index().begin());
44 opt::Instruction
* FindUniformVariable(
45 const protobufs::UniformBufferElementDescriptor
&
46 uniform_buffer_element_descriptor
,
47 opt::IRContext
* context
, bool check_unique
) {
48 opt::Instruction
* result
= nullptr;
50 for (auto& inst
: context
->types_values()) {
51 // Consider all global variables with uniform storage class.
52 if (inst
.opcode() != spv::Op::OpVariable
) {
55 if (spv::StorageClass(inst
.GetSingleWordInOperand(0)) !=
56 spv::StorageClass::Uniform
) {
60 // Determine whether the variable is decorated with a descriptor set
61 // matching that in |uniform_buffer_element|.
62 bool descriptor_set_matches
= false;
63 context
->get_decoration_mgr()->ForEachDecoration(
64 inst
.result_id(), uint32_t(spv::Decoration::DescriptorSet
),
65 [&descriptor_set_matches
, &uniform_buffer_element_descriptor
](
66 const opt::Instruction
& decoration_inst
) {
67 const uint32_t kDescriptorSetOperandIndex
= 2;
68 if (decoration_inst
.GetSingleWordInOperand(
69 kDescriptorSetOperandIndex
) ==
70 uniform_buffer_element_descriptor
.descriptor_set()) {
71 descriptor_set_matches
= true;
74 if (!descriptor_set_matches
) {
75 // Descriptor set does not match.
79 // Determine whether the variable is decorated with a binding matching that
80 // in |uniform_buffer_element|.
81 bool binding_matches
= false;
82 context
->get_decoration_mgr()->ForEachDecoration(
83 inst
.result_id(), uint32_t(spv::Decoration::Binding
),
84 [&binding_matches
, &uniform_buffer_element_descriptor
](
85 const opt::Instruction
& decoration_inst
) {
86 const uint32_t kBindingOperandIndex
= 2;
87 if (decoration_inst
.GetSingleWordInOperand(kBindingOperandIndex
) ==
88 uniform_buffer_element_descriptor
.binding()) {
89 binding_matches
= true;
92 if (!binding_matches
) {
93 // Binding does not match.
97 // This instruction is a uniform variable with the right descriptor set and
100 // If we aren't checking uniqueness, return it.
105 // More than one uniform variable is decorated with the given descriptor
106 // set and binding. This means the fact is ambiguous.
112 // We get here either if no match was found, or if |check_unique| holds and
113 // exactly one match was found.
114 assert(result
== nullptr || check_unique
);
119 } // namespace spvtools