r600: add ARB_query_buffer_object support
authorDave Airlie <airlied@redhat.com>
Sun, 3 Dec 2017 19:31:46 +0000 (05:31 +1000)
committerDave Airlie <airlied@redhat.com>
Sun, 28 Jan 2018 19:42:28 +0000 (05:42 +1000)
This uses a different shader than radeonsi, as we can't address non-256
aligned ssbos, which the radeonsi code does. This passes some extra
offsets into the shader.

It also contains a set of u64 instruction implementation that may
or may not be complete (at least the u64div is definitely not something
that works outside this use-case). If r600 grows 64-bit integers,
it will use the GLSL lowering for divmod.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/r600_hw_context.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_pipe_common.c
src/gallium/drivers/r600/r600_pipe_common.h
src/gallium/drivers/r600/r600_query.c
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/r600/r600_state_common.c
src/gallium/drivers/r600/r600d.h

index ccd20a8ddd858f37d4a2958fecfe6abf247e1891..63a39a23f8fce3a03e128380f7b7058c969c6f33 100644 (file)
@@ -22,6 +22,7 @@
  */
 #include "r600_formats.h"
 #include "r600_shader.h"
+#include "r600_query.h"
 #include "evergreend.h"
 
 #include "pipe/p_shader_tokens.h"
@@ -4235,6 +4236,64 @@ static void evergreen_set_shader_images(struct pipe_context *ctx,
        r600_mark_atom_dirty(rctx, &istate->atom);
 }
 
+static void evergreen_get_pipe_constant_buffer(struct r600_context *rctx,
+                                              enum pipe_shader_type shader, uint slot,
+                                              struct pipe_constant_buffer *cbuf)
+{
+       struct r600_constbuf_state *state = &rctx->constbuf_state[shader];
+       struct pipe_constant_buffer *cb;
+       cbuf->user_buffer = NULL;
+
+       cb = &state->cb[slot];
+
+       cbuf->buffer_size = cb->buffer_size;
+       pipe_resource_reference(&cbuf->buffer, cb->buffer);
+}
+
+static void evergreen_get_shader_buffers(struct r600_context *rctx,
+                                        enum pipe_shader_type shader,
+                                        uint start_slot, uint count,
+                                        struct pipe_shader_buffer *sbuf)
+{
+       assert(shader == PIPE_SHADER_COMPUTE);
+       int idx, i;
+       struct r600_image_state *istate = &rctx->compute_buffers;
+       struct r600_image_view *rview;
+
+       for (i = start_slot, idx = 0; i < start_slot + count; i++, idx++) {
+
+               rview = &istate->views[i];
+
+               pipe_resource_reference(&sbuf[idx].buffer, rview->base.resource);
+               if (rview->base.resource) {
+                       uint64_t rview_va = ((struct r600_resource *)rview->base.resource)->gpu_address;
+
+                       uint64_t prog_va = rview->resource_words[0];
+
+                       prog_va += ((uint64_t)G_030008_BASE_ADDRESS_HI(rview->resource_words[2])) << 32;
+                       prog_va -= rview_va;
+
+                       sbuf[idx].buffer_offset = prog_va & 0xffffffff;
+                       sbuf[idx].buffer_size = rview->resource_words[1] + 1;;
+               } else {
+                       sbuf[idx].buffer_offset = 0;
+                       sbuf[idx].buffer_size = 0;
+               }
+       }
+}
+
+static void evergreen_save_qbo_state(struct pipe_context *ctx, struct r600_qbo_state *st)
+{
+       struct r600_context *rctx = (struct r600_context *)ctx;
+       st->saved_compute = rctx->cs_shader_state.shader;
+
+       /* save constant buffer 0 */
+       evergreen_get_pipe_constant_buffer(rctx, PIPE_SHADER_COMPUTE, 0, &st->saved_const0);
+       /* save ssbo 0 */
+       evergreen_get_shader_buffers(rctx, PIPE_SHADER_COMPUTE, 0, 3, st->saved_ssbo);
+}
+
+
 void evergreen_init_state_functions(struct r600_context *rctx)
 {
        unsigned id = 1;
@@ -4332,6 +4391,7 @@ void evergreen_init_state_functions(struct r600_context *rctx)
         else
                 rctx->b.b.get_sample_position = cayman_get_sample_position;
        rctx->b.dma_copy = evergreen_dma_copy;
+       rctx->b.save_qbo_state = evergreen_save_qbo_state;
 
        evergreen_init_compute_state_functions(rctx);
 }
index 259e1a826a3d432692d1eb555218421a3283429e..4b6d951af6b7eb6db608ba9d84938f43e6f898e0 100644 (file)
@@ -123,6 +123,11 @@ void r600_flush_emit(struct r600_context *rctx)
                radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_PS_PARTIAL_FLUSH) | EVENT_INDEX(4));
        }
 
