diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv_image.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 90817f161..6008980af 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -147,24 +147,31 @@ private: | |||
| 147 | spv::ImageOperandsMask mask{}; | 147 | spv::ImageOperandsMask mask{}; |
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | Id Texture(EmitContext& ctx, const IR::Value& index) { | 150 | Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { |
| 151 | if (index.IsImmediate()) { | 151 | const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; |
| 152 | const TextureDefinition def{ctx.textures.at(index.U32())}; | 152 | if (def.count > 1) { |
| 153 | const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; | ||
| 154 | return ctx.OpLoad(def.sampled_type, pointer); | ||
| 155 | } else { | ||
| 153 | return ctx.OpLoad(def.sampled_type, def.id); | 156 | return ctx.OpLoad(def.sampled_type, def.id); |
| 154 | } | 157 | } |
| 155 | throw NotImplementedException("Indirect texture sample"); | ||
| 156 | } | 158 | } |
| 157 | 159 | ||
| 158 | Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { | 160 | Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, |
| 159 | if (!index.IsImmediate()) { | 161 | [[maybe_unused]] const IR::Value& index) { |
| 160 | throw NotImplementedException("Indirect texture sample"); | ||
| 161 | } | ||
| 162 | if (info.type == TextureType::Buffer) { | 162 | if (info.type == TextureType::Buffer) { |
| 163 | const Id sampler_id{ctx.texture_buffers.at(index.U32())}; | 163 | const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)}; |
| 164 | if (def.count > 1) { | ||
| 165 | throw NotImplementedException("Indirect texture sample"); | ||
| 166 | } | ||
| 167 | const Id sampler_id{def.id}; | ||
| 164 | const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)}; | 168 | const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)}; |
| 165 | return ctx.OpImage(ctx.image_buffer_type, id); | 169 | return ctx.OpImage(ctx.image_buffer_type, id); |
| 166 | } else { | 170 | } else { |
| 167 | const TextureDefinition def{ctx.textures.at(index.U32())}; | 171 | const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; |
| 172 | if (def.count > 1) { | ||
| 173 | throw NotImplementedException("Indirect texture sample"); | ||
| 174 | } | ||
| 168 | return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); | 175 | return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); |
| 169 | } | 176 | } |
| 170 | } | 177 | } |
| @@ -311,7 +318,7 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& | |||
| 311 | bias_lc, offset); | 318 | bias_lc, offset); |
| 312 | return Emit(&EmitContext::OpImageSparseSampleImplicitLod, | 319 | return Emit(&EmitContext::OpImageSparseSampleImplicitLod, |
| 313 | &EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4], | 320 | &EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4], |
| 314 | Texture(ctx, index), coords, operands.Mask(), operands.Span()); | 321 | Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
| 315 | } else { | 322 | } else { |
| 316 | // We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as | 323 | // We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as |
| 317 | // if the lod was explicitly zero. This may change on Turing with implicit compute | 324 | // if the lod was explicitly zero. This may change on Turing with implicit compute |
| @@ -320,7 +327,7 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& | |||
| 320 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset); | 327 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset); |
| 321 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, | 328 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
| 322 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], | 329 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], |
| 323 | Texture(ctx, index), coords, operands.Mask(), operands.Span()); | 330 | Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
| 324 | } | 331 | } |
| 325 | } | 332 | } |
| 326 | 333 | ||
| @@ -329,8 +336,8 @@ Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& | |||
| 329 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 336 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 330 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); | 337 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); |
| 331 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, | 338 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
| 332 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index), | 339 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], |
| 333 | coords, operands.Mask(), operands.Span()); | 340 | Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
| 334 | } | 341 | } |
| 335 | 342 | ||
| 336 | Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 343 | Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, |
| @@ -340,7 +347,7 @@ Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va | |||
| 340 | offset); | 347 | offset); |
| 341 | return Emit(&EmitContext::OpImageSparseSampleDrefImplicitLod, | 348 | return Emit(&EmitContext::OpImageSparseSampleDrefImplicitLod, |
| 342 | &EmitContext::OpImageSampleDrefImplicitLod, ctx, inst, ctx.F32[1], | 349 | &EmitContext::OpImageSampleDrefImplicitLod, ctx, inst, ctx.F32[1], |
| 343 | Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); | 350 | Texture(ctx, info, index), coords, dref, operands.Mask(), operands.Span()); |
| 344 | } | 351 | } |
| 345 | 352 | ||
| 346 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 353 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, |
| @@ -349,7 +356,7 @@ Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va | |||
| 349 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); | 356 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); |
| 350 | return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod, | 357 | return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod, |
| 351 | &EmitContext::OpImageSampleDrefExplicitLod, ctx, inst, ctx.F32[1], | 358 | &EmitContext::OpImageSampleDrefExplicitLod, ctx, inst, ctx.F32[1], |
| 352 | Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); | 359 | Texture(ctx, info, index), coords, dref, operands.Mask(), operands.Span()); |
| 353 | } | 360 | } |
| 354 | 361 | ||
| 355 | Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 362 | Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| @@ -357,15 +364,17 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id | |||
| 357 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 364 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 358 | const ImageOperands operands(ctx, offset, offset2); | 365 | const ImageOperands operands(ctx, offset, offset2); |
| 359 | return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, | 366 | return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, |
| 360 | ctx.F32[4], Texture(ctx, index), coords, ctx.Const(info.gather_component), | 367 | ctx.F32[4], Texture(ctx, info, index), coords, ctx.Const(info.gather_component), |
| 361 | operands.Mask(), operands.Span()); | 368 | operands.Mask(), operands.Span()); |
| 362 | } | 369 | } |
| 363 | 370 | ||
| 364 | Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 371 | Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 365 | const IR::Value& offset, const IR::Value& offset2, Id dref) { | 372 | const IR::Value& offset, const IR::Value& offset2, Id dref) { |
| 373 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | ||
| 366 | const ImageOperands operands(ctx, offset, offset2); | 374 | const ImageOperands operands(ctx, offset, offset2); |
| 367 | return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst, | 375 | return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst, |
| 368 | ctx.F32[4], Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); | 376 | ctx.F32[4], Texture(ctx, info, index), coords, dref, operands.Mask(), |
| 377 | operands.Span()); | ||
| 369 | } | 378 | } |
| 370 | 379 | ||
| 371 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, | 380 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, |
| @@ -376,12 +385,12 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c | |||
| 376 | } | 385 | } |
| 377 | const ImageOperands operands(offset, lod, ms); | 386 | const ImageOperands operands(offset, lod, ms); |
| 378 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], | 387 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], |
| 379 | TextureImage(ctx, index, info), coords, operands.Mask(), operands.Span()); | 388 | TextureImage(ctx, info, index), coords, operands.Mask(), operands.Span()); |
| 380 | } | 389 | } |
| 381 | 390 | ||
| 382 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { | 391 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { |
| 383 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 392 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 384 | const Id image{TextureImage(ctx, index, info)}; | 393 | const Id image{TextureImage(ctx, info, index)}; |
| 385 | const Id zero{ctx.u32_zero_value}; | 394 | const Id zero{ctx.u32_zero_value}; |
| 386 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; | 395 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; |
| 387 | switch (info.type) { | 396 | switch (info.type) { |
| @@ -405,9 +414,10 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 405 | throw LogicError("Unspecified image type {}", info.type.Value()); | 414 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 406 | } | 415 | } |
| 407 | 416 | ||
| 408 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst*, const IR::Value& index, Id coords) { | 417 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { |
| 418 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | ||
| 409 | const Id zero{ctx.f32_zero_value}; | 419 | const Id zero{ctx.f32_zero_value}; |
| 410 | const Id sampler{Texture(ctx, index)}; | 420 | const Id sampler{Texture(ctx, info, index)}; |
| 411 | return ctx.OpCompositeConstruct(ctx.F32[4], ctx.OpImageQueryLod(ctx.F32[2], sampler, coords), | 421 | return ctx.OpCompositeConstruct(ctx.F32[4], ctx.OpImageQueryLod(ctx.F32[2], sampler, coords), |
| 412 | zero, zero); | 422 | zero, zero); |
| 413 | } | 423 | } |
| @@ -418,8 +428,8 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I | |||
| 418 | const ImageOperands operands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, | 428 | const ImageOperands operands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, |
| 419 | offset, lod_clamp); | 429 | offset, lod_clamp); |
| 420 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, | 430 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
| 421 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index), | 431 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], |
| 422 | coords, operands.Mask(), operands.Span()); | 432 | Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
| 423 | } | 433 | } |
| 424 | 434 | ||
| 425 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { | 435 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { |