[Mesa-dev] [PATCH 1/5] gallium/u_tests: test FBFETCH and shader-based blending with MSAA
Marek Olšák
maraeo at gmail.com
Fri Mar 23 19:35:59 UTC 2018
From: Marek Olšák <marek.olsak at amd.com>
---
src/gallium/auxiliary/util/u_tests.c | 168 ++++++++++++++++++++++++++---------
1 file changed, 128 insertions(+), 40 deletions(-)
diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c
index 86eee6e68b1..293a4580a9f 100644
--- a/src/gallium/auxiliary/util/u_tests.c
+++ b/src/gallium/auxiliary/util/u_tests.c
@@ -37,29 +37,31 @@
#include "util/u_tile.h"
#include "tgsi/tgsi_strings.h"
#include "tgsi/tgsi_text.h"
#include "cso_cache/cso_context.h"
#include <stdio.h>
#define TOLERANCE 0.01
static struct pipe_resource *
util_create_texture2d(struct pipe_screen *screen, unsigned width,
- unsigned height, enum pipe_format format)
+ unsigned height, enum pipe_format format,
+ unsigned num_samples)
{
struct pipe_resource templ = {{0}};
templ.target = PIPE_TEXTURE_2D;
templ.width0 = width;
templ.height0 = height;
templ.depth0 = 1;
templ.array_size = 1;
+ templ.nr_samples = num_samples;
templ.format = format;
templ.usage = PIPE_USAGE_DEFAULT;
templ.bind = PIPE_BIND_SAMPLER_VIEW |
(util_format_is_depth_or_stencil(format) ?
PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET);
return screen->resource_create(screen, &templ);
}
static void
@@ -181,20 +183,34 @@ util_draw_fullscreen_quad(struct cso_context *cso)
static float vertices[] = {
-1, -1, 0, 1, 0, 0, 0, 0,
-1, 1, 0, 1, 0, 1, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0,
1, -1, 0, 1, 1, 0, 0, 0
};
util_set_interleaved_vertex_elements(cso, 2);
util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
}
+static void
+util_draw_fullscreen_quad_fill(struct cso_context *cso,
+ float r, float g, float b, float a)
+{
+ float vertices[] = {
+ -1, -1, 0, 1, r, g, b, a,
+ -1, 1, 0, 1, r, g, b, a,
+ 1, 1, 0, 1, r, g, b, a,
+ 1, -1, 0, 1, r, g, b, a,
+ };
+ util_set_interleaved_vertex_elements(cso, 2);
+ util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
+}
+
/**
* Probe and test if the rectangle contains the expected color.
*
* If "num_expected_colors" > 1, at least one expected color must match
* the probed color. "expected" should be an array of 4*num_expected_colors
* floats.
*/
static bool
util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
unsigned offx, unsigned offy, unsigned w,
@@ -299,21 +315,21 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
static const float red[] = {1, 0, 0, 1};
if (!ctx->screen->get_param(ctx->screen,
PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) {
util_report_result(SKIP);
return;
}
cso = cso_create_context(ctx, 0);
cb = util_create_texture2d(ctx->screen, 256, 256,
- PIPE_FORMAT_R8G8B8A8_UNORM);
+ PIPE_FORMAT_R8G8B8A8_UNORM, 0);
util_set_common_states_and_clear(cso, ctx, cb);
/* Fragment shader. */
fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC,
TGSI_INTERPOLATE_LINEAR, TRUE);
cso_set_fragment_shader_handle(cso, fs);
/* Vertex shader. */
vs = util_set_passthrough_vertex_shader(cso, ctx, true);
@@ -359,21 +375,21 @@ null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
if (tgsi_tex_target == TGSI_TEXTURE_BUFFER &&
!ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) {
util_report_result_helper(SKIP, "%s: %s", __func__,
tgsi_texture_names[tgsi_tex_target]);
return;
}
cso = cso_create_context(ctx, 0);
cb = util_create_texture2d(ctx->screen, 256, 256,
- PIPE_FORMAT_R8G8B8A8_UNORM);
+ PIPE_FORMAT_R8G8B8A8_UNORM, 0);
util_set_common_states_and_clear(cso, ctx, cb);
ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
/* Fragment shader. */
fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target,
TGSI_INTERPOLATE_LINEAR,
TGSI_RETURN_TYPE_FLOAT,
TGSI_RETURN_TYPE_FLOAT, false, false);
cso_set_fragment_shader_handle(cso, fs);
@@ -402,21 +418,21 @@ util_test_constant_buffer(struct pipe_context *ctx,
struct pipe_resource *constbuf)
{
struct cso_context *cso;
struct pipe_resource *cb;
void *fs, *vs;
bool pass = true;
static const float zero[] = {0, 0, 0, 0};
cso = cso_create_context(ctx, 0);
cb = util_create_texture2d(ctx->screen, 256, 256,
- PIPE_FORMAT_R8G8B8A8_UNORM);
+ PIPE_FORMAT_R8G8B8A8_UNORM, 0);
util_set_common_states_and_clear(cso, ctx, cb);
pipe_set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, 0, constbuf);
/* Fragment shader. */
{
static const char *text = /* I don't like ureg... */
"FRAG\n"
"DCL CONST[0][0]\n"
"DCL OUT[0], COLOR\n"
@@ -458,21 +474,21 @@ null_fragment_shader(struct pipe_context *ctx)
{
struct cso_context *cso;
struct pipe_resource *cb;
void *vs;
struct pipe_rasterizer_state rs = {0};
struct pipe_query *query;
union pipe_query_result qresult;
cso = cso_create_context(ctx, 0);
cb = util_create_texture2d(ctx->screen, 256, 256,
- PIPE_FORMAT_R8G8B8A8_UNORM);
+ PIPE_FORMAT_R8G8B8A8_UNORM, 0);
util_set_common_states_and_clear(cso, ctx, cb);
/* No rasterization. */
rs.rasterizer_discard = 1;
cso_set_rasterizer(cso, &rs);
vs = util_set_passthrough_vertex_shader(cso, ctx, false);
query = ctx->create_query(ctx, PIPE_QUERY_PRIMITIVES_GENERATED, 0);
ctx->begin_query(ctx, query);
@@ -504,21 +520,21 @@ test_sync_file_fences(struct pipe_context *ctx)
bool pass = true;
enum pipe_fd_type fd_type = PIPE_FD_TYPE_NATIVE_SYNC;
if (!screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))
return;
struct cso_context *cso = cso_create_context(ctx, 0);
struct pipe_resource *buf =
pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 1024 * 1024);
struct pipe_resource *tex =
- util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM);
+ util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM, 0);
struct pipe_fence_handle *buf_fence = NULL, *tex_fence = NULL;
/* Run 2 clears, get fencess. */
uint32_t value = 0;
ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
ctx->flush(ctx, &buf_fence, PIPE_FLUSH_FENCE_FD);
struct pipe_box box;
u_box_2d(0, 0, tex->width0, tex->height0, &box);
ctx->clear_texture(ctx, tex, 0, &box, &value);
@@ -587,45 +603,86 @@ test_sync_file_fences(struct pipe_context *ctx)
screen->fence_reference(screen, &final_fence, NULL);
cso_destroy_context(cso);
pipe_resource_reference(&buf, NULL);
pipe_resource_reference(&tex, NULL);
util_report_result(pass);
}
static void
-test_texture_barrier(struct pipe_context *ctx, bool use_fbfetch)
+test_texture_barrier(struct pipe_context *ctx, bool use_fbfetch,
+ unsigned num_samples)
{
struct cso_context *cso;
struct pipe_resource *cb;
- void *fs, *vs;
struct pipe_sampler_view *view = NULL;
+ char name[256];
const char *text;
+ assert(num_samples >= 1 && num_samples <= 8);
+
+ snprintf(name, sizeof(name), "%s: %s, %u samples", __func__,
+ use_fbfetch ? "FBFETCH" : "sampler", MAX2(num_samples, 1));
+
if (!ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BARRIER)) {
- util_report_result_helper(SKIP, "%s: %s", __func__,
- use_fbfetch ? "FBFETCH" : "sampler");
+ util_report_result_helper(SKIP, name);
return;
}
if (use_fbfetch &&
!ctx->screen->get_param(ctx->screen, PIPE_CAP_TGSI_FS_FBFETCH)) {
- util_report_result_helper(SKIP, "%s: %s", __func__,
- use_fbfetch ? "FBFETCH" : "sampler");
+ util_report_result_helper(SKIP, name);
return;
}
cso = cso_create_context(ctx, 0);
cb = util_create_texture2d(ctx->screen, 256, 256,
- PIPE_FORMAT_R8G8B8A8_UNORM);
+ PIPE_FORMAT_R8G8B8A8_UNORM, num_samples);
util_set_common_states_and_clear(cso, ctx, cb);
+ /* Clear each sample to a different value. */
+ if (num_samples > 1) {
+ void *fs =
+ util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC,
+ TGSI_INTERPOLATE_LINEAR, TRUE);
+ cso_set_fragment_shader_handle(cso, fs);
+
+ /* Vertex shader. */
+ void *vs = util_set_passthrough_vertex_shader(cso, ctx, false);
+
+ for (int i = 0; i < num_samples / 2; i++) {
+ float value;
+
+ /* 2 consecutive samples should have the same color to test MSAA
+ * compression properly.
+ */
+ if (num_samples == 2) {
+ value = 0.1;
+ } else {
+ /* The average value must be 0.1 */
+ static const float values[] = {
+ 0.0, 0.2, 0.05, 0.15
+ };
+ value = values[i];
+ }
+
+ ctx->set_sample_mask(ctx, 0x3 << (i * 2));
+ util_draw_fullscreen_quad_fill(cso, value, value, value, value);
+ }
+ ctx->set_sample_mask(ctx, ~0);
+
+ cso_set_vertex_shader_handle(cso, NULL);
+ cso_set_fragment_shader_handle(cso, NULL);
+ ctx->delete_vs_state(ctx, vs);
+ ctx->delete_fs_state(ctx, fs);
+ }
+
if (use_fbfetch) {
/* Fragment shader. */
text = "FRAG\n"
"DCL OUT[0], COLOR[0]\n"
"DCL TEMP[0]\n"
"IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
"FBFETCH TEMP[0], OUT[0]\n"
"ADD OUT[0], TEMP[0], IMM[0]\n"
"END\n";
@@ -634,92 +691,123 @@ test_texture_barrier(struct pipe_context *ctx, bool use_fbfetch)
templ.format = cb->format;
templ.target = cb->target;
templ.swizzle_r = PIPE_SWIZZLE_X;
templ.swizzle_g = PIPE_SWIZZLE_Y;
templ.swizzle_b = PIPE_SWIZZLE_Z;
templ.swizzle_a = PIPE_SWIZZLE_W;
view = ctx->create_sampler_view(ctx, cb, &templ);
ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &view);
/* Fragment shader. */
- text = "FRAG\n"
- "DCL SV[0], POSITION\n"
- "DCL SAMP[0]\n"
- "DCL SVIEW[0], 2D, FLOAT\n"
- "DCL OUT[0], COLOR[0]\n"
- "DCL TEMP[0]\n"
- "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
- "IMM[1] INT32 { 0, 0, 0, 0}\n"
-
- "F2I TEMP[0].xy, SV[0].xyyy\n"
- "MOV TEMP[0].z, IMM[1].xxxx\n"
- "TXF TEMP[0], TEMP[0].xyzz, SAMP[0], 2D\n"
- "ADD OUT[0], TEMP[0], IMM[0]\n"
- "END\n";
+ if (num_samples > 1) {
+ text = "FRAG\n"
+ "DCL SV[0], POSITION\n"
+ "DCL SV[1], SAMPLEID\n"
+ "DCL SAMP[0]\n"
+ "DCL SVIEW[0], 2D_MSAA, FLOAT\n"
+ "DCL OUT[0], COLOR[0]\n"
+ "DCL TEMP[0]\n"
+ "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
+
+ "F2I TEMP[0].xy, SV[0].xyyy\n"
+ "MOV TEMP[0].w, SV[1].xxxx\n"
+ "TXF TEMP[0], TEMP[0], SAMP[0], 2D_MSAA\n"
+ "ADD OUT[0], TEMP[0], IMM[0]\n"
+ "END\n";
+ } else {
+ text = "FRAG\n"
+ "DCL SV[0], POSITION\n"
+ "DCL SAMP[0]\n"
+ "DCL SVIEW[0], 2D, FLOAT\n"
+ "DCL OUT[0], COLOR[0]\n"
+ "DCL TEMP[0]\n"
+ "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
+ "IMM[1] INT32 { 0, 0, 0, 0}\n"
+
+ "F2I TEMP[0].xy, SV[0].xyyy\n"
+ "MOV TEMP[0].zw, IMM[1]\n"
+ "TXF TEMP[0], TEMP[0], SAMP[0], 2D\n"
+ "ADD OUT[0], TEMP[0], IMM[0]\n"
+ "END\n";
+ }
}
struct tgsi_token tokens[1000];
struct pipe_shader_state state;
if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
assert(0);
- util_report_result_helper(FAIL, "%s: %s", __func__,
- use_fbfetch ? "FBFETCH" : "sampler");
+ util_report_result_helper(FAIL, name);
return;
}
pipe_shader_state_from_tgsi(&state, tokens);
-#if 0
- tgsi_dump(state.tokens, 0);
-#endif
- fs = ctx->create_fs_state(ctx, &state);
+ void *fs = ctx->create_fs_state(ctx, &state);
cso_set_fragment_shader_handle(cso, fs);
/* Vertex shader. */
- vs = util_set_passthrough_vertex_shader(cso, ctx, false);
+ void *vs = util_set_passthrough_vertex_shader(cso, ctx, false);
+
+ if (num_samples > 1 && !use_fbfetch)
+ ctx->set_min_samples(ctx, num_samples);
for (int i = 0; i < 2; i++) {
ctx->texture_barrier(ctx,
use_fbfetch ? PIPE_TEXTURE_BARRIER_FRAMEBUFFER :
PIPE_TEXTURE_BARRIER_SAMPLER);
util_draw_fullscreen_quad(cso);
}
-
- /* Probe pixels. */
+ if (num_samples > 1 && !use_fbfetch)
+ ctx->set_min_samples(ctx, 1);
+
+ /* Probe pixels.
+ *
+ * For single sample:
+ * result = 0.1 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.3, 0.5, 0.7, 0.9)
+ *
+ * For MSAA 4x:
+ * sample0 = 0.0 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.2, 0.4, 0.6, 0.8)
+ * sample1 = sample0
+ * sample2 = 0.2 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.4, 0.6, 0.8, 1.0)
+ * sample3 = sample2
+ * resolved = sum(sample[0:3]) / 4 = (0.3, 0.5, 0.7, 0.9)
+ */
static const float expected[] = {0.3, 0.5, 0.7, 0.9};
bool pass = util_probe_rect_rgba(ctx, cb, 0, 0,
cb->width0, cb->height0, expected);
/* Cleanup. */
cso_destroy_context(cso);
ctx->delete_vs_state(ctx, vs);
ctx->delete_fs_state(ctx, fs);
pipe_sampler_view_reference(&view, NULL);
pipe_resource_reference(&cb, NULL);
- util_report_result_helper(pass, "%s: %s", __func__,
- use_fbfetch ? "FBFETCH" : "sampler");
+ util_report_result_helper(pass, name);
}
/**
* Run all tests. This should be run with a clean context after
* context_create.
*/
void
util_run_tests(struct pipe_screen *screen)
{
struct pipe_context *ctx = screen->context_create(screen, NULL, 0);
null_fragment_shader(ctx);
tgsi_vs_window_space_position(ctx);
null_sampler_view(ctx, TGSI_TEXTURE_2D);
null_sampler_view(ctx, TGSI_TEXTURE_BUFFER);
util_test_constant_buffer(ctx, NULL);
test_sync_file_fences(ctx);
- test_texture_barrier(ctx, false);
- test_texture_barrier(ctx, true);
+
+ for (int i = 1; i <= 8; i = i * 2)
+ test_texture_barrier(ctx, false, i);
+ for (int i = 1; i <= 8; i = i * 2)
+ test_texture_barrier(ctx, true, i);
ctx->destroy(ctx);
puts("Done. Exiting..");
exit(0);
}
--
2.15.1
More information about the mesa-dev
mailing list