+       if (rctx->b.flags & R600_CONTEXT_CS_PARTIAL_FLUSH) {
+               radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0));
+               radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_CS_PARTIAL_FLUSH) | EVENT_INDEX(4));
+       }
+
        if (wait_until) {
                /* Use of WAIT_UNTIL is deprecated on Cayman+ */
                if (rctx->b.family < CHIP_CAYMAN) {
index e7f8ae83eccc6294fdb77f26a7ff9aefbb018579..bd2cd884cb995237327fb2dbd7bd2d093a5ce854 100644 (file)
@@ -352,6 +352,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_TGSI_PACK_HALF_FLOAT:
        case PIPE_CAP_TGSI_CLOCK:
        case PIPE_CAP_TGSI_ARRAY_COMPONENTS:
+       case PIPE_CAP_QUERY_BUFFER_OBJECT:
                return family >= CHIP_CEDAR ? 1 : 0;
        case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
                return family >= CHIP_CEDAR ? 4 : 0;
@@ -384,7 +385,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
        case PIPE_CAP_GENERATE_MIPMAP:
        case PIPE_CAP_STRING_MARKER:
-       case PIPE_CAP_QUERY_BUFFER_OBJECT:
        case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES:
        case PIPE_CAP_TGSI_VOTE:
        case PIPE_CAP_MAX_WINDOW_RECTANGLES:
@@ -759,7 +759,7 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws,
                R600_CONTEXT_INV_VERTEX_CACHE |
                R600_CONTEXT_INV_TEX_CACHE |
                R600_CONTEXT_INV_CONST_CACHE;
-       rscreen->b.barrier_flags.compute_to_L2 = R600_CONTEXT_PS_PARTIAL_FLUSH;
+       rscreen->b.barrier_flags.compute_to_L2 = R600_CONTEXT_CS_PARTIAL_FLUSH | R600_CONTEXT_FLUSH_AND_INV;
 
        rscreen->global_pool = compute_memory_pool_new(rscreen);
 
index 0b4542fb7eeeac6bd93c7d65a12bd7bb85f14037..e9f95a512f6b0cf07d9558b4241c7d36eb3fd8c5 100644 (file)
@@ -63,6 +63,7 @@
 #define R600_CONTEXT_PS_PARTIAL_FLUSH          (R600_CONTEXT_PRIVATE_FLAG << 8)
 #define R600_CONTEXT_WAIT_3D_IDLE              (R600_CONTEXT_PRIVATE_FLAG << 9)
 #define R600_CONTEXT_WAIT_CP_DMA_IDLE          (R600_CONTEXT_PRIVATE_FLAG << 10)
+#define R600_CONTEXT_CS_PARTIAL_FLUSH           (R600_CONTEXT_PRIVATE_FLAG << 11)
 
 /* the number of CS dwords for flushing and drawing */
 #define R600_MAX_FLUSH_CS_DWORDS       18
index e02c43f93b8cd823f3a90fde2f31b23f103cc23c..5d14e588b51372f0a4ac95fd8ae2fc3a3317be06 100644 (file)
@@ -134,6 +134,7 @@ unsigned r600_gfx_write_fence_dwords(struct r600_common_screen *screen)
 }
 
 void r600_gfx_wait_fence(struct r600_common_context *ctx,
+                        struct r600_resource *buf,
                         uint64_t va, uint32_t ref, uint32_t mask)
 {
        struct radeon_winsys_cs *cs = ctx->gfx.cs;
@@ -145,6 +146,10 @@ void r600_gfx_wait_fence(struct r600_common_context *ctx,
        radeon_emit(cs, ref); /* reference value */
        radeon_emit(cs, mask); /* mask */
        radeon_emit(cs, 4); /* poll interval */
+
+       if (buf)
+               r600_emit_reloc(ctx, &ctx->gfx, buf, RADEON_USAGE_READ,
+                               RADEON_PRIO_QUERY);
 }
 
 void r600_draw_rectangle(struct blitter_context *blitter,
index 1fdbc39a560a38f4f03f6d480a3092868c106e04..86a20f8639b80f0596a4b61afe8ecce0eb1d93aa 100644 (file)
@@ -679,6 +679,7 @@ void r600_gfx_write_event_eop(struct r600_common_context *ctx,
                              uint32_t new_fence, unsigned query_type);
 unsigned r600_gfx_write_fence_dwords(struct r600_common_screen *screen);
 void r600_gfx_wait_fence(struct r600_common_context *ctx,
+                        struct r600_resource *buf,
                         uint64_t va, uint32_t ref, uint32_t mask);
 void r600_draw_rectangle(struct blitter_context *blitter,
                         void *vertex_elements_cso,
index b4519830cc4d37490375614b8c117852ad58f8a4..729c6f2aaa746cccad80b91b3e0d9655110c0aa2 100644 (file)
@@ -535,7 +535,8 @@ static bool r600_query_hw_prepare_buffer(struct r600_common_screen *rscreen,
        memset(results, 0, buffer->b.b.width0);
 
        if (query->b.type == PIPE_QUERY_OCCLUSION_COUNTER ||
-           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE) {
+           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE ||
+           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
                unsigned max_rbs = rscreen->info.num_render_backends;
                unsigned enabled_rb_mask = rscreen->info.enabled_rb_mask;
                unsigned num_results;
@@ -620,6 +621,7 @@ static struct pipe_query *r600_query_hw_create(struct r600_common_screen *rscree
        switch (query_type) {
        case PIPE_QUERY_OCCLUSION_COUNTER:
        case PIPE_QUERY_OCCLUSION_PREDICATE:
+       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
                query->result_size = 16 * rscreen->info.num_render_backends;
                query->result_size += 16; /* for the fence + alignment */
                query->num_cs_dw_begin = 6;
@@ -676,7 +678,8 @@ static void r600_update_occlusion_query_state(struct r600_common_context *rctx,
                                              unsigned type, int diff)
 {
        if (type == PIPE_QUERY_OCCLUSION_COUNTER ||
-           type == PIPE_QUERY_OCCLUSION_PREDICATE) {
+           type == PIPE_QUERY_OCCLUSION_PREDICATE ||
+           type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
                bool old_enable = rctx->num_occlusion_queries != 0;
                bool old_perfect_enable =
                        rctx->num_perfect_occlusion_queries != 0;
@@ -685,7 +688,7 @@ static void r600_update_occlusion_query_state(struct r600_common_context *rctx,
                rctx->num_occlusion_queries += diff;
                assert(rctx->num_occlusion_queries >= 0);
 
-               if (type == PIPE_QUERY_OCCLUSION_COUNTER) {
+               if (type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
                        rctx->num_perfect_occlusion_queries += diff;
                        assert(rctx->num_perfect_occlusion_queries >= 0);
                }
@@ -730,6 +733,7 @@ static void r600_query_hw_do_emit_start(struct r600_common_context *ctx,
        switch (query->b.type) {
        case PIPE_QUERY_OCCLUSION_COUNTER:
        case PIPE_QUERY_OCCLUSION_PREDICATE:
+       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
                radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
                radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
                radeon_emit(cs, va);
@@ -810,6 +814,7 @@ static void r600_query_hw_do_emit_stop(struct r600_common_context *ctx,
        switch (query->b.type) {
        case PIPE_QUERY_OCCLUSION_COUNTER:
        case PIPE_QUERY_OCCLUSION_PREDICATE:
+       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
                va += 8;
                radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
                radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
@@ -922,6 +927,7 @@ static void r600_emit_query_predication(struct r600_common_context *ctx,
        switch (query->b.type) {
        case PIPE_QUERY_OCCLUSION_COUNTER:
        case PIPE_QUERY_OCCLUSION_PREDICATE:
+       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
                op = PRED_OP(PREDICATION_OP_ZPASS);
                break;
        case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
@@ -1084,6 +1090,7 @@ static void r600_get_hw_query_params(struct r600_common_context *rctx,
        switch (rquery->b.type) {
        case PIPE_QUERY_OCCLUSION_COUNTER:
        case PIPE_QUERY_OCCLUSION_PREDICATE:
+       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
                params->start_offset = 0;
                params->end_offset = 8;
                params->fence_offset = max_rbs * 16;
@@ -1176,7 +1183,8 @@ static void r600_query_hw_add_result(struct r600_common_screen *rscreen,
                }
                break;
        }
-       case PIPE_QUERY_OCCLUSION_PREDICATE: {
+       case PIPE_QUERY_OCCLUSION_PREDICATE:
+       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
                for (unsigned i = 0; i < max_rbs; ++i) {
                        unsigned results_base = i * 16;
                        result->b = result->b ||
@@ -1383,6 +1391,8 @@ bool r600_query_hw_get_result(struct r600_common_context *rctx,
  *  1.x = fence_offset
  *  1.y = pair_stride
  *  1.z = pair_count
+ *  1.w = result_offset
+ *  2.x = buffer0 offset
  *
  * BUFFER[0] = query result buffer
  * BUFFER[1] = previous summary buffer
@@ -1404,7 +1414,7 @@ static void r600_create_query_result_shader(struct r600_common_context *rctx)
                "DCL BUFFER[0]\n"
                "DCL BUFFER[1]\n"
                "DCL BUFFER[2]\n"
-               "DCL CONST[0][0..1]\n"
+               "DCL CONST[0][0..2]\n"
                "DCL TEMP[0..5]\n"
                "IMM[0] UINT32 {0, 31, 2147483647, 4294967295}\n"
                "IMM[1] UINT32 {1, 2, 4, 8}\n"
@@ -1415,14 +1425,16 @@ static void r600_create_query_result_shader(struct r600_common_context *rctx)
                "AND TEMP[5], CONST[0][0].wwww, IMM[2].xxxx\n"
                "UIF TEMP[5]\n"
                        /* Check result availability. */
-                       "LOAD TEMP[1].x, BUFFER[0], CONST[0][1].xxxx\n"
+                       "UADD TEMP[1].x, CONST[0][1].xxxx, CONST[0][2].xxxx\n"
+                       "LOAD TEMP[1].x, BUFFER[0], TEMP[1].xxxx\n"
                        "ISHR TEMP[0].z, TEMP[1].xxxx, IMM[0].yyyy\n"
                        "MOV TEMP[1], TEMP[0].zzzz\n"
                        "NOT TEMP[0].z, TEMP[0].zzzz\n"
 
                        /* Load result if available. */
                        "UIF TEMP[1]\n"
-                               "LOAD TEMP[0].xy, BUFFER[0], IMM[0].xxxx\n"
+                               "UADD TEMP[0].x, IMM[0].xxxx, CONST[0][2].xxxx\n"
+                               "LOAD TEMP[0].xy, BUFFER[0], TEMP[0].xxxx\n"
                        "ENDIF\n"
                "ELSE\n"
                        /* Load previously accumulated result if requested. */
@@ -1447,6 +1459,7 @@ static void r600_create_query_result_shader(struct r600_common_context *rctx)
 
                                /* Load fence and check result availability */
                                "UMAD TEMP[5].x, TEMP[1].xxxx, CONST[0][0].yyyy, CONST[0][1].xxxx\n"
+                               "UADD TEMP[5].x, TEMP[5].xxxx, CONST[0][2].xxxx\n"
                                "LOAD TEMP[5].x, BUFFER[0], TEMP[5].xxxx\n"
                                "ISHR TEMP[0].z, TEMP[5].xxxx, IMM[0].yyyy\n"
                                "NOT TEMP[0].z, TEMP[0].zzzz\n"
@@ -1459,6 +1472,7 @@ static void r600_create_query_result_shader(struct r600_common_context *rctx)
                                        /* Load start and end. */
                                        "UMUL TEMP[5].x, TEMP[1].xxxx, CONST[0][0].yyyy\n"
                                        "UMAD TEMP[5].x, TEMP[1].yyyy, CONST[0][1].yyyy, TEMP[5].xxxx\n"
+                                       "UADD TEMP[5].x, TEMP[5].xxxx, CONST[0][2].xxxx\n"
                                        "LOAD TEMP[2].xy, BUFFER[0], TEMP[5].xxxx\n"
 
                                        "UADD TEMP[5].y, TEMP[5].xxxx, CONST[0][0].xxxx\n"
@@ -1497,18 +1511,18 @@ static void r600_create_query_result_shader(struct r600_common_context *rctx)
                "AND TEMP[4], CONST[0][0].wwww, IMM[1].yyyy\n"
                "UIF TEMP[4]\n"
                        /* Store accumulated data for chaining. */
-                       "STORE BUFFER[2].xyz, IMM[0].xxxx, TEMP[0]\n"
+                       "STORE BUFFER[2].xyz, CONST[0][1].wwww, TEMP[0]\n"
                "ELSE\n"
                        "AND TEMP[4], CONST[0][0].wwww, IMM[1].zzzz\n"
                        "UIF TEMP[4]\n"
                                /* Store result availability. */
                                "NOT TEMP[0].z, TEMP[0]\n"
                                "AND TEMP[0].z, TEMP[0].zzzz, IMM[1].xxxx\n"
-                               "STORE BUFFER[2].x, IMM[0].xxxx, TEMP[0].zzzz\n"
+                               "STORE BUFFER[2].x, CONST[0][1].wwww, TEMP[0].zzzz\n"
 
                                "AND TEMP[4], CONST[0][0].wwww, IMM[2].zzzz\n"
                                "UIF TEMP[4]\n"
-                                       "STORE BUFFER[2].y, IMM[0].xxxx, IMM[0].xxxx\n"
+                                       "STORE BUFFER[2].y, CONST[0][1].wwww, IMM[0].xxxx\n"
                                "ENDIF\n"
                        "ELSE\n"
                                /* Store result if it is available. */
@@ -1531,7 +1545,7 @@ static void r600_create_query_result_shader(struct r600_common_context *rctx)
 
                                        "AND TEMP[4], CONST[0][0].wwww, IMM[2].zzzz\n"
                                        "UIF TEMP[4]\n"
-                                               "STORE BUFFER[2].xy, IMM[0].xxxx, TEMP[0].xyxy\n"
+                                               "STORE BUFFER[2].xy, CONST[0][1].wwww, TEMP[0].xyxy\n"
                                        "ELSE\n"
                                                /* Clamping */
                                                "UIF TEMP[0].yyyy\n"
@@ -1543,7 +1557,7 @@ static void r600_create_query_result_shader(struct r600_common_context *rctx)
                                                        "UMIN TEMP[0].x, TEMP[0].xxxx, IMM[0].zzzz\n"
                                                "ENDIF\n"
 
-                                               "STORE BUFFER[2].x, IMM[0].xxxx, TEMP[0].xxxx\n"
+                                               "STORE BUFFER[2].x, CONST[0][1].wwww, TEMP[0].xxxx\n"
                                        "ENDIF\n"
                                "ENDIF\n"
                        "ENDIF\n"
@@ -1611,6 +1625,8 @@ static void r600_query_hw_get_result_resource(struct r600_common_context *rctx,
                uint32_t fence_offset;
                uint32_t pair_stride;
                uint32_t pair_count;
+               uint32_t buffer_offset;
+               uint32_t buffer0_offset;
        } consts;
 
        if (!rctx->query_result_shader) {
@@ -1656,7 +1672,8 @@ static void r600_query_hw_get_result_resource(struct r600_common_context *rctx,
        consts.config = 0;
        if (index < 0)
                consts.config |= 4;
-       if (query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE)
+       if (query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE ||
+           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE)
                consts.config |= 8;
        else if (query->b.type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
                 query->b.type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE)
@@ -1696,18 +1713,20 @@ static void r600_query_hw_get_result_resource(struct r600_common_context *rctx,
                        params.start_offset += qbuf->results_end - query->result_size;
                }
 
-               rctx->b.set_constant_buffer(&rctx->b, PIPE_SHADER_COMPUTE, 0, &constant_buffer);
-
                ssbo[0].buffer = &qbuf->buf->b.b;
-               ssbo[0].buffer_offset = params.start_offset;
-               ssbo[0].buffer_size = qbuf->results_end - params.start_offset;
-
+               ssbo[0].buffer_offset = params.start_offset & ~0xff;
+               ssbo[0].buffer_size = qbuf->results_end - ssbo[0].buffer_offset;
+               consts.buffer0_offset = (params.start_offset & 0xff);
                if (!qbuf->previous) {
+
                        ssbo[2].buffer = resource;
-                       ssbo[2].buffer_offset = offset;
-                       ssbo[2].buffer_size = 8;
+                       ssbo[2].buffer_offset = offset & ~0xff;
+                       ssbo[2].buffer_size = offset + 8;
+                       consts.buffer_offset = (offset & 0xff);
+               } else
+                       consts.buffer_offset = 0;
 
-               }
+               rctx->b.set_constant_buffer(&rctx->b, PIPE_SHADER_COMPUTE, 0, &constant_buffer);
 
                rctx->b.set_shader_buffers(&rctx->b, PIPE_SHADER_COMPUTE, 0, 3, ssbo);
 
@@ -1721,7 +1740,7 @@ static void r600_query_hw_get_result_resource(struct r600_common_context *rctx,
                        va = qbuf->buf->gpu_address + qbuf->results_end - query->result_size;
                        va += params.fence_offset;
 
-                       r600_gfx_wait_fence(rctx, va, 0x80000000, 0x80000000);
+                       r600_gfx_wait_fence(rctx, qbuf->buf, va, 0x80000000, 0x80000000);
                }
 
                rctx->b.launch_grid(&rctx->b, &grid);
index cf66978120273713392d5b1acf146490e31f8d77..3344bcb76a7b3ca787797ddf5041e6fbda53c3ef 100644 (file)
@@ -770,7 +770,7 @@ static int single_alu_op3(struct r600_shader_ctx *ctx, int op,
        int r;
 
        /* validate this for other ops */
-       assert(op == ALU_OP3_MULADD_UINT24 || op == ALU_OP3_CNDE_INT);
+       assert(op == ALU_OP3_MULADD_UINT24 || op == ALU_OP3_CNDE_INT || op == ALU_OP3_BFE_UINT);
        memset(&alu, 0, sizeof(struct r600_bytecode_alu));
        alu.op = op;
        alu.src[0].sel = src0_sel;
@@ -9457,7 +9457,8 @@ static int tgsi_opdst(struct r600_shader_ctx *ctx)
        return 0;
 }
 
-static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode, int alu_type)
+static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode, int alu_type,
+                          struct r600_bytecode_alu_src *src)
 {
        struct r600_bytecode_alu alu;
        int r;
@@ -9471,7 +9472,7 @@ static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode, int alu_type
        alu.dst.write = 1;
        alu.dst.chan = 0;
 
-       r600_bytecode_src(&alu.src[0], &ctx->src[0], 0);
+       alu.src[0] = *src;
        alu.src[1].sel = V_SQ_ALU_SRC_0;
        alu.src[1].chan = 0;
 
@@ -9697,7 +9698,8 @@ static void break_loop_on_flag(struct r600_shader_ctx *ctx, unsigned fc_sp)
 }
 #endif
 
-static int emit_if(struct r600_shader_ctx *ctx, int opcode)
+static int emit_if(struct r600_shader_ctx *ctx, int opcode,
+                  struct r600_bytecode_alu_src *src)
 {
        int alu_type = CF_OP_ALU_PUSH_BEFORE;
 
@@ -9711,7 +9713,7 @@ static int emit_if(struct r600_shader_ctx *ctx, int opcode)
                alu_type = CF_OP_ALU;
        }
 
-       emit_logic_pred(ctx, opcode, alu_type);
+       emit_logic_pred(ctx, opcode, alu_type, src);
 
        r600_bytecode_add_cfinst(ctx->bc, CF_OP_JUMP);
 
@@ -9723,12 +9725,17 @@ static int emit_if(struct r600_shader_ctx *ctx, int opcode)
 
 static int tgsi_if(struct r600_shader_ctx *ctx)
 {
-       return emit_if(ctx, ALU_OP2_PRED_SETNE);
+       struct r600_bytecode_alu_src alu_src;
+       r600_bytecode_src(&alu_src, &ctx->src[0], 0);
+
+       return emit_if(ctx, ALU_OP2_PRED_SETNE, &alu_src);
 }
 
 static int tgsi_uif(struct r600_shader_ctx *ctx)
 {
-       return emit_if(ctx, ALU_OP2_PRED_SETNE_INT);
+       struct r600_bytecode_alu_src alu_src;
+       r600_bytecode_src(&alu_src, &ctx->src[0], 0);
+       return emit_if(ctx, ALU_OP2_PRED_SETNE_INT, &alu_src);
 }
 
 static int tgsi_else(struct r600_shader_ctx *ctx)
@@ -10077,6 +10084,684 @@ static int tgsi_clock(struct r600_shader_ctx *ctx)
        return 0;
 }
 
+static int emit_u64add(struct r600_shader_ctx *ctx, int op,
+                      int treg,
+                      int src0_sel, int src0_chan,
+                      int src1_sel, int src1_chan)
+{
+       struct r600_bytecode_alu alu;
+       int r;
+       int opc;
+
+       if (op == ALU_OP2_ADD_INT)
+               opc = ALU_OP2_ADDC_UINT;
+       else
+               opc = ALU_OP2_SUBB_UINT;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;            ;
+       alu.dst.sel = treg;
+       alu.dst.chan = 0;
+       alu.dst.write = 1;
+       alu.src[0].sel = src0_sel;
+       alu.src[0].chan = src0_chan + 0;
+       alu.src[1].sel = src1_sel;
+       alu.src[1].chan = src1_chan + 0;
+       alu.src[1].neg = 0;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;
+       alu.dst.sel = treg;
+       alu.dst.chan = 1;
+       alu.dst.write = 1;
+       alu.src[0].sel = src0_sel;
+       alu.src[0].chan = src0_chan + 1;
+       alu.src[1].sel = src1_sel;
+       alu.src[1].chan = src1_chan + 1;
+       alu.src[1].neg = 0;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = opc;
+       alu.dst.sel = treg;
+       alu.dst.chan = 2;
+       alu.dst.write = 1;
+       alu.last = 1;
+       alu.src[0].sel = src0_sel;
+       alu.src[0].chan = src0_chan + 0;
+       alu.src[1].sel = src1_sel;
+       alu.src[1].chan = src1_chan + 0;
+       alu.src[1].neg = 0;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;
+       alu.dst.sel = treg;
+       alu.dst.chan = 1;
+       alu.dst.write = 1;
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 1;
+       alu.src[1].sel = treg;
+       alu.src[1].chan = 2;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       return 0;
+}
+
+static int egcm_u64add(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bytecode_alu alu;
+       int r;
+       int treg = ctx->temp_reg;
+       int op = ALU_OP2_ADD_INT, opc = ALU_OP2_ADDC_UINT;
+
+       if (ctx->src[1].neg) {
+               op = ALU_OP2_SUB_INT;
+               opc = ALU_OP2_SUBB_UINT;
+       }
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;            ;
+       alu.dst.sel = treg;
+       alu.dst.chan = 0;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 0);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 0);
+       alu.src[1].neg = 0;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;
+       alu.dst.sel = treg;
+       alu.dst.chan = 1;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 1);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 1);
+       alu.src[1].neg = 0;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = opc              ;
+       alu.dst.sel = treg;
+       alu.dst.chan = 2;
+       alu.dst.write = 1;
+       alu.last = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 0);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 0);
+       alu.src[1].neg = 0;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;
+       tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 1;
+       alu.src[1].sel = treg;
+       alu.src[1].chan = 2;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP1_MOV;
+       tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 0;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       return 0;
+}
+
+/* result.y = mul_high a, b
+   result.x = mul a,b
+   result.y += a.x * b.y + a.y * b.x;
+*/
+static int egcm_u64mul(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bytecode_alu alu;
+       int r;
+       int treg = ctx->temp_reg;
+
+       /* temp.x = mul_lo a.x, b.x */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_MULLO_UINT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 0;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 0);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 0);
+       r = emit_mul_int_op(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* temp.y = mul_hi a.x, b.x */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_MULHI_UINT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 1;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 0);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 0);
+       r = emit_mul_int_op(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* temp.z = mul a.x, b.y */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_MULLO_UINT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 2;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 0);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 1);
+       r = emit_mul_int_op(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* temp.w = mul a.y, b.x */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_MULLO_UINT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 3;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 1);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 0);
+       r = emit_mul_int_op(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* temp.z = temp.z + temp.w */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_ADD_INT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 2;
+       alu.dst.write = 1;
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 2;
+       alu.src[1].sel = treg;
+       alu.src[1].chan = 3;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* temp.y = temp.y + temp.z */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_ADD_INT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 1;
+       alu.dst.write = 1;
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 1;
+       alu.src[1].sel = treg;
+       alu.src[1].chan = 2;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* dst.x = temp.x */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP1_MOV;
+       tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 0;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* dst.y = temp.y */
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP1_MOV;
+       tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 1;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static int emit_u64sge(struct r600_shader_ctx *ctx,
+                      int treg,
+                      int src0_sel, int src0_base_chan,
+                      int src1_sel, int src1_base_chan)
+{
+       int r;
+       /* for 64-bit sge */
+       /* result = (src0.y > src1.y) || ((src0.y == src1.y) && src0.x >= src1.x)) */
+       r = single_alu_op2(ctx, ALU_OP2_SETGT_UINT,
+                          treg, 1,
+                          src0_sel, src0_base_chan + 1,
+                          src1_sel, src1_base_chan + 1);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP2_SETGE_UINT,
+                          treg, 0,
+                          src0_sel, src0_base_chan,
+                          src1_sel, src1_base_chan);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP2_SETE_INT,
+                          treg, 2,
+                          src0_sel, src0_base_chan + 1,
+                          src1_sel, src1_base_chan + 1);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP2_AND_INT,
+                          treg, 0,
+                          treg, 0,
+                          treg, 2);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP2_OR_INT,
+                          treg, 0,
+                          treg, 0,
+                          treg, 1);
+       if (r)
+               return r;
+       return 0;
+}
+
+/* this isn't a complete div it's just enough for qbo shader to work */
+static int egcm_u64div(struct r600_shader_ctx *ctx)
+{
+       struct r600_bytecode_alu alu;
+       struct r600_bytecode_alu_src alu_num_hi, alu_num_lo, alu_denom_hi, alu_denom_lo, alu_src;
+       int r, i;
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+
+       /* make sure we are dividing my a const with 0 in the high bits */
+       if (ctx->src[1].sel != V_SQ_ALU_SRC_LITERAL)
+               return -1;
+       if (ctx->src[1].value[ctx->src[1].swizzle[1]] != 0)
+               return -1;
+       /* make sure we are doing one division */
+       if (inst->Dst[0].Register.WriteMask != 0x3)
+               return -1;
+
+       /* emit_if uses ctx->temp_reg so we can't */
+       int treg = r600_get_temp(ctx);
+       int tmp_num = r600_get_temp(ctx);
+       int sub_tmp = r600_get_temp(ctx);
+
+       /* tmp quot are tmp_num.zw */
+       r600_bytecode_src(&alu_num_lo, &ctx->src[0], 0);
+       r600_bytecode_src(&alu_num_hi, &ctx->src[0], 1);
+       r600_bytecode_src(&alu_denom_lo, &ctx->src[1], 0);
+       r600_bytecode_src(&alu_denom_hi, &ctx->src[1], 1);
+
+       /* MOV tmp_num.xy, numerator */
+       r = single_alu_op2(ctx, ALU_OP1_MOV,
+                          tmp_num, 0,
+                          alu_num_lo.sel, alu_num_lo.chan,
+                          0, 0);
+       if (r)
+               return r;
+       r = single_alu_op2(ctx, ALU_OP1_MOV,
+                          tmp_num, 1,
+                          alu_num_hi.sel, alu_num_hi.chan,
+                          0, 0);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP1_MOV,
+                          tmp_num, 2,
+                          V_SQ_ALU_SRC_LITERAL, 0,
+                          0, 0);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP1_MOV,
+                          tmp_num, 3,
+                          V_SQ_ALU_SRC_LITERAL, 0,
+                          0, 0);
+       if (r)
+               return r;
+
+       /* treg 0 is log2_denom */
+       /* normally this gets the MSB for the denom high value
+          - however we know this will always be 0 here. */
+       r = single_alu_op2(ctx,
+                          ALU_OP1_MOV,
+                          treg, 0,
+                          V_SQ_ALU_SRC_LITERAL, 32,
+                          0, 0);
+       if (r)
+               return r;
+
+       /* normally check demon hi for 0, but we know it is already */
+       /* t0.z = num_hi >= denom_lo */
+       r = single_alu_op2(ctx,
+                          ALU_OP2_SETGE_UINT,
+                          treg, 1,
+                          alu_num_hi.sel, alu_num_hi.chan,
+                          V_SQ_ALU_SRC_LITERAL, alu_denom_lo.value);
+       if (r)
+               return r;
+
+       memset(&alu_src, 0, sizeof(alu_src));
+       alu_src.sel = treg;
+       alu_src.chan = 1;
+       r = emit_if(ctx, ALU_OP2_PRED_SETNE_INT, &alu_src);
+       if (r)
+               return r;
+
+       /* for loops in here */
+       /* get msb t0.x = msb(src[1].x) first */
+       int msb_lo = util_last_bit(alu_denom_lo.value);
+       r = single_alu_op2(ctx, ALU_OP1_MOV,
+                          treg, 0,
+                          V_SQ_ALU_SRC_LITERAL, msb_lo,
+                          0, 0);
+       if (r)
+               return r;
+
+       /* unroll the asm here */
+       for (i = 0; i < 31; i++) {
+               r = single_alu_op2(ctx, ALU_OP2_SETGE_UINT,
+                                  treg, 2,
+                                  V_SQ_ALU_SRC_LITERAL, i,
+                                  treg, 0);
+               if (r)
+                       return r;
+
+               /* we can do this on the CPU */
+               uint32_t denom_lo_shl = alu_denom_lo.value << (31 - i);
+               /* t0.z = tmp_num.y >= t0.z */
+               r = single_alu_op2(ctx, ALU_OP2_SETGE_UINT,
+                                  treg, 1,
+                                  tmp_num, 1,
+                                  V_SQ_ALU_SRC_LITERAL, denom_lo_shl);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP2_AND_INT,
+                                  treg, 1,
+                                  treg, 1,
+                                  treg, 2);
+               if (r)
+                       return r;
+
+               memset(&alu_src, 0, sizeof(alu_src));
+               alu_src.sel = treg;
+               alu_src.chan = 1;
+               r = emit_if(ctx, ALU_OP2_PRED_SETNE_INT, &alu_src);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP2_SUB_INT,
+                                  tmp_num, 1,
+                                  tmp_num, 1,
+                                  V_SQ_ALU_SRC_LITERAL, denom_lo_shl);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP2_OR_INT,
+                                  tmp_num, 3,
+                                  tmp_num, 3,
+                                  V_SQ_ALU_SRC_LITERAL, 1U << (31 - i));
+               if (r)
+                       return r;
+
+               r = tgsi_endif(ctx);
+               if (r)
+                       return r;
+       }
+
+       /* log2_denom is always <= 31, so manually peel the last loop
+        * iteration.
+        */
+       r = single_alu_op2(ctx, ALU_OP2_SETGE_UINT,
+                          treg, 1,
+                          tmp_num, 1,
+                          V_SQ_ALU_SRC_LITERAL, alu_denom_lo.value);
+       if (r)
+               return r;
+
+       memset(&alu_src, 0, sizeof(alu_src));
+       alu_src.sel = treg;
+       alu_src.chan = 1;
+       r = emit_if(ctx, ALU_OP2_PRED_SETNE_INT, &alu_src);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP2_SUB_INT,
+                          tmp_num, 1,
+                          tmp_num, 1,
+                          V_SQ_ALU_SRC_LITERAL, alu_denom_lo.value);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP2_OR_INT,
+                          tmp_num, 3,
+                          tmp_num, 3,
+                          V_SQ_ALU_SRC_LITERAL, 1U);
+       if (r)
+               return r;
+       r = tgsi_endif(ctx);
+       if (r)
+               return r;
+
+       r = tgsi_endif(ctx);
+       if (r)
+               return r;
+
+       /* onto the second loop to unroll */
+       for (i = 0; i < 31; i++) {
+               r = single_alu_op2(ctx, ALU_OP2_SETGE_UINT,
+                                  treg, 1,
+                                  V_SQ_ALU_SRC_LITERAL, (63 - (31 - i)),
+                                  treg, 0);
+               if (r)
+                       return r;
+
+               uint64_t denom_shl = (uint64_t)alu_denom_lo.value << (31 - i);
+               r = single_alu_op2(ctx, ALU_OP1_MOV,
+                                  treg, 2,
+                                  V_SQ_ALU_SRC_LITERAL, (denom_shl & 0xffffffff),
+                                  0, 0);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP1_MOV,
+                                  treg, 3,
+                                  V_SQ_ALU_SRC_LITERAL, (denom_shl >> 32),
+                                  0, 0);
+               if (r)
+                       return r;
+
+               r = emit_u64sge(ctx, sub_tmp,
+                               tmp_num, 0,
+                               treg, 2);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP2_AND_INT,
+                                  treg, 1,
+                                  treg, 1,
+                                  sub_tmp, 0);
+               if (r)
+                       return r;
+
+               memset(&alu_src, 0, sizeof(alu_src));
+               alu_src.sel = treg;
+               alu_src.chan = 1;
+               r = emit_if(ctx, ALU_OP2_PRED_SETNE_INT, &alu_src);
+               if (r)
+                       return r;
+
+
+               r = emit_u64add(ctx, ALU_OP2_SUB_INT,
+                               sub_tmp,
+                               tmp_num, 0,
+                               treg, 2);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP1_MOV,
+                                  tmp_num, 0,
+                                  sub_tmp, 0,
+                                  0, 0);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP1_MOV,
+                                  tmp_num, 1,
+                                  sub_tmp, 1,
+                                  0, 0);
+               if (r)
+                       return r;
+
+               r = single_alu_op2(ctx, ALU_OP2_OR_INT,
+                                  tmp_num, 2,
+                                  tmp_num, 2,
+                                  V_SQ_ALU_SRC_LITERAL, 1U << (31 - i));
+               if (r)
+                       return r;
+
+               r = tgsi_endif(ctx);
+               if (r)
+                       return r;
+       }
+
+       /* log2_denom is always <= 63, so manually peel the last loop
+        * iteration.
+        */
+       uint64_t denom_shl = (uint64_t)alu_denom_lo.value;
+       r = single_alu_op2(ctx, ALU_OP1_MOV,
+                          treg, 2,
+                          V_SQ_ALU_SRC_LITERAL, (denom_shl & 0xffffffff),
+                          0, 0);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP1_MOV,
+                          treg, 3,
+                          V_SQ_ALU_SRC_LITERAL, (denom_shl >> 32),
+                          0, 0);
+       if (r)
+               return r;
+
+       r = emit_u64sge(ctx, sub_tmp,
+                       tmp_num, 0,
+                       treg, 2);
+       if (r)
+               return r;
+
+       memset(&alu_src, 0, sizeof(alu_src));
+       alu_src.sel = sub_tmp;
+       alu_src.chan = 0;
+       r = emit_if(ctx, ALU_OP2_PRED_SETNE_INT, &alu_src);
+       if (r)
+               return r;
+
+       r = emit_u64add(ctx, ALU_OP2_SUB_INT,
+                       sub_tmp,
+                       tmp_num, 0,
+                       treg, 2);
+       if (r)
+               return r;
+
+       r = single_alu_op2(ctx, ALU_OP2_OR_INT,
+                          tmp_num, 2,
+                          tmp_num, 2,
+                          V_SQ_ALU_SRC_LITERAL, 1U);
+       if (r)
+               return r;
+       r = tgsi_endif(ctx);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP1_MOV;
+       tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
+       alu.src[0].sel = tmp_num;
+       alu.src[0].chan = 2;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP1_MOV;
+       tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
+       alu.src[0].sel = tmp_num;
+       alu.src[0].chan = 3;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       return 0;
+}
+
+static int egcm_u64sne(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bytecode_alu alu;
+       int r;
+       int treg = ctx->temp_reg;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_SETNE_INT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 0;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 0);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 0);
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_SETNE_INT;
+       alu.dst.sel = treg;
+       alu.dst.chan = 1;
+       alu.dst.write = 1;
+       r600_bytecode_src(&alu.src[0], &ctx->src[0], 1);
+       r600_bytecode_src(&alu.src[1], &ctx->src[1], 1);
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = ALU_OP2_OR_INT;
+       tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
+       alu.src[0].sel = treg;
+       alu.src[0].chan = 0;
+       alu.src[1].sel = treg;
+       alu.src[1].chan = 1;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       return 0;
+}
+
 static const struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
        [TGSI_OPCODE_ARL]       = { ALU_OP0_NOP, tgsi_r600_arl},
        [TGSI_OPCODE_MOV]       = { ALU_OP1_MOV, tgsi_op2},
