1b8e80941Smrg/* 2b8e80941Smrg * Copyright 2007 VMware, Inc. 3b8e80941Smrg * Copyright 2016 Advanced Micro Devices, Inc. 4b8e80941Smrg * 5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 7b8e80941Smrg * to deal in the Software without restriction, including without limitation 8b8e80941Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 9b8e80941Smrg * license, and/or sell copies of the Software, and to permit persons to whom 10b8e80941Smrg * the Software is furnished to do so, subject to the following conditions: 11b8e80941Smrg * 12b8e80941Smrg * The above copyright notice and this permission notice (including the next 13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 14b8e80941Smrg * Software. 15b8e80941Smrg * 16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19b8e80941Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20b8e80941Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21b8e80941Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22b8e80941Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 23b8e80941Smrg */ 24b8e80941Smrg 25b8e80941Smrg/** 26b8e80941Smrg * \file 27b8e80941Smrg * 28b8e80941Smrg * Common helper functions for PBO up- and downloads. 29b8e80941Smrg */ 30b8e80941Smrg 31b8e80941Smrg#include "state_tracker/st_context.h" 32b8e80941Smrg#include "state_tracker/st_nir.h" 33b8e80941Smrg#include "state_tracker/st_pbo.h" 34b8e80941Smrg#include "state_tracker/st_cb_bufferobjects.h" 35b8e80941Smrg 36b8e80941Smrg#include "pipe/p_context.h" 37b8e80941Smrg#include "pipe/p_defines.h" 38b8e80941Smrg#include "pipe/p_screen.h" 39b8e80941Smrg#include "cso_cache/cso_context.h" 40b8e80941Smrg#include "tgsi/tgsi_ureg.h" 41b8e80941Smrg#include "util/u_format.h" 42b8e80941Smrg#include "util/u_inlines.h" 43b8e80941Smrg#include "util/u_upload_mgr.h" 44b8e80941Smrg 45b8e80941Smrg#include "compiler/nir/nir_builder.h" 46b8e80941Smrg 47b8e80941Smrg/* Conversion to apply in the fragment shader. */ 48b8e80941Smrgenum st_pbo_conversion { 49b8e80941Smrg ST_PBO_CONVERT_NONE = 0, 50b8e80941Smrg ST_PBO_CONVERT_UINT_TO_SINT, 51b8e80941Smrg ST_PBO_CONVERT_SINT_TO_UINT, 52b8e80941Smrg 53b8e80941Smrg ST_NUM_PBO_CONVERSIONS 54b8e80941Smrg}; 55b8e80941Smrg 56b8e80941Smrg/* Final setup of buffer addressing information. 57b8e80941Smrg * 58b8e80941Smrg * buf_offset is in pixels. 59b8e80941Smrg * 60b8e80941Smrg * Returns false if something (e.g. alignment) prevents PBO upload/download. 61b8e80941Smrg */ 62b8e80941Smrgbool 63b8e80941Smrgst_pbo_addresses_setup(struct st_context *st, 64b8e80941Smrg struct pipe_resource *buf, intptr_t buf_offset, 65b8e80941Smrg struct st_pbo_addresses *addr) 66b8e80941Smrg{ 67b8e80941Smrg unsigned skip_pixels; 68b8e80941Smrg 69b8e80941Smrg /* Check alignment against texture buffer requirements. */ 70b8e80941Smrg { 71b8e80941Smrg unsigned ofs = (buf_offset * addr->bytes_per_pixel) % st->ctx->Const.TextureBufferOffsetAlignment; 72b8e80941Smrg if (ofs != 0) { 73b8e80941Smrg if (ofs % addr->bytes_per_pixel != 0) 74b8e80941Smrg return false; 75b8e80941Smrg 76b8e80941Smrg skip_pixels = ofs / addr->bytes_per_pixel; 77b8e80941Smrg buf_offset -= skip_pixels; 78b8e80941Smrg } else { 79b8e80941Smrg skip_pixels = 0; 80b8e80941Smrg } 81b8e80941Smrg } 82b8e80941Smrg 83b8e80941Smrg assert(buf_offset >= 0); 84b8e80941Smrg 85b8e80941Smrg addr->buffer = buf; 86b8e80941Smrg addr->first_element = buf_offset; 87b8e80941Smrg addr->last_element = buf_offset + skip_pixels + addr->width - 1 88b8e80941Smrg + (addr->height - 1 + (addr->depth - 1) * addr->image_height) * addr->pixels_per_row; 89b8e80941Smrg 90b8e80941Smrg if (addr->last_element - addr->first_element > st->ctx->Const.MaxTextureBufferSize - 1) 91b8e80941Smrg return false; 92b8e80941Smrg 93b8e80941Smrg /* This should be ensured by Mesa before calling our callbacks */ 94b8e80941Smrg assert((addr->last_element + 1) * addr->bytes_per_pixel <= buf->width0); 95b8e80941Smrg 96b8e80941Smrg addr->constants.xoffset = -addr->xoffset + skip_pixels; 97b8e80941Smrg addr->constants.yoffset = -addr->yoffset; 98b8e80941Smrg addr->constants.stride = addr->pixels_per_row; 99b8e80941Smrg addr->constants.image_size = addr->pixels_per_row * addr->image_height; 100b8e80941Smrg addr->constants.layer_offset = 0; 101b8e80941Smrg 102b8e80941Smrg return true; 103b8e80941Smrg} 104b8e80941Smrg 105b8e80941Smrg/* Validate and fill buffer addressing information based on GL pixelstore 106b8e80941Smrg * attributes. 107b8e80941Smrg * 108b8e80941Smrg * Returns false if some aspect of the addressing (e.g. alignment) prevents 109b8e80941Smrg * PBO upload/download. 110b8e80941Smrg */ 111b8e80941Smrgbool 112b8e80941Smrgst_pbo_addresses_pixelstore(struct st_context *st, 113b8e80941Smrg GLenum gl_target, bool skip_images, 114b8e80941Smrg const struct gl_pixelstore_attrib *store, 115b8e80941Smrg const void *pixels, 116b8e80941Smrg struct st_pbo_addresses *addr) 117b8e80941Smrg{ 118b8e80941Smrg struct pipe_resource *buf = st_buffer_object(store->BufferObj)->buffer; 119b8e80941Smrg intptr_t buf_offset = (intptr_t) pixels; 120b8e80941Smrg 121b8e80941Smrg if (buf_offset % addr->bytes_per_pixel) 122b8e80941Smrg return false; 123b8e80941Smrg 124b8e80941Smrg /* Convert to texels */ 125b8e80941Smrg buf_offset = buf_offset / addr->bytes_per_pixel; 126b8e80941Smrg 127b8e80941Smrg /* Determine image height */ 128b8e80941Smrg if (gl_target == GL_TEXTURE_1D_ARRAY) { 129b8e80941Smrg addr->image_height = 1; 130b8e80941Smrg } else { 131b8e80941Smrg addr->image_height = store->ImageHeight > 0 ? store->ImageHeight : addr->height; 132b8e80941Smrg } 133b8e80941Smrg 134b8e80941Smrg /* Compute the stride, taking store->Alignment into account */ 135b8e80941Smrg { 136b8e80941Smrg unsigned pixels_per_row = store->RowLength > 0 ? 137b8e80941Smrg store->RowLength : addr->width; 138b8e80941Smrg unsigned bytes_per_row = pixels_per_row * addr->bytes_per_pixel; 139b8e80941Smrg unsigned remainder = bytes_per_row % store->Alignment; 140b8e80941Smrg unsigned offset_rows; 141b8e80941Smrg 142b8e80941Smrg if (remainder > 0) 143b8e80941Smrg bytes_per_row += store->Alignment - remainder; 144b8e80941Smrg 145b8e80941Smrg if (bytes_per_row % addr->bytes_per_pixel) 146b8e80941Smrg return false; 147b8e80941Smrg 148b8e80941Smrg addr->pixels_per_row = bytes_per_row / addr->bytes_per_pixel; 149b8e80941Smrg 150b8e80941Smrg offset_rows = store->SkipRows; 151b8e80941Smrg if (skip_images) 152b8e80941Smrg offset_rows += addr->image_height * store->SkipImages; 153b8e80941Smrg 154b8e80941Smrg buf_offset += store->SkipPixels + addr->pixels_per_row * offset_rows; 155b8e80941Smrg } 156b8e80941Smrg 157b8e80941Smrg if (!st_pbo_addresses_setup(st, buf, buf_offset, addr)) 158b8e80941Smrg return false; 159b8e80941Smrg 160b8e80941Smrg /* Support GL_PACK_INVERT_MESA */ 161b8e80941Smrg if (store->Invert) { 162b8e80941Smrg addr->constants.xoffset += (addr->height - 1) * addr->constants.stride; 163b8e80941Smrg addr->constants.stride = -addr->constants.stride; 164b8e80941Smrg } 165b8e80941Smrg 166b8e80941Smrg return true; 167b8e80941Smrg} 168b8e80941Smrg 169b8e80941Smrg/* For download from a framebuffer, we may have to invert the Y axis. The 170b8e80941Smrg * setup is as follows: 171b8e80941Smrg * - set viewport to inverted, so that the position sysval is correct for 172b8e80941Smrg * texel fetches 173b8e80941Smrg * - this function adjusts the fragment shader's constant buffer to compute 174b8e80941Smrg * the correct destination addresses. 175b8e80941Smrg */ 176b8e80941Smrgvoid 177b8e80941Smrgst_pbo_addresses_invert_y(struct st_pbo_addresses *addr, 178b8e80941Smrg unsigned viewport_height) 179b8e80941Smrg{ 180b8e80941Smrg addr->constants.xoffset += 181b8e80941Smrg (viewport_height - 1 + 2 * addr->constants.yoffset) * addr->constants.stride; 182b8e80941Smrg addr->constants.stride = -addr->constants.stride; 183b8e80941Smrg} 184b8e80941Smrg 185b8e80941Smrg/* Setup all vertex pipeline state, rasterizer state, and fragment shader 186b8e80941Smrg * constants, and issue the draw call for PBO upload/download. 187b8e80941Smrg * 188b8e80941Smrg * The caller is responsible for saving and restoring state, as well as for 189b8e80941Smrg * setting other fragment shader state (fragment shader, samplers), and 190b8e80941Smrg * framebuffer/viewport/DSA/blend state. 191b8e80941Smrg */ 192b8e80941Smrgbool 193b8e80941Smrgst_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr, 194b8e80941Smrg unsigned surface_width, unsigned surface_height) 195b8e80941Smrg{ 196b8e80941Smrg struct cso_context *cso = st->cso_context; 197b8e80941Smrg 198b8e80941Smrg /* Setup vertex and geometry shaders */ 199b8e80941Smrg if (!st->pbo.vs) { 200b8e80941Smrg st->pbo.vs = st_pbo_create_vs(st); 201b8e80941Smrg if (!st->pbo.vs) 202b8e80941Smrg return false; 203b8e80941Smrg } 204b8e80941Smrg 205b8e80941Smrg if (addr->depth != 1 && st->pbo.use_gs && !st->pbo.gs) { 206b8e80941Smrg st->pbo.gs = st_pbo_create_gs(st); 207b8e80941Smrg if (!st->pbo.gs) 208b8e80941Smrg return false; 209b8e80941Smrg } 210b8e80941Smrg 211b8e80941Smrg cso_set_vertex_shader_handle(cso, st->pbo.vs); 212b8e80941Smrg 213b8e80941Smrg cso_set_geometry_shader_handle(cso, addr->depth != 1 ? st->pbo.gs : NULL); 214b8e80941Smrg 215b8e80941Smrg cso_set_tessctrl_shader_handle(cso, NULL); 216b8e80941Smrg 217b8e80941Smrg cso_set_tesseval_shader_handle(cso, NULL); 218b8e80941Smrg 219b8e80941Smrg /* Upload vertices */ 220b8e80941Smrg { 221b8e80941Smrg struct pipe_vertex_buffer vbo = {0}; 222b8e80941Smrg struct pipe_vertex_element velem; 223b8e80941Smrg 224b8e80941Smrg float x0 = (float) addr->xoffset / surface_width * 2.0f - 1.0f; 225b8e80941Smrg float y0 = (float) addr->yoffset / surface_height * 2.0f - 1.0f; 226b8e80941Smrg float x1 = (float) (addr->xoffset + addr->width) / surface_width * 2.0f - 1.0f; 227b8e80941Smrg float y1 = (float) (addr->yoffset + addr->height) / surface_height * 2.0f - 1.0f; 228b8e80941Smrg 229b8e80941Smrg float *verts = NULL; 230b8e80941Smrg 231b8e80941Smrg vbo.stride = 2 * sizeof(float); 232b8e80941Smrg 233b8e80941Smrg u_upload_alloc(st->pipe->stream_uploader, 0, 8 * sizeof(float), 4, 234b8e80941Smrg &vbo.buffer_offset, &vbo.buffer.resource, (void **) &verts); 235b8e80941Smrg if (!verts) 236b8e80941Smrg return false; 237b8e80941Smrg 238b8e80941Smrg verts[0] = x0; 239b8e80941Smrg verts[1] = y0; 240b8e80941Smrg verts[2] = x0; 241b8e80941Smrg verts[3] = y1; 242b8e80941Smrg verts[4] = x1; 243b8e80941Smrg verts[5] = y0; 244b8e80941Smrg verts[6] = x1; 245b8e80941Smrg verts[7] = y1; 246b8e80941Smrg 247b8e80941Smrg u_upload_unmap(st->pipe->stream_uploader); 248b8e80941Smrg 249b8e80941Smrg velem.src_offset = 0; 250b8e80941Smrg velem.instance_divisor = 0; 251b8e80941Smrg velem.vertex_buffer_index = 0; 252b8e80941Smrg velem.src_format = PIPE_FORMAT_R32G32_FLOAT; 253b8e80941Smrg 254b8e80941Smrg cso_set_vertex_elements(cso, 1, &velem); 255b8e80941Smrg 256b8e80941Smrg cso_set_vertex_buffers(cso, velem.vertex_buffer_index, 1, &vbo); 257b8e80941Smrg 258b8e80941Smrg pipe_resource_reference(&vbo.buffer.resource, NULL); 259b8e80941Smrg } 260b8e80941Smrg 261b8e80941Smrg /* Upload constants */ 262b8e80941Smrg { 263b8e80941Smrg struct pipe_constant_buffer cb; 264b8e80941Smrg 265b8e80941Smrg cb.buffer = NULL; 266b8e80941Smrg cb.user_buffer = &addr->constants; 267b8e80941Smrg cb.buffer_offset = 0; 268b8e80941Smrg cb.buffer_size = sizeof(addr->constants); 269b8e80941Smrg 270b8e80941Smrg cso_set_constant_buffer(cso, PIPE_SHADER_FRAGMENT, 0, &cb); 271b8e80941Smrg 272b8e80941Smrg pipe_resource_reference(&cb.buffer, NULL); 273b8e80941Smrg } 274b8e80941Smrg 275b8e80941Smrg /* Rasterizer state */ 276b8e80941Smrg cso_set_rasterizer(cso, &st->pbo.raster); 277b8e80941Smrg 278b8e80941Smrg /* Disable stream output */ 279b8e80941Smrg cso_set_stream_outputs(cso, 0, NULL, 0); 280b8e80941Smrg 281b8e80941Smrg if (addr->depth == 1) { 282b8e80941Smrg cso_draw_arrays(cso, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); 283b8e80941Smrg } else { 284b8e80941Smrg cso_draw_arrays_instanced(cso, PIPE_PRIM_TRIANGLE_STRIP, 285b8e80941Smrg 0, 4, 0, addr->depth); 286b8e80941Smrg } 287b8e80941Smrg 288b8e80941Smrg return true; 289b8e80941Smrg} 290b8e80941Smrg 291b8e80941Smrgvoid * 292b8e80941Smrgst_pbo_create_vs(struct st_context *st) 293b8e80941Smrg{ 294b8e80941Smrg struct pipe_screen *pscreen = st->pipe->screen; 295b8e80941Smrg bool use_nir = PIPE_SHADER_IR_NIR == 296b8e80941Smrg pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX, 297b8e80941Smrg PIPE_SHADER_CAP_PREFERRED_IR); 298b8e80941Smrg 299b8e80941Smrg if (use_nir) { 300b8e80941Smrg unsigned inputs[] = { VERT_ATTRIB_POS, SYSTEM_VALUE_INSTANCE_ID, }; 301b8e80941Smrg unsigned outputs[] = { VARYING_SLOT_POS, VARYING_SLOT_LAYER }; 302b8e80941Smrg 303b8e80941Smrg return st_nir_make_passthrough_shader(st, "st/pbo VS", 304b8e80941Smrg MESA_SHADER_VERTEX, 305b8e80941Smrg st->pbo.layers ? 2 : 1, 306b8e80941Smrg inputs, outputs, NULL, (1 << 1)); 307b8e80941Smrg } 308b8e80941Smrg 309b8e80941Smrg struct ureg_program *ureg; 310b8e80941Smrg struct ureg_src in_pos; 311b8e80941Smrg struct ureg_src in_instanceid; 312b8e80941Smrg struct ureg_dst out_pos; 313b8e80941Smrg struct ureg_dst out_layer; 314b8e80941Smrg 315b8e80941Smrg ureg = ureg_create(PIPE_SHADER_VERTEX); 316b8e80941Smrg if (!ureg) 317b8e80941Smrg return NULL; 318b8e80941Smrg 319b8e80941Smrg in_pos = ureg_DECL_vs_input(ureg, TGSI_SEMANTIC_POSITION); 320b8e80941Smrg 321b8e80941Smrg out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 322b8e80941Smrg 323b8e80941Smrg if (st->pbo.layers) { 324b8e80941Smrg in_instanceid = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0); 325b8e80941Smrg 326b8e80941Smrg if (!st->pbo.use_gs) 327b8e80941Smrg out_layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0); 328b8e80941Smrg } 329b8e80941Smrg 330b8e80941Smrg /* out_pos = in_pos */ 331b8e80941Smrg ureg_MOV(ureg, out_pos, in_pos); 332b8e80941Smrg 333b8e80941Smrg if (st->pbo.layers) { 334b8e80941Smrg if (st->pbo.use_gs) { 335b8e80941Smrg /* out_pos.z = i2f(gl_InstanceID) */ 336b8e80941Smrg ureg_I2F(ureg, ureg_writemask(out_pos, TGSI_WRITEMASK_Z), 337b8e80941Smrg ureg_scalar(in_instanceid, TGSI_SWIZZLE_X)); 338b8e80941Smrg } else { 339b8e80941Smrg /* out_layer = gl_InstanceID */ 340b8e80941Smrg ureg_MOV(ureg, ureg_writemask(out_layer, TGSI_WRITEMASK_X), 341b8e80941Smrg ureg_scalar(in_instanceid, TGSI_SWIZZLE_X)); 342b8e80941Smrg } 343b8e80941Smrg } 344b8e80941Smrg 345b8e80941Smrg ureg_END(ureg); 346b8e80941Smrg 347b8e80941Smrg return ureg_create_shader_and_destroy(ureg, st->pipe); 348b8e80941Smrg} 349b8e80941Smrg 350b8e80941Smrgvoid * 351b8e80941Smrgst_pbo_create_gs(struct st_context *st) 352b8e80941Smrg{ 353b8e80941Smrg static const int zero = 0; 354b8e80941Smrg struct ureg_program *ureg; 355b8e80941Smrg struct ureg_dst out_pos; 356b8e80941Smrg struct ureg_dst out_layer; 357b8e80941Smrg struct ureg_src in_pos; 358b8e80941Smrg struct ureg_src imm; 359b8e80941Smrg unsigned i; 360b8e80941Smrg 361b8e80941Smrg ureg = ureg_create(PIPE_SHADER_GEOMETRY); 362b8e80941Smrg if (!ureg) 363b8e80941Smrg return NULL; 364b8e80941Smrg 365b8e80941Smrg ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_TRIANGLES); 366b8e80941Smrg ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_TRIANGLE_STRIP); 367b8e80941Smrg ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 3); 368b8e80941Smrg 369b8e80941Smrg out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 370b8e80941Smrg out_layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0); 371b8e80941Smrg 372b8e80941Smrg in_pos = ureg_DECL_input(ureg, TGSI_SEMANTIC_POSITION, 0, 0, 1); 373b8e80941Smrg 374b8e80941Smrg imm = ureg_DECL_immediate_int(ureg, &zero, 1); 375b8e80941Smrg 376b8e80941Smrg for (i = 0; i < 3; ++i) { 377b8e80941Smrg struct ureg_src in_pos_vertex = ureg_src_dimension(in_pos, i); 378b8e80941Smrg 379b8e80941Smrg /* out_pos = in_pos[i] */ 380b8e80941Smrg ureg_MOV(ureg, out_pos, in_pos_vertex); 381b8e80941Smrg 382b8e80941Smrg /* out_layer.x = f2i(in_pos[i].z) */ 383b8e80941Smrg ureg_F2I(ureg, ureg_writemask(out_layer, TGSI_WRITEMASK_X), 384b8e80941Smrg ureg_scalar(in_pos_vertex, TGSI_SWIZZLE_Z)); 385b8e80941Smrg 386b8e80941Smrg ureg_EMIT(ureg, ureg_scalar(imm, TGSI_SWIZZLE_X)); 387b8e80941Smrg } 388b8e80941Smrg 389b8e80941Smrg ureg_END(ureg); 390b8e80941Smrg 391b8e80941Smrg return ureg_create_shader_and_destroy(ureg, st->pipe); 392b8e80941Smrg} 393b8e80941Smrg 394b8e80941Smrgstatic void 395b8e80941Smrgbuild_conversion(struct ureg_program *ureg, const struct ureg_dst *temp, 396b8e80941Smrg enum st_pbo_conversion conversion) 397b8e80941Smrg{ 398b8e80941Smrg switch (conversion) { 399b8e80941Smrg case ST_PBO_CONVERT_SINT_TO_UINT: 400b8e80941Smrg ureg_IMAX(ureg, *temp, ureg_src(*temp), ureg_imm1i(ureg, 0)); 401b8e80941Smrg break; 402b8e80941Smrg case ST_PBO_CONVERT_UINT_TO_SINT: 403b8e80941Smrg ureg_UMIN(ureg, *temp, ureg_src(*temp), ureg_imm1u(ureg, (1u << 31) - 1)); 404b8e80941Smrg break; 405b8e80941Smrg default: 406b8e80941Smrg /* no-op */ 407b8e80941Smrg break; 408b8e80941Smrg } 409b8e80941Smrg} 410b8e80941Smrg 411b8e80941Smrgstatic const struct glsl_type * 412b8e80941Smrgsampler_type_for_target(enum pipe_texture_target target) 413b8e80941Smrg{ 414b8e80941Smrg bool is_array = target >= PIPE_TEXTURE_1D_ARRAY; 415b8e80941Smrg static const enum glsl_sampler_dim dim[] = { 416b8e80941Smrg [PIPE_BUFFER] = GLSL_SAMPLER_DIM_BUF, 417b8e80941Smrg [PIPE_TEXTURE_1D] = GLSL_SAMPLER_DIM_1D, 418b8e80941Smrg [PIPE_TEXTURE_2D] = GLSL_SAMPLER_DIM_2D, 419b8e80941Smrg [PIPE_TEXTURE_3D] = GLSL_SAMPLER_DIM_3D, 420b8e80941Smrg [PIPE_TEXTURE_CUBE] = GLSL_SAMPLER_DIM_CUBE, 421b8e80941Smrg [PIPE_TEXTURE_RECT] = GLSL_SAMPLER_DIM_RECT, 422b8e80941Smrg [PIPE_TEXTURE_1D_ARRAY] = GLSL_SAMPLER_DIM_1D, 423b8e80941Smrg [PIPE_TEXTURE_2D_ARRAY] = GLSL_SAMPLER_DIM_2D, 424b8e80941Smrg [PIPE_TEXTURE_CUBE_ARRAY] = GLSL_SAMPLER_DIM_CUBE, 425b8e80941Smrg }; 426b8e80941Smrg 427b8e80941Smrg return glsl_sampler_type(dim[target], false, is_array, GLSL_TYPE_FLOAT); 428b8e80941Smrg} 429b8e80941Smrg 430b8e80941Smrgstatic void * 431b8e80941Smrgcreate_fs_nir(struct st_context *st, 432b8e80941Smrg bool download, 433b8e80941Smrg enum pipe_texture_target target, 434b8e80941Smrg enum st_pbo_conversion conversion) 435b8e80941Smrg{ 436b8e80941Smrg struct pipe_screen *screen = st->pipe->screen; 437b8e80941Smrg struct nir_builder b; 438b8e80941Smrg const nir_shader_compiler_options *options = 439b8e80941Smrg st->ctx->Const.ShaderCompilerOptions[MESA_SHADER_FRAGMENT].NirOptions; 440b8e80941Smrg bool pos_is_sysval = 441b8e80941Smrg screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL); 442b8e80941Smrg 443b8e80941Smrg nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, options); 444b8e80941Smrg 445b8e80941Smrg nir_ssa_def *zero = nir_imm_int(&b, 0); 446b8e80941Smrg 447b8e80941Smrg /* param = [ -xoffset + skip_pixels, -yoffset, stride, image_height ] */ 448b8e80941Smrg nir_variable *param_var = 449b8e80941Smrg nir_variable_create(b.shader, nir_var_uniform, glsl_vec4_type(), "param"); 450b8e80941Smrg b.shader->num_uniforms += 4; 451b8e80941Smrg nir_ssa_def *param = nir_load_var(&b, param_var); 452b8e80941Smrg 453b8e80941Smrg nir_variable *fragcoord = 454b8e80941Smrg nir_variable_create(b.shader, pos_is_sysval ? nir_var_system_value : 455b8e80941Smrg nir_var_shader_in, glsl_vec4_type(), "gl_FragCoord"); 456b8e80941Smrg fragcoord->data.location = pos_is_sysval ? SYSTEM_VALUE_FRAG_COORD 457b8e80941Smrg : VARYING_SLOT_POS; 458b8e80941Smrg nir_ssa_def *coord = nir_load_var(&b, fragcoord); 459b8e80941Smrg 460b8e80941Smrg nir_ssa_def *layer = NULL; 461b8e80941Smrg if (st->pbo.layers && (!download || target == PIPE_TEXTURE_1D_ARRAY || 462b8e80941Smrg target == PIPE_TEXTURE_2D_ARRAY || 463b8e80941Smrg target == PIPE_TEXTURE_3D || 464b8e80941Smrg target == PIPE_TEXTURE_CUBE || 465b8e80941Smrg target == PIPE_TEXTURE_CUBE_ARRAY)) { 466b8e80941Smrg nir_variable *var = nir_variable_create(b.shader, nir_var_shader_in, 467b8e80941Smrg glsl_int_type(), "gl_Layer"); 468b8e80941Smrg var->data.location = VARYING_SLOT_LAYER; 469b8e80941Smrg var->data.interpolation = INTERP_MODE_FLAT; 470b8e80941Smrg layer = nir_load_var(&b, var); 471b8e80941Smrg } 472b8e80941Smrg 473b8e80941Smrg /* offset_pos = param.xy + f2i(coord.xy) */ 474b8e80941Smrg nir_ssa_def *offset_pos = 475b8e80941Smrg nir_iadd(&b, nir_channels(&b, param, TGSI_WRITEMASK_XY), 476b8e80941Smrg nir_f2i32(&b, nir_channels(&b, coord, TGSI_WRITEMASK_XY))); 477b8e80941Smrg 478b8e80941Smrg /* addr = offset_pos.x + offset_pos.y * stride */ 479b8e80941Smrg nir_ssa_def *pbo_addr = 480b8e80941Smrg nir_iadd(&b, nir_channel(&b, offset_pos, 0), 481b8e80941Smrg nir_imul(&b, nir_channel(&b, offset_pos, 1), 482b8e80941Smrg nir_channel(&b, param, 2))); 483b8e80941Smrg if (layer) { 484b8e80941Smrg /* pbo_addr += image_height * layer */ 485b8e80941Smrg pbo_addr = nir_iadd(&b, pbo_addr, 486b8e80941Smrg nir_imul(&b, layer, nir_channel(&b, param, 3))); 487b8e80941Smrg } 488b8e80941Smrg 489b8e80941Smrg nir_ssa_def *texcoord; 490b8e80941Smrg if (download) { 491b8e80941Smrg texcoord = nir_f2i32(&b, nir_channels(&b, coord, TGSI_WRITEMASK_XY)); 492b8e80941Smrg 493b8e80941Smrg if (layer) { 494b8e80941Smrg nir_ssa_def *src_layer = layer; 495b8e80941Smrg 496b8e80941Smrg if (target == PIPE_TEXTURE_3D) { 497b8e80941Smrg nir_variable *layer_offset_var = 498b8e80941Smrg nir_variable_create(b.shader, nir_var_uniform, 499b8e80941Smrg glsl_int_type(), "layer_offset"); 500b8e80941Smrg b.shader->num_uniforms += 1; 501b8e80941Smrg layer_offset_var->data.driver_location = 4; 502b8e80941Smrg nir_ssa_def *layer_offset = nir_load_var(&b, layer_offset_var); 503b8e80941Smrg 504b8e80941Smrg src_layer = nir_iadd(&b, layer, layer_offset); 505b8e80941Smrg } 506b8e80941Smrg 507b8e80941Smrg texcoord = nir_vec3(&b, nir_channel(&b, texcoord, 0), 508b8e80941Smrg nir_channel(&b, texcoord, 1), 509b8e80941Smrg src_layer); 510b8e80941Smrg } 511b8e80941Smrg } else { 512b8e80941Smrg texcoord = pbo_addr; 513b8e80941Smrg } 514b8e80941Smrg 515b8e80941Smrg nir_variable *tex_var = 516b8e80941Smrg nir_variable_create(b.shader, nir_var_uniform, 517b8e80941Smrg sampler_type_for_target(target), "tex"); 518b8e80941Smrg tex_var->data.explicit_binding = true; 519b8e80941Smrg tex_var->data.binding = 0; 520b8e80941Smrg 521b8e80941Smrg nir_deref_instr *tex_deref = nir_build_deref_var(&b, tex_var); 522b8e80941Smrg 523b8e80941Smrg nir_tex_instr *tex = nir_tex_instr_create(b.shader, 3); 524b8e80941Smrg tex->op = nir_texop_txf; 525b8e80941Smrg tex->sampler_dim = glsl_get_sampler_dim(tex_var->type); 526b8e80941Smrg tex->coord_components = 527b8e80941Smrg glsl_get_sampler_coordinate_components(tex_var->type); 528b8e80941Smrg tex->dest_type = nir_type_float; 529b8e80941Smrg tex->src[0].src_type = nir_tex_src_texture_deref; 530b8e80941Smrg tex->src[0].src = nir_src_for_ssa(&tex_deref->dest.ssa); 531b8e80941Smrg tex->src[1].src_type = nir_tex_src_sampler_deref; 532b8e80941Smrg tex->src[1].src = nir_src_for_ssa(&tex_deref->dest.ssa); 533b8e80941Smrg tex->src[2].src_type = nir_tex_src_coord; 534b8e80941Smrg tex->src[2].src = nir_src_for_ssa(texcoord); 535b8e80941Smrg nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL); 536b8e80941Smrg nir_builder_instr_insert(&b, &tex->instr); 537b8e80941Smrg nir_ssa_def *result = &tex->dest.ssa; 538b8e80941Smrg 539b8e80941Smrg if (conversion == ST_PBO_CONVERT_SINT_TO_UINT) 540b8e80941Smrg result = nir_imax(&b, result, zero); 541b8e80941Smrg else if (conversion == ST_PBO_CONVERT_UINT_TO_SINT) 542b8e80941Smrg result = nir_umin(&b, result, nir_imm_int(&b, (1u << 31) - 1)); 543b8e80941Smrg 544b8e80941Smrg if (download) { 545b8e80941Smrg nir_variable *img_var = 546b8e80941Smrg nir_variable_create(b.shader, nir_var_uniform, 547b8e80941Smrg glsl_image_type(GLSL_SAMPLER_DIM_BUF, false, 548b8e80941Smrg GLSL_TYPE_FLOAT), "img"); 549b8e80941Smrg img_var->data.image.access = ACCESS_NON_READABLE; 550b8e80941Smrg img_var->data.explicit_binding = true; 551b8e80941Smrg img_var->data.binding = 0; 552b8e80941Smrg nir_deref_instr *img_deref = nir_build_deref_var(&b, img_var); 553b8e80941Smrg nir_intrinsic_instr *intrin = 554b8e80941Smrg nir_intrinsic_instr_create(b.shader, nir_intrinsic_image_deref_store); 555b8e80941Smrg intrin->src[0] = nir_src_for_ssa(&img_deref->dest.ssa); 556b8e80941Smrg intrin->src[1] = 557b8e80941Smrg nir_src_for_ssa(nir_vec4(&b, pbo_addr, zero, zero, zero)); 558b8e80941Smrg intrin->src[2] = nir_src_for_ssa(zero); 559b8e80941Smrg intrin->src[3] = nir_src_for_ssa(result); 560b8e80941Smrg intrin->num_components = 4; 561b8e80941Smrg nir_builder_instr_insert(&b, &intrin->instr); 562b8e80941Smrg } else { 563b8e80941Smrg nir_variable *color = 564b8e80941Smrg nir_variable_create(b.shader, nir_var_shader_out, glsl_vec4_type(), 565b8e80941Smrg "gl_FragColor"); 566b8e80941Smrg color->data.location = FRAG_RESULT_COLOR; 567b8e80941Smrg 568b8e80941Smrg nir_store_var(&b, color, result, TGSI_WRITEMASK_XYZW); 569b8e80941Smrg } 570b8e80941Smrg 571b8e80941Smrg return st_nir_finish_builtin_shader(st, b.shader, download ? 572b8e80941Smrg "st/pbo download FS" : 573b8e80941Smrg "st/pbo upload FS"); 574b8e80941Smrg} 575b8e80941Smrg 576b8e80941Smrgstatic void * 577b8e80941Smrgcreate_fs_tgsi(struct st_context *st, bool download, 578b8e80941Smrg enum pipe_texture_target target, 579b8e80941Smrg enum st_pbo_conversion conversion) 580b8e80941Smrg{ 581b8e80941Smrg struct pipe_context *pipe = st->pipe; 582b8e80941Smrg struct pipe_screen *screen = pipe->screen; 583b8e80941Smrg struct ureg_program *ureg; 584b8e80941Smrg bool have_layer; 585b8e80941Smrg struct ureg_dst out; 586b8e80941Smrg struct ureg_src sampler; 587b8e80941Smrg struct ureg_src pos; 588b8e80941Smrg struct ureg_src layer; 589b8e80941Smrg struct ureg_src const0; 590b8e80941Smrg struct ureg_src const1; 591b8e80941Smrg struct ureg_dst temp0; 592b8e80941Smrg 593b8e80941Smrg have_layer = 594b8e80941Smrg st->pbo.layers && 595b8e80941Smrg (!download || target == PIPE_TEXTURE_1D_ARRAY 596b8e80941Smrg || target == PIPE_TEXTURE_2D_ARRAY 597b8e80941Smrg || target == PIPE_TEXTURE_3D 598b8e80941Smrg || target == PIPE_TEXTURE_CUBE 599b8e80941Smrg || target == PIPE_TEXTURE_CUBE_ARRAY); 600b8e80941Smrg 601b8e80941Smrg ureg = ureg_create(PIPE_SHADER_FRAGMENT); 602b8e80941Smrg if (!ureg) 603b8e80941Smrg return NULL; 604b8e80941Smrg 605b8e80941Smrg if (!download) { 606b8e80941Smrg out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 607b8e80941Smrg } else { 608b8e80941Smrg struct ureg_src image; 609b8e80941Smrg 610b8e80941Smrg /* writeonly images do not require an explicitly given format. */ 611b8e80941Smrg image = ureg_DECL_image(ureg, 0, TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE, 612b8e80941Smrg true, false); 613b8e80941Smrg out = ureg_dst(image); 614b8e80941Smrg } 615b8e80941Smrg 616b8e80941Smrg sampler = ureg_DECL_sampler(ureg, 0); 617b8e80941Smrg if (screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL)) { 618b8e80941Smrg pos = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0); 619b8e80941Smrg } else { 620b8e80941Smrg pos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0, 621b8e80941Smrg TGSI_INTERPOLATE_LINEAR); 622b8e80941Smrg } 623b8e80941Smrg if (have_layer) { 624b8e80941Smrg layer = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_LAYER, 0, 625b8e80941Smrg TGSI_INTERPOLATE_CONSTANT); 626b8e80941Smrg } 627b8e80941Smrg const0 = ureg_DECL_constant(ureg, 0); 628b8e80941Smrg const1 = ureg_DECL_constant(ureg, 1); 629b8e80941Smrg temp0 = ureg_DECL_temporary(ureg); 630b8e80941Smrg 631b8e80941Smrg /* Note: const0 = [ -xoffset + skip_pixels, -yoffset, stride, image_height ] */ 632b8e80941Smrg 633b8e80941Smrg /* temp0.xy = f2i(temp0.xy) */ 634b8e80941Smrg ureg_F2I(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), 635b8e80941Smrg ureg_swizzle(pos, 636b8e80941Smrg TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 637b8e80941Smrg TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y)); 638b8e80941Smrg 639b8e80941Smrg /* temp0.xy = temp0.xy + const0.xy */ 640b8e80941Smrg ureg_UADD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), 641b8e80941Smrg ureg_swizzle(ureg_src(temp0), 642b8e80941Smrg TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 643b8e80941Smrg TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y), 644b8e80941Smrg ureg_swizzle(const0, 645b8e80941Smrg TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 646b8e80941Smrg TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y)); 647b8e80941Smrg 648b8e80941Smrg /* temp0.x = const0.z * temp0.y + temp0.x */ 649b8e80941Smrg ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X), 650b8e80941Smrg ureg_scalar(const0, TGSI_SWIZZLE_Z), 651b8e80941Smrg ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Y), 652b8e80941Smrg ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X)); 653b8e80941Smrg 654b8e80941Smrg if (have_layer) { 655b8e80941Smrg /* temp0.x = const0.w * layer + temp0.x */ 656b8e80941Smrg ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X), 657b8e80941Smrg ureg_scalar(const0, TGSI_SWIZZLE_W), 658b8e80941Smrg ureg_scalar(layer, TGSI_SWIZZLE_X), 659b8e80941Smrg ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X)); 660b8e80941Smrg } 661b8e80941Smrg 662b8e80941Smrg /* temp0.w = 0 */ 663b8e80941Smrg ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_W), ureg_imm1u(ureg, 0)); 664b8e80941Smrg 665b8e80941Smrg if (download) { 666b8e80941Smrg struct ureg_dst temp1; 667b8e80941Smrg struct ureg_src op[2]; 668b8e80941Smrg 669b8e80941Smrg temp1 = ureg_DECL_temporary(ureg); 670b8e80941Smrg 671b8e80941Smrg /* temp1.xy = pos.xy */ 672b8e80941Smrg ureg_F2I(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_XY), pos); 673b8e80941Smrg 674b8e80941Smrg /* temp1.zw = 0 */ 675b8e80941Smrg ureg_MOV(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_ZW), ureg_imm1u(ureg, 0)); 676b8e80941Smrg 677b8e80941Smrg if (have_layer) { 678b8e80941Smrg struct ureg_dst temp1_layer = 679b8e80941Smrg ureg_writemask(temp1, target == PIPE_TEXTURE_1D_ARRAY ? TGSI_WRITEMASK_Y 680b8e80941Smrg : TGSI_WRITEMASK_Z); 681b8e80941Smrg 682b8e80941Smrg /* temp1.y/z = layer */ 683b8e80941Smrg ureg_MOV(ureg, temp1_layer, ureg_scalar(layer, TGSI_SWIZZLE_X)); 684b8e80941Smrg 685b8e80941Smrg if (target == PIPE_TEXTURE_3D) { 686b8e80941Smrg /* temp1.z += layer_offset */ 687b8e80941Smrg ureg_UADD(ureg, temp1_layer, 688b8e80941Smrg ureg_scalar(ureg_src(temp1), TGSI_SWIZZLE_Z), 689b8e80941Smrg ureg_scalar(const1, TGSI_SWIZZLE_X)); 690b8e80941Smrg } 691b8e80941Smrg } 692b8e80941Smrg 693b8e80941Smrg /* temp1 = txf(sampler, temp1) */ 694b8e80941Smrg ureg_TXF(ureg, temp1, util_pipe_tex_to_tgsi_tex(target, 1), 695b8e80941Smrg ureg_src(temp1), sampler); 696b8e80941Smrg 697b8e80941Smrg build_conversion(ureg, &temp1, conversion); 698b8e80941Smrg 699b8e80941Smrg /* store(out, temp0, temp1) */ 700b8e80941Smrg op[0] = ureg_src(temp0); 701b8e80941Smrg op[1] = ureg_src(temp1); 702b8e80941Smrg ureg_memory_insn(ureg, TGSI_OPCODE_STORE, &out, 1, op, 2, 0, 703b8e80941Smrg TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE); 704b8e80941Smrg 705b8e80941Smrg ureg_release_temporary(ureg, temp1); 706b8e80941Smrg } else { 707b8e80941Smrg /* out = txf(sampler, temp0.x) */ 708b8e80941Smrg ureg_TXF(ureg, temp0, TGSI_TEXTURE_BUFFER, ureg_src(temp0), sampler); 709b8e80941Smrg 710b8e80941Smrg build_conversion(ureg, &temp0, conversion); 711b8e80941Smrg 712b8e80941Smrg ureg_MOV(ureg, out, ureg_src(temp0)); 713b8e80941Smrg } 714b8e80941Smrg 715b8e80941Smrg ureg_release_temporary(ureg, temp0); 716b8e80941Smrg 717b8e80941Smrg ureg_END(ureg); 718b8e80941Smrg 719b8e80941Smrg return ureg_create_shader_and_destroy(ureg, pipe); 720b8e80941Smrg} 721b8e80941Smrg 722b8e80941Smrgstatic void * 723b8e80941Smrgcreate_fs(struct st_context *st, bool download, 724b8e80941Smrg enum pipe_texture_target target, 725b8e80941Smrg enum st_pbo_conversion conversion) 726b8e80941Smrg{ 727b8e80941Smrg struct pipe_screen *pscreen = st->pipe->screen; 728b8e80941Smrg bool use_nir = PIPE_SHADER_IR_NIR == 729b8e80941Smrg pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX, 730b8e80941Smrg PIPE_SHADER_CAP_PREFERRED_IR); 731b8e80941Smrg 732b8e80941Smrg if (use_nir) 733b8e80941Smrg return create_fs_nir(st, download, target, conversion); 734b8e80941Smrg 735b8e80941Smrg return create_fs_tgsi(st, download, target, conversion); 736b8e80941Smrg} 737b8e80941Smrg 738b8e80941Smrgstatic enum st_pbo_conversion 739b8e80941Smrgget_pbo_conversion(enum pipe_format src_format, enum pipe_format dst_format) 740b8e80941Smrg{ 741b8e80941Smrg if (util_format_is_pure_uint(src_format)) { 742b8e80941Smrg if (util_format_is_pure_sint(dst_format)) 743b8e80941Smrg return ST_PBO_CONVERT_UINT_TO_SINT; 744b8e80941Smrg } else if (util_format_is_pure_sint(src_format)) { 745b8e80941Smrg if (util_format_is_pure_uint(dst_format)) 746b8e80941Smrg return ST_PBO_CONVERT_SINT_TO_UINT; 747b8e80941Smrg } 748b8e80941Smrg 749b8e80941Smrg return ST_PBO_CONVERT_NONE; 750b8e80941Smrg} 751b8e80941Smrg 752b8e80941Smrgvoid * 753b8e80941Smrgst_pbo_get_upload_fs(struct st_context *st, 754b8e80941Smrg enum pipe_format src_format, 755b8e80941Smrg enum pipe_format dst_format) 756b8e80941Smrg{ 757b8e80941Smrg STATIC_ASSERT(ARRAY_SIZE(st->pbo.upload_fs) == ST_NUM_PBO_CONVERSIONS); 758b8e80941Smrg 759b8e80941Smrg enum st_pbo_conversion conversion = get_pbo_conversion(src_format, dst_format); 760b8e80941Smrg 761b8e80941Smrg if (!st->pbo.upload_fs[conversion]) 762b8e80941Smrg st->pbo.upload_fs[conversion] = create_fs(st, false, 0, conversion); 763b8e80941Smrg 764b8e80941Smrg return st->pbo.upload_fs[conversion]; 765b8e80941Smrg} 766b8e80941Smrg 767b8e80941Smrgvoid * 768b8e80941Smrgst_pbo_get_download_fs(struct st_context *st, enum pipe_texture_target target, 769b8e80941Smrg enum pipe_format src_format, 770b8e80941Smrg enum pipe_format dst_format) 771b8e80941Smrg{ 772b8e80941Smrg STATIC_ASSERT(ARRAY_SIZE(st->pbo.download_fs) == ST_NUM_PBO_CONVERSIONS); 773b8e80941Smrg assert(target < PIPE_MAX_TEXTURE_TYPES); 774b8e80941Smrg 775b8e80941Smrg enum st_pbo_conversion conversion = get_pbo_conversion(src_format, dst_format); 776b8e80941Smrg 777b8e80941Smrg if (!st->pbo.download_fs[conversion][target]) 778b8e80941Smrg st->pbo.download_fs[conversion][target] = create_fs(st, true, target, conversion); 779b8e80941Smrg 780b8e80941Smrg return st->pbo.download_fs[conversion][target]; 781b8e80941Smrg} 782b8e80941Smrg 783b8e80941Smrgvoid 784b8e80941Smrgst_init_pbo_helpers(struct st_context *st) 785b8e80941Smrg{ 786b8e80941Smrg struct pipe_context *pipe = st->pipe; 787b8e80941Smrg struct pipe_screen *screen = pipe->screen; 788b8e80941Smrg 789b8e80941Smrg st->pbo.upload_enabled = 790b8e80941Smrg screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS) && 791b8e80941Smrg screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT) >= 1 && 792b8e80941Smrg screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS); 793b8e80941Smrg if (!st->pbo.upload_enabled) 794b8e80941Smrg return; 795b8e80941Smrg 796b8e80941Smrg st->pbo.download_enabled = 797b8e80941Smrg st->pbo.upload_enabled && 798b8e80941Smrg screen->get_param(screen, PIPE_CAP_SAMPLER_VIEW_TARGET) && 799b8e80941Smrg screen->get_param(screen, PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT) && 800b8e80941Smrg screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, 801b8e80941Smrg PIPE_SHADER_CAP_MAX_SHADER_IMAGES) >= 1; 802b8e80941Smrg 803b8e80941Smrg st->pbo.rgba_only = 804b8e80941Smrg screen->get_param(screen, PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY); 805b8e80941Smrg 806b8e80941Smrg if (screen->get_param(screen, PIPE_CAP_TGSI_INSTANCEID)) { 807b8e80941Smrg if (screen->get_param(screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT)) { 808b8e80941Smrg st->pbo.layers = true; 809b8e80941Smrg } else if (screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES) >= 3) { 810b8e80941Smrg st->pbo.layers = true; 811b8e80941Smrg st->pbo.use_gs = true; 812b8e80941Smrg } 813b8e80941Smrg } 814b8e80941Smrg 815b8e80941Smrg /* Blend state */ 816b8e80941Smrg memset(&st->pbo.upload_blend, 0, sizeof(struct pipe_blend_state)); 817b8e80941Smrg st->pbo.upload_blend.rt[0].colormask = PIPE_MASK_RGBA; 818b8e80941Smrg 819b8e80941Smrg /* Rasterizer state */ 820b8e80941Smrg memset(&st->pbo.raster, 0, sizeof(struct pipe_rasterizer_state)); 821b8e80941Smrg st->pbo.raster.half_pixel_center = 1; 822b8e80941Smrg} 823b8e80941Smrg 824b8e80941Smrgvoid 825b8e80941Smrgst_destroy_pbo_helpers(struct st_context *st) 826b8e80941Smrg{ 827b8e80941Smrg unsigned i; 828b8e80941Smrg 829b8e80941Smrg for (i = 0; i < ARRAY_SIZE(st->pbo.upload_fs); ++i) { 830b8e80941Smrg if (st->pbo.upload_fs[i]) { 831b8e80941Smrg cso_delete_fragment_shader(st->cso_context, st->pbo.upload_fs[i]); 832b8e80941Smrg st->pbo.upload_fs[i] = NULL; 833b8e80941Smrg } 834b8e80941Smrg } 835b8e80941Smrg 836b8e80941Smrg for (i = 0; i < ARRAY_SIZE(st->pbo.download_fs); ++i) { 837b8e80941Smrg for (unsigned j = 0; j < ARRAY_SIZE(st->pbo.download_fs[0]); ++j) { 838b8e80941Smrg if (st->pbo.download_fs[i][j]) { 839b8e80941Smrg cso_delete_fragment_shader(st->cso_context, st->pbo.download_fs[i][j]); 840b8e80941Smrg st->pbo.download_fs[i][j] = NULL; 841b8e80941Smrg } 842b8e80941Smrg } 843b8e80941Smrg } 844b8e80941Smrg 845b8e80941Smrg if (st->pbo.gs) { 846b8e80941Smrg cso_delete_geometry_shader(st->cso_context, st->pbo.gs); 847b8e80941Smrg st->pbo.gs = NULL; 848b8e80941Smrg } 849b8e80941Smrg 850b8e80941Smrg if (st->pbo.vs) { 851b8e80941Smrg cso_delete_vertex_shader(st->cso_context, st->pbo.vs); 852b8e80941Smrg st->pbo.vs = NULL; 853b8e80941Smrg } 854b8e80941Smrg} 855