diff options
Diffstat (limited to 'src')
31 files changed, 732 insertions, 202 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 6b5df23e2..8e1d37373 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -133,6 +133,7 @@ add_library(shader_recompiler STATIC | |||
| 133 | frontend/maxwell/translate/impl/predicate_set_predicate.cpp | 133 | frontend/maxwell/translate/impl/predicate_set_predicate.cpp |
| 134 | frontend/maxwell/translate/impl/predicate_set_register.cpp | 134 | frontend/maxwell/translate/impl/predicate_set_register.cpp |
| 135 | frontend/maxwell/translate/impl/select_source_with_predicate.cpp | 135 | frontend/maxwell/translate/impl/select_source_with_predicate.cpp |
| 136 | frontend/maxwell/translate/impl/surface_load_store.cpp | ||
| 136 | frontend/maxwell/translate/impl/texture_fetch.cpp | 137 | frontend/maxwell/translate/impl/texture_fetch.cpp |
| 137 | frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp | 138 | frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp |
| 138 | frontend/maxwell/translate/impl/texture_gather_swizzled.cpp | 139 | frontend/maxwell/translate/impl/texture_gather_swizzled.cpp |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 0c114402b..32f8c4508 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -18,41 +18,70 @@ namespace { | |||
| 18 | Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { | 18 | Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { |
| 19 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | 19 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; |
| 20 | const Id type{ctx.F32[1]}; | 20 | const Id type{ctx.F32[1]}; |
| 21 | const bool depth{desc.is_depth}; | ||
| 21 | switch (desc.type) { | 22 | switch (desc.type) { |
| 22 | case TextureType::Color1D: | 23 | case TextureType::Color1D: |
| 23 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 1, format); | 24 | return ctx.TypeImage(type, spv::Dim::Dim1D, depth, false, false, 1, format); |
| 24 | case TextureType::ColorArray1D: | 25 | case TextureType::ColorArray1D: |
| 25 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 1, format); | 26 | return ctx.TypeImage(type, spv::Dim::Dim1D, depth, true, false, 1, format); |
| 26 | case TextureType::Color2D: | 27 | case TextureType::Color2D: |
| 27 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 1, format); | 28 | return ctx.TypeImage(type, spv::Dim::Dim2D, depth, false, false, 1, format); |
| 28 | case TextureType::ColorArray2D: | 29 | case TextureType::ColorArray2D: |
| 29 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 1, format); | 30 | return ctx.TypeImage(type, spv::Dim::Dim2D, depth, true, false, 1, format); |
| 30 | case TextureType::Color3D: | 31 | case TextureType::Color3D: |
| 31 | return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 1, format); | 32 | return ctx.TypeImage(type, spv::Dim::Dim3D, depth, false, false, 1, format); |
| 32 | case TextureType::ColorCube: | 33 | case TextureType::ColorCube: |
| 33 | return ctx.TypeImage(type, spv::Dim::Cube, false, false, false, 1, format); | 34 | return ctx.TypeImage(type, spv::Dim::Cube, depth, false, false, 1, format); |
| 34 | case TextureType::ColorArrayCube: | 35 | case TextureType::ColorArrayCube: |
| 35 | return ctx.TypeImage(type, spv::Dim::Cube, false, true, false, 1, format); | 36 | return ctx.TypeImage(type, spv::Dim::Cube, depth, true, false, 1, format); |
| 36 | case TextureType::Shadow1D: | ||
| 37 | return ctx.TypeImage(type, spv::Dim::Dim1D, true, false, false, 1, format); | ||
| 38 | case TextureType::ShadowArray1D: | ||
| 39 | return ctx.TypeImage(type, spv::Dim::Dim1D, true, true, false, 1, format); | ||
| 40 | case TextureType::Shadow2D: | ||
| 41 | return ctx.TypeImage(type, spv::Dim::Dim2D, true, false, false, 1, format); | ||
| 42 | case TextureType::ShadowArray2D: | ||
| 43 | return ctx.TypeImage(type, spv::Dim::Dim2D, true, true, false, 1, format); | ||
| 44 | case TextureType::Shadow3D: | ||
| 45 | return ctx.TypeImage(type, spv::Dim::Dim3D, true, false, false, 1, format); | ||
| 46 | case TextureType::ShadowCube: | ||
| 47 | return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format); | ||
| 48 | case TextureType::ShadowArrayCube: | ||
| 49 | return ctx.TypeImage(type, spv::Dim::Cube, true, true, false, 1, format); | ||
| 50 | case TextureType::Buffer: | 37 | case TextureType::Buffer: |
| 51 | break; | 38 | break; |
| 52 | } | 39 | } |
| 53 | throw InvalidArgument("Invalid texture type {}", desc.type); | 40 | throw InvalidArgument("Invalid texture type {}", desc.type); |
| 54 | } | 41 | } |
| 55 | 42 | ||
| 43 | Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) { | ||
| 44 | const spv::ImageFormat format{[&] { | ||
| 45 | switch (desc.format) { | ||
| 46 | case ImageFormat::Typeless: | ||
| 47 | return spv::ImageFormat::Unknown; | ||
| 48 | case ImageFormat::R8_UINT: | ||
| 49 | return spv::ImageFormat::R8ui; | ||
| 50 | case ImageFormat::R8_SINT: | ||
| 51 | return spv::ImageFormat::R8i; | ||
| 52 | case ImageFormat::R16_UINT: | ||
| 53 | return spv::ImageFormat::R16ui; | ||
| 54 | case ImageFormat::R16_SINT: | ||
| 55 | return spv::ImageFormat::R16i; | ||
| 56 | case ImageFormat::R32_UINT: | ||
| 57 | return spv::ImageFormat::R32ui; | ||
| 58 | case ImageFormat::R32G32_UINT: | ||
| 59 | return spv::ImageFormat::Rg32ui; | ||
| 60 | case ImageFormat::R32G32B32A32_UINT: | ||
| 61 | return spv::ImageFormat::Rgba32ui; | ||
| 62 | } | ||
| 63 | throw InvalidArgument("Invalid image format {}", desc.format); | ||
| 64 | }()}; | ||
| 65 | const Id type{ctx.U32[1]}; | ||
| 66 | switch (desc.type) { | ||
| 67 | case TextureType::Color1D: | ||
| 68 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format); | ||
| 69 | case TextureType::ColorArray1D: | ||
| 70 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 2, format); | ||
| 71 | case TextureType::Color2D: | ||
| 72 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 2, format); | ||
| 73 | case TextureType::ColorArray2D: | ||
| 74 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 2, format); | ||
| 75 | case TextureType::Color3D: | ||
| 76 | return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 2, format); | ||
| 77 | case TextureType::Buffer: | ||
| 78 | throw NotImplementedException("Image buffer"); | ||
| 79 | default: | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | throw InvalidArgument("Invalid texture type {}", desc.type); | ||
| 83 | } | ||
| 84 | |||
| 56 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, | 85 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, |
| 57 | spv::StorageClass storage_class) { | 86 | spv::StorageClass storage_class) { |
| 58 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; | 87 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; |
| @@ -134,6 +163,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin | |||
| 134 | DefineStorageBuffers(program.info, binding); | 163 | DefineStorageBuffers(program.info, binding); |
| 135 | DefineTextureBuffers(program.info, binding); | 164 | DefineTextureBuffers(program.info, binding); |
| 136 | DefineTextures(program.info, binding); | 165 | DefineTextures(program.info, binding); |
| 166 | DefineImages(program.info, binding); | ||
| 137 | DefineAttributeMemAccess(program.info); | 167 | DefineAttributeMemAccess(program.info); |
| 138 | DefineLabels(program); | 168 | DefineLabels(program); |
| 139 | } | 169 | } |
| @@ -572,6 +602,31 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) { | |||
| 572 | } | 602 | } |
| 573 | } | 603 | } |
| 574 | 604 | ||
| 605 | void EmitContext::DefineImages(const Info& info, u32& binding) { | ||
| 606 | images.reserve(info.image_descriptors.size()); | ||
| 607 | for (const ImageDescriptor& desc : info.image_descriptors) { | ||
| 608 | if (desc.count != 1) { | ||
| 609 | throw NotImplementedException("Array of textures"); | ||
| 610 | } | ||
| 611 | const Id image_type{ImageType(*this, desc)}; | ||
| 612 | const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; | ||
| 613 | const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; | ||
| 614 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 615 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 616 | Name(id, fmt::format("img{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); | ||
| 617 | for (u32 index = 0; index < desc.count; ++index) { | ||
| 618 | images.push_back(ImageDefinition{ | ||
| 619 | .id{id}, | ||
| 620 | .image_type{image_type}, | ||
| 621 | }); | ||
| 622 | } | ||
| 623 | if (profile.supported_spirv >= 0x00010400) { | ||
| 624 | interfaces.push_back(id); | ||
| 625 | } | ||
| 626 | binding += desc.count; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 575 | void EmitContext::DefineLabels(IR::Program& program) { | 630 | void EmitContext::DefineLabels(IR::Program& program) { |
| 576 | for (IR::Block* const block : program.blocks) { | 631 | for (IR::Block* const block : program.blocks) { |
| 577 | block->SetDefinition(OpLabel()); | 632 | block->SetDefinition(OpLabel()); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index f1ac4430c..e70f3458c 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -35,6 +35,11 @@ struct TextureDefinition { | |||
| 35 | Id image_type; | 35 | Id image_type; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | struct ImageDefinition { | ||
| 39 | Id id; | ||
| 40 | Id image_type; | ||
| 41 | }; | ||
| 42 | |||
| 38 | struct UniformDefinitions { | 43 | struct UniformDefinitions { |
| 39 | Id U8{}; | 44 | Id U8{}; |
| 40 | Id S8{}; | 45 | Id S8{}; |
| @@ -95,8 +100,9 @@ public: | |||
| 95 | 100 | ||
| 96 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; | 101 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; |
| 97 | std::array<Id, Info::MAX_SSBOS> ssbos{}; | 102 | std::array<Id, Info::MAX_SSBOS> ssbos{}; |
| 98 | std::vector<TextureDefinition> textures; | ||
| 99 | std::vector<Id> texture_buffers; | 103 | std::vector<Id> texture_buffers; |
| 104 | std::vector<TextureDefinition> textures; | ||
| 105 | std::vector<ImageDefinition> images; | ||
| 100 | 106 | ||
| 101 | Id workgroup_id{}; | 107 | Id workgroup_id{}; |
| 102 | Id local_invocation_id{}; | 108 | Id local_invocation_id{}; |
| @@ -156,6 +162,7 @@ private: | |||
| 156 | void DefineStorageBuffers(const Info& info, u32& binding); | 162 | void DefineStorageBuffers(const Info& info, u32& binding); |
| 157 | void DefineTextureBuffers(const Info& info, u32& binding); | 163 | void DefineTextureBuffers(const Info& info, u32& binding); |
| 158 | void DefineTextures(const Info& info, u32& binding); | 164 | void DefineTextures(const Info& info, u32& binding); |
| 165 | void DefineImages(const Info& info, u32& binding); | ||
| 159 | void DefineAttributeMemAccess(const Info& info); | 166 | void DefineAttributeMemAccess(const Info& info); |
| 160 | void DefineLabels(IR::Program& program); | 167 | void DefineLabels(IR::Program& program); |
| 161 | 168 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 355cf0ca8..ecd0fac5c 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -253,6 +253,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | |||
| 253 | ctx.AddCapability(spv::Capability::ImageGatherExtended); | 253 | ctx.AddCapability(spv::Capability::ImageGatherExtended); |
| 254 | ctx.AddCapability(spv::Capability::ImageQuery); | 254 | ctx.AddCapability(spv::Capability::ImageQuery); |
| 255 | ctx.AddCapability(spv::Capability::SampledBuffer); | 255 | ctx.AddCapability(spv::Capability::SampledBuffer); |
| 256 | ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat); | ||
| 256 | } | 257 | } |
| 257 | 258 | ||
| 258 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { | 259 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 08460c94e..a39b16f1e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -369,6 +369,8 @@ Id EmitBindlessImageFetch(EmitContext&); | |||
| 369 | Id EmitBindlessImageQueryDimensions(EmitContext&); | 369 | Id EmitBindlessImageQueryDimensions(EmitContext&); |
| 370 | Id EmitBindlessImageQueryLod(EmitContext&); | 370 | Id EmitBindlessImageQueryLod(EmitContext&); |
| 371 | Id EmitBindlessImageGradient(EmitContext&); | 371 | Id EmitBindlessImageGradient(EmitContext&); |
| 372 | Id EmitBindlessImageRead(EmitContext&); | ||
| 373 | Id EmitBindlessImageWrite(EmitContext&); | ||
| 372 | Id EmitBoundImageSampleImplicitLod(EmitContext&); | 374 | Id EmitBoundImageSampleImplicitLod(EmitContext&); |
| 373 | Id EmitBoundImageSampleExplicitLod(EmitContext&); | 375 | Id EmitBoundImageSampleExplicitLod(EmitContext&); |
| 374 | Id EmitBoundImageSampleDrefImplicitLod(EmitContext&); | 376 | Id EmitBoundImageSampleDrefImplicitLod(EmitContext&); |
| @@ -379,6 +381,8 @@ Id EmitBoundImageFetch(EmitContext&); | |||
| 379 | Id EmitBoundImageQueryDimensions(EmitContext&); | 381 | Id EmitBoundImageQueryDimensions(EmitContext&); |
| 380 | Id EmitBoundImageQueryLod(EmitContext&); | 382 | Id EmitBoundImageQueryLod(EmitContext&); |
| 381 | Id EmitBoundImageGradient(EmitContext&); | 383 | Id EmitBoundImageGradient(EmitContext&); |
| 384 | Id EmitBoundImageRead(EmitContext&); | ||
| 385 | Id EmitBoundImageWrite(EmitContext&); | ||
| 382 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 386 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 383 | Id bias_lc, Id offset); | 387 | Id bias_lc, Id offset); |
| 384 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 388 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| @@ -397,6 +401,8 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 397 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | 401 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); |
| 398 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 402 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 399 | Id derivates, Id offset, Id lod_clamp); | 403 | Id derivates, Id offset, Id lod_clamp); |
| 404 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | ||
| 405 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); | ||
| 400 | Id EmitVoteAll(EmitContext& ctx, Id pred); | 406 | Id EmitVoteAll(EmitContext& ctx, Id pred); |
| 401 | Id EmitVoteAny(EmitContext& ctx, Id pred); | 407 | Id EmitVoteAny(EmitContext& ctx, Id pred); |
| 402 | Id EmitVoteEqual(EmitContext& ctx, Id pred); | 408 | Id EmitVoteEqual(EmitContext& ctx, Id pred); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 6a89c0f79..dd261fd47 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -144,6 +144,18 @@ Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo in | |||
| 144 | } | 144 | } |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { | ||
| 148 | if (!index.IsImmediate()) { | ||
| 149 | throw NotImplementedException("Indirect image indexing"); | ||
| 150 | } | ||
| 151 | if (info.type == TextureType::Buffer) { | ||
| 152 | throw NotImplementedException("Image buffer"); | ||
| 153 | } else { | ||
| 154 | const ImageDefinition def{ctx.images.at(index.U32())}; | ||
| 155 | return ctx.OpLoad(def.image_type, def.id); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 147 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { | 159 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { |
| 148 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 160 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 149 | if (info.relaxed_precision != 0) { | 161 | if (info.relaxed_precision != 0) { |
| @@ -209,6 +221,14 @@ Id EmitBindlessImageGradient(EmitContext&) { | |||
| 209 | throw LogicError("Unreachable instruction"); | 221 | throw LogicError("Unreachable instruction"); |
| 210 | } | 222 | } |
| 211 | 223 | ||
| 224 | Id EmitBindlessImageRead(EmitContext&) { | ||
| 225 | throw LogicError("Unreachable instruction"); | ||
| 226 | } | ||
| 227 | |||
| 228 | Id EmitBindlessImageWrite(EmitContext&) { | ||
| 229 | throw LogicError("Unreachable instruction"); | ||
| 230 | } | ||
| 231 | |||
| 212 | Id EmitBoundImageSampleImplicitLod(EmitContext&) { | 232 | Id EmitBoundImageSampleImplicitLod(EmitContext&) { |
| 213 | throw LogicError("Unreachable instruction"); | 233 | throw LogicError("Unreachable instruction"); |
| 214 | } | 234 | } |
| @@ -249,6 +269,14 @@ Id EmitBoundImageGradient(EmitContext&) { | |||
| 249 | throw LogicError("Unreachable instruction"); | 269 | throw LogicError("Unreachable instruction"); |
| 250 | } | 270 | } |
| 251 | 271 | ||
| 272 | Id EmitBoundImageRead(EmitContext&) { | ||
| 273 | throw LogicError("Unreachable instruction"); | ||
| 274 | } | ||
| 275 | |||
| 276 | Id EmitBoundImageWrite(EmitContext&) { | ||
| 277 | throw LogicError("Unreachable instruction"); | ||
| 278 | } | ||
| 279 | |||
| 252 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 280 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 253 | Id bias_lc, Id offset) { | 281 | Id bias_lc, Id offset) { |
| 254 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 282 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| @@ -322,23 +350,16 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 322 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; | 350 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; |
| 323 | switch (info.type) { | 351 | switch (info.type) { |
| 324 | case TextureType::Color1D: | 352 | case TextureType::Color1D: |
| 325 | case TextureType::Shadow1D: | ||
| 326 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), | 353 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), |
| 327 | zero, zero, mips()); | 354 | zero, zero, mips()); |
| 328 | case TextureType::ColorArray1D: | 355 | case TextureType::ColorArray1D: |
| 329 | case TextureType::Color2D: | 356 | case TextureType::Color2D: |
| 330 | case TextureType::ColorCube: | 357 | case TextureType::ColorCube: |
| 331 | case TextureType::ShadowArray1D: | ||
| 332 | case TextureType::Shadow2D: | ||
| 333 | case TextureType::ShadowCube: | ||
| 334 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), | 358 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), |
| 335 | zero, mips()); | 359 | zero, mips()); |
| 336 | case TextureType::ColorArray2D: | 360 | case TextureType::ColorArray2D: |
| 337 | case TextureType::Color3D: | 361 | case TextureType::Color3D: |
| 338 | case TextureType::ColorArrayCube: | 362 | case TextureType::ColorArrayCube: |
| 339 | case TextureType::ShadowArray2D: | ||
| 340 | case TextureType::Shadow3D: | ||
| 341 | case TextureType::ShadowArrayCube: | ||
| 342 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), | 363 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), |
| 343 | mips()); | 364 | mips()); |
| 344 | case TextureType::Buffer: | 365 | case TextureType::Buffer: |
| @@ -365,4 +386,15 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I | |||
| 365 | coords, operands.Mask(), operands.Span()); | 386 | coords, operands.Mask(), operands.Span()); |
| 366 | } | 387 | } |
| 367 | 388 | ||
| 389 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { | ||
| 390 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | ||
| 391 | return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4], | ||
| 392 | Image(ctx, index, info), coords, std::nullopt, std::span<const Id>{}); | ||
| 393 | } | ||
| 394 | |||
| 395 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) { | ||
| 396 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | ||
| 397 | ctx.OpImageWrite(Image(ctx, index, info), coords, color); | ||
| 398 | } | ||
| 399 | |||
| 368 | } // namespace Shader::Backend::SPIRV | 400 | } // namespace Shader::Backend::SPIRV |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index a2104bdb3..17be0c639 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -1620,6 +1620,17 @@ Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const V | |||
| 1620 | return Inst(op, Flags{info}, handle, coords, derivates, offset, lod_clamp); | 1620 | return Inst(op, Flags{info}, handle, coords, derivates, offset, lod_clamp); |
| 1621 | } | 1621 | } |
| 1622 | 1622 | ||
| 1623 | Value IREmitter::ImageRead(const Value& handle, const Value& coords, TextureInstInfo info) { | ||
| 1624 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageRead : Opcode::BindlessImageRead}; | ||
| 1625 | return Inst(op, Flags{info}, handle, coords); | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | void IREmitter::ImageWrite(const Value& handle, const Value& coords, const Value& color, | ||
| 1629 | TextureInstInfo info) { | ||
| 1630 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageWrite : Opcode::BindlessImageWrite}; | ||
| 1631 | Inst(op, Flags{info}, handle, coords, color); | ||
| 1632 | } | ||
| 1633 | |||
| 1623 | U1 IREmitter::VoteAll(const U1& value) { | 1634 | U1 IREmitter::VoteAll(const U1& value) { |
| 1624 | return Inst<U1>(Opcode::VoteAll, value); | 1635 | return Inst<U1>(Opcode::VoteAll, value); |
| 1625 | } | 1636 | } |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 2cab1dc5d..ec60070ef 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -265,20 +265,19 @@ public: | |||
| 265 | 265 | ||
| 266 | [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords, | 266 | [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords, |
| 267 | TextureInstInfo info); | 267 | TextureInstInfo info); |
| 268 | |||
| 269 | [[nodiscard]] Value ImageGather(const Value& handle, const Value& coords, const Value& offset, | 268 | [[nodiscard]] Value ImageGather(const Value& handle, const Value& coords, const Value& offset, |
| 270 | const Value& offset2, TextureInstInfo info); | 269 | const Value& offset2, TextureInstInfo info); |
| 271 | |||
| 272 | [[nodiscard]] Value ImageGatherDref(const Value& handle, const Value& coords, | 270 | [[nodiscard]] Value ImageGatherDref(const Value& handle, const Value& coords, |
| 273 | const Value& offset, const Value& offset2, const F32& dref, | 271 | const Value& offset, const Value& offset2, const F32& dref, |
| 274 | TextureInstInfo info); | 272 | TextureInstInfo info); |
| 275 | |||
| 276 | [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset, | 273 | [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset, |
| 277 | const U32& lod, const U32& multisampling, TextureInstInfo info); | 274 | const U32& lod, const U32& multisampling, TextureInstInfo info); |
| 278 | |||
| 279 | [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, | 275 | [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, |
| 280 | const Value& derivates, const Value& offset, | 276 | const Value& derivates, const Value& offset, |
| 281 | const F32& lod_clamp, TextureInstInfo info); | 277 | const F32& lod_clamp, TextureInstInfo info); |
| 278 | [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info); | ||
| 279 | [[nodiscard]] void ImageWrite(const Value& handle, const Value& coords, const Value& color, | ||
| 280 | TextureInstInfo info); | ||
| 282 | 281 | ||
| 283 | [[nodiscard]] U1 VoteAll(const U1& value); | 282 | [[nodiscard]] U1 VoteAll(const U1& value); |
| 284 | [[nodiscard]] U1 VoteAny(const U1& value); | 283 | [[nodiscard]] U1 VoteAny(const U1& value); |
diff --git a/src/shader_recompiler/frontend/ir/modifiers.h b/src/shader_recompiler/frontend/ir/modifiers.h index 461671326..447e9703c 100644 --- a/src/shader_recompiler/frontend/ir/modifiers.h +++ b/src/shader_recompiler/frontend/ir/modifiers.h | |||
| @@ -43,11 +43,13 @@ static_assert(sizeof(FpControl) <= sizeof(u32)); | |||
| 43 | union TextureInstInfo { | 43 | union TextureInstInfo { |
| 44 | u32 raw; | 44 | u32 raw; |
| 45 | BitField<0, 8, TextureType> type; | 45 | BitField<0, 8, TextureType> type; |
| 46 | BitField<8, 1, u32> has_bias; | 46 | BitField<8, 1, u32> is_depth; |
| 47 | BitField<9, 1, u32> has_lod_clamp; | 47 | BitField<9, 1, u32> has_bias; |
| 48 | BitField<10, 1, u32> relaxed_precision; | 48 | BitField<10, 1, u32> has_lod_clamp; |
| 49 | BitField<11, 2, u32> gather_component; | 49 | BitField<11, 1, u32> relaxed_precision; |
| 50 | BitField<13, 2, u32> num_derivates; | 50 | BitField<12, 2, u32> gather_component; |
| 51 | BitField<14, 2, u32> num_derivates; | ||
| 52 | BitField<16, 3, ImageFormat> image_format; | ||
| 51 | }; | 53 | }; |
| 52 | static_assert(sizeof(TextureInstInfo) <= sizeof(u32)); | 54 | static_assert(sizeof(TextureInstInfo) <= sizeof(u32)); |
| 53 | 55 | ||
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 1697de965..82c5b37ba 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -389,6 +389,8 @@ OPCODE(BindlessImageFetch, F32x4, U32, | |||
| 389 | OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, ) | 389 | OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, ) |
| 390 | OPCODE(BindlessImageQueryLod, F32x4, U32, Opaque, ) | 390 | OPCODE(BindlessImageQueryLod, F32x4, U32, Opaque, ) |
| 391 | OPCODE(BindlessImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) | 391 | OPCODE(BindlessImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) |
| 392 | OPCODE(BindlessImageRead, U32x4, U32, Opaque, ) | ||
| 393 | OPCODE(BindlessImageWrite, Void, U32, Opaque, U32x4, ) | ||
| 392 | 394 | ||
| 393 | OPCODE(BoundImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) | 395 | OPCODE(BoundImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) |
| 394 | OPCODE(BoundImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) | 396 | OPCODE(BoundImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) |
| @@ -400,6 +402,8 @@ OPCODE(BoundImageFetch, F32x4, U32, | |||
| 400 | OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, ) | 402 | OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, ) |
| 401 | OPCODE(BoundImageQueryLod, F32x4, U32, Opaque, ) | 403 | OPCODE(BoundImageQueryLod, F32x4, U32, Opaque, ) |
| 402 | OPCODE(BoundImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) | 404 | OPCODE(BoundImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) |
| 405 | OPCODE(BoundImageRead, U32x4, U32, Opaque, ) | ||
| 406 | OPCODE(BoundImageWrite, Void, U32, Opaque, U32x4, ) | ||
| 403 | 407 | ||
| 404 | OPCODE(ImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) | 408 | OPCODE(ImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) |
| 405 | OPCODE(ImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) | 409 | OPCODE(ImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) |
| @@ -411,6 +415,8 @@ OPCODE(ImageFetch, F32x4, U32, | |||
| 411 | OPCODE(ImageQueryDimensions, U32x4, U32, U32, ) | 415 | OPCODE(ImageQueryDimensions, U32x4, U32, U32, ) |
| 412 | OPCODE(ImageQueryLod, F32x4, U32, Opaque, ) | 416 | OPCODE(ImageQueryLod, F32x4, U32, Opaque, ) |
| 413 | OPCODE(ImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) | 417 | OPCODE(ImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) |
| 418 | OPCODE(ImageRead, U32x4, U32, Opaque, ) | ||
| 419 | OPCODE(ImageWrite, Void, U32, Opaque, U32x4, ) | ||
| 414 | 420 | ||
| 415 | // Warp operations | 421 | // Warp operations |
| 416 | OPCODE(VoteAll, U1, U1, ) | 422 | OPCODE(VoteAll, U1, U1, ) |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index c23901052..327941223 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -281,18 +281,10 @@ void TranslatorVisitor::SUATOM_cas(u64) { | |||
| 281 | ThrowNotImplemented(Opcode::SUATOM_cas); | 281 | ThrowNotImplemented(Opcode::SUATOM_cas); |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | void TranslatorVisitor::SULD(u64) { | ||
| 285 | ThrowNotImplemented(Opcode::SULD); | ||
| 286 | } | ||
| 287 | |||
| 288 | void TranslatorVisitor::SURED(u64) { | 284 | void TranslatorVisitor::SURED(u64) { |
| 289 | ThrowNotImplemented(Opcode::SURED); | 285 | ThrowNotImplemented(Opcode::SURED); |
| 290 | } | 286 | } |
| 291 | 287 | ||
| 292 | void TranslatorVisitor::SUST(u64) { | ||
| 293 | ThrowNotImplemented(Opcode::SUST); | ||
| 294 | } | ||
| 295 | |||
| 296 | void TranslatorVisitor::SYNC(u64) { | 288 | void TranslatorVisitor::SYNC(u64) { |
| 297 | ThrowNotImplemented(Opcode::SYNC); | 289 | ThrowNotImplemented(Opcode::SYNC); |
| 298 | } | 290 | } |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_load_store.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_load_store.cpp new file mode 100644 index 000000000..9a2d16a6e --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_load_store.cpp | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <bit> | ||
| 7 | |||
| 8 | #include "common/bit_field.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "shader_recompiler/frontend/ir/modifiers.h" | ||
| 11 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 12 | |||
| 13 | namespace Shader::Maxwell { | ||
| 14 | namespace { | ||
| 15 | enum class Type : u64 { | ||
| 16 | _1D, | ||
| 17 | BUFFER_1D, | ||
| 18 | ARRAY_1D, | ||
| 19 | _2D, | ||
| 20 | ARRAY_2D, | ||
| 21 | _3D, | ||
| 22 | }; | ||
| 23 | |||
| 24 | constexpr unsigned R = 1 << 0; | ||
| 25 | constexpr unsigned G = 1 << 1; | ||
| 26 | constexpr unsigned B = 1 << 2; | ||
| 27 | constexpr unsigned A = 1 << 3; | ||
| 28 | |||
| 29 | constexpr std::array MASK{ | ||
| 30 | 0U, // | ||
| 31 | R, // | ||
| 32 | G, // | ||
| 33 | R | G, // | ||
| 34 | B, // | ||
| 35 | R | B, // | ||
| 36 | G | B, // | ||
| 37 | R | G | B, // | ||
| 38 | A, // | ||
| 39 | R | A, // | ||
| 40 | G | A, // | ||
| 41 | R | G | A, // | ||
| 42 | B | A, // | ||
| 43 | R | B | A, // | ||
| 44 | G | B | A, // | ||
| 45 | R | G | B | A, // | ||
| 46 | }; | ||
| 47 | |||
| 48 | enum class Size : u64 { | ||
| 49 | U8, | ||
| 50 | S8, | ||
| 51 | U16, | ||
| 52 | S16, | ||
| 53 | B32, | ||
| 54 | B64, | ||
| 55 | B128, | ||
| 56 | }; | ||
| 57 | |||
| 58 | enum class Clamp : u64 { | ||
| 59 | IGN, | ||
| 60 | Default, | ||
| 61 | TRAP, | ||
| 62 | }; | ||
| 63 | |||
| 64 | enum class LoadCache : u64 { | ||
| 65 | Default, | ||
| 66 | CG, | ||
| 67 | CI, | ||
| 68 | CV, | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum class StoreCache : u64 { | ||
| 72 | Default, | ||
| 73 | CG, | ||
| 74 | CS, | ||
| 75 | WT, | ||
| 76 | }; | ||
| 77 | |||
| 78 | ImageFormat Format(Size size) { | ||
| 79 | switch (size) { | ||
| 80 | case Size::U8: | ||
| 81 | return ImageFormat::R8_UINT; | ||
| 82 | case Size::S8: | ||
| 83 | return ImageFormat::R8_SINT; | ||
| 84 | case Size::U16: | ||
| 85 | return ImageFormat::R16_UINT; | ||
| 86 | case Size::S16: | ||
| 87 | return ImageFormat::R16_SINT; | ||
| 88 | case Size::B32: | ||
| 89 | return ImageFormat::R32_UINT; | ||
| 90 | case Size::B64: | ||
| 91 | return ImageFormat::R32G32_UINT; | ||
| 92 | case Size::B128: | ||
| 93 | return ImageFormat::R32G32B32A32_UINT; | ||
| 94 | } | ||
| 95 | throw NotImplementedException("Invalid size {}", size); | ||
| 96 | } | ||
| 97 | |||
| 98 | int SizeInRegs(Size size) { | ||
| 99 | switch (size) { | ||
| 100 | case Size::U8: | ||
| 101 | case Size::S8: | ||
| 102 | case Size::U16: | ||
| 103 | case Size::S16: | ||
| 104 | case Size::B32: | ||
| 105 | return 1; | ||
| 106 | case Size::B64: | ||
| 107 | return 2; | ||
| 108 | case Size::B128: | ||
| 109 | return 4; | ||
| 110 | } | ||
| 111 | throw NotImplementedException("Invalid size {}", size); | ||
| 112 | } | ||
| 113 | |||
| 114 | TextureType GetType(Type type) { | ||
| 115 | switch (type) { | ||
| 116 | case Type::_1D: | ||
| 117 | return TextureType::Color1D; | ||
| 118 | case Type::BUFFER_1D: | ||
| 119 | return TextureType::Buffer; | ||
| 120 | case Type::ARRAY_1D: | ||
| 121 | return TextureType::ColorArray1D; | ||
| 122 | case Type::_2D: | ||
| 123 | return TextureType::Color2D; | ||
| 124 | case Type::ARRAY_2D: | ||
| 125 | return TextureType::ColorArray2D; | ||
| 126 | case Type::_3D: | ||
| 127 | return TextureType::Color3D; | ||
| 128 | } | ||
| 129 | throw NotImplementedException("Invalid type {}", type); | ||
| 130 | } | ||
| 131 | |||
| 132 | IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, Type type) { | ||
| 133 | const auto array{[&](int index) { | ||
| 134 | return v.ir.BitFieldExtract(v.X(reg + index), v.ir.Imm32(0), v.ir.Imm32(16)); | ||
| 135 | }}; | ||
| 136 | switch (type) { | ||
| 137 | case Type::_1D: | ||
| 138 | case Type::BUFFER_1D: | ||
| 139 | return v.X(reg); | ||
| 140 | case Type::ARRAY_1D: | ||
| 141 | return v.ir.CompositeConstruct(v.X(reg), array(1)); | ||
| 142 | case Type::_2D: | ||
| 143 | return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1)); | ||
| 144 | case Type::ARRAY_2D: | ||
| 145 | return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), array(2)); | ||
| 146 | case Type::_3D: | ||
| 147 | return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), v.X(reg + 3)); | ||
| 148 | } | ||
| 149 | throw NotImplementedException("Invalid type {}", type); | ||
| 150 | } | ||
| 151 | |||
| 152 | unsigned SwizzleMask(u64 swizzle) { | ||
| 153 | if (swizzle == 0 || swizzle >= MASK.size()) { | ||
| 154 | throw NotImplementedException("Invalid swizzle {}", swizzle); | ||
| 155 | } | ||
| 156 | return MASK[swizzle]; | ||
| 157 | } | ||
| 158 | |||
| 159 | IR::Value MakeColor(IR::IREmitter& ir, IR::Reg reg, int num_regs) { | ||
| 160 | std::array<IR::U32, 4> colors; | ||
| 161 | for (int i = 0; i < num_regs; ++i) { | ||
| 162 | colors[i] = ir.GetReg(reg + i); | ||
| 163 | } | ||
| 164 | for (int i = num_regs; i < 4; ++i) { | ||
| 165 | colors[i] = ir.Imm32(0); | ||
| 166 | } | ||
| 167 | return ir.CompositeConstruct(colors[0], colors[1], colors[2], colors[3]); | ||
| 168 | } | ||
| 169 | } // Anonymous namespace | ||
| 170 | |||
| 171 | void TranslatorVisitor::SULD(u64 insn) { | ||
| 172 | union { | ||
| 173 | u64 raw; | ||
| 174 | BitField<51, 1, u64> is_bound; | ||
| 175 | BitField<52, 1, u64> d; | ||
| 176 | BitField<23, 1, u64> ba; | ||
| 177 | BitField<33, 3, Type> type; | ||
| 178 | BitField<24, 2, LoadCache> cache; | ||
| 179 | BitField<20, 3, Size> size; // .D | ||
| 180 | BitField<20, 4, u64> swizzle; // .P | ||
| 181 | BitField<49, 2, Clamp> clamp; | ||
| 182 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 183 | BitField<8, 8, IR::Reg> coord_reg; | ||
| 184 | BitField<36, 13, u64> bound_offset; // is_bound | ||
| 185 | BitField<39, 8, IR::Reg> bindless_reg; // !is_bound | ||
| 186 | } const suld{insn}; | ||
| 187 | |||
| 188 | if (suld.clamp != Clamp::IGN) { | ||
| 189 | throw NotImplementedException("Clamp {}", suld.clamp.Value()); | ||
| 190 | } | ||
| 191 | if (suld.cache != LoadCache::Default) { | ||
| 192 | throw NotImplementedException("Cache {}", suld.cache.Value()); | ||
| 193 | } | ||
| 194 | const bool is_typed{suld.d != 0}; | ||
| 195 | if (is_typed && suld.ba != 0) { | ||
| 196 | throw NotImplementedException("BA"); | ||
| 197 | } | ||
| 198 | |||
| 199 | const ImageFormat format{is_typed ? Format(suld.size) : ImageFormat::Typeless}; | ||
| 200 | const TextureType type{GetType(suld.type)}; | ||
| 201 | const IR::Value coords{MakeCoords(*this, suld.coord_reg, suld.type)}; | ||
| 202 | const IR::U32 handle{suld.is_bound != 0 ? ir.Imm32(static_cast<u32>(suld.bound_offset * 4)) | ||
| 203 | : X(suld.bindless_reg)}; | ||
| 204 | IR::TextureInstInfo info{}; | ||
| 205 | info.type.Assign(type); | ||
| 206 | info.image_format.Assign(format); | ||
| 207 | |||
| 208 | const IR::Value result{ir.ImageRead(handle, coords, info)}; | ||
| 209 | IR::Reg dest_reg{suld.dest_reg}; | ||
| 210 | if (is_typed) { | ||
| 211 | const int num_regs{SizeInRegs(suld.size)}; | ||
| 212 | for (int i = 0; i < num_regs; ++i) { | ||
| 213 | X(dest_reg + i, IR::U32{ir.CompositeExtract(result, i)}); | ||
| 214 | } | ||
| 215 | } else { | ||
| 216 | const unsigned mask{SwizzleMask(suld.swizzle)}; | ||
| 217 | const int bits{std::popcount(mask)}; | ||
| 218 | if (!IR::IsAligned(dest_reg, bits == 3 ? 4 : bits)) { | ||
| 219 | throw NotImplementedException("Unaligned destination register"); | ||
| 220 | } | ||
| 221 | for (unsigned component = 0; component < 4; ++component) { | ||
| 222 | if (((mask >> component) & 1) == 0) { | ||
| 223 | continue; | ||
| 224 | } | ||
| 225 | X(dest_reg, IR::U32{ir.CompositeExtract(result, component)}); | ||
| 226 | ++dest_reg; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | void TranslatorVisitor::SUST(u64 insn) { | ||
| 232 | union { | ||
| 233 | u64 raw; | ||
| 234 | BitField<51, 1, u64> is_bound; | ||
| 235 | BitField<52, 1, u64> d; | ||
| 236 | BitField<23, 1, u64> ba; | ||
| 237 | BitField<33, 3, Type> type; | ||
| 238 | BitField<24, 2, StoreCache> cache; | ||
| 239 | BitField<20, 3, Size> size; // .D | ||
| 240 | BitField<20, 4, u64> swizzle; // .P | ||
| 241 | BitField<49, 2, Clamp> clamp; | ||
| 242 | BitField<0, 8, IR::Reg> data_reg; | ||
| 243 | BitField<8, 8, IR::Reg> coord_reg; | ||
| 244 | BitField<36, 13, u64> bound_offset; // is_bound | ||
| 245 | BitField<39, 8, IR::Reg> bindless_reg; // !is_bound | ||
| 246 | } const sust{insn}; | ||
| 247 | |||
| 248 | if (sust.clamp != Clamp::IGN) { | ||
| 249 | throw NotImplementedException("Clamp {}", sust.clamp.Value()); | ||
| 250 | } | ||
| 251 | if (sust.cache != StoreCache::Default) { | ||
| 252 | throw NotImplementedException("Cache {}", sust.cache.Value()); | ||
| 253 | } | ||
| 254 | const bool is_typed{sust.d != 0}; | ||
| 255 | if (is_typed && sust.ba != 0) { | ||
| 256 | throw NotImplementedException("BA"); | ||
| 257 | } | ||
| 258 | const ImageFormat format{is_typed ? Format(sust.size) : ImageFormat::Typeless}; | ||
| 259 | const TextureType type{GetType(sust.type)}; | ||
| 260 | const IR::Value coords{MakeCoords(*this, sust.coord_reg, sust.type)}; | ||
| 261 | const IR::U32 handle{sust.is_bound != 0 ? ir.Imm32(static_cast<u32>(sust.bound_offset * 4)) | ||
| 262 | : X(sust.bindless_reg)}; | ||
| 263 | IR::TextureInstInfo info{}; | ||
| 264 | info.type.Assign(type); | ||
| 265 | info.image_format.Assign(format); | ||
| 266 | |||
| 267 | IR::Value color; | ||
| 268 | if (is_typed) { | ||
| 269 | color = MakeColor(ir, sust.data_reg, SizeInRegs(sust.size)); | ||
| 270 | } else { | ||
| 271 | const unsigned mask{SwizzleMask(sust.swizzle)}; | ||
| 272 | if (mask != 0xf) { | ||
| 273 | throw NotImplementedException("Non-full mask"); | ||
| 274 | } | ||
| 275 | color = MakeColor(ir, sust.data_reg, 4); | ||
| 276 | } | ||
| 277 | ir.ImageWrite(handle, coords, color, info); | ||
| 278 | } | ||
| 279 | |||
| 280 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp index 95d416586..9671d115e 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp | |||
| @@ -33,24 +33,24 @@ enum class TextureType : u64 { | |||
| 33 | ARRAY_CUBE, | 33 | ARRAY_CUBE, |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | Shader::TextureType GetType(TextureType type, bool dc) { | 36 | Shader::TextureType GetType(TextureType type) { |
| 37 | switch (type) { | 37 | switch (type) { |
| 38 | case TextureType::_1D: | 38 | case TextureType::_1D: |
| 39 | return dc ? Shader::TextureType::Shadow1D : Shader::TextureType::Color1D; | 39 | return Shader::TextureType::Color1D; |
| 40 | case TextureType::ARRAY_1D: | 40 | case TextureType::ARRAY_1D: |
| 41 | return dc ? Shader::TextureType::ShadowArray1D : Shader::TextureType::ColorArray1D; | 41 | return Shader::TextureType::ColorArray1D; |
| 42 | case TextureType::_2D: | 42 | case TextureType::_2D: |
| 43 | return dc ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D; | 43 | return Shader::TextureType::Color2D; |
| 44 | case TextureType::ARRAY_2D: | 44 | case TextureType::ARRAY_2D: |
| 45 | return dc ? Shader::TextureType::ShadowArray2D : Shader::TextureType::ColorArray2D; | 45 | return Shader::TextureType::ColorArray2D; |
| 46 | case TextureType::_3D: | 46 | case TextureType::_3D: |
| 47 | return dc ? Shader::TextureType::Shadow3D : Shader::TextureType::Color3D; | 47 | return Shader::TextureType::Color3D; |
| 48 | case TextureType::ARRAY_3D: | 48 | case TextureType::ARRAY_3D: |
| 49 | throw NotImplementedException("3D array texture type"); | 49 | throw NotImplementedException("3D array texture type"); |
| 50 | case TextureType::CUBE: | 50 | case TextureType::CUBE: |
| 51 | return dc ? Shader::TextureType::ShadowCube : Shader::TextureType::ColorCube; | 51 | return Shader::TextureType::ColorCube; |
| 52 | case TextureType::ARRAY_CUBE: | 52 | case TextureType::ARRAY_CUBE: |
| 53 | return dc ? Shader::TextureType::ShadowArrayCube : Shader::TextureType::ColorArrayCube; | 53 | return Shader::TextureType::ColorArrayCube; |
| 54 | } | 54 | } |
| 55 | throw NotImplementedException("Invalid texture type {}", type); | 55 | throw NotImplementedException("Invalid texture type {}", type); |
| 56 | } | 56 | } |
| @@ -169,7 +169,8 @@ void Impl(TranslatorVisitor& v, u64 insn, bool aoffi, Blod blod, bool lc, | |||
| 169 | dref = v.F(meta_reg++); | 169 | dref = v.F(meta_reg++); |
| 170 | } | 170 | } |
| 171 | IR::TextureInstInfo info{}; | 171 | IR::TextureInstInfo info{}; |
| 172 | info.type.Assign(GetType(tex.type, tex.dc != 0)); | 172 | info.type.Assign(GetType(tex.type)); |
| 173 | info.is_depth.Assign(tex.dc != 0 ? 1 : 0); | ||
| 173 | info.has_bias.Assign(blod == Blod::LB || blod == Blod::LBA ? 1 : 0); | 174 | info.has_bias.Assign(blod == Blod::LB || blod == Blod::LBA ? 1 : 0); |
| 174 | info.has_lod_clamp.Assign(lc ? 1 : 0); | 175 | info.has_lod_clamp.Assign(lc ? 1 : 0); |
| 175 | 176 | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp index fe2c7db85..3500a4559 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp | |||
| @@ -95,18 +95,21 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { | |||
| 95 | {}, info); | 95 | {}, info); |
| 96 | case 4: // 2D.DC | 96 | case 4: // 2D.DC |
| 97 | CheckAlignment(reg_a, 2); | 97 | CheckAlignment(reg_a, 2); |
| 98 | info.type.Assign(TextureType::Shadow2D); | 98 | info.type.Assign(TextureType::Color2D); |
| 99 | info.is_depth.Assign(1); | ||
| 99 | return v.ir.ImageSampleDrefImplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b), | 100 | return v.ir.ImageSampleDrefImplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b), |
| 100 | {}, {}, {}, info); | 101 | {}, {}, {}, info); |
| 101 | case 5: // 2D.LL.DC | 102 | case 5: // 2D.LL.DC |
| 102 | CheckAlignment(reg_a, 2); | 103 | CheckAlignment(reg_a, 2); |
| 103 | CheckAlignment(reg_b, 2); | 104 | CheckAlignment(reg_b, 2); |
| 104 | info.type.Assign(TextureType::Shadow2D); | 105 | info.type.Assign(TextureType::Color2D); |
| 106 | info.is_depth.Assign(1); | ||
| 105 | return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1), | 107 | return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1), |
| 106 | v.F(reg_b + 1), v.F(reg_b), {}, {}, info); | 108 | v.F(reg_b + 1), v.F(reg_b), {}, {}, info); |
| 107 | case 6: // 2D.LZ.DC | 109 | case 6: // 2D.LZ.DC |
| 108 | CheckAlignment(reg_a, 2); | 110 | CheckAlignment(reg_a, 2); |
| 109 | info.type.Assign(TextureType::Shadow2D); | 111 | info.type.Assign(TextureType::Color2D); |
| 112 | info.is_depth.Assign(1); | ||
| 110 | return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b), | 113 | return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b), |
| 111 | zero, {}, {}, info); | 114 | zero, {}, {}, info); |
| 112 | case 7: // ARRAY_2D | 115 | case 7: // ARRAY_2D |
| @@ -124,7 +127,8 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { | |||
| 124 | case 9: // ARRAY_2D.LZ.DC | 127 | case 9: // ARRAY_2D.LZ.DC |
| 125 | CheckAlignment(reg_a, 2); | 128 | CheckAlignment(reg_a, 2); |
| 126 | CheckAlignment(reg_b, 2); | 129 | CheckAlignment(reg_b, 2); |
| 127 | info.type.Assign(TextureType::ShadowArray2D); | 130 | info.type.Assign(TextureType::ColorArray2D); |
| 131 | info.is_depth.Assign(1); | ||
| 128 | return v.ir.ImageSampleDrefExplicitLod( | 132 | return v.ir.ImageSampleDrefExplicitLod( |
| 129 | handle, v.ir.CompositeConstruct(v.F(reg_a + 1), v.F(reg_b), ReadArray(v, v.X(reg_a))), | 133 | handle, v.ir.CompositeConstruct(v.F(reg_a + 1), v.F(reg_b), ReadArray(v, v.X(reg_a))), |
| 130 | v.F(reg_b + 1), zero, {}, {}, info); | 134 | v.F(reg_b + 1), zero, {}, {}, info); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp index b2f9cda46..218cbc1a8 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp | |||
| @@ -37,24 +37,24 @@ enum class ComponentType : u64 { | |||
| 37 | A = 3, | 37 | A = 3, |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | Shader::TextureType GetType(TextureType type, bool dc) { | 40 | Shader::TextureType GetType(TextureType type) { |
| 41 | switch (type) { | 41 | switch (type) { |
| 42 | case TextureType::_1D: | 42 | case TextureType::_1D: |
| 43 | return dc ? Shader::TextureType::Shadow1D : Shader::TextureType::Color1D; | 43 | return Shader::TextureType::Color1D; |
| 44 | case TextureType::ARRAY_1D: | 44 | case TextureType::ARRAY_1D: |
| 45 | return dc ? Shader::TextureType::ShadowArray1D : Shader::TextureType::ColorArray1D; | 45 | return Shader::TextureType::ColorArray1D; |
| 46 | case TextureType::_2D: | 46 | case TextureType::_2D: |
| 47 | return dc ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D; | 47 | return Shader::TextureType::Color2D; |
| 48 | case TextureType::ARRAY_2D: | 48 | case TextureType::ARRAY_2D: |
| 49 | return dc ? Shader::TextureType::ShadowArray2D : Shader::TextureType::ColorArray2D; | 49 | return Shader::TextureType::ColorArray2D; |
| 50 | case TextureType::_3D: | 50 | case TextureType::_3D: |
| 51 | return dc ? Shader::TextureType::Shadow3D : Shader::TextureType::Color3D; | 51 | return Shader::TextureType::Color3D; |
| 52 | case TextureType::ARRAY_3D: | 52 | case TextureType::ARRAY_3D: |
| 53 | throw NotImplementedException("3D array texture type"); | 53 | throw NotImplementedException("3D array texture type"); |
| 54 | case TextureType::CUBE: | 54 | case TextureType::CUBE: |
| 55 | return dc ? Shader::TextureType::ShadowCube : Shader::TextureType::ColorCube; | 55 | return Shader::TextureType::ColorCube; |
| 56 | case TextureType::ARRAY_CUBE: | 56 | case TextureType::ARRAY_CUBE: |
| 57 | return dc ? Shader::TextureType::ShadowArrayCube : Shader::TextureType::ColorArrayCube; | 57 | return Shader::TextureType::ColorArrayCube; |
| 58 | } | 58 | } |
| 59 | throw NotImplementedException("Invalid texture type {}", type); | 59 | throw NotImplementedException("Invalid texture type {}", type); |
| 60 | } | 60 | } |
| @@ -163,7 +163,8 @@ void Impl(TranslatorVisitor& v, u64 insn, ComponentType component_type, OffsetTy | |||
| 163 | dref = v.F(meta_reg++); | 163 | dref = v.F(meta_reg++); |
| 164 | } | 164 | } |
| 165 | IR::TextureInstInfo info{}; | 165 | IR::TextureInstInfo info{}; |
| 166 | info.type.Assign(GetType(tld4.type, tld4.dc != 0)); | 166 | info.type.Assign(GetType(tld4.type)); |
| 167 | info.is_depth.Assign(tld4.dc != 0 ? 1 : 0); | ||
| 167 | info.gather_component.Assign(static_cast<u32>(component_type)); | 168 | info.gather_component.Assign(static_cast<u32>(component_type)); |
| 168 | const IR::Value sample{[&] { | 169 | const IR::Value sample{[&] { |
| 169 | if (tld4.dc == 0) { | 170 | if (tld4.dc == 0) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp index 2ba9c1018..34efa2d50 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp | |||
| @@ -59,7 +59,8 @@ IR::Value Sample(TranslatorVisitor& v, u64 insn) { | |||
| 59 | info.relaxed_precision.Assign(1); | 59 | info.relaxed_precision.Assign(1); |
| 60 | } | 60 | } |
| 61 | info.gather_component.Assign(static_cast<u32>(tld4s.component_type.Value())); | 61 | info.gather_component.Assign(static_cast<u32>(tld4s.component_type.Value())); |
| 62 | info.type.Assign(tld4s.dc != 0 ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D); | 62 | info.type.Assign(Shader::TextureType::Color2D); |
| 63 | info.is_depth.Assign(tld4s.dc != 0 ? 1 : 0); | ||
| 63 | IR::Value coords; | 64 | IR::Value coords; |
| 64 | if (tld4s.aoffi != 0) { | 65 | if (tld4s.aoffi != 0) { |
| 65 | CheckAlignment(reg_a, 2); | 66 | CheckAlignment(reg_a, 2); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp index c66468a48..c3fe3ffda 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp | |||
| @@ -23,24 +23,24 @@ enum class TextureType : u64 { | |||
| 23 | ARRAY_CUBE, | 23 | ARRAY_CUBE, |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | Shader::TextureType GetType(TextureType type, bool dc) { | 26 | Shader::TextureType GetType(TextureType type) { |
| 27 | switch (type) { | 27 | switch (type) { |
| 28 | case TextureType::_1D: | 28 | case TextureType::_1D: |
| 29 | return dc ? Shader::TextureType::Shadow1D : Shader::TextureType::Color1D; | 29 | return Shader::TextureType::Color1D; |
| 30 | case TextureType::ARRAY_1D: | 30 | case TextureType::ARRAY_1D: |
| 31 | return dc ? Shader::TextureType::ShadowArray1D : Shader::TextureType::ColorArray1D; | 31 | return Shader::TextureType::ColorArray1D; |
| 32 | case TextureType::_2D: | 32 | case TextureType::_2D: |
| 33 | return dc ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D; | 33 | return Shader::TextureType::Color2D; |
| 34 | case TextureType::ARRAY_2D: | 34 | case TextureType::ARRAY_2D: |
| 35 | return dc ? Shader::TextureType::ShadowArray2D : Shader::TextureType::ColorArray2D; | 35 | return Shader::TextureType::ColorArray2D; |
| 36 | case TextureType::_3D: | 36 | case TextureType::_3D: |
| 37 | return dc ? Shader::TextureType::Shadow3D : Shader::TextureType::Color3D; | 37 | return Shader::TextureType::Color3D; |
| 38 | case TextureType::ARRAY_3D: | 38 | case TextureType::ARRAY_3D: |
| 39 | throw NotImplementedException("3D array texture type"); | 39 | throw NotImplementedException("3D array texture type"); |
| 40 | case TextureType::CUBE: | 40 | case TextureType::CUBE: |
| 41 | return dc ? Shader::TextureType::ShadowCube : Shader::TextureType::ColorCube; | 41 | return Shader::TextureType::ColorCube; |
| 42 | case TextureType::ARRAY_CUBE: | 42 | case TextureType::ARRAY_CUBE: |
| 43 | return dc ? Shader::TextureType::ShadowArrayCube : Shader::TextureType::ColorArrayCube; | 43 | return Shader::TextureType::ColorArrayCube; |
| 44 | } | 44 | } |
| 45 | throw NotImplementedException("Invalid texture type {}", type); | 45 | throw NotImplementedException("Invalid texture type {}", type); |
| 46 | } | 46 | } |
| @@ -152,7 +152,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | IR::TextureInstInfo info{}; | 154 | IR::TextureInstInfo info{}; |
| 155 | info.type.Assign(GetType(txd.type, false)); | 155 | info.type.Assign(GetType(txd.type)); |
| 156 | info.num_derivates.Assign(num_derivates); | 156 | info.num_derivates.Assign(num_derivates); |
| 157 | info.has_lod_clamp.Assign(has_lod_clamp ? 1 : 0); | 157 | info.has_lod_clamp.Assign(has_lod_clamp ? 1 : 0); |
| 158 | const IR::Value sample{v.ir.ImageGradient(handle, coords, derivates, offset, lod_clamp, info)}; | 158 | const IR::Value sample{v.ir.ImageGradient(handle, coords, derivates, offset, lod_clamp, info)}; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp index 987b7ec34..983058303 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp | |||
| @@ -23,24 +23,24 @@ enum class TextureType : u64 { | |||
| 23 | ARRAY_CUBE, | 23 | ARRAY_CUBE, |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | Shader::TextureType GetType(TextureType type, bool dc) { | 26 | Shader::TextureType GetType(TextureType type) { |
| 27 | switch (type) { | 27 | switch (type) { |
| 28 | case TextureType::_1D: | 28 | case TextureType::_1D: |
| 29 | return dc ? Shader::TextureType::Shadow1D : Shader::TextureType::Color1D; | 29 | return Shader::TextureType::Color1D; |
| 30 | case TextureType::ARRAY_1D: | 30 | case TextureType::ARRAY_1D: |
| 31 | return dc ? Shader::TextureType::ShadowArray1D : Shader::TextureType::ColorArray1D; | 31 | return Shader::TextureType::ColorArray1D; |
| 32 | case TextureType::_2D: | 32 | case TextureType::_2D: |
| 33 | return dc ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D; | 33 | return Shader::TextureType::Color2D; |
| 34 | case TextureType::ARRAY_2D: | 34 | case TextureType::ARRAY_2D: |
| 35 | return dc ? Shader::TextureType::ShadowArray2D : Shader::TextureType::ColorArray2D; | 35 | return Shader::TextureType::ColorArray2D; |
| 36 | case TextureType::_3D: | 36 | case TextureType::_3D: |
| 37 | return dc ? Shader::TextureType::Shadow3D : Shader::TextureType::Color3D; | 37 | return Shader::TextureType::Color3D; |
| 38 | case TextureType::ARRAY_3D: | 38 | case TextureType::ARRAY_3D: |
| 39 | throw NotImplementedException("3D array texture type"); | 39 | throw NotImplementedException("3D array texture type"); |
| 40 | case TextureType::CUBE: | 40 | case TextureType::CUBE: |
| 41 | return dc ? Shader::TextureType::ShadowCube : Shader::TextureType::ColorCube; | 41 | return Shader::TextureType::ColorCube; |
| 42 | case TextureType::ARRAY_CUBE: | 42 | case TextureType::ARRAY_CUBE: |
| 43 | return dc ? Shader::TextureType::ShadowArrayCube : Shader::TextureType::ColorArrayCube; | 43 | return Shader::TextureType::ColorArrayCube; |
| 44 | } | 44 | } |
| 45 | throw NotImplementedException("Invalid texture type {}", type); | 45 | throw NotImplementedException("Invalid texture type {}", type); |
| 46 | } | 46 | } |
| @@ -137,7 +137,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { | |||
| 137 | throw NotImplementedException("TLD.CL - CLAMP is not implmented"); | 137 | throw NotImplementedException("TLD.CL - CLAMP is not implmented"); |
| 138 | } | 138 | } |
| 139 | IR::TextureInstInfo info{}; | 139 | IR::TextureInstInfo info{}; |
| 140 | info.type.Assign(GetType(tld.type, false)); | 140 | info.type.Assign(GetType(tld.type)); |
| 141 | const IR::Value sample{v.ir.ImageFetch(handle, coords, offset, lod, multisample, info)}; | 141 | const IR::Value sample{v.ir.ImageFetch(handle, coords, offset, lod, multisample, info)}; |
| 142 | 142 | ||
| 143 | IR::Reg dest_reg{tld.dest_reg}; | 143 | IR::Reg dest_reg{tld.dest_reg}; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load_swizzled.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load_swizzled.cpp index 0863bdfcd..5dd7e31b2 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load_swizzled.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load_swizzled.cpp | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <utility> | 5 | #include <array> |
| 6 | 6 | ||
| 7 | #include "common/bit_field.h" | 7 | #include "common/bit_field.h" |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp index b6efc04f0..2277d24ff 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp | |||
| @@ -23,24 +23,24 @@ enum class TextureType : u64 { | |||
| 23 | ARRAY_CUBE, | 23 | ARRAY_CUBE, |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | Shader::TextureType GetType(TextureType type, bool dc) { | 26 | Shader::TextureType GetType(TextureType type) { |
| 27 | switch (type) { | 27 | switch (type) { |
| 28 | case TextureType::_1D: | 28 | case TextureType::_1D: |
| 29 | return dc ? Shader::TextureType::Shadow1D : Shader::TextureType::Color1D; | 29 | return Shader::TextureType::Color1D; |
| 30 | case TextureType::ARRAY_1D: | 30 | case TextureType::ARRAY_1D: |
| 31 | return dc ? Shader::TextureType::ShadowArray1D : Shader::TextureType::ColorArray1D; | 31 | return Shader::TextureType::ColorArray1D; |
| 32 | case TextureType::_2D: | 32 | case TextureType::_2D: |
| 33 | return dc ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D; | 33 | return Shader::TextureType::Color2D; |
| 34 | case TextureType::ARRAY_2D: | 34 | case TextureType::ARRAY_2D: |
| 35 | return dc ? Shader::TextureType::ShadowArray2D : Shader::TextureType::ColorArray2D; | 35 | return Shader::TextureType::ColorArray2D; |
| 36 | case TextureType::_3D: | 36 | case TextureType::_3D: |
| 37 | return dc ? Shader::TextureType::Shadow3D : Shader::TextureType::Color3D; | 37 | return Shader::TextureType::Color3D; |
| 38 | case TextureType::ARRAY_3D: | 38 | case TextureType::ARRAY_3D: |
| 39 | throw NotImplementedException("3D array texture type"); | 39 | throw NotImplementedException("3D array texture type"); |
| 40 | case TextureType::CUBE: | 40 | case TextureType::CUBE: |
| 41 | return dc ? Shader::TextureType::ShadowCube : Shader::TextureType::ColorCube; | 41 | return Shader::TextureType::ColorCube; |
| 42 | case TextureType::ARRAY_CUBE: | 42 | case TextureType::ARRAY_CUBE: |
| 43 | return dc ? Shader::TextureType::ShadowArrayCube : Shader::TextureType::ColorArrayCube; | 43 | return Shader::TextureType::ColorArrayCube; |
| 44 | } | 44 | } |
| 45 | throw NotImplementedException("Invalid texture type {}", type); | 45 | throw NotImplementedException("Invalid texture type {}", type); |
| 46 | } | 46 | } |
| @@ -97,7 +97,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { | |||
| 97 | handle = v.ir.Imm32(static_cast<u32>(tmml.cbuf_offset.Value() * 4)); | 97 | handle = v.ir.Imm32(static_cast<u32>(tmml.cbuf_offset.Value() * 4)); |
| 98 | } | 98 | } |
| 99 | IR::TextureInstInfo info{}; | 99 | IR::TextureInstInfo info{}; |
| 100 | info.type.Assign(GetType(tmml.type, false)); | 100 | info.type.Assign(GetType(tmml.type)); |
| 101 | const IR::Value sample{v.ir.ImageQueryLod(handle, coords, info)}; | 101 | const IR::Value sample{v.ir.ImageQueryLod(handle, coords, info)}; |
| 102 | 102 | ||
| 103 | IR::Reg dest_reg{tmml.dest_reg}; | 103 | IR::Reg dest_reg{tmml.dest_reg}; |
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index edbfcd308..bc23b0211 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -416,8 +416,7 @@ void VisitUsages(Info& info, IR::Inst& inst) { | |||
| 416 | case IR::Opcode::ImageQueryLod: | 416 | case IR::Opcode::ImageQueryLod: |
| 417 | case IR::Opcode::ImageGradient: { | 417 | case IR::Opcode::ImageGradient: { |
| 418 | const TextureType type{inst.Flags<IR::TextureInstInfo>().type}; | 418 | const TextureType type{inst.Flags<IR::TextureInstInfo>().type}; |
| 419 | info.uses_sampled_1d |= type == TextureType::Color1D || type == TextureType::ColorArray1D || | 419 | info.uses_sampled_1d |= type == TextureType::Color1D || type == TextureType::ColorArray1D; |
| 420 | type == TextureType::Shadow1D || type == TextureType::ShadowArray1D; | ||
| 421 | info.uses_sparse_residency |= | 420 | info.uses_sparse_residency |= |
| 422 | inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr; | 421 | inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr; |
| 423 | break; | 422 | break; |
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index c8aee3d3d..a7b1fcfad 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp | |||
| @@ -61,6 +61,12 @@ IR::Opcode IndexedInstruction(const IR::Inst& inst) { | |||
| 61 | case IR::Opcode::BoundImageGradient: | 61 | case IR::Opcode::BoundImageGradient: |
| 62 | case IR::Opcode::BindlessImageGradient: | 62 | case IR::Opcode::BindlessImageGradient: |
| 63 | return IR::Opcode::ImageGradient; | 63 | return IR::Opcode::ImageGradient; |
| 64 | case IR::Opcode::BoundImageRead: | ||
| 65 | case IR::Opcode::BindlessImageRead: | ||
| 66 | return IR::Opcode::ImageRead; | ||
| 67 | case IR::Opcode::BoundImageWrite: | ||
| 68 | case IR::Opcode::BindlessImageWrite: | ||
| 69 | return IR::Opcode::ImageWrite; | ||
| 64 | default: | 70 | default: |
| 65 | return IR::Opcode::Void; | 71 | return IR::Opcode::Void; |
| 66 | } | 72 | } |
| @@ -78,6 +84,8 @@ bool IsBindless(const IR::Inst& inst) { | |||
| 78 | case IR::Opcode::BindlessImageQueryDimensions: | 84 | case IR::Opcode::BindlessImageQueryDimensions: |
| 79 | case IR::Opcode::BindlessImageQueryLod: | 85 | case IR::Opcode::BindlessImageQueryLod: |
| 80 | case IR::Opcode::BindlessImageGradient: | 86 | case IR::Opcode::BindlessImageGradient: |
| 87 | case IR::Opcode::BindlessImageRead: | ||
| 88 | case IR::Opcode::BindlessImageWrite: | ||
| 81 | return true; | 89 | return true; |
| 82 | case IR::Opcode::BoundImageSampleImplicitLod: | 90 | case IR::Opcode::BoundImageSampleImplicitLod: |
| 83 | case IR::Opcode::BoundImageSampleExplicitLod: | 91 | case IR::Opcode::BoundImageSampleExplicitLod: |
| @@ -89,6 +97,8 @@ bool IsBindless(const IR::Inst& inst) { | |||
| 89 | case IR::Opcode::BoundImageQueryDimensions: | 97 | case IR::Opcode::BoundImageQueryDimensions: |
| 90 | case IR::Opcode::BoundImageQueryLod: | 98 | case IR::Opcode::BoundImageQueryLod: |
| 91 | case IR::Opcode::BoundImageGradient: | 99 | case IR::Opcode::BoundImageGradient: |
| 100 | case IR::Opcode::BoundImageRead: | ||
| 101 | case IR::Opcode::BoundImageWrite: | ||
| 92 | return false; | 102 | return false; |
| 93 | default: | 103 | default: |
| 94 | throw InvalidArgument("Invalid opcode {}", inst.GetOpcode()); | 104 | throw InvalidArgument("Invalid opcode {}", inst.GetOpcode()); |
| @@ -147,10 +157,18 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { | |||
| 147 | 157 | ||
| 148 | class Descriptors { | 158 | class Descriptors { |
| 149 | public: | 159 | public: |
| 150 | explicit Descriptors(TextureDescriptors& texture_descriptors_, | 160 | explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_, |
| 151 | TextureBufferDescriptors& texture_buffer_descriptors_) | 161 | TextureDescriptors& texture_descriptors_, |
| 152 | : texture_descriptors{texture_descriptors_}, texture_buffer_descriptors{ | 162 | ImageDescriptors& image_descriptors_) |
| 153 | texture_buffer_descriptors_} {} | 163 | : texture_buffer_descriptors{texture_buffer_descriptors_}, |
| 164 | texture_descriptors{texture_descriptors_}, image_descriptors{image_descriptors_} {} | ||
| 165 | |||
| 166 | u32 Add(const TextureBufferDescriptor& desc) { | ||
| 167 | return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { | ||
| 168 | return desc.cbuf_index == existing.cbuf_index && | ||
| 169 | desc.cbuf_offset == existing.cbuf_offset; | ||
| 170 | }); | ||
| 171 | } | ||
| 154 | 172 | ||
| 155 | u32 Add(const TextureDescriptor& desc) { | 173 | u32 Add(const TextureDescriptor& desc) { |
| 156 | return Add(texture_descriptors, desc, [&desc](const auto& existing) { | 174 | return Add(texture_descriptors, desc, [&desc](const auto& existing) { |
| @@ -159,11 +177,14 @@ public: | |||
| 159 | }); | 177 | }); |
| 160 | } | 178 | } |
| 161 | 179 | ||
| 162 | u32 Add(const TextureBufferDescriptor& desc) { | 180 | u32 Add(const ImageDescriptor& desc) { |
| 163 | return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { | 181 | const u32 index{Add(image_descriptors, desc, [&desc](const auto& existing) { |
| 164 | return desc.cbuf_index == existing.cbuf_index && | 182 | return desc.type == existing.type && desc.format == existing.format && |
| 183 | desc.cbuf_index == existing.cbuf_index && | ||
| 165 | desc.cbuf_offset == existing.cbuf_offset; | 184 | desc.cbuf_offset == existing.cbuf_offset; |
| 166 | }); | 185 | })}; |
| 186 | image_descriptors[index].is_written |= desc.is_written; | ||
| 187 | return index; | ||
| 167 | } | 188 | } |
| 168 | 189 | ||
| 169 | private: | 190 | private: |
| @@ -178,8 +199,9 @@ private: | |||
| 178 | return static_cast<u32>(descriptors.size()) - 1; | 199 | return static_cast<u32>(descriptors.size()) - 1; |
| 179 | } | 200 | } |
| 180 | 201 | ||
| 181 | TextureDescriptors& texture_descriptors; | ||
| 182 | TextureBufferDescriptors& texture_buffer_descriptors; | 202 | TextureBufferDescriptors& texture_buffer_descriptors; |
| 203 | TextureDescriptors& texture_descriptors; | ||
| 204 | ImageDescriptors& image_descriptors; | ||
| 183 | }; | 205 | }; |
| 184 | } // Anonymous namespace | 206 | } // Anonymous namespace |
| 185 | 207 | ||
| @@ -201,8 +223,9 @@ void TexturePass(Environment& env, IR::Program& program) { | |||
| 201 | return lhs.cbuf.index < rhs.cbuf.index; | 223 | return lhs.cbuf.index < rhs.cbuf.index; |
| 202 | }); | 224 | }); |
| 203 | Descriptors descriptors{ | 225 | Descriptors descriptors{ |
| 204 | program.info.texture_descriptors, | ||
| 205 | program.info.texture_buffer_descriptors, | 226 | program.info.texture_buffer_descriptors, |
| 227 | program.info.texture_descriptors, | ||
| 228 | program.info.image_descriptors, | ||
| 206 | }; | 229 | }; |
| 207 | for (TextureInst& texture_inst : to_replace) { | 230 | for (TextureInst& texture_inst : to_replace) { |
| 208 | // TODO: Handle arrays | 231 | // TODO: Handle arrays |
| @@ -233,19 +256,41 @@ void TexturePass(Environment& env, IR::Program& program) { | |||
| 233 | break; | 256 | break; |
| 234 | } | 257 | } |
| 235 | u32 index; | 258 | u32 index; |
| 236 | if (flags.type == TextureType::Buffer) { | 259 | switch (inst->GetOpcode()) { |
| 237 | index = descriptors.Add(TextureBufferDescriptor{ | 260 | case IR::Opcode::ImageRead: |
| 238 | .cbuf_index = cbuf.index, | 261 | case IR::Opcode::ImageWrite: { |
| 239 | .cbuf_offset = cbuf.offset, | 262 | const bool is_written{inst->GetOpcode() == IR::Opcode::ImageWrite}; |
| 240 | .count = 1, | 263 | if (flags.type == TextureType::Buffer) { |
| 241 | }); | 264 | throw NotImplementedException("Image buffer"); |
| 242 | } else { | 265 | } else { |
| 243 | index = descriptors.Add(TextureDescriptor{ | 266 | index = descriptors.Add(ImageDescriptor{ |
| 244 | .type = flags.type, | 267 | .type = flags.type, |
| 245 | .cbuf_index = cbuf.index, | 268 | .format = flags.image_format, |
| 246 | .cbuf_offset = cbuf.offset, | 269 | .is_written = is_written, |
| 247 | .count = 1, | 270 | .cbuf_index = cbuf.index, |
| 248 | }); | 271 | .cbuf_offset = cbuf.offset, |
| 272 | .count = 1, | ||
| 273 | }); | ||
| 274 | } | ||
| 275 | break; | ||
| 276 | } | ||
| 277 | default: | ||
| 278 | if (flags.type == TextureType::Buffer) { | ||
| 279 | index = descriptors.Add(TextureBufferDescriptor{ | ||
| 280 | .cbuf_index = cbuf.index, | ||
| 281 | .cbuf_offset = cbuf.offset, | ||
| 282 | .count = 1, | ||
| 283 | }); | ||
| 284 | } else { | ||
| 285 | index = descriptors.Add(TextureDescriptor{ | ||
| 286 | .type = flags.type, | ||
| 287 | .is_depth = flags.is_depth != 0, | ||
| 288 | .cbuf_index = cbuf.index, | ||
| 289 | .cbuf_offset = cbuf.offset, | ||
| 290 | .count = 1, | ||
| 291 | }); | ||
| 292 | } | ||
| 293 | break; | ||
| 249 | } | 294 | } |
| 250 | inst->SetArg(0, IR::Value{index}); | 295 | inst->SetArg(0, IR::Value{index}); |
| 251 | } | 296 | } |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 4cc731198..253b6eacf 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -22,15 +22,20 @@ enum class TextureType : u32 { | |||
| 22 | Color3D, | 22 | Color3D, |
| 23 | ColorCube, | 23 | ColorCube, |
| 24 | ColorArrayCube, | 24 | ColorArrayCube, |
| 25 | Shadow1D, | ||
| 26 | ShadowArray1D, | ||
| 27 | Shadow2D, | ||
| 28 | ShadowArray2D, | ||
| 29 | Shadow3D, | ||
| 30 | ShadowCube, | ||
| 31 | ShadowArrayCube, | ||
| 32 | Buffer, | 25 | Buffer, |
| 33 | }; | 26 | }; |
| 27 | constexpr u32 NUM_TEXTURE_TYPES = 8; | ||
| 28 | |||
| 29 | enum class ImageFormat : u32 { | ||
| 30 | Typeless, | ||
| 31 | R8_UINT, | ||
| 32 | R8_SINT, | ||
| 33 | R16_UINT, | ||
| 34 | R16_SINT, | ||
| 35 | R32_UINT, | ||
| 36 | R32G32_UINT, | ||
| 37 | R32G32B32A32_UINT, | ||
| 38 | }; | ||
| 34 | 39 | ||
| 35 | enum class Interpolation { | 40 | enum class Interpolation { |
| 36 | Smooth, | 41 | Smooth, |
| @@ -43,32 +48,43 @@ struct InputVarying { | |||
| 43 | bool used{false}; | 48 | bool used{false}; |
| 44 | }; | 49 | }; |
| 45 | 50 | ||
| 46 | struct TextureDescriptor { | 51 | struct ConstantBufferDescriptor { |
| 47 | TextureType type; | 52 | u32 index; |
| 53 | u32 count; | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct StorageBufferDescriptor { | ||
| 48 | u32 cbuf_index; | 57 | u32 cbuf_index; |
| 49 | u32 cbuf_offset; | 58 | u32 cbuf_offset; |
| 50 | u32 count; | 59 | u32 count; |
| 60 | bool is_written; | ||
| 51 | }; | 61 | }; |
| 52 | using TextureDescriptors = boost::container::small_vector<TextureDescriptor, 12>; | ||
| 53 | 62 | ||
| 54 | struct TextureBufferDescriptor { | 63 | struct TextureBufferDescriptor { |
| 55 | u32 cbuf_index; | 64 | u32 cbuf_index; |
| 56 | u32 cbuf_offset; | 65 | u32 cbuf_offset; |
| 57 | u32 count; | 66 | u32 count; |
| 58 | }; | 67 | }; |
| 59 | using TextureBufferDescriptors = boost::container::small_vector<TextureBufferDescriptor, 2>; | 68 | using TextureBufferDescriptors = boost::container::small_vector<TextureBufferDescriptor, 6>; |
| 60 | 69 | ||
| 61 | struct ConstantBufferDescriptor { | 70 | struct TextureDescriptor { |
| 62 | u32 index; | 71 | TextureType type; |
| 72 | bool is_depth; | ||
| 73 | u32 cbuf_index; | ||
| 74 | u32 cbuf_offset; | ||
| 63 | u32 count; | 75 | u32 count; |
| 64 | }; | 76 | }; |
| 77 | using TextureDescriptors = boost::container::small_vector<TextureDescriptor, 12>; | ||
| 65 | 78 | ||
| 66 | struct StorageBufferDescriptor { | 79 | struct ImageDescriptor { |
| 80 | TextureType type; | ||
| 81 | ImageFormat format; | ||
| 82 | bool is_written; | ||
| 67 | u32 cbuf_index; | 83 | u32 cbuf_index; |
| 68 | u32 cbuf_offset; | 84 | u32 cbuf_offset; |
| 69 | u32 count; | 85 | u32 count; |
| 70 | bool is_written; | ||
| 71 | }; | 86 | }; |
| 87 | using ImageDescriptors = boost::container::small_vector<ImageDescriptor, 4>; | ||
| 72 | 88 | ||
| 73 | struct Info { | 89 | struct Info { |
| 74 | static constexpr size_t MAX_CBUFS{18}; | 90 | static constexpr size_t MAX_CBUFS{18}; |
| @@ -121,6 +137,7 @@ struct Info { | |||
| 121 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; | 137 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; |
| 122 | TextureBufferDescriptors texture_buffer_descriptors; | 138 | TextureBufferDescriptors texture_buffer_descriptors; |
| 123 | TextureDescriptors texture_descriptors; | 139 | TextureDescriptors texture_descriptors; |
| 140 | ImageDescriptors image_descriptors; | ||
| 124 | }; | 141 | }; |
| 125 | 142 | ||
| 126 | } // namespace Shader | 143 | } // namespace Shader |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 6c0d5c7f4..39fe9289b 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -361,7 +361,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV | |||
| 361 | .operation = operation, | 361 | .operation = operation, |
| 362 | }; | 362 | }; |
| 363 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | 363 | const VkPipelineLayout layout = *one_texture_pipeline_layout; |
| 364 | const VkImageView src_view = src_image_view.Handle(ImageViewType::e2D); | 364 | const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); |
| 365 | const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler; | 365 | const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler; |
| 366 | const VkPipeline pipeline = FindOrEmplacePipeline(key); | 366 | const VkPipeline pipeline = FindOrEmplacePipeline(key); |
| 367 | const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); | 367 | const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); |
| @@ -435,7 +435,7 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, | |||
| 435 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 435 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 436 | const ImageView& src_image_view) { | 436 | const ImageView& src_image_view) { |
| 437 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | 437 | const VkPipelineLayout layout = *one_texture_pipeline_layout; |
| 438 | const VkImageView src_view = src_image_view.Handle(ImageViewType::e2D); | 438 | const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); |
| 439 | const VkSampler sampler = *nearest_sampler; | 439 | const VkSampler sampler = *nearest_sampler; |
| 440 | const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); | 440 | const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); |
| 441 | const VkExtent2D extent{ | 441 | const VkExtent2D extent{ |
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index cff93cc60..d2c3f11c1 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h | |||
| @@ -97,6 +97,9 @@ public: | |||
| 97 | for ([[maybe_unused]] const auto& desc : info.texture_descriptors) { | 97 | for ([[maybe_unused]] const auto& desc : info.texture_descriptors) { |
| 98 | Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage); | 98 | Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage); |
| 99 | } | 99 | } |
| 100 | for (const auto& desc : info.image_descriptors) { | ||
| 101 | Add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stage); | ||
| 102 | } | ||
| 100 | } | 103 | } |
| 101 | 104 | ||
| 102 | private: | 105 | private: |
| @@ -127,36 +130,6 @@ private: | |||
| 127 | size_t offset{}; | 130 | size_t offset{}; |
| 128 | }; | 131 | }; |
| 129 | 132 | ||
| 130 | inline VideoCommon::ImageViewType CastType(Shader::TextureType type) { | ||
| 131 | switch (type) { | ||
| 132 | case Shader::TextureType::Color1D: | ||
| 133 | case Shader::TextureType::Shadow1D: | ||
| 134 | return VideoCommon::ImageViewType::e1D; | ||
| 135 | case Shader::TextureType::ColorArray1D: | ||
| 136 | case Shader::TextureType::ShadowArray1D: | ||
| 137 | return VideoCommon::ImageViewType::e1DArray; | ||
| 138 | case Shader::TextureType::Color2D: | ||
| 139 | case Shader::TextureType::Shadow2D: | ||
| 140 | return VideoCommon::ImageViewType::e2D; | ||
| 141 | case Shader::TextureType::ColorArray2D: | ||
| 142 | case Shader::TextureType::ShadowArray2D: | ||
| 143 | return VideoCommon::ImageViewType::e2DArray; | ||
| 144 | case Shader::TextureType::Color3D: | ||
| 145 | case Shader::TextureType::Shadow3D: | ||
| 146 | return VideoCommon::ImageViewType::e3D; | ||
| 147 | case Shader::TextureType::ColorCube: | ||
| 148 | case Shader::TextureType::ShadowCube: | ||
| 149 | return VideoCommon::ImageViewType::Cube; | ||
| 150 | case Shader::TextureType::ColorArrayCube: | ||
| 151 | case Shader::TextureType::ShadowArrayCube: | ||
| 152 | return VideoCommon::ImageViewType::CubeArray; | ||
| 153 | case Shader::TextureType::Buffer: | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | UNREACHABLE_MSG("Invalid texture type {}", type); | ||
| 157 | return {}; | ||
| 158 | } | ||
| 159 | |||
| 160 | inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers, | 133 | inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers, |
| 161 | const ImageId*& image_view_ids, TextureCache& texture_cache, | 134 | const ImageId*& image_view_ids, TextureCache& texture_cache, |
| 162 | VKUpdateDescriptorQueue& update_descriptor_queue) { | 135 | VKUpdateDescriptorQueue& update_descriptor_queue) { |
| @@ -164,9 +137,17 @@ inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& sam | |||
| 164 | for (const auto& desc : info.texture_descriptors) { | 137 | for (const auto& desc : info.texture_descriptors) { |
| 165 | const VkSampler sampler{*(samplers++)}; | 138 | const VkSampler sampler{*(samplers++)}; |
| 166 | ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; | 139 | ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; |
| 167 | const VkImageView vk_image_view{image_view.Handle(CastType(desc.type))}; | 140 | const VkImageView vk_image_view{image_view.Handle(desc.type)}; |
| 168 | update_descriptor_queue.AddSampledImage(vk_image_view, sampler); | 141 | update_descriptor_queue.AddSampledImage(vk_image_view, sampler); |
| 169 | } | 142 | } |
| 143 | for (const auto& desc : info.image_descriptors) { | ||
| 144 | ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; | ||
| 145 | if (desc.is_written) { | ||
| 146 | texture_cache.MarkModification(image_view.image_id); | ||
| 147 | } | ||
| 148 | const VkImageView vk_image_view{image_view.StorageView(desc.type, desc.format)}; | ||
| 149 | update_descriptor_queue.AddImage(vk_image_view); | ||
| 150 | } | ||
| 170 | } | 151 | } |
| 171 | 152 | ||
| 172 | } // namespace Vulkan | 153 | } // 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 ac47b1f3c..3d690f335 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -108,6 +108,10 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 108 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); | 108 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); |
| 109 | samplers.push_back(sampler->Handle()); | 109 | samplers.push_back(sampler->Handle()); |
| 110 | } | 110 | } |
| 111 | for (const auto& desc : info.image_descriptors) { | ||
| 112 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 113 | image_view_indices.push_back(handle.image); | ||
| 114 | } | ||
| 111 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | 115 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); |
| 112 | texture_cache.FillComputeImageViews(indices_span, image_view_ids); | 116 | texture_cache.FillComputeImageViews(indices_span, image_view_ids); |
| 113 | 117 | ||
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 57e2d569c..23c01f24e 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -186,6 +186,10 @@ void GraphicsPipeline::Configure(bool is_indexed) { | |||
| 186 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; | 186 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; |
| 187 | samplers.push_back(sampler->Handle()); | 187 | samplers.push_back(sampler->Handle()); |
| 188 | } | 188 | } |
| 189 | for (const auto& desc : info.image_descriptors) { | ||
| 190 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 191 | image_view_indices.push_back(handle.image); | ||
| 192 | } | ||
| 189 | } | 193 | } |
| 190 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | 194 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); |
| 191 | texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); | 195 | texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 0292a1b94..2ba44330f 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -494,7 +494,7 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, | |||
| 494 | if (!image_view) { | 494 | if (!image_view) { |
| 495 | return false; | 495 | return false; |
| 496 | } | 496 | } |
| 497 | screen_info.image_view = image_view->Handle(VideoCommon::ImageViewType::e2D); | 497 | screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D); |
| 498 | screen_info.width = image_view->size.width; | 498 | screen_info.width = image_view->size.width; |
| 499 | screen_info.height = image_view->size.height; | 499 | screen_info.height = image_view->size.height; |
| 500 | screen_info.is_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format); | 500 | screen_info.is_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 70328680d..8e029bcb3 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -215,6 +215,30 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 215 | return VK_COMPONENT_SWIZZLE_ZERO; | 215 | return VK_COMPONENT_SWIZZLE_ZERO; |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | [[nodiscard]] VkImageViewType ImageViewType(Shader::TextureType type) { | ||
| 219 | switch (type) { | ||
| 220 | case Shader::TextureType::Color1D: | ||
| 221 | return VK_IMAGE_VIEW_TYPE_1D; | ||
| 222 | case Shader::TextureType::Color2D: | ||
| 223 | return VK_IMAGE_VIEW_TYPE_2D; | ||
| 224 | case Shader::TextureType::ColorCube: | ||
| 225 | return VK_IMAGE_VIEW_TYPE_CUBE; | ||
| 226 | case Shader::TextureType::Color3D: | ||
| 227 | return VK_IMAGE_VIEW_TYPE_3D; | ||
| 228 | case Shader::TextureType::ColorArray1D: | ||
| 229 | return VK_IMAGE_VIEW_TYPE_1D_ARRAY; | ||
| 230 | case Shader::TextureType::ColorArray2D: | ||
| 231 | return VK_IMAGE_VIEW_TYPE_2D_ARRAY; | ||
| 232 | case Shader::TextureType::ColorArrayCube: | ||
| 233 | return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; | ||
| 234 | case Shader::TextureType::Buffer: | ||
| 235 | UNREACHABLE_MSG("Texture buffers can't be image views"); | ||
| 236 | return VK_IMAGE_VIEW_TYPE_1D; | ||
| 237 | } | ||
| 238 | UNREACHABLE_MSG("Invalid image view type={}", type); | ||
| 239 | return VK_IMAGE_VIEW_TYPE_2D; | ||
| 240 | } | ||
| 241 | |||
| 218 | [[nodiscard]] VkImageViewType ImageViewType(VideoCommon::ImageViewType type) { | 242 | [[nodiscard]] VkImageViewType ImageViewType(VideoCommon::ImageViewType type) { |
| 219 | switch (type) { | 243 | switch (type) { |
| 220 | case VideoCommon::ImageViewType::e1D: | 244 | case VideoCommon::ImageViewType::e1D: |
| @@ -232,7 +256,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 232 | case VideoCommon::ImageViewType::CubeArray: | 256 | case VideoCommon::ImageViewType::CubeArray: |
| 233 | return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; | 257 | return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; |
| 234 | case VideoCommon::ImageViewType::Rect: | 258 | case VideoCommon::ImageViewType::Rect: |
| 235 | LOG_WARNING(Render_Vulkan, "Unnormalized image view type not supported"); | 259 | UNIMPLEMENTED_MSG("Rect image view"); |
| 236 | return VK_IMAGE_VIEW_TYPE_2D; | 260 | return VK_IMAGE_VIEW_TYPE_2D; |
| 237 | case VideoCommon::ImageViewType::Buffer: | 261 | case VideoCommon::ImageViewType::Buffer: |
| 238 | UNREACHABLE_MSG("Texture buffers can't be image views"); | 262 | UNREACHABLE_MSG("Texture buffers can't be image views"); |
| @@ -539,6 +563,28 @@ struct RangedBarrierRange { | |||
| 539 | } | 563 | } |
| 540 | }; | 564 | }; |
| 541 | 565 | ||
| 566 | [[nodiscard]] VkFormat Format(Shader::ImageFormat format) { | ||
| 567 | switch (format) { | ||
| 568 | case Shader::ImageFormat::Typeless: | ||
| 569 | break; | ||
| 570 | case Shader::ImageFormat::R8_SINT: | ||
| 571 | return VK_FORMAT_R8_SINT; | ||
| 572 | case Shader::ImageFormat::R8_UINT: | ||
| 573 | return VK_FORMAT_R8_UINT; | ||
| 574 | case Shader::ImageFormat::R16_UINT: | ||
| 575 | return VK_FORMAT_R16_UINT; | ||
| 576 | case Shader::ImageFormat::R16_SINT: | ||
| 577 | return VK_FORMAT_R16_SINT; | ||
| 578 | case Shader::ImageFormat::R32_UINT: | ||
| 579 | return VK_FORMAT_R32_UINT; | ||
| 580 | case Shader::ImageFormat::R32G32_UINT: | ||
| 581 | return VK_FORMAT_R32G32_UINT; | ||
| 582 | case Shader::ImageFormat::R32G32B32A32_UINT: | ||
| 583 | return VK_FORMAT_R32G32B32A32_UINT; | ||
| 584 | } | ||
| 585 | UNREACHABLE_MSG("Invalid image format={}", format); | ||
| 586 | return VK_FORMAT_R32_UINT; | ||
| 587 | } | ||
| 542 | } // Anonymous namespace | 588 | } // Anonymous namespace |
| 543 | 589 | ||
| 544 | void TextureCacheRuntime::Finish() { | 590 | void TextureCacheRuntime::Finish() { |
| @@ -577,7 +623,7 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst | |||
| 577 | return; | 623 | return; |
| 578 | } | 624 | } |
| 579 | } | 625 | } |
| 580 | ASSERT(src.ImageFormat() == dst.ImageFormat()); | 626 | ASSERT(src.format == dst.format); |
| 581 | ASSERT(!(is_dst_msaa && !is_src_msaa)); | 627 | ASSERT(!(is_dst_msaa && !is_src_msaa)); |
| 582 | ASSERT(operation == Fermi2D::Operation::SrcCopy); | 628 | ASSERT(operation == Fermi2D::Operation::SrcCopy); |
| 583 | 629 | ||
| @@ -915,8 +961,9 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm | |||
| 915 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, | 961 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, |
| 916 | ImageId image_id_, Image& image) | 962 | ImageId image_id_, Image& image) |
| 917 | : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, | 963 | : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, |
| 918 | image_handle{image.Handle()}, image_format{image.info.format}, samples{ConvertSampleCount( | 964 | image_handle{image.Handle()}, samples{ConvertSampleCount(image.info.num_samples)} { |
| 919 | image.info.num_samples)} { | 965 | using Shader::TextureType; |
| 966 | |||
| 920 | const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); | 967 | const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); |
| 921 | std::array<SwizzleSource, 4> swizzle{ | 968 | std::array<SwizzleSource, 4> swizzle{ |
| 922 | SwizzleSource::R, | 969 | SwizzleSource::R, |
| @@ -954,39 +1001,39 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 954 | }, | 1001 | }, |
| 955 | .subresourceRange = MakeSubresourceRange(aspect_mask, info.range), | 1002 | .subresourceRange = MakeSubresourceRange(aspect_mask, info.range), |
| 956 | }; | 1003 | }; |
| 957 | const auto create = [&](VideoCommon::ImageViewType view_type, std::optional<u32> num_layers) { | 1004 | const auto create = [&](TextureType tex_type, std::optional<u32> num_layers) { |
| 958 | VkImageViewCreateInfo ci{create_info}; | 1005 | VkImageViewCreateInfo ci{create_info}; |
| 959 | ci.viewType = ImageViewType(view_type); | 1006 | ci.viewType = ImageViewType(tex_type); |
| 960 | if (num_layers) { | 1007 | if (num_layers) { |
| 961 | ci.subresourceRange.layerCount = *num_layers; | 1008 | ci.subresourceRange.layerCount = *num_layers; |
| 962 | } | 1009 | } |
| 963 | vk::ImageView handle = device->GetLogical().CreateImageView(ci); | 1010 | vk::ImageView handle = device->GetLogical().CreateImageView(ci); |
| 964 | if (device->HasDebuggingToolAttached()) { | 1011 | if (device->HasDebuggingToolAttached()) { |
| 965 | handle.SetObjectNameEXT(VideoCommon::Name(*this, view_type).c_str()); | 1012 | handle.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); |
| 966 | } | 1013 | } |
| 967 | image_views[static_cast<size_t>(view_type)] = std::move(handle); | 1014 | image_views[static_cast<size_t>(tex_type)] = std::move(handle); |
| 968 | }; | 1015 | }; |
| 969 | switch (info.type) { | 1016 | switch (info.type) { |
| 970 | case VideoCommon::ImageViewType::e1D: | 1017 | case VideoCommon::ImageViewType::e1D: |
| 971 | case VideoCommon::ImageViewType::e1DArray: | 1018 | case VideoCommon::ImageViewType::e1DArray: |
| 972 | create(VideoCommon::ImageViewType::e1D, 1); | 1019 | create(TextureType::Color1D, 1); |
| 973 | create(VideoCommon::ImageViewType::e1DArray, std::nullopt); | 1020 | create(TextureType::ColorArray1D, std::nullopt); |
| 974 | render_target = Handle(VideoCommon::ImageViewType::e1DArray); | 1021 | render_target = Handle(TextureType::ColorArray1D); |
| 975 | break; | 1022 | break; |
| 976 | case VideoCommon::ImageViewType::e2D: | 1023 | case VideoCommon::ImageViewType::e2D: |
| 977 | case VideoCommon::ImageViewType::e2DArray: | 1024 | case VideoCommon::ImageViewType::e2DArray: |
| 978 | create(VideoCommon::ImageViewType::e2D, 1); | 1025 | create(TextureType::Color2D, 1); |
| 979 | create(VideoCommon::ImageViewType::e2DArray, std::nullopt); | 1026 | create(TextureType::ColorArray2D, std::nullopt); |
| 980 | render_target = Handle(VideoCommon::ImageViewType::e2DArray); | 1027 | render_target = Handle(Shader::TextureType::ColorArray2D); |
| 981 | break; | 1028 | break; |
| 982 | case VideoCommon::ImageViewType::e3D: | 1029 | case VideoCommon::ImageViewType::e3D: |
| 983 | create(VideoCommon::ImageViewType::e3D, std::nullopt); | 1030 | create(TextureType::Color3D, std::nullopt); |
| 984 | render_target = Handle(VideoCommon::ImageViewType::e3D); | 1031 | render_target = Handle(Shader::TextureType::Color3D); |
| 985 | break; | 1032 | break; |
| 986 | case VideoCommon::ImageViewType::Cube: | 1033 | case VideoCommon::ImageViewType::Cube: |
| 987 | case VideoCommon::ImageViewType::CubeArray: | 1034 | case VideoCommon::ImageViewType::CubeArray: |
| 988 | create(VideoCommon::ImageViewType::Cube, 6); | 1035 | create(TextureType::ColorCube, 6); |
| 989 | create(VideoCommon::ImageViewType::CubeArray, std::nullopt); | 1036 | create(TextureType::ColorArrayCube, std::nullopt); |
| 990 | break; | 1037 | break; |
| 991 | case VideoCommon::ImageViewType::Rect: | 1038 | case VideoCommon::ImageViewType::Rect: |
| 992 | UNIMPLEMENTED(); | 1039 | UNIMPLEMENTED(); |
| @@ -1009,7 +1056,8 @@ VkImageView ImageView::DepthView() { | |||
| 1009 | if (depth_view) { | 1056 | if (depth_view) { |
| 1010 | return *depth_view; | 1057 | return *depth_view; |
| 1011 | } | 1058 | } |
| 1012 | depth_view = MakeDepthStencilView(VK_IMAGE_ASPECT_DEPTH_BIT); | 1059 | const auto& info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); |
| 1060 | depth_view = MakeView(info.format, VK_IMAGE_ASPECT_DEPTH_BIT); | ||
| 1013 | return *depth_view; | 1061 | return *depth_view; |
| 1014 | } | 1062 | } |
| 1015 | 1063 | ||
| @@ -1017,18 +1065,38 @@ VkImageView ImageView::StencilView() { | |||
| 1017 | if (stencil_view) { | 1065 | if (stencil_view) { |
| 1018 | return *stencil_view; | 1066 | return *stencil_view; |
| 1019 | } | 1067 | } |
| 1020 | stencil_view = MakeDepthStencilView(VK_IMAGE_ASPECT_STENCIL_BIT); | 1068 | const auto& info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); |
| 1069 | stencil_view = MakeView(info.format, VK_IMAGE_ASPECT_STENCIL_BIT); | ||
| 1021 | return *stencil_view; | 1070 | return *stencil_view; |
| 1022 | } | 1071 | } |
| 1023 | 1072 | ||
| 1024 | vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) { | 1073 | VkImageView ImageView::StorageView(Shader::TextureType texture_type, |
| 1074 | Shader::ImageFormat image_format) { | ||
| 1075 | if (image_format == Shader::ImageFormat::Typeless) { | ||
| 1076 | return Handle(texture_type); | ||
| 1077 | } | ||
| 1078 | const bool is_signed{image_format == Shader::ImageFormat::R8_SINT || | ||
| 1079 | image_format == Shader::ImageFormat::R16_SINT}; | ||
| 1080 | if (!storage_views) { | ||
| 1081 | storage_views = std::make_unique<StorageViews>(); | ||
| 1082 | } | ||
| 1083 | auto& views{is_signed ? storage_views->signeds : storage_views->unsigneds}; | ||
| 1084 | auto& view{views[static_cast<size_t>(texture_type)]}; | ||
| 1085 | if (view) { | ||
| 1086 | return *view; | ||
| 1087 | } | ||
| 1088 | view = MakeView(Format(image_format), VK_IMAGE_ASPECT_COLOR_BIT); | ||
| 1089 | return *view; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) { | ||
| 1025 | return device->GetLogical().CreateImageView({ | 1093 | return device->GetLogical().CreateImageView({ |
| 1026 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 1094 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 1027 | .pNext = nullptr, | 1095 | .pNext = nullptr, |
| 1028 | .flags = 0, | 1096 | .flags = 0, |
| 1029 | .image = image_handle, | 1097 | .image = image_handle, |
| 1030 | .viewType = ImageViewType(type), | 1098 | .viewType = ImageViewType(type), |
| 1031 | .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format).format, | 1099 | .format = vk_format, |
| 1032 | .components{ | 1100 | .components{ |
| 1033 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | 1101 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 1034 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | 1102 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 498e76a1c..0b73d55f8 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <compare> | 7 | #include <compare> |
| 8 | #include <span> | 8 | #include <span> |
| 9 | 9 | ||
| 10 | #include "shader_recompiler/shader_info.h" | ||
| 10 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" | 11 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" |
| 11 | #include "video_core/texture_cache/texture_cache.h" | 12 | #include "video_core/texture_cache/texture_cache.h" |
| 12 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 13 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| @@ -133,8 +134,11 @@ public: | |||
| 133 | 134 | ||
| 134 | [[nodiscard]] VkImageView StencilView(); | 135 | [[nodiscard]] VkImageView StencilView(); |
| 135 | 136 | ||
| 136 | [[nodiscard]] VkImageView Handle(VideoCommon::ImageViewType query_type) const noexcept { | 137 | [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type, |
| 137 | return *image_views[static_cast<size_t>(query_type)]; | 138 | Shader::ImageFormat image_format); |
| 139 | |||
| 140 | [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept { | ||
| 141 | return *image_views[static_cast<size_t>(texture_type)]; | ||
| 138 | } | 142 | } |
| 139 | 143 | ||
| 140 | [[nodiscard]] VkImage ImageHandle() const noexcept { | 144 | [[nodiscard]] VkImage ImageHandle() const noexcept { |
| @@ -145,10 +149,6 @@ public: | |||
| 145 | return render_target; | 149 | return render_target; |
| 146 | } | 150 | } |
| 147 | 151 | ||
| 148 | [[nodiscard]] PixelFormat ImageFormat() const noexcept { | ||
| 149 | return image_format; | ||
| 150 | } | ||
| 151 | |||
| 152 | [[nodiscard]] VkSampleCountFlagBits Samples() const noexcept { | 152 | [[nodiscard]] VkSampleCountFlagBits Samples() const noexcept { |
| 153 | return samples; | 153 | return samples; |
| 154 | } | 154 | } |
| @@ -162,15 +162,20 @@ public: | |||
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | private: | 164 | private: |
| 165 | [[nodiscard]] vk::ImageView MakeDepthStencilView(VkImageAspectFlags aspect_mask); | 165 | struct StorageViews { |
| 166 | std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> signeds; | ||
| 167 | std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> unsigneds; | ||
| 168 | }; | ||
| 169 | |||
| 170 | [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); | ||
| 166 | 171 | ||
| 167 | const Device* device = nullptr; | 172 | const Device* device = nullptr; |
| 168 | std::array<vk::ImageView, VideoCommon::NUM_IMAGE_VIEW_TYPES> image_views; | 173 | std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views; |
| 174 | std::unique_ptr<StorageViews> storage_views; | ||
| 169 | vk::ImageView depth_view; | 175 | vk::ImageView depth_view; |
| 170 | vk::ImageView stencil_view; | 176 | vk::ImageView stencil_view; |
| 171 | VkImage image_handle = VK_NULL_HANDLE; | 177 | VkImage image_handle = VK_NULL_HANDLE; |
| 172 | VkImageView render_target = VK_NULL_HANDLE; | 178 | VkImageView render_target = VK_NULL_HANDLE; |
| 173 | PixelFormat image_format = PixelFormat::Invalid; | ||
| 174 | VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; | 179 | VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; |
| 175 | GPUVAddr gpu_addr = 0; | 180 | GPUVAddr gpu_addr = 0; |
| 176 | u32 buffer_size = 0; | 181 | u32 buffer_size = 0; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 5e8d99482..255b07cf8 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -117,6 +117,9 @@ public: | |||
| 117 | /// Return a reference to the given image view id | 117 | /// Return a reference to the given image view id |
| 118 | [[nodiscard]] ImageView& GetImageView(ImageViewId id) noexcept; | 118 | [[nodiscard]] ImageView& GetImageView(ImageViewId id) noexcept; |
| 119 | 119 | ||
| 120 | /// Mark an image as modified from the GPU | ||
| 121 | void MarkModification(ImageId id) noexcept; | ||
| 122 | |||
| 120 | /// Fill image_view_ids with the graphics images in indices | 123 | /// Fill image_view_ids with the graphics images in indices |
| 121 | void FillGraphicsImageViews(std::span<const u32> indices, | 124 | void FillGraphicsImageViews(std::span<const u32> indices, |
| 122 | std::span<ImageViewId> image_view_ids); | 125 | std::span<ImageViewId> image_view_ids); |
| @@ -527,6 +530,11 @@ typename P::ImageView& TextureCache<P>::GetImageView(ImageViewId id) noexcept { | |||
| 527 | } | 530 | } |
| 528 | 531 | ||
| 529 | template <class P> | 532 | template <class P> |
| 533 | void TextureCache<P>::MarkModification(ImageId id) noexcept { | ||
| 534 | MarkModification(slot_images[id]); | ||
| 535 | } | ||
| 536 | |||
| 537 | template <class P> | ||
| 530 | void TextureCache<P>::FillGraphicsImageViews(std::span<const u32> indices, | 538 | void TextureCache<P>::FillGraphicsImageViews(std::span<const u32> indices, |
| 531 | std::span<ImageViewId> image_view_ids) { | 539 | std::span<ImageViewId> image_view_ids) { |
| 532 | FillImageViews(graphics_image_table, graphics_image_view_ids, indices, image_view_ids); | 540 | FillImageViews(graphics_image_table, graphics_image_view_ids, indices, image_view_ids); |