@@ -10497,6 +11182,10 @@ static const struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] =
        [TGSI_OPCODE_D2U]       = { ALU_OP1_FLT_TO_UINT, egcm_double_to_int},
        [TGSI_OPCODE_U2D]       = { ALU_OP1_UINT_TO_FLT, egcm_int_to_double},
        [TGSI_OPCODE_DRSQ]      = { ALU_OP2_RECIPSQRT_64, cayman_emit_double_instr},
+       [TGSI_OPCODE_U64SNE]    = { ALU_OP0_NOP, egcm_u64sne },
+       [TGSI_OPCODE_U64ADD]    = { ALU_OP0_NOP, egcm_u64add },
+       [TGSI_OPCODE_U64MUL]    = { ALU_OP0_NOP, egcm_u64mul },
+       [TGSI_OPCODE_U64DIV]    = { ALU_OP0_NOP, egcm_u64div },
        [TGSI_OPCODE_LAST]      = { ALU_OP0_NOP, tgsi_unsupported},
 };
 
@@ -10719,5 +11408,9 @@ static const struct r600_shader_tgsi_instruction cm_shader_tgsi_instruction[] =
        [TGSI_OPCODE_D2U]       = { ALU_OP1_FLT_TO_UINT, egcm_double_to_int},
        [TGSI_OPCODE_U2D]       = { ALU_OP1_UINT_TO_FLT, egcm_int_to_double},
        [TGSI_OPCODE_DRSQ]      = { ALU_OP2_RECIPSQRT_64, cayman_emit_double_instr},
+       [TGSI_OPCODE_U64SNE]    = { ALU_OP0_NOP, egcm_u64sne },
+       [TGSI_OPCODE_U64ADD]    = { ALU_OP0_NOP, egcm_u64add },
+       [TGSI_OPCODE_U64MUL]    = { ALU_OP0_NOP, egcm_u64mul },
+       [TGSI_OPCODE_U64DIV]    = { ALU_OP0_NOP, egcm_u64div },
        [TGSI_OPCODE_LAST]      = { ALU_OP0_NOP, tgsi_unsupported},
 };
index b49b05608d6c7b788709df91611a002ff2dbdfa1..d9c74b5f47c3b227b34635da6b306d16fe6a8761 100644 (file)
@@ -3219,6 +3219,7 @@ void r600_init_common_state_functions(struct r600_context *rctx)
        rctx->b.b.texture_barrier = r600_texture_barrier;
        rctx->b.b.set_stream_output_targets = r600_set_streamout_targets;
        rctx->b.b.set_active_query_state = r600_set_active_query_state;
+
        rctx->b.b.draw_vbo = r600_draw_vbo;
        rctx->b.invalidate_buffer = r600_invalidate_buffer;
        rctx->b.need_gfx_cs_space = r600_need_gfx_cs_space;
index 0d04708043e0f6d8970895bd047e0909596e0b79..0717eab96174db7a545cf850a08eb3271fb0e8fd 100644 (file)
 #define                SURFACE_BASE_UPDATE_COLOR_NUM(x) (((1 << x) - 1) << 1)
 #define                SURFACE_BASE_UPDATE_STRMOUT(x) (0x200 << (x))
 
+#define EVENT_TYPE_CS_PARTIAL_FLUSH            0x07 /* eg+ */
 #define EVENT_TYPE_PS_PARTIAL_FLUSH            0x10
 #define EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT 0x14
 #define EVENT_TYPE_ZPASS_DONE                  0x15