diff --git a/README.md b/README.md index 24290ba28..c7ce08835 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3972. +This is the source code for early-access 3973. ## Legal Notice diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index ef53007bc..37d258a84 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -196,34 +196,42 @@ Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR } Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& index) { - if (!index.IsImmediate() || index.U32() != 0) { - throw NotImplementedException("Indirect image indexing"); - } if (info.type == TextureType::Buffer) { const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)}; if (def.count > 1) { - throw NotImplementedException("Indirect texture sample"); + const Id buffer_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; + return ctx.OpLoad(ctx.image_buffer_type, buffer_pointer); + } else { + return ctx.OpLoad(ctx.image_buffer_type, def.id); } - return ctx.OpLoad(ctx.image_buffer_type, def.id); } else { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - throw NotImplementedException("Indirect texture sample"); + const Id texture_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; + return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, texture_pointer)); + } else { + return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); } - return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); } } Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { - if (!index.IsImmediate() || index.U32() != 0) { - throw NotImplementedException("Indirect image indexing"); - } if (info.type == TextureType::Buffer) { const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)}; - return ctx.OpLoad(def.image_type, def.id); + if (def.count > 1) { + const Id image_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; + return ctx.OpLoad(def.image_type, image_pointer); + } else { + return ctx.OpLoad(def.image_type, def.id); + } } else { const ImageDefinition def{ctx.images.at(info.descriptor_index)}; - return ctx.OpLoad(def.image_type, def.id); + if (def.count > 1) { + const Id image_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; + return ctx.OpLoad(def.image_type, image_pointer); + } else { + return ctx.OpLoad(def.image_type, def.id); + } } } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp index fd09b32a6..808fa9b62 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp @@ -7,13 +7,21 @@ namespace Shader::Backend::SPIRV { namespace { -Id Image(EmitContext& ctx, IR::TextureInstInfo info) { +Id ImagePointer(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { if (info.type == TextureType::Buffer) { const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)}; - return def.id; + if (def.count > 1) { + return ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index)); + } else { + return def.id; + } } else { const ImageDefinition def{ctx.images.at(info.descriptor_index)}; - return def.id; + if (def.count > 1) { + return ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index)); + } else { + return def.id; + } } } @@ -25,15 +33,12 @@ std::pair AtomicArgs(EmitContext& ctx) { Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id value, Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) { - if (!index.IsImmediate() || index.U32() != 0) { - // TODO: handle layers - throw NotImplementedException("Image indexing"); - } const auto info{inst->Flags()}; - const Id image{Image(ctx, info)}; - const Id pointer{ctx.OpImageTexelPointer(ctx.image_u32, image, coords, ctx.Const(0U))}; + const Id image_pointer{ImagePointer(ctx, index, info)}; + const Id texel_pointer{ + ctx.OpImageTexelPointer(ctx.image_u32, image_pointer, coords, ctx.Const(0U))}; const auto [scope, semantics]{AtomicArgs(ctx)}; - return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value); + return (ctx.*atomic_func)(ctx.U32[1], texel_pointer, scope, semantics, value); } } // Anonymous namespace diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 8baaff063..cf6164dd6 100755 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1243,18 +1243,20 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { const spv::ImageFormat format{spv::ImageFormat::Unknown}; image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); - const Id type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)}; + const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)}; texture_buffers.reserve(info.texture_buffer_descriptors.size()); for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) { if (desc.count != 1) { - throw NotImplementedException("Array of texture buffers"); + LOG_WARNING(Shader_SPIRV, "Array of texture buffers"); } - const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; + const Id desc_type{DescType(*this, image_buffer_type, pointer_type, desc.count)}; + const Id id{AddGlobalVariable(desc_type, spv::StorageClass::UniformConstant)}; Decorate(id, spv::Decoration::Binding, binding); Decorate(id, spv::Decoration::DescriptorSet, 0U); Name(id, NameOf(stage, desc, "texbuf")); texture_buffers.push_back({ .id = id, + .pointer_type = pointer_type, .count = desc.count, }); if (profile.supported_spirv >= 0x00010400) { @@ -1268,7 +1270,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) { image_buffers.reserve(info.image_buffer_descriptors.size()); for (const ImageBufferDescriptor& desc : info.image_buffer_descriptors) { if (desc.count != 1) { - throw NotImplementedException("Array of image buffers"); + LOG_WARNING(Shader_SPIRV, "Array of image buffers"); } const spv::ImageFormat format{GetImageFormat(desc.format)}; const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)}; @@ -1280,6 +1282,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) { image_buffers.push_back({ .id = id, .image_type = image_type, + .pointer_type = pointer_type, .count = desc.count, }); if (profile.supported_spirv >= 0x00010400) { @@ -1323,17 +1326,19 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde images.reserve(info.image_descriptors.size()); for (const ImageDescriptor& desc : info.image_descriptors) { if (desc.count != 1) { - throw NotImplementedException("Array of images"); + LOG_WARNING(Shader_SPIRV, "Array of images"); } const Id image_type{ImageType(*this, desc)}; const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; - const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; + const Id desc_type{DescType(*this, image_type, pointer_type, desc.count)}; + const Id id{AddGlobalVariable(desc_type, spv::StorageClass::UniformConstant)}; Decorate(id, spv::Decoration::Binding, binding); Decorate(id, spv::Decoration::DescriptorSet, 0U); Name(id, NameOf(stage, desc, "img")); images.push_back({ .id = id, .image_type = image_type, + .pointer_type = pointer_type, .count = desc.count, }); if (profile.supported_spirv >= 0x00010400) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 469d16f7e..c443c4c7b 100755 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -40,18 +40,21 @@ struct TextureDefinition { struct TextureBufferDefinition { Id id; + Id pointer_type; u32 count; }; struct ImageBufferDefinition { Id id; Id image_type; + Id pointer_type; u32 count; }; struct ImageDefinition { Id id; Id image_type; + Id pointer_type; u32 count; }; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a85c6c34b..2918728da 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -555,7 +555,7 @@ void RasterizerOpenGL::OnCacheInvalidation(VAddr addr, u64 size) { } { std::scoped_lock lock{buffer_cache.mutex}; - buffer_cache.CachedWriteMemory(addr, size); + buffer_cache.WriteMemory(addr, size); } shader_cache.InvalidateRegion(addr, size); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 66bf2ecc5..747a709ba 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -621,7 +621,7 @@ void RasterizerVulkan::OnCacheInvalidation(VAddr addr, u64 size) { } { std::scoped_lock lock{buffer_cache.mutex}; - buffer_cache.CachedWriteMemory(addr, size); + buffer_cache.WriteMemory(addr, size); } pipeline_cache.InvalidateRegion(addr, size); } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index c92bc239f..e47c8f698 100755 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -222,6 +222,14 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se const u64 signal_value = master_semaphore->NextTick(); RecordWithUploadBuffer([signal_semaphore, wait_semaphore, signal_value, this](vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf) { + static constexpr VkMemoryBarrier WRITE_BARRIER{ + .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, + }; + upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER); upload_cmdbuf.End(); cmdbuf.End();