diff --git a/src/graphics/host_gpu/renderer/pipeline/shaders.cpp b/src/graphics/host_gpu/renderer/pipeline/shaders.cpp index 4ce567aed..d0ec84962 100644 --- a/src/graphics/host_gpu/renderer/pipeline/shaders.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/shaders.cpp @@ -12,6 +12,7 @@ #include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderTarget.h" #include "graphics/host_gpu/vulkanCommon.h" +#include "graphics/shader/recompiler/BufferFormat.h" #include "graphics/shader/recompiler/ir/ShaderIR.h" #include "graphics/shader/rectListShader.h" #include "graphics/shader/shader.h" @@ -122,220 +123,10 @@ static void GetInputFormat(const ShaderBufferResource& res, vk::Format& format, return; } - switch (fmt) { - case Prospero::BufferFormat::k32_32_32_32Float: - format = vk::Format::eR32G32B32A32Sfloat; - size = 4; - break; - case Prospero::BufferFormat::k32_32_32_32SInt: - format = vk::Format::eR32G32B32A32Sint; - size = 4; - break; - case Prospero::BufferFormat::k32_32_32_32UInt: - format = vk::Format::eR32G32B32A32Uint; - size = 4; - break; - case Prospero::BufferFormat::k32_32_32Float: - format = vk::Format::eR32G32B32Sfloat; - size = 3; - break; - case Prospero::BufferFormat::k32_32_32SInt: - format = vk::Format::eR32G32B32Sint; - size = 3; - break; - case Prospero::BufferFormat::k32_32_32UInt: - format = vk::Format::eR32G32B32Uint; - size = 3; - break; - case Prospero::BufferFormat::k16_16_16_16Float: - format = vk::Format::eR16G16B16A16Sfloat; - size = 4; - break; - case Prospero::BufferFormat::k16_16_16_16SInt: - format = vk::Format::eR16G16B16A16Sint; - size = 4; - break; - case Prospero::BufferFormat::k16_16_16_16UInt: - format = vk::Format::eR16G16B16A16Uint; - size = 4; - break; - case Prospero::BufferFormat::k16_16_16_16SScaled: - format = vk::Format::eR16G16B16A16Sscaled; - size = 4; - break; - case Prospero::BufferFormat::k16_16_16_16UScaled: - format = vk::Format::eR16G16B16A16Uscaled; - size = 4; - break; - case Prospero::BufferFormat::k16_16_16_16SNorm: - format = vk::Format::eR16G16B16A16Snorm; - size = 4; - break; - case Prospero::BufferFormat::k16_16_16_16UNorm: - format = vk::Format::eR16G16B16A16Unorm; - size = 4; - break; - case Prospero::BufferFormat::k32_32Float: - format = vk::Format::eR32G32Sfloat; - size = 2; - break; - case Prospero::BufferFormat::k32_32SInt: - format = vk::Format::eR32G32Sint; - size = 2; - break; - case Prospero::BufferFormat::k32_32UInt: - format = vk::Format::eR32G32Uint; - size = 2; - break; - case Prospero::BufferFormat::k8_8_8_8UInt: - format = vk::Format::eR8G8B8A8Uint; - size = 4; - break; - case Prospero::BufferFormat::k8_8_8_8SScaled: - format = vk::Format::eR8G8B8A8Sscaled; - size = 4; - break; - case Prospero::BufferFormat::k8_8_8_8UScaled: - format = vk::Format::eR8G8B8A8Uscaled; - size = 4; - break; - case Prospero::BufferFormat::k8_8_8_8SNorm: - format = vk::Format::eR8G8B8A8Snorm; - size = 4; - break; - case Prospero::BufferFormat::k8_8_8_8UNorm: - format = vk::Format::eR8G8B8A8Unorm; - size = 4; - break; - case Prospero::BufferFormat::k10_10_10_2UNorm: - format = vk::Format::eA2B10G10R10UnormPack32; - size = 4; - break; - case Prospero::BufferFormat::k10_10_10_2SNorm: - format = vk::Format::eA2B10G10R10SnormPack32; - size = 4; - break; - case Prospero::BufferFormat::k16_16Float: - format = vk::Format::eR16G16Sfloat; - size = 2; - break; - case Prospero::BufferFormat::k16_16SInt: - format = vk::Format::eR16G16Sint; - size = 2; - break; - case Prospero::BufferFormat::k16_16UInt: - format = vk::Format::eR16G16Uint; - size = 2; - break; - case Prospero::BufferFormat::k16_16SScaled: - format = vk::Format::eR16G16Sscaled; - size = 2; - break; - case Prospero::BufferFormat::k16_16UScaled: - format = vk::Format::eR16G16Uscaled; - size = 2; - break; - case Prospero::BufferFormat::k16_16SNorm: - format = vk::Format::eR16G16Snorm; - size = 2; - break; - case Prospero::BufferFormat::k16_16UNorm: - format = vk::Format::eR16G16Unorm; - size = 2; - break; - case Prospero::BufferFormat::k32Float: - format = vk::Format::eR32Sfloat; - size = 1; - break; - case Prospero::BufferFormat::k32SInt: - format = vk::Format::eR32Sint; - size = 1; - break; - case Prospero::BufferFormat::k32UInt: - format = vk::Format::eR32Uint; - size = 1; - break; - case Prospero::BufferFormat::k8_8SInt: - format = vk::Format::eR8G8Sint; - size = 2; - break; - case Prospero::BufferFormat::k8_8UInt: - format = vk::Format::eR8G8Uint; - size = 2; - break; - case Prospero::BufferFormat::k8_8SScaled: - format = vk::Format::eR8G8Sscaled; - size = 2; - break; - case Prospero::BufferFormat::k8_8UScaled: - format = vk::Format::eR8G8Uscaled; - size = 2; - break; - case Prospero::BufferFormat::k8_8SNorm: - format = vk::Format::eR8G8Snorm; - size = 2; - break; - case Prospero::BufferFormat::k8_8UNorm: - format = vk::Format::eR8G8Unorm; - size = 2; - break; - case Prospero::BufferFormat::k16Float: - format = vk::Format::eR16Sfloat; - size = 1; - break; - case Prospero::BufferFormat::k16SInt: - format = vk::Format::eR16Sint; - size = 1; - break; - case Prospero::BufferFormat::k16UInt: - format = vk::Format::eR16Uint; - size = 1; - break; - case Prospero::BufferFormat::k16SScaled: - format = vk::Format::eR16Sscaled; - size = 1; - break; - case Prospero::BufferFormat::k16UScaled: - format = vk::Format::eR16Uscaled; - size = 1; - break; - case Prospero::BufferFormat::k16SNorm: - format = vk::Format::eR16Snorm; - size = 1; - break; - case Prospero::BufferFormat::k16UNorm: - format = vk::Format::eR16Unorm; - size = 1; - break; - case Prospero::BufferFormat::k8SInt: - format = vk::Format::eR8Sint; - size = 1; - break; - case Prospero::BufferFormat::k8UInt: - format = vk::Format::eR8Uint; - size = 1; - break; - case Prospero::BufferFormat::k8SScaled: - format = vk::Format::eR8Sscaled; - size = 1; - break; - case Prospero::BufferFormat::k8UScaled: - format = vk::Format::eR8Uscaled; - size = 1; - break; - case Prospero::BufferFormat::k8SNorm: - format = vk::Format::eR8Snorm; - size = 1; - break; - case Prospero::BufferFormat::k8UNorm: - format = vk::Format::eR8Unorm; - size = 1; - break; - default: - EXIT("unknown format: fmt = %u\n", raw_format); - format = vk::Format::eUndefined; - size = 4; - break; + format = VulkanFormat(fmt); + size = ShaderRecompiler::Format::GetFormatInfo(fmt).component_count; + if (format == vk::Format::eUndefined || size == 0) { + EXIT("unknown vertex format: fmt = %u\n", raw_format); } if (NarrowInputFormat(format, size, used_components)) { diff --git a/src/graphics/host_gpu/vulkanCommon.cpp b/src/graphics/host_gpu/vulkanCommon.cpp index df628f2d2..bdb84d413 100644 --- a/src/graphics/host_gpu/vulkanCommon.cpp +++ b/src/graphics/host_gpu/vulkanCommon.cpp @@ -17,14 +17,22 @@ struct FormatMapping { constexpr FormatMapping kFormatMappings[] = { {Prospero::BufferFormat::k8UNorm, vk::Format::eR8Unorm}, + {Prospero::BufferFormat::k8SNorm, vk::Format::eR8Snorm}, + {Prospero::BufferFormat::k8UScaled, vk::Format::eR8Uscaled}, + {Prospero::BufferFormat::k8SScaled, vk::Format::eR8Sscaled}, {Prospero::BufferFormat::k8UInt, vk::Format::eR8Uint}, + {Prospero::BufferFormat::k8SInt, vk::Format::eR8Sint}, {Prospero::BufferFormat::k16UNorm, vk::Format::eR16Unorm}, {Prospero::BufferFormat::k16SNorm, vk::Format::eR16Snorm}, + {Prospero::BufferFormat::k16UScaled, vk::Format::eR16Uscaled}, + {Prospero::BufferFormat::k16SScaled, vk::Format::eR16Sscaled}, {Prospero::BufferFormat::k16UInt, vk::Format::eR16Uint}, {Prospero::BufferFormat::k16SInt, vk::Format::eR16Sint}, {Prospero::BufferFormat::k16Float, vk::Format::eR16Sfloat}, {Prospero::BufferFormat::k8_8UNorm, vk::Format::eR8G8Unorm}, {Prospero::BufferFormat::k8_8SNorm, vk::Format::eR8G8Snorm}, + {Prospero::BufferFormat::k8_8UScaled, vk::Format::eR8G8Uscaled}, + {Prospero::BufferFormat::k8_8SScaled, vk::Format::eR8G8Sscaled}, {Prospero::BufferFormat::k8_8UInt, vk::Format::eR8G8Uint}, {Prospero::BufferFormat::k8_8SInt, vk::Format::eR8G8Sint}, {Prospero::BufferFormat::k32UInt, vk::Format::eR32Uint}, @@ -32,14 +40,19 @@ constexpr FormatMapping kFormatMappings[] = { {Prospero::BufferFormat::k32Float, vk::Format::eR32Sfloat}, {Prospero::BufferFormat::k16_16UNorm, vk::Format::eR16G16Unorm}, {Prospero::BufferFormat::k16_16SNorm, vk::Format::eR16G16Snorm}, + {Prospero::BufferFormat::k16_16UScaled, vk::Format::eR16G16Uscaled}, + {Prospero::BufferFormat::k16_16SScaled, vk::Format::eR16G16Sscaled}, {Prospero::BufferFormat::k16_16UInt, vk::Format::eR16G16Uint}, {Prospero::BufferFormat::k16_16SInt, vk::Format::eR16G16Sint}, {Prospero::BufferFormat::k16_16Float, vk::Format::eR16G16Sfloat}, {Prospero::BufferFormat::k11_11_10Float, vk::Format::eB10G11R11UfloatPack32}, {Prospero::BufferFormat::k10_10_10_2UNorm, vk::Format::eA2B10G10R10UnormPack32}, + {Prospero::BufferFormat::k10_10_10_2SNorm, vk::Format::eA2B10G10R10SnormPack32}, {Prospero::BufferFormat::k10_10_10_2UInt, vk::Format::eA2B10G10R10UintPack32}, {Prospero::BufferFormat::k8_8_8_8UNorm, vk::Format::eR8G8B8A8Unorm}, {Prospero::BufferFormat::k8_8_8_8SNorm, vk::Format::eR8G8B8A8Snorm}, + {Prospero::BufferFormat::k8_8_8_8UScaled, vk::Format::eR8G8B8A8Uscaled}, + {Prospero::BufferFormat::k8_8_8_8SScaled, vk::Format::eR8G8B8A8Sscaled}, {Prospero::BufferFormat::k8_8_8_8UInt, vk::Format::eR8G8B8A8Uint}, {Prospero::BufferFormat::k8_8_8_8SInt, vk::Format::eR8G8B8A8Sint}, {Prospero::BufferFormat::k32_32UInt, vk::Format::eR32G32Uint}, @@ -47,6 +60,8 @@ constexpr FormatMapping kFormatMappings[] = { {Prospero::BufferFormat::k32_32Float, vk::Format::eR32G32Sfloat}, {Prospero::BufferFormat::k16_16_16_16UNorm, vk::Format::eR16G16B16A16Unorm}, {Prospero::BufferFormat::k16_16_16_16SNorm, vk::Format::eR16G16B16A16Snorm}, + {Prospero::BufferFormat::k16_16_16_16UScaled, vk::Format::eR16G16B16A16Uscaled}, + {Prospero::BufferFormat::k16_16_16_16SScaled, vk::Format::eR16G16B16A16Sscaled}, {Prospero::BufferFormat::k16_16_16_16UInt, vk::Format::eR16G16B16A16Uint}, {Prospero::BufferFormat::k16_16_16_16SInt, vk::Format::eR16G16B16A16Sint}, {Prospero::BufferFormat::k16_16_16_16Float, vk::Format::eR16G16B16A16Sfloat}, diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 84d618d05..b1332029c 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -11812,9 +11812,10 @@ public: m_device.destroyShaderModule(module, nullptr); } - void CheckRasterization(bool depth_feedback) { - const char *name = depth_feedback ? "DepthAttachmentFeedback" - : "PolygonModeRasterization"; + void CheckRasterization(bool depth_feedback, bool packed_vertex_color = false) { + const char *name = packed_vertex_color ? "PackedFloatVertexColor" + : depth_feedback ? "DepthAttachmentFeedback" + : "PolygonModeRasterization"; const uint32_t extent = depth_feedback ? 8 : 32; constexpr uintptr_t depth_address = 0x0000000204400000ull; constexpr uint64_t allocation_size = 0x20000; @@ -11898,10 +11899,13 @@ public: test.fragment_code.push_back(EncodeExp1(1, 1, 1, 1)); } else { test.pixel_interpolator_settings = {0x400u}; - test.fragment_code.push_back(EncodeVintrp(0x02, 0, 0, 0, 2)); + for (uint32_t component = 0; component < (packed_vertex_color ? 4u : 1u); component++) { + test.fragment_code.push_back(EncodeVintrp(0x02, component, 0, component, 2)); + } } test.fragment_code.push_back(EncodeExp0(0x00, 0xf)); - test.fragment_code.push_back(EncodeExp1(0, 0, 0, 0)); + test.fragment_code.push_back(packed_vertex_color ? EncodeExp1(0, 1, 2, 3) + : EncodeExp1(0, 0, 0, 0)); AppendEnd(&test.fragment_code); auto fragment = CompileFragmentCase(test); const auto vertex_spirv = TestSpv::MakePassthroughVertexSpirv(false); @@ -11910,7 +11914,7 @@ public: ShaderRecompiler::IR::CompiledShaderInfo vertex_program{}; vertex_program.stage = ShaderType::Vertex; vertex_program.info.vertex_fetch_components[0] = 2; - vertex_program.info.vertex_fetch_components[1] = 4; + vertex_program.info.vertex_fetch_components[1] = packed_vertex_color ? 3 : 4; ShaderRecompiler::IR::CompiledShaderInfo pixel_program{}; pixel_program.stage = ShaderType::Pixel; pixel_program.info = fragment.program.info; @@ -11925,10 +11929,12 @@ public: vertex.buffers[0].attr_offsets[1] = 2 * sizeof(float); for (uint32_t i = 0; i < 2; i++) { const auto format = i == 0 ? Prospero::BufferFormat::k32_32Float - : Prospero::BufferFormat::k32_32_32_32Float; + : packed_vertex_color ? Prospero::BufferFormat::k11_11_10Float + : Prospero::BufferFormat::k32_32_32_32Float; vertex.resources[i].fields[3] = DstSel(4, 5, 6, 7) | (static_cast(format) << 12u); - vertex.resources_dst[i].registers_num = i == 0 ? 2 : 4; + vertex.resources_dst[i].registers_num = + i == 0 ? 2 : vertex_program.info.vertex_fetch_components[1]; } ShaderPixelInputInfo pixel{}; pixel.stage.program = &pixel_program; @@ -11954,6 +11960,12 @@ public: } std::vector vertex_words(vertices.size()); std::memcpy(vertex_words.data(), vertices.data(), sizeof(vertices)); + if (packed_vertex_color) { + // R11/G11/B10 unsigned floats: 0.5, 1.0, 2.0; Vulkan supplies the missing alpha as 1. + for (uint32_t i = 0; i < 3; i++) { + vertex_words[i * 6 + 2] = 0x801e0380u; + } + } auto buffer = CreateHostBuffer(name, sizeof(vertices), vk::BufferUsageFlagBits::eVertexBuffer, vertex_words); const auto pipeline = [&](bool enabled, uint8_t front, uint8_t back, @@ -12019,7 +12031,16 @@ public: }; draw(filled); const auto solid_pixels = read_color(); - if (depth_feedback) { + if (packed_vertex_color) { + const std::array expected{0.5f, 1.0f, 2.0f, 1.0f}; + const auto center = 4 * ((extent / 2) * extent + extent / 2); + for (uint32_t component = 0; component < expected.size(); component++) { + Require(name, "packed vertex fetch and coverage", + std::abs(std::bit_cast(solid_pixels[center + component]) - + expected[component]) < 0.0001f && solid_pixels[component] == 0, + "packed vertex color changed channels, clamped HDR, or filled outside the triangle"); + } + } else if (depth_feedback) { // Consecutive draws in the same submission must see each earlier depth write. draw(filled); draw(filled); @@ -29072,6 +29093,7 @@ int main(int argc, char **argv) { if (argc == 2 && std::strcmp(argv[1], "--polygon-mode-only") == 0) { VulkanHarness vulkan; vulkan.CheckRasterization(false); + vulkan.CheckRasterization(false, true); return 0; } if (argc == 2 && std::strcmp(argv[1], "--htile-clear-only") == 0) { @@ -29276,6 +29298,7 @@ int main(int argc, char **argv) { vulkan.CheckUnifiedTextureCacheFlow(); vulkan.CheckBgra16Readback(); vulkan.CheckRasterization(false); + vulkan.CheckRasterization(false, true); vulkan.CheckBufferCacheDirtyGarbageCollection(); #endif vulkan.CheckUnifiedImageViewCache();