1afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/* 2afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Copyright 2016 Red Hat. 3afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * 4afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 5afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * copy of this software and associated documentation files (the "Software"), 6afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * to deal in the Software without restriction, including without limitation 7afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * on the rights to use, copy, modify, merge, publish, distribute, sub 8afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * license, and/or sell copies of the Software, and to permit persons to whom 9afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * the Software is furnished to do so, subject to the following conditions: 10afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * 11afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * The above copyright notice and this permission notice (including the next 12afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * paragraph) shall be included in all copies or substantial portions of the 13afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Software. 14afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * 15afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * USE OR OTHER DEALINGS IN THE SOFTWARE. 22afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */ 23afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 24afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "sp_context.h" 25afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "sp_buffer.h" 26afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "sp_texture.h" 27afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 28afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "util/u_format.h" 29afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 30afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic bool 31afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlieget_dimensions(const struct pipe_shader_buffer *bview, 32afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct softpipe_resource *spr, 33afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned *width) 34afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{ 35afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie *width = bview->buffer_size; 36afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie /* 37afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Bounds check the buffer size from the view 38afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * and the buffer size from the underlying buffer. 39afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */ 40afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (*width > spr->base.width0) 41afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return false; 42afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return true; 43afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie} 44afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 45afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/* 46afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement the image LOAD operation. 47afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */ 48afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void 49afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_load(const struct tgsi_buffer *buffer, 50afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct tgsi_buffer_params *params, 51afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const int s[TGSI_QUAD_SIZE], 52afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 53afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{ 54afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer; 55afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct pipe_shader_buffer *bview; 56afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct softpipe_resource *spr; 57afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned width; 58afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int c, j; 59afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned char *data_ptr; 60afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT); 61afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 626d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen if (params->unit >= PIPE_MAX_SHADER_BUFFERS) 63afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie goto fail_write_all_zero; 64afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 65afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie bview = &sp_buf->sp_bview[params->unit]; 66afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie spr = softpipe_resource(bview->buffer); 67afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!spr) 68afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie goto fail_write_all_zero; 69afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 70afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!get_dimensions(bview, spr, &width)) 71afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 72afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 73afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (j = 0; j < TGSI_QUAD_SIZE; j++) { 74afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int s_coord; 75afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie bool fill_zero = false; 76afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie uint32_t sdata[4]; 77afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 78afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!(params->execmask & (1 << j))) 79afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie fill_zero = true; 80afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 81afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie s_coord = s[j]; 82afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (s_coord >= width) 83afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie fill_zero = true; 84afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 85afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (fill_zero) { 86afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) 87afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie rgba[c][j] = 0; 88afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie continue; 89afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 90afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord; 91afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 92afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie format_desc->fetch_rgba_uint(sdata, data_ptr, 0, 0); 93afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[j] = sdata[0]; 94afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie data_ptr += 4; 95afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 96afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 97afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 98afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliefail_write_all_zero: 99afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4); 100afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 101afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie} 102afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 103afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/* 104afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement the buffer STORE operation. 105afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */ 106afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void 107afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_store(const struct tgsi_buffer *buffer, 108afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct tgsi_buffer_params *params, 109afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const int s[TGSI_QUAD_SIZE], 110afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 111afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{ 112afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer; 113afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct pipe_shader_buffer *bview; 114afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct softpipe_resource *spr; 115afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned width; 116afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned char *data_ptr; 117afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int j, c; 118afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT); 119afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 1206d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen if (params->unit >= PIPE_MAX_SHADER_BUFFERS) 121afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 122afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 123afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie bview = &sp_buf->sp_bview[params->unit]; 124afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie spr = softpipe_resource(bview->buffer); 125afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!spr) 126afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 127afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 128afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!get_dimensions(bview, spr, &width)) 129afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 130afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 131afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (j = 0; j < TGSI_QUAD_SIZE; j++) { 132afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int s_coord; 133afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 134afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!(params->execmask & (1 << j))) 135afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie continue; 136afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 137afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie s_coord = s[j]; 138afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (s_coord >= width) 139afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie continue; 140afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 141afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord; 142afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 143afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 144afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (params->writemask & (1 << c)) { 145afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp[4]; 146afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned char *dptr = data_ptr + (c * 4); 147afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie temp[0] = ((uint32_t *)rgba[c])[j]; 148afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1); 149afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 150afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 151afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 152afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie} 153afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 154afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/* 155afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement atomic operations on unsigned integers. 156afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */ 157afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void 158afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliehandle_op_uint(const struct pipe_shader_buffer *bview, 159afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie bool just_read, 160afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned char *data_ptr, 161afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie uint qi, 162afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned opcode, 163afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned writemask, 164afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 165afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 166afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{ 167afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie uint c; 168afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT); 169afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned sdata[4]; 170afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 171afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 172afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp[4]; 173afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned char *dptr = data_ptr + (c * 4); 174afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie format_desc->fetch_rgba_uint(temp, dptr, 0, 0); 175afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] = temp[0]; 176afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 177afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 178afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (just_read) { 179afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 180afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = sdata[c]; 181afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 182afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 183afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 184afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 185afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie switch (opcode) { 186afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMUADD: 187afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 188afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp = sdata[c]; 189afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] += ((uint32_t *)rgba[c])[qi]; 190afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = temp; 191afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 192afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 193afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMXCHG: 194afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 195afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp = sdata[c]; 196afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] = ((uint32_t *)rgba[c])[qi]; 197afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = temp; 198afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 199afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 200afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMCAS: 201afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 202afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned dst_x = sdata[c]; 203afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned cmp_x = ((uint32_t *)rgba[c])[qi]; 204afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned src_x = ((uint32_t *)rgba2[c])[qi]; 205afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp = sdata[c]; 206afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] = (dst_x == cmp_x) ? src_x : dst_x; 207afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = temp; 208afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 209afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 210afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMAND: 211afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 212afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp = sdata[c]; 213afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] &= ((uint32_t *)rgba[c])[qi]; 214afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = temp; 215afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 216afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 217afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMOR: 218afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 219afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp = sdata[c]; 220afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] |= ((uint32_t *)rgba[c])[qi]; 221afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = temp; 222afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 223afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 224afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMXOR: 225afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 226afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp = sdata[c]; 227afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] ^= ((uint32_t *)rgba[c])[qi]; 228afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = temp; 229afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 230afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 231afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMUMIN: 232afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 233afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned dst_x = sdata[c]; 234afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned src_x = ((uint32_t *)rgba[c])[qi]; 235afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] = MIN2(dst_x, src_x); 236afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = dst_x; 237afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 238afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 239afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMUMAX: 240afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 241afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned dst_x = sdata[c]; 242afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned src_x = ((uint32_t *)rgba[c])[qi]; 243afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] = MAX2(dst_x, src_x); 244afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = dst_x; 245afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 246afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 247afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMIMIN: 248afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 249afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int dst_x = sdata[c]; 250afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int src_x = ((uint32_t *)rgba[c])[qi]; 251afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] = MIN2(dst_x, src_x); 252afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = dst_x; 253afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 254afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 255afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie case TGSI_OPCODE_ATOMIMAX: 256afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 257afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int dst_x = sdata[c]; 258afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int src_x = ((uint32_t *)rgba[c])[qi]; 259afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie sdata[c] = MAX2(dst_x, src_x); 260afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie ((uint32_t *)rgba[c])[qi] = dst_x; 261afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 262afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 263afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie default: 264afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie assert(!"Unexpected TGSI opcode in sp_tgsi_op"); 265afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie break; 266afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 267afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 268afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 269afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (writemask & (1 << c)) { 270afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned temp[4]; 271afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned char *dptr = data_ptr + (c * 4); 272afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie temp[0] = sdata[c]; 273afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1); 274afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 275afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 276afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie} 277afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 278afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/* 279afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement atomic buffer operations. 280afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */ 281afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void 282afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_op(const struct tgsi_buffer *buffer, 283afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct tgsi_buffer_params *params, 284afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned opcode, 285afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const int s[TGSI_QUAD_SIZE], 286afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 287afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 288afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{ 289afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer; 290afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct pipe_shader_buffer *bview; 291afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct softpipe_resource *spr; 292afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned width; 293afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int j, c; 294afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie unsigned char *data_ptr; 295afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 2966d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen if (params->unit >= PIPE_MAX_SHADER_BUFFERS) 297afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 298afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 299afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie bview = &sp_buf->sp_bview[params->unit]; 300afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie spr = softpipe_resource(bview->buffer); 301afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!spr) 302afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie goto fail_write_all_zero; 303afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 304afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!get_dimensions(bview, spr, &width)) 305afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie goto fail_write_all_zero; 306afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 307afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (j = 0; j < TGSI_QUAD_SIZE; j++) { 308afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int s_coord; 309afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie bool just_read = false; 310afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 311afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie s_coord = s[j]; 312afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (s_coord >= width) { 313afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie for (c = 0; c < 4; c++) { 314afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie rgba[c][j] = 0; 315afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 316afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie continue; 317afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 318afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 319afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie /* just readback the value for atomic if execmask isn't set */ 320afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!(params->execmask & (1 << j))) { 321afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie just_read = true; 322afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 323afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 324afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord; 325afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie /* we should see atomic operations on r32 formats */ 326afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 327afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie handle_op_uint(bview, just_read, data_ptr, j, 328afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie opcode, params->writemask, rgba, rgba2); 329afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie } 330afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 331afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliefail_write_all_zero: 332afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4); 333afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 334afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie} 335afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 336afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/* 337afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * return size of the attached buffer for RESQ opcode. 338afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */ 339afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void 340afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_get_dims(const struct tgsi_buffer *buffer, 341afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie const struct tgsi_buffer_params *params, 342afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie int *dim) 343afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{ 344afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer; 345afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct pipe_shader_buffer *bview; 346afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct softpipe_resource *spr; 347afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 3486d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen if (params->unit >= PIPE_MAX_SHADER_BUFFERS) 349afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 350afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 351afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie bview = &sp_buf->sp_bview[params->unit]; 352afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie spr = softpipe_resource(bview->buffer); 353afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!spr) 354afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return; 355afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 356afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie *dim = bview->buffer_size; 357afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie} 358afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 359afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestruct sp_tgsi_buffer * 360afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_create_tgsi_buffer(void) 361afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{ 362afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie struct sp_tgsi_buffer *buf = CALLOC_STRUCT(sp_tgsi_buffer); 363afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie if (!buf) 364afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return NULL; 365afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie 366afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie buf->base.load = sp_tgsi_load; 367afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie buf->base.store = sp_tgsi_store; 368afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie buf->base.op = sp_tgsi_op; 369afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie buf->base.get_dims = sp_tgsi_get_dims; 370afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie return buf; 371afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie}; 372