diff options
| author | 2021-04-06 02:56:15 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:26 -0400 | |
| commit | 1f3eb601acdcdfa4c119cffbf36b5792147b893f (patch) | |
| tree | 1a8dcc5e4ce11e9090dd6d7a8b4e8aaa130ff67b /src/shader_recompiler/ir_opt/texture_pass.cpp | |
| parent | shader: Address feedback (diff) | |
| download | yuzu-1f3eb601acdcdfa4c119cffbf36b5792147b893f.tar.gz yuzu-1f3eb601acdcdfa4c119cffbf36b5792147b893f.tar.xz yuzu-1f3eb601acdcdfa4c119cffbf36b5792147b893f.zip | |
shader: Implement texture buffers
Diffstat (limited to 'src/shader_recompiler/ir_opt/texture_pass.cpp')
| -rw-r--r-- | src/shader_recompiler/ir_opt/texture_pass.cpp | 80 |
1 files changed, 62 insertions, 18 deletions
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index bcb94ce4d..290ce4179 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp | |||
| @@ -147,24 +147,39 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { | |||
| 147 | 147 | ||
| 148 | class Descriptors { | 148 | class Descriptors { |
| 149 | public: | 149 | public: |
| 150 | explicit Descriptors(TextureDescriptors& descriptors_) : descriptors{descriptors_} {} | 150 | explicit Descriptors(TextureDescriptors& texture_descriptors_, |
| 151 | TextureBufferDescriptors& texture_buffer_descriptors_) | ||
| 152 | : texture_descriptors{texture_descriptors_}, texture_buffer_descriptors{ | ||
| 153 | texture_buffer_descriptors_} {} | ||
| 154 | |||
| 155 | u32 Add(const TextureDescriptor& desc) { | ||
| 156 | return Add(texture_descriptors, desc, [&desc](const auto& existing) { | ||
| 157 | return desc.cbuf_index == existing.cbuf_index && | ||
| 158 | desc.cbuf_offset == existing.cbuf_offset && desc.type == existing.type; | ||
| 159 | }); | ||
| 160 | } | ||
| 161 | |||
| 162 | u32 Add(const TextureBufferDescriptor& desc) { | ||
| 163 | return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { | ||
| 164 | return desc.cbuf_index == existing.cbuf_index && | ||
| 165 | desc.cbuf_offset == existing.cbuf_offset; | ||
| 166 | }); | ||
| 167 | } | ||
| 151 | 168 | ||
| 152 | u32 Add(const TextureDescriptor& descriptor) { | 169 | private: |
| 170 | template <typename Descriptors, typename Descriptor, typename Func> | ||
| 171 | static u32 Add(Descriptors& descriptors, const Descriptor& desc, Func&& pred) { | ||
| 153 | // TODO: Handle arrays | 172 | // TODO: Handle arrays |
| 154 | auto it{std::ranges::find_if(descriptors, [&descriptor](const TextureDescriptor& existing) { | 173 | const auto it{std::ranges::find_if(descriptors, pred)}; |
| 155 | return descriptor.cbuf_index == existing.cbuf_index && | ||
| 156 | descriptor.cbuf_offset == existing.cbuf_offset && | ||
| 157 | descriptor.type == existing.type; | ||
| 158 | })}; | ||
| 159 | if (it != descriptors.end()) { | 174 | if (it != descriptors.end()) { |
| 160 | return static_cast<u32>(std::distance(descriptors.begin(), it)); | 175 | return static_cast<u32>(std::distance(descriptors.begin(), it)); |
| 161 | } | 176 | } |
| 162 | descriptors.push_back(descriptor); | 177 | descriptors.push_back(desc); |
| 163 | return static_cast<u32>(descriptors.size()) - 1; | 178 | return static_cast<u32>(descriptors.size()) - 1; |
| 164 | } | 179 | } |
| 165 | 180 | ||
| 166 | private: | 181 | TextureDescriptors& texture_descriptors; |
| 167 | TextureDescriptors& descriptors; | 182 | TextureBufferDescriptors& texture_buffer_descriptors; |
| 168 | }; | 183 | }; |
| 169 | } // Anonymous namespace | 184 | } // Anonymous namespace |
| 170 | 185 | ||
| @@ -185,7 +200,10 @@ void TexturePass(Environment& env, IR::Program& program) { | |||
| 185 | std::stable_sort(to_replace.begin(), to_replace.end(), [](const auto& lhs, const auto& rhs) { | 200 | std::stable_sort(to_replace.begin(), to_replace.end(), [](const auto& lhs, const auto& rhs) { |
| 186 | return lhs.cbuf.index < rhs.cbuf.index; | 201 | return lhs.cbuf.index < rhs.cbuf.index; |
| 187 | }); | 202 | }); |
| 188 | Descriptors descriptors{program.info.texture_descriptors}; | 203 | Descriptors descriptors{ |
| 204 | program.info.texture_descriptors, | ||
| 205 | program.info.texture_buffer_descriptors, | ||
| 206 | }; | ||
| 189 | for (TextureInst& texture_inst : to_replace) { | 207 | for (TextureInst& texture_inst : to_replace) { |
| 190 | // TODO: Handle arrays | 208 | // TODO: Handle arrays |
| 191 | IR::Inst* const inst{texture_inst.inst}; | 209 | IR::Inst* const inst{texture_inst.inst}; |
| @@ -193,16 +211,42 @@ void TexturePass(Environment& env, IR::Program& program) { | |||
| 193 | 211 | ||
| 194 | const auto& cbuf{texture_inst.cbuf}; | 212 | const auto& cbuf{texture_inst.cbuf}; |
| 195 | auto flags{inst->Flags<IR::TextureInstInfo>()}; | 213 | auto flags{inst->Flags<IR::TextureInstInfo>()}; |
| 196 | if (inst->Opcode() == IR::Opcode::ImageQueryDimensions) { | 214 | switch (inst->Opcode()) { |
| 215 | case IR::Opcode::ImageQueryDimensions: | ||
| 197 | flags.type.Assign(env.ReadTextureType(cbuf.index, cbuf.offset)); | 216 | flags.type.Assign(env.ReadTextureType(cbuf.index, cbuf.offset)); |
| 198 | inst->SetFlags(flags); | 217 | inst->SetFlags(flags); |
| 218 | break; | ||
| 219 | case IR::Opcode::ImageFetch: | ||
| 220 | if (flags.type != TextureType::Color1D) { | ||
| 221 | break; | ||
| 222 | } | ||
| 223 | if (env.ReadTextureType(cbuf.index, cbuf.offset) == TextureType::Buffer) { | ||
| 224 | // Replace with the bound texture type only when it's a texture buffer | ||
| 225 | // If the instruction is 1D and the bound type is 2D, don't change the code and let | ||
| 226 | // the rasterizer robustness handle it | ||
| 227 | // This happens on Fire Emblem: Three Houses | ||
| 228 | flags.type.Assign(TextureType::Buffer); | ||
| 229 | } | ||
| 230 | inst->SetFlags(flags); | ||
| 231 | break; | ||
| 232 | default: | ||
| 233 | break; | ||
| 234 | } | ||
| 235 | u32 index; | ||
| 236 | if (flags.type == TextureType::Buffer) { | ||
| 237 | index = descriptors.Add(TextureBufferDescriptor{ | ||
| 238 | .cbuf_index{cbuf.index}, | ||
| 239 | .cbuf_offset{cbuf.offset}, | ||
| 240 | .count{1}, | ||
| 241 | }); | ||
| 242 | } else { | ||
| 243 | index = descriptors.Add(TextureDescriptor{ | ||
| 244 | .type{flags.type}, | ||
| 245 | .cbuf_index{cbuf.index}, | ||
| 246 | .cbuf_offset{cbuf.offset}, | ||
| 247 | .count{1}, | ||
| 248 | }); | ||
| 199 | } | 249 | } |
| 200 | const u32 index{descriptors.Add(TextureDescriptor{ | ||
| 201 | .type{flags.type}, | ||
| 202 | .cbuf_index{cbuf.index}, | ||
| 203 | .cbuf_offset{cbuf.offset}, | ||
| 204 | .count{1}, | ||
| 205 | })}; | ||
| 206 | inst->SetArg(0, IR::Value{index}); | 250 | inst->SetArg(0, IR::Value{index}); |
| 207 | } | 251 | } |
| 208 | } | 252 | } |