radv/meta: add srgb conversion to end of resolve shader.
authorDave Airlie <airlied@redhat.com>
Thu, 20 Apr 2017 03:42:26 +0000 (04:42 +0100)
committerDave Airlie <airlied@redhat.com>
Sun, 7 May 2017 22:41:38 +0000 (23:41 +0100)
If we are resolving into an srgb dest, we need to convert
to linear so the store does the conversion back.

This should fix some wierdness seen when we subresolves
hit the compute path.

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/amd/vulkan/radv_meta_resolve_cs.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/vk_format.h

index dc4a1bb53d117c9bedc3b33b3444884b92e3a67c..99a3a06381cd5f97f0c0b5a44ae100303aaa359c 100644 (file)
@@ -32,7 +32,7 @@
 #include "vk_format.h"
 
 static nir_shader *
-build_resolve_compute_shader(struct radv_device *dev, bool is_integer, int samples)
+build_resolve_compute_shader(struct radv_device *dev, bool is_integer, bool is_srgb, int samples)
 {
        nir_builder b;
        char name[64];
@@ -45,7 +45,7 @@ build_resolve_compute_shader(struct radv_device *dev, bool is_integer, int sampl
                                                             false,
                                                             false,
                                                             GLSL_TYPE_FLOAT);
-       snprintf(name, 64, "meta_resolve_cs-%d-%s", samples, is_integer ? "int" : "float");
+       snprintf(name, 64, "meta_resolve_cs-%d-%s", samples, is_integer ? "int" : (is_srgb ? "srgb" : "float"));
        nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_COMPUTE, NULL);
        b.shader->info->name = ralloc_strdup(b.shader, name);
        b.shader->info->cs.local_size[0] = 16;
@@ -158,6 +158,44 @@ build_resolve_compute_shader(struct radv_device *dev, bool is_integer, int sampl
                b.cursor = nir_after_cf_node(&outer_if->cf_node);
 
        nir_ssa_def *newv = nir_load_var(&b, color);
+
+       if (is_srgb) {
+               nir_const_value v;
+               unsigned i;
+               v.u32[0] = 0x3b4d2e1c; // 0.00313080009
+
+               nir_ssa_def *cmp[3];
+               for (i = 0; i < 3; i++)
+                       cmp[i] = nir_flt(&b, nir_channel(&b, newv, i),
+                                        nir_build_imm(&b, 1, 32, v));
+
+               nir_ssa_def *ltvals[3];
+               v.f32[0] = 12.92;
+               for (i = 0; i < 3; i++)
+                       ltvals[i] = nir_fmul(&b, nir_channel(&b, newv, i),
+                                            nir_build_imm(&b, 1, 32, v));
+
+               nir_ssa_def *gtvals[3];
+
+               for (i = 0; i < 3; i++) {
+                       v.f32[0] = 1.0/2.4;
+                       gtvals[i] = nir_fpow(&b, nir_channel(&b, newv, i),
+                                            nir_build_imm(&b, 1, 32, v));
+                       v.f32[0] = 1.055;
+                       gtvals[i] = nir_fmul(&b, gtvals[i],
+                                            nir_build_imm(&b, 1, 32, v));
+                       v.f32[0] = 0.055;
+                       gtvals[i] = nir_fsub(&b, gtvals[i],
+                                            nir_build_imm(&b, 1, 32, v));
+               }
+
+               nir_ssa_def *comp[4];
+               for (i = 0; i < 3; i++)
+                       comp[i] = nir_bcsel(&b, cmp[i], ltvals[i], gtvals[i]);
+               comp[3] = nir_channels(&b, newv, 3);
+               newv = nir_vec(&b, comp, 4);
+       }
+
        nir_ssa_def *coord = nir_iadd(&b, global_id, &dst_offset->dest.ssa);
        nir_intrinsic_instr *store = nir_intrinsic_instr_create(b.shader, nir_intrinsic_image_store);
        store->src[0] = nir_src_for_ssa(coord);
@@ -230,12 +268,13 @@ static VkResult
 create_resolve_pipeline(struct radv_device *device,
                        int samples,
                        bool is_integer,
+                       bool is_srgb,
                        VkPipeline *pipeline)
 {
        VkResult result;
        struct radv_shader_module cs = { .nir = NULL };
 
-       cs.nir = build_resolve_compute_shader(device, is_integer, samples);
+       cs.nir = build_resolve_compute_shader(device, is_integer, is_srgb, samples);
 
        /* compute shader */
 
@@ -282,12 +321,15 @@ radv_device_init_meta_resolve_compute_state(struct radv_device *device)
        for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
                uint32_t samples = 1 << i;
 
-               res = create_resolve_pipeline(device, samples, false,
+               res = create_resolve_pipeline(device, samples, false, false,
                                              &state->resolve_compute.rc[i].pipeline);
 
-               res = create_resolve_pipeline(device, samples, true,
+               res = create_resolve_pipeline(device, samples, true, false,
                                              &state->resolve_compute.rc[i].i_pipeline);
 
+               res = create_resolve_pipeline(device, samples, false, true,
+                                             &state->resolve_compute.rc[i].srgb_pipeline);
+
        }
 
        return res;
@@ -305,6 +347,10 @@ radv_device_finish_meta_resolve_compute_state(struct radv_device *device)
                radv_DestroyPipeline(radv_device_to_handle(device),
                                     state->resolve_compute.rc[i].i_pipeline,
                                     &state->alloc);
+
+               radv_DestroyPipeline(radv_device_to_handle(device),
+                                    state->resolve_compute.rc[i].srgb_pipeline,
+                                    &state->alloc);
        }
 
        radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
@@ -443,6 +489,8 @@ void radv_meta_resolve_compute_image(struct radv_cmd_buffer *cmd_buffer,
                        VkPipeline pipeline;
                        if (vk_format_is_int(src_image->vk_format))
                                pipeline = device->meta_state.resolve_compute.rc[samples_log2].i_pipeline;
+                       else if (vk_format_is_srgb(src_image->vk_format))
+                               pipeline = device->meta_state.resolve_compute.rc[samples_log2].srgb_pipeline;
                        else
                                pipeline = device->meta_state.resolve_compute.rc[samples_log2].pipeline;
                        if (cmd_buffer->state.compute_pipeline != radv_pipeline_from_handle(pipeline)) {
index 1fe54bb8a07052afb49f9ffa5f68ac17854021bf..a02310b2644077b1640a30c70878f2b75557bb4d 100644 (file)
@@ -415,6 +415,7 @@ struct radv_meta_state {
                struct {
                        VkPipeline                                pipeline;
                        VkPipeline                                i_pipeline;
+                       VkPipeline                                srgb_pipeline;
                } rc[MAX_SAMPLES_LOG2];
        } resolve_compute;
 
index 13ac1793460491d9e8ef368c28afc0bb0def9b7e..af71e29f6adee49eead61d449e3d513dd726e327 100644 (file)
@@ -396,6 +396,13 @@ vk_format_is_int(VkFormat format)
        return channel >= 0 && desc->channel[channel].pure_integer;
 }
 
+static inline bool
+vk_format_is_srgb(VkFormat format)
+{
+       const struct vk_format_description *desc = vk_format_description(format);
+       return desc->colorspace == VK_FORMAT_COLORSPACE_SRGB;
+}
+
 static inline VkFormat
 vk_format_stencil_only(VkFormat format)
 {