diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.cpp | 29 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.h | 5 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv.cpp | 1 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 24 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/texture_pass.cpp | 80 | ||||
| -rw-r--r-- | src/shader_recompiler/shader_info.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/pipeline_helper.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 2 |
10 files changed, 154 insertions, 35 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 2d39ea373..d01633628 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -46,6 +46,8 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { | |||
| 46 | return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format); | 46 | return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format); |
| 47 | case TextureType::ShadowArrayCube: | 47 | case TextureType::ShadowArrayCube: |
| 48 | return ctx.TypeImage(type, spv::Dim::Cube, true, true, false, 1, format); | 48 | return ctx.TypeImage(type, spv::Dim::Cube, true, true, false, 1, format); |
| 49 | case TextureType::Buffer: | ||
| 50 | break; | ||
| 49 | } | 51 | } |
| 50 | throw InvalidArgument("Invalid texture type {}", desc.type); | 52 | throw InvalidArgument("Invalid texture type {}", desc.type); |
| 51 | } | 53 | } |
| @@ -129,6 +131,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin | |||
| 129 | DefineConstantBuffers(program.info, binding); | 131 | DefineConstantBuffers(program.info, binding); |
| 130 | DefineStorageBuffers(program.info, binding); | 132 | DefineStorageBuffers(program.info, binding); |
| 131 | DefineTextures(program.info, binding); | 133 | DefineTextures(program.info, binding); |
| 134 | DefineTextureBuffers(program.info, binding); | ||
| 132 | DefineAttributeMemAccess(program.info); | 135 | DefineAttributeMemAccess(program.info); |
| 133 | DefineLabels(program); | 136 | DefineLabels(program); |
| 134 | } | 137 | } |
| @@ -541,6 +544,32 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) { | |||
| 541 | } | 544 | } |
| 542 | } | 545 | } |
| 543 | 546 | ||
| 547 | void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { | ||
| 548 | if (info.texture_buffer_descriptors.empty()) { | ||
| 549 | return; | ||
| 550 | } | ||
| 551 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | ||
| 552 | image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); | ||
| 553 | sampled_texture_buffer_type = TypeSampledImage(image_buffer_type); | ||
| 554 | |||
| 555 | const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)}; | ||
| 556 | texture_buffers.reserve(info.texture_buffer_descriptors.size()); | ||
| 557 | for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) { | ||
| 558 | if (desc.count != 1) { | ||
| 559 | throw NotImplementedException("Array of texture buffers"); | ||
| 560 | } | ||
| 561 | const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; | ||
| 562 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 563 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 564 | Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); | ||
| 565 | texture_buffers.insert(texture_buffers.end(), desc.count, id); | ||
| 566 | if (profile.supported_spirv >= 0x00010400) { | ||
| 567 | interfaces.push_back(id); | ||
| 568 | } | ||
| 569 | binding += desc.count; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 544 | void EmitContext::DefineLabels(IR::Program& program) { | 573 | void EmitContext::DefineLabels(IR::Program& program) { |
| 545 | for (IR::Block* const block : program.blocks) { | 574 | for (IR::Block* const block : program.blocks) { |
| 546 | block->SetDefinition(OpLabel()); | 575 | block->SetDefinition(OpLabel()); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 7a2ac0511..2a10e94e5 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -90,9 +90,13 @@ public: | |||
| 90 | 90 | ||
| 91 | Id storage_u32{}; | 91 | Id storage_u32{}; |
| 92 | 92 | ||
| 93 | Id image_buffer_type{}; | ||
| 94 | Id sampled_texture_buffer_type{}; | ||
| 95 | |||
| 93 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; | 96 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; |
| 94 | std::array<Id, Info::MAX_SSBOS> ssbos{}; | 97 | std::array<Id, Info::MAX_SSBOS> ssbos{}; |
| 95 | std::vector<TextureDefinition> textures; | 98 | std::vector<TextureDefinition> textures; |
| 99 | std::vector<Id> texture_buffers; | ||
| 96 | 100 | ||
| 97 | Id workgroup_id{}; | 101 | Id workgroup_id{}; |
| 98 | Id local_invocation_id{}; | 102 | Id local_invocation_id{}; |
| @@ -151,6 +155,7 @@ private: | |||
| 151 | void DefineConstantBuffers(const Info& info, u32& binding); | 155 | void DefineConstantBuffers(const Info& info, u32& binding); |
| 152 | void DefineStorageBuffers(const Info& info, u32& binding); | 156 | void DefineStorageBuffers(const Info& info, u32& binding); |
| 153 | void DefineTextures(const Info& info, u32& binding); | 157 | void DefineTextures(const Info& info, u32& binding); |
| 158 | void DefineTextureBuffers(const Info& info, u32& binding); | ||
| 154 | void DefineAttributeMemAccess(const Info& info); | 159 | void DefineAttributeMemAccess(const Info& info); |
| 155 | void DefineLabels(IR::Program& program); | 160 | void DefineLabels(IR::Program& program); |
| 156 | 161 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 191380db0..32512a0e5 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -249,6 +249,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | |||
| 249 | // TODO: Track this usage | 249 | // TODO: Track this usage |
| 250 | ctx.AddCapability(spv::Capability::ImageGatherExtended); | 250 | ctx.AddCapability(spv::Capability::ImageGatherExtended); |
| 251 | ctx.AddCapability(spv::Capability::ImageQuery); | 251 | ctx.AddCapability(spv::Capability::ImageQuery); |
| 252 | ctx.AddCapability(spv::Capability::SampledBuffer); | ||
| 252 | } | 253 | } |
| 253 | 254 | ||
| 254 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { | 255 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index fc40615af..525f67c6e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -128,12 +128,18 @@ Id Texture(EmitContext& ctx, const IR::Value& index) { | |||
| 128 | throw NotImplementedException("Indirect texture sample"); | 128 | throw NotImplementedException("Indirect texture sample"); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | Id TextureImage(EmitContext& ctx, const IR::Value& index) { | 131 | Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { |
| 132 | if (index.IsImmediate()) { | 132 | if (!index.IsImmediate()) { |
| 133 | throw NotImplementedException("Indirect texture sample"); | ||
| 134 | } | ||
| 135 | if (info.type == TextureType::Buffer) { | ||
| 136 | const Id sampler_id{ctx.texture_buffers.at(index.U32())}; | ||
| 137 | const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)}; | ||
| 138 | return ctx.OpImage(ctx.image_buffer_type, id); | ||
| 139 | } else { | ||
| 133 | const TextureDefinition def{ctx.textures.at(index.U32())}; | 140 | const TextureDefinition def{ctx.textures.at(index.U32())}; |
| 134 | return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); | 141 | return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); |
| 135 | } | 142 | } |
| 136 | throw NotImplementedException("Indirect texture sample"); | ||
| 137 | } | 143 | } |
| 138 | 144 | ||
| 139 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { | 145 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { |
| @@ -297,17 +303,22 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | |||
| 297 | ctx.F32[4], Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); | 303 | ctx.F32[4], Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); |
| 298 | } | 304 | } |
| 299 | 305 | ||
| 306 | #pragma optimize("", off) | ||
| 307 | |||
| 300 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, | 308 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, |
| 301 | Id lod, Id ms) { | 309 | Id lod, Id ms) { |
| 302 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 310 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 311 | if (info.type == TextureType::Buffer) { | ||
| 312 | lod = Id{}; | ||
| 313 | } | ||
| 303 | const ImageOperands operands(offset, lod, ms); | 314 | const ImageOperands operands(offset, lod, ms); |
| 304 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], | 315 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], |
| 305 | TextureImage(ctx, index), coords, operands.Mask(), operands.Span()); | 316 | TextureImage(ctx, index, info), coords, operands.Mask(), operands.Span()); |
| 306 | } | 317 | } |
| 307 | 318 | ||
| 308 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { | 319 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { |
| 309 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 320 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 310 | const Id image{TextureImage(ctx, index)}; | 321 | const Id image{TextureImage(ctx, index, info)}; |
| 311 | const Id zero{ctx.u32_zero_value}; | 322 | const Id zero{ctx.u32_zero_value}; |
| 312 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; | 323 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; |
| 313 | switch (info.type) { | 324 | switch (info.type) { |
| @@ -331,6 +342,9 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 331 | case TextureType::ShadowArrayCube: | 342 | case TextureType::ShadowArrayCube: |
| 332 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), | 343 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), |
| 333 | mips()); | 344 | mips()); |
| 345 | case TextureType::Buffer: | ||
| 346 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySize(ctx.U32[1], image), zero, | ||
| 347 | zero, mips()); | ||
| 334 | } | 348 | } |
| 335 | throw LogicError("Unspecified image type {}", info.type.Value()); | 349 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 336 | } | 350 | } |
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 | } |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 41bb5b9a1..e6f0de8d8 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -29,6 +29,7 @@ enum class TextureType : u32 { | |||
| 29 | Shadow3D, | 29 | Shadow3D, |
| 30 | ShadowCube, | 30 | ShadowCube, |
| 31 | ShadowArrayCube, | 31 | ShadowArrayCube, |
| 32 | Buffer, | ||
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| 34 | enum class Interpolation { | 35 | enum class Interpolation { |
| @@ -50,6 +51,13 @@ struct TextureDescriptor { | |||
| 50 | }; | 51 | }; |
| 51 | using TextureDescriptors = boost::container::small_vector<TextureDescriptor, 12>; | 52 | using TextureDescriptors = boost::container::small_vector<TextureDescriptor, 12>; |
| 52 | 53 | ||
| 54 | struct TextureBufferDescriptor { | ||
| 55 | u32 cbuf_index; | ||
| 56 | u32 cbuf_offset; | ||
| 57 | u32 count; | ||
| 58 | }; | ||
| 59 | using TextureBufferDescriptors = boost::container::small_vector<TextureBufferDescriptor, 2>; | ||
| 60 | |||
| 53 | struct ConstantBufferDescriptor { | 61 | struct ConstantBufferDescriptor { |
| 54 | u32 index; | 62 | u32 index; |
| 55 | u32 count; | 63 | u32 count; |
| @@ -112,6 +120,7 @@ struct Info { | |||
| 112 | constant_buffer_descriptors; | 120 | constant_buffer_descriptors; |
| 113 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; | 121 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; |
| 114 | TextureDescriptors texture_descriptors; | 122 | TextureDescriptors texture_descriptors; |
| 123 | TextureBufferDescriptors texture_buffer_descriptors; | ||
| 115 | }; | 124 | }; |
| 116 | 125 | ||
| 117 | } // namespace Shader | 126 | } // namespace Shader |
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index eebe5d569..decf0d32c 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h | |||
| @@ -93,6 +93,9 @@ public: | |||
| 93 | for ([[maybe_unused]] const auto& desc : info.texture_descriptors) { | 93 | for ([[maybe_unused]] const auto& desc : info.texture_descriptors) { |
| 94 | Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage); | 94 | Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage); |
| 95 | } | 95 | } |
| 96 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 97 | Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage); | ||
| 98 | } | ||
| 96 | } | 99 | } |
| 97 | 100 | ||
| 98 | private: | 101 | private: |
| @@ -146,6 +149,8 @@ inline VideoCommon::ImageViewType CastType(Shader::TextureType type) { | |||
| 146 | case Shader::TextureType::ColorArrayCube: | 149 | case Shader::TextureType::ColorArrayCube: |
| 147 | case Shader::TextureType::ShadowArrayCube: | 150 | case Shader::TextureType::ShadowArrayCube: |
| 148 | return VideoCommon::ImageViewType::CubeArray; | 151 | return VideoCommon::ImageViewType::CubeArray; |
| 152 | case Shader::TextureType::Buffer: | ||
| 153 | break; | ||
| 149 | } | 154 | } |
| 150 | UNREACHABLE_MSG("Invalid texture type {}", type); | 155 | UNREACHABLE_MSG("Invalid texture type {}", type); |
| 151 | return {}; | 156 | return {}; |
| @@ -161,6 +166,11 @@ inline void PushImageDescriptors(const Shader::Info& info, const VkSampler* samp | |||
| 161 | update_descriptor_queue.AddSampledImage(vk_image_view, sampler); | 166 | update_descriptor_queue.AddSampledImage(vk_image_view, sampler); |
| 162 | ++index; | 167 | ++index; |
| 163 | } | 168 | } |
| 169 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 170 | ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])}; | ||
| 171 | update_descriptor_queue.AddTexelBuffer(image_view.BufferView()); | ||
| 172 | ++index; | ||
| 173 | } | ||
| 164 | } | 174 | } |
| 165 | 175 | ||
| 166 | } // namespace Vulkan | 176 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 0bb5b852d..9922cbd0f 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -93,20 +93,23 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 93 | const auto& launch_desc{kepler_compute.launch_description}; | 93 | const auto& launch_desc{kepler_compute.launch_description}; |
| 94 | const auto& cbufs{launch_desc.const_buffer_config}; | 94 | const auto& cbufs{launch_desc.const_buffer_config}; |
| 95 | const bool via_header_index{launch_desc.linked_tsc}; | 95 | const bool via_header_index{launch_desc.linked_tsc}; |
| 96 | for (const auto& desc : info.texture_descriptors) { | 96 | const auto read_handle{[&](u32 cbuf_index, u32 cbuf_offset) { |
| 97 | const u32 cbuf_index{desc.cbuf_index}; | ||
| 98 | const u32 cbuf_offset{desc.cbuf_offset}; | ||
| 99 | ASSERT(((launch_desc.const_buffer_enable_mask >> cbuf_index) & 1) != 0); | 97 | ASSERT(((launch_desc.const_buffer_enable_mask >> cbuf_index) & 1) != 0); |
| 100 | |||
| 101 | const GPUVAddr addr{cbufs[cbuf_index].Address() + cbuf_offset}; | 98 | const GPUVAddr addr{cbufs[cbuf_index].Address() + cbuf_offset}; |
| 102 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; | 99 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; |
| 103 | 100 | return TextureHandle(raw_handle, via_header_index); | |
| 104 | const TextureHandle handle(raw_handle, via_header_index); | 101 | }}; |
| 102 | for (const auto& desc : info.texture_descriptors) { | ||
| 103 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 105 | image_view_indices.push_back(handle.image); | 104 | image_view_indices.push_back(handle.image); |
| 106 | 105 | ||
| 107 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); | 106 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); |
| 108 | samplers.push_back(sampler->Handle()); | 107 | samplers.push_back(sampler->Handle()); |
| 109 | } | 108 | } |
| 109 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 110 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 111 | image_view_indices.push_back(handle.image); | ||
| 112 | } | ||
| 110 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | 113 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); |
| 111 | texture_cache.FillComputeImageViews(indices_span, image_view_ids); | 114 | texture_cache.FillComputeImageViews(indices_span, image_view_ids); |
| 112 | 115 | ||
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index a0ef0e98b..afdd8b371 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -169,19 +169,23 @@ void GraphicsPipeline::Configure(bool is_indexed) { | |||
| 169 | ++index; | 169 | ++index; |
| 170 | } | 170 | } |
| 171 | const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers}; | 171 | const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers}; |
| 172 | for (const auto& desc : info.texture_descriptors) { | 172 | const auto read_handle{[&](u32 cbuf_index, u32 cbuf_offset) { |
| 173 | const u32 cbuf_index{desc.cbuf_index}; | ||
| 174 | const u32 cbuf_offset{desc.cbuf_offset}; | ||
| 175 | ASSERT(cbufs[cbuf_index].enabled); | 173 | ASSERT(cbufs[cbuf_index].enabled); |
| 176 | const GPUVAddr addr{cbufs[cbuf_index].address + cbuf_offset}; | 174 | const GPUVAddr addr{cbufs[cbuf_index].address + cbuf_offset}; |
| 177 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; | 175 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; |
| 178 | 176 | return TextureHandle(raw_handle, via_header_index); | |
| 179 | const TextureHandle handle(raw_handle, via_header_index); | 177 | }}; |
| 178 | for (const auto& desc : info.texture_descriptors) { | ||
| 179 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 180 | image_view_indices.push_back(handle.image); | 180 | image_view_indices.push_back(handle.image); |
| 181 | 181 | ||
| 182 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; | 182 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; |
| 183 | samplers.push_back(sampler->Handle()); | 183 | samplers.push_back(sampler->Handle()); |
| 184 | } | 184 | } |
| 185 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 186 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 187 | image_view_indices.push_back(handle.image); | ||
| 188 | } | ||
| 185 | } | 189 | } |
| 186 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | 190 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); |
| 187 | buffer_cache.UpdateGraphicsBuffers(is_indexed); | 191 | buffer_cache.UpdateGraphicsBuffers(is_indexed); |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 25f592b8a..23bf84a92 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -212,7 +212,7 @@ protected: | |||
| 212 | case Tegra::Texture::TextureType::Texture2DArray: | 212 | case Tegra::Texture::TextureType::Texture2DArray: |
| 213 | return Shader::TextureType::ColorArray2D; | 213 | return Shader::TextureType::ColorArray2D; |
| 214 | case Tegra::Texture::TextureType::Texture1DBuffer: | 214 | case Tegra::Texture::TextureType::Texture1DBuffer: |
| 215 | throw Shader::NotImplementedException("Texture buffer"); | 215 | return Shader::TextureType::Buffer; |
| 216 | case Tegra::Texture::TextureType::TextureCubeArray: | 216 | case Tegra::Texture::TextureType::TextureCubeArray: |
| 217 | return Shader::TextureType::ColorArrayCube; | 217 | return Shader::TextureType::ColorArrayCube; |
| 218 | default: | 218 | default: |