diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 661aaedf6e..1662dbe0b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Eglantine has lots of different ways that you can contribute to its efforts, even without knowing how to write code: -- Join our [Discord](https://discord.gg/jCCZ58VExk) community +- Join our [Discord](https://discord.gg/XkS5NVPTUY) community - Submit [bug reports or feature requests](https://github.com/Djihads80/Eglantine/issues) - Improve documentation or share reproducible testing results - Contribute to our [translation efforts](./dist/languages/README.md) @@ -47,4 +47,4 @@ Before opening a pull request, make sure your branch is up-to-date with Eglantin Alongside the other contribution methods listed up top, you can also choose to contribute through documentation, organization, or community guides. These can be done either through the code contribution methods described above, or created externally and shared via our Discord community. -If you have an external tool/page that you believe would be handy to integrate/link into Eglantine, please discuss it with the developers on [Discord](https://discord.gg/jCCZ58VExk). **Do not submit vibe-coded or AI generated tools or applications**. +If you have an external tool/page that you believe would be handy to integrate/link into Eglantine, please discuss it with the developers on [Discord](https://discord.gg/XkS5NVPTUY). **Do not submit vibe-coded or AI generated tools or applications**. diff --git a/README.md b/README.md index baf60d4cc9..a30ca10093 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ A list of supported games will be available in future. Please be patient. ## Development -For development discussions, please join us on [Discord](https://discord.gg/jCCZ58VExk) +For development discussions, please join us on [Discord](https://discord.gg/XkS5NVPTUY) If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Stoat to learn more about the current state of the emulator. @@ -67,7 +67,7 @@ You can download the latest releases from [here](https://github.com/Djihads80/Eg We currently do not take in any donations for the time being -If you would prefer to support us in a different way, please join our [Discord](https://discord.gg/jCCZ58VExk) +If you would prefer to support us in a different way, please join our [Discord](https://discord.gg/XkS5NVPTUY) ## Star History diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index fa23b40e78..7577f07d3e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -1301,12 +1301,14 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline( } Shader::Environment& env{*envs[env_index]}; ++env_index; - // Without VK_EXT_mesh_shader the driver cannot build a task/mesh pipeline; the draw is // skipped (see the pipeline check in the rasterizer). if ((env.ShaderStage() == Shader::Stage::Task || env.ShaderStage() == Shader::Stage::Mesh) && !device.IsExtMeshShaderSupported()) { + LOG_WARNING(Render_Vulkan, "Skipping {} shader pipeline {:#016x}: the device has no VK_EXT_mesh_shader", + env.ShaderStage() == Shader::Stage::Task ? "task" : "mesh", + key.unique_hashes[index]); return nullptr; } diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 27646c0044..e1324660b4 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -94,7 +94,19 @@ static Shader::TextureType ConvertTextureType(const Tegra::Texture::TICEntry& en } } -static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry) { +static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry, + u32 handle) { + if (static_cast(entry.format.Value()) == 0) { + // Known benign case: a null/placeholder TIC (address 0, 1x1x1) bound to handle 0; the + // lookup falls back to A8B8G8R8. Log the raw words to distinguish it from a real + // unmapped NX2 format when something does read through it. + LOG_WARNING(Shader, + "TIC with INVALID format bound to handle {:#x}: raw={{{:016x} {:016x} {:016x} " + "{:016x}}} addr={:#x} {}x{}x{} type={} hv={}", + handle, entry.raw[0], entry.raw[1], entry.raw[2], entry.raw[3], entry.Address(), + entry.Width(), entry.Height(), entry.Depth(), entry.texture_type.Value(), + entry.header_version.Value()); + } return static_cast( PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type, entry.a_type, entry.srgb_conversion)); @@ -839,7 +851,7 @@ Shader::TexturePixelFormat GraphicsEnvironment::ReadTexturePixelFormat(u32 handl const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding}; auto entry = ReadTextureInfo(regs.tex_header.Address(), regs.tex_header.limit, via_header_index, handle); - const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry)); + const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry, handle)); texture_pixel_formats.emplace(handle, result); return result; } @@ -903,7 +915,7 @@ Shader::TexturePixelFormat ComputeEnvironment::ReadTexturePixelFormat(u32 handle const auto& regs{kepler_compute->regs}; const auto& qmd{kepler_compute->launch_description}; auto entry = ReadTextureInfo(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle); - const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry)); + const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry, handle)); texture_pixel_formats.emplace(handle, result); return result; } diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 7e86bf00cf..e0dca79ece 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -37,6 +37,23 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { dma_downloaded = forced_flushed; format = PixelFormatFromTextureInfo(config.format, config.r_type, config.g_type, config.b_type, config.a_type, config.srgb_conversion); + // Log the raw TIC once per unknown format, to tell a real unmapped NX2 format from a + // zeroed/placeholder descriptor (format 0, all-UNORM). + if (static_cast(config.format.Value()) == 0) { + static std::vector> logged_zero_formats; + if (std::find(logged_zero_formats.begin(), logged_zero_formats.end(), config.raw) == + logged_zero_formats.end()) { + logged_zero_formats.push_back(config.raw); + LOG_WARNING(HW_GPU, + "format-0 TIC raw {:016x} {:016x} {:016x} {:016x}: type {} header_ver {} " + "{}x{}x{} pitch {:#x} addr {:#x}", + config.raw[0], config.raw[1], config.raw[2], config.raw[3], + static_cast(config.texture_type.Value()), + static_cast(config.header_version.Value()), config.Width(), + config.Height(), config.Depth(), + config.IsPitchLinear() ? config.Pitch() : 0, config.Address()); + } + } num_samples = NumSamples(config.msaa_mode); resources.levels = config.max_mip_level + 1; if (config.IsPitchLinear()) { diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 9ced844732..bf3bc3f040 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1106,7 +1106,6 @@ bool Device::GetSuitability(bool requires_swapchain) { for (const VkExtensionProperties& property : extension_properties) { supported_extensions.insert(property.extensionName); } - // Generate list of extensions to load. loaded_extensions.clear(); @@ -1597,6 +1596,12 @@ void Device::RemoveUnsuitableExtensions() { features.mesh_shader.multiviewMeshShader = VK_FALSE; features.mesh_shader.primitiveFragmentShadingRateMeshShader = VK_FALSE; features.mesh_shader.meshShaderQueries = VK_FALSE; + LOG_INFO(Render_Vulkan, + "VK_EXT_mesh_shader: extension{} taskShader={} meshShader={} -> enabled={}", + loaded_extensions.contains(VK_EXT_MESH_SHADER_EXTENSION_NAME) ? "" : " NOT loaded", + static_cast(features.mesh_shader.taskShader), + static_cast(features.mesh_shader.meshShader), + features.mesh_shader.taskShader && features.mesh_shader.meshShader); extensions.mesh_shader = features.mesh_shader.taskShader && features.mesh_shader.meshShader; RemoveExtensionFeatureIfUnsuitable(extensions.mesh_shader, features.mesh_shader, VK_EXT_MESH_SHADER_EXTENSION_NAME);