101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2014-2017 Broadcom 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 247ec681f3Smrg#include "util/format/u_format.h" 257ec681f3Smrg#include "util/half_float.h" 2601e04c3fSmrg#include "v3d_context.h" 2701e04c3fSmrg#include "broadcom/common/v3d_macros.h" 2801e04c3fSmrg#include "broadcom/cle/v3dx_pack.h" 2901e04c3fSmrg#include "broadcom/compiler/v3d_compiler.h" 3001e04c3fSmrg 3101e04c3fSmrgstatic uint8_t 3201e04c3fSmrgv3d_factor(enum pipe_blendfactor factor, bool dst_alpha_one) 3301e04c3fSmrg{ 3401e04c3fSmrg /* We may get a bad blendfactor when blending is disabled. */ 3501e04c3fSmrg if (factor == 0) 3601e04c3fSmrg return V3D_BLEND_FACTOR_ZERO; 3701e04c3fSmrg 3801e04c3fSmrg switch (factor) { 3901e04c3fSmrg case PIPE_BLENDFACTOR_ZERO: 4001e04c3fSmrg return V3D_BLEND_FACTOR_ZERO; 4101e04c3fSmrg case PIPE_BLENDFACTOR_ONE: 4201e04c3fSmrg return V3D_BLEND_FACTOR_ONE; 4301e04c3fSmrg case PIPE_BLENDFACTOR_SRC_COLOR: 4401e04c3fSmrg return V3D_BLEND_FACTOR_SRC_COLOR; 4501e04c3fSmrg case PIPE_BLENDFACTOR_INV_SRC_COLOR: 4601e04c3fSmrg return V3D_BLEND_FACTOR_INV_SRC_COLOR; 4701e04c3fSmrg case PIPE_BLENDFACTOR_DST_COLOR: 4801e04c3fSmrg return V3D_BLEND_FACTOR_DST_COLOR; 4901e04c3fSmrg case PIPE_BLENDFACTOR_INV_DST_COLOR: 5001e04c3fSmrg return V3D_BLEND_FACTOR_INV_DST_COLOR; 5101e04c3fSmrg case PIPE_BLENDFACTOR_SRC_ALPHA: 5201e04c3fSmrg return V3D_BLEND_FACTOR_SRC_ALPHA; 5301e04c3fSmrg case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 5401e04c3fSmrg return V3D_BLEND_FACTOR_INV_SRC_ALPHA; 5501e04c3fSmrg case PIPE_BLENDFACTOR_DST_ALPHA: 5601e04c3fSmrg return (dst_alpha_one ? 5701e04c3fSmrg V3D_BLEND_FACTOR_ONE : 5801e04c3fSmrg V3D_BLEND_FACTOR_DST_ALPHA); 5901e04c3fSmrg case PIPE_BLENDFACTOR_INV_DST_ALPHA: 6001e04c3fSmrg return (dst_alpha_one ? 6101e04c3fSmrg V3D_BLEND_FACTOR_ZERO : 6201e04c3fSmrg V3D_BLEND_FACTOR_INV_DST_ALPHA); 6301e04c3fSmrg case PIPE_BLENDFACTOR_CONST_COLOR: 6401e04c3fSmrg return V3D_BLEND_FACTOR_CONST_COLOR; 6501e04c3fSmrg case PIPE_BLENDFACTOR_INV_CONST_COLOR: 6601e04c3fSmrg return V3D_BLEND_FACTOR_INV_CONST_COLOR; 6701e04c3fSmrg case PIPE_BLENDFACTOR_CONST_ALPHA: 6801e04c3fSmrg return V3D_BLEND_FACTOR_CONST_ALPHA; 6901e04c3fSmrg case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 7001e04c3fSmrg return V3D_BLEND_FACTOR_INV_CONST_ALPHA; 7101e04c3fSmrg case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 7201e04c3fSmrg return (dst_alpha_one ? 7301e04c3fSmrg V3D_BLEND_FACTOR_ZERO : 7401e04c3fSmrg V3D_BLEND_FACTOR_SRC_ALPHA_SATURATE); 7501e04c3fSmrg default: 7601e04c3fSmrg unreachable("Bad blend factor"); 7701e04c3fSmrg } 7801e04c3fSmrg} 7901e04c3fSmrg 8001e04c3fSmrgstatic inline uint16_t 8101e04c3fSmrgswizzled_border_color(const struct v3d_device_info *devinfo, 8201e04c3fSmrg struct pipe_sampler_state *sampler, 8301e04c3fSmrg struct v3d_sampler_view *sview, 8401e04c3fSmrg int chan) 8501e04c3fSmrg{ 8601e04c3fSmrg const struct util_format_description *desc = 8701e04c3fSmrg util_format_description(sview->base.format); 8801e04c3fSmrg uint8_t swiz = chan; 8901e04c3fSmrg 9001e04c3fSmrg /* If we're doing swizzling in the sampler, then only rearrange the 917ec681f3Smrg * border color for the mismatch between the V3D texture format and 9201e04c3fSmrg * the PIPE_FORMAT, since GL_ARB_texture_swizzle will be handled by 9301e04c3fSmrg * the sampler's swizzle. 9401e04c3fSmrg * 9501e04c3fSmrg * For swizzling in the shader, we don't do any pre-swizzling of the 9601e04c3fSmrg * border color. 9701e04c3fSmrg */ 9801e04c3fSmrg if (v3d_get_tex_return_size(devinfo, sview->base.format, 9901e04c3fSmrg sampler->compare_mode) != 32) 10001e04c3fSmrg swiz = desc->swizzle[swiz]; 10101e04c3fSmrg 10201e04c3fSmrg switch (swiz) { 10301e04c3fSmrg case PIPE_SWIZZLE_0: 1047ec681f3Smrg return _mesa_float_to_half(0.0); 10501e04c3fSmrg case PIPE_SWIZZLE_1: 1067ec681f3Smrg return _mesa_float_to_half(1.0); 10701e04c3fSmrg default: 1087ec681f3Smrg return _mesa_float_to_half(sampler->border_color.f[swiz]); 10901e04c3fSmrg } 11001e04c3fSmrg} 11101e04c3fSmrg 11201e04c3fSmrg#if V3D_VERSION < 40 11301e04c3fSmrgstatic uint32_t 11401e04c3fSmrgtranslate_swizzle(unsigned char pipe_swizzle) 11501e04c3fSmrg{ 11601e04c3fSmrg switch (pipe_swizzle) { 11701e04c3fSmrg case PIPE_SWIZZLE_0: 11801e04c3fSmrg return 0; 11901e04c3fSmrg case PIPE_SWIZZLE_1: 12001e04c3fSmrg return 1; 12101e04c3fSmrg case PIPE_SWIZZLE_X: 12201e04c3fSmrg case PIPE_SWIZZLE_Y: 12301e04c3fSmrg case PIPE_SWIZZLE_Z: 12401e04c3fSmrg case PIPE_SWIZZLE_W: 12501e04c3fSmrg return 2 + pipe_swizzle; 12601e04c3fSmrg default: 12701e04c3fSmrg unreachable("unknown swizzle"); 12801e04c3fSmrg } 12901e04c3fSmrg} 13001e04c3fSmrg 13101e04c3fSmrgstatic void 13201e04c3fSmrgemit_one_texture(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex, 13301e04c3fSmrg int i) 13401e04c3fSmrg{ 13501e04c3fSmrg struct v3d_job *job = v3d->job; 13601e04c3fSmrg struct pipe_sampler_state *psampler = stage_tex->samplers[i]; 13701e04c3fSmrg struct v3d_sampler_state *sampler = v3d_sampler_state(psampler); 13801e04c3fSmrg struct pipe_sampler_view *psview = stage_tex->textures[i]; 13901e04c3fSmrg struct v3d_sampler_view *sview = v3d_sampler_view(psview); 14001e04c3fSmrg struct pipe_resource *prsc = psview->texture; 14101e04c3fSmrg struct v3d_resource *rsc = v3d_resource(prsc); 14201e04c3fSmrg const struct v3d_device_info *devinfo = &v3d->screen->devinfo; 14301e04c3fSmrg 14401e04c3fSmrg stage_tex->texture_state[i].offset = 14501e04c3fSmrg v3d_cl_ensure_space(&job->indirect, 14601e04c3fSmrg cl_packet_length(TEXTURE_SHADER_STATE), 14701e04c3fSmrg 32); 14801e04c3fSmrg v3d_bo_set_reference(&stage_tex->texture_state[i].bo, 14901e04c3fSmrg job->indirect.bo); 15001e04c3fSmrg 15101e04c3fSmrg uint32_t return_size = v3d_get_tex_return_size(devinfo, psview->format, 15201e04c3fSmrg psampler->compare_mode); 15301e04c3fSmrg 15401e04c3fSmrg struct V3D33_TEXTURE_SHADER_STATE unpacked = { 15501e04c3fSmrg /* XXX */ 15601e04c3fSmrg .border_color_red = swizzled_border_color(devinfo, psampler, 15701e04c3fSmrg sview, 0), 15801e04c3fSmrg .border_color_green = swizzled_border_color(devinfo, psampler, 15901e04c3fSmrg sview, 1), 16001e04c3fSmrg .border_color_blue = swizzled_border_color(devinfo, psampler, 16101e04c3fSmrg sview, 2), 16201e04c3fSmrg .border_color_alpha = swizzled_border_color(devinfo, psampler, 16301e04c3fSmrg sview, 3), 16401e04c3fSmrg 16501e04c3fSmrg /* In the normal texturing path, the LOD gets clamped between 16601e04c3fSmrg * min/max, and the base_level field (set in the sampler view 16701e04c3fSmrg * from first_level) only decides where the min/mag switch 16801e04c3fSmrg * happens, so we need to use the LOD clamps to keep us 16901e04c3fSmrg * between min and max. 17001e04c3fSmrg * 17101e04c3fSmrg * For txf, the LOD clamp is still used, despite GL not 17201e04c3fSmrg * wanting that. We will need to have a separate 17301e04c3fSmrg * TEXTURE_SHADER_STATE that ignores psview->min/max_lod to 17401e04c3fSmrg * support txf properly. 17501e04c3fSmrg */ 17601e04c3fSmrg .min_level_of_detail = MIN2(psview->u.tex.first_level + 17701e04c3fSmrg MAX2(psampler->min_lod, 0), 17801e04c3fSmrg psview->u.tex.last_level), 17901e04c3fSmrg .max_level_of_detail = MIN2(psview->u.tex.first_level + 1807ec681f3Smrg MAX2(psampler->max_lod, 1817ec681f3Smrg psampler->min_lod), 18201e04c3fSmrg psview->u.tex.last_level), 18301e04c3fSmrg 18401e04c3fSmrg .texture_base_pointer = cl_address(rsc->bo, 18501e04c3fSmrg rsc->slices[0].offset), 18601e04c3fSmrg 18701e04c3fSmrg .output_32_bit = return_size == 32, 18801e04c3fSmrg }; 18901e04c3fSmrg 19001e04c3fSmrg /* Set up the sampler swizzle if we're doing 16-bit sampling. For 19101e04c3fSmrg * 32-bit, we leave swizzling up to the shader compiler. 19201e04c3fSmrg * 19301e04c3fSmrg * Note: Contrary to the docs, the swizzle still applies even if the 19401e04c3fSmrg * return size is 32. It's just that you probably want to swizzle in 19501e04c3fSmrg * the shader, because you need the Y/Z/W channels to be defined. 19601e04c3fSmrg */ 19701e04c3fSmrg if (return_size == 32) { 19801e04c3fSmrg unpacked.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X); 19901e04c3fSmrg unpacked.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y); 20001e04c3fSmrg unpacked.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z); 20101e04c3fSmrg unpacked.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W); 20201e04c3fSmrg } else { 20301e04c3fSmrg unpacked.swizzle_r = translate_swizzle(sview->swizzle[0]); 20401e04c3fSmrg unpacked.swizzle_g = translate_swizzle(sview->swizzle[1]); 20501e04c3fSmrg unpacked.swizzle_b = translate_swizzle(sview->swizzle[2]); 20601e04c3fSmrg unpacked.swizzle_a = translate_swizzle(sview->swizzle[3]); 20701e04c3fSmrg } 20801e04c3fSmrg 20901e04c3fSmrg int min_img_filter = psampler->min_img_filter; 21001e04c3fSmrg int min_mip_filter = psampler->min_mip_filter; 21101e04c3fSmrg int mag_img_filter = psampler->mag_img_filter; 21201e04c3fSmrg 21301e04c3fSmrg if (return_size == 32) { 21401e04c3fSmrg min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 21501e04c3fSmrg min_img_filter = PIPE_TEX_FILTER_NEAREST; 21601e04c3fSmrg mag_img_filter = PIPE_TEX_FILTER_NEAREST; 21701e04c3fSmrg } 21801e04c3fSmrg 21901e04c3fSmrg bool min_nearest = min_img_filter == PIPE_TEX_FILTER_NEAREST; 22001e04c3fSmrg switch (min_mip_filter) { 22101e04c3fSmrg case PIPE_TEX_MIPFILTER_NONE: 22201e04c3fSmrg unpacked.filter += min_nearest ? 2 : 0; 22301e04c3fSmrg break; 22401e04c3fSmrg case PIPE_TEX_MIPFILTER_NEAREST: 22501e04c3fSmrg unpacked.filter += min_nearest ? 4 : 8; 22601e04c3fSmrg break; 22701e04c3fSmrg case PIPE_TEX_MIPFILTER_LINEAR: 22801e04c3fSmrg unpacked.filter += min_nearest ? 4 : 8; 22901e04c3fSmrg unpacked.filter += 2; 23001e04c3fSmrg break; 23101e04c3fSmrg } 23201e04c3fSmrg 23301e04c3fSmrg if (mag_img_filter == PIPE_TEX_FILTER_NEAREST) 23401e04c3fSmrg unpacked.filter++; 23501e04c3fSmrg 23601e04c3fSmrg if (psampler->max_anisotropy > 8) 23701e04c3fSmrg unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_16_1; 23801e04c3fSmrg else if (psampler->max_anisotropy > 4) 23901e04c3fSmrg unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_8_1; 24001e04c3fSmrg else if (psampler->max_anisotropy > 2) 24101e04c3fSmrg unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_4_1; 24201e04c3fSmrg else if (psampler->max_anisotropy) 24301e04c3fSmrg unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_2_1; 24401e04c3fSmrg 24501e04c3fSmrg uint8_t packed[cl_packet_length(TEXTURE_SHADER_STATE)]; 24601e04c3fSmrg cl_packet_pack(TEXTURE_SHADER_STATE)(&job->indirect, packed, &unpacked); 24701e04c3fSmrg 24801e04c3fSmrg for (int i = 0; i < ARRAY_SIZE(packed); i++) 24901e04c3fSmrg packed[i] |= sview->texture_shader_state[i] | sampler->texture_shader_state[i]; 25001e04c3fSmrg 25101e04c3fSmrg /* TMU indirect structs need to be 32b aligned. */ 25201e04c3fSmrg v3d_cl_ensure_space(&job->indirect, ARRAY_SIZE(packed), 32); 25301e04c3fSmrg cl_emit_prepacked(&job->indirect, &packed); 25401e04c3fSmrg} 25501e04c3fSmrg 25601e04c3fSmrgstatic void 25701e04c3fSmrgemit_textures(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex) 25801e04c3fSmrg{ 25901e04c3fSmrg for (int i = 0; i < stage_tex->num_textures; i++) { 26001e04c3fSmrg if (stage_tex->textures[i]) 26101e04c3fSmrg emit_one_texture(v3d, stage_tex, i); 26201e04c3fSmrg } 26301e04c3fSmrg} 26401e04c3fSmrg#endif /* V3D_VERSION < 40 */ 26501e04c3fSmrg 26601e04c3fSmrgstatic uint32_t 26701e04c3fSmrgtranslate_colormask(struct v3d_context *v3d, uint32_t colormask, int rt) 26801e04c3fSmrg{ 26901e04c3fSmrg if (v3d->swap_color_rb & (1 << rt)) { 27001e04c3fSmrg colormask = ((colormask & (2 | 8)) | 27101e04c3fSmrg ((colormask & 1) << 2) | 27201e04c3fSmrg ((colormask & 4) >> 2)); 27301e04c3fSmrg } 27401e04c3fSmrg 27501e04c3fSmrg return (~colormask) & 0xf; 27601e04c3fSmrg} 27701e04c3fSmrg 27801e04c3fSmrgstatic void 27901e04c3fSmrgemit_rt_blend(struct v3d_context *v3d, struct v3d_job *job, 28001e04c3fSmrg struct pipe_blend_state *blend, int rt) 28101e04c3fSmrg{ 28201e04c3fSmrg struct pipe_rt_blend_state *rtblend = &blend->rt[rt]; 28301e04c3fSmrg 28401e04c3fSmrg#if V3D_VERSION >= 40 28501e04c3fSmrg /* We don't need to emit blend state for disabled RTs. */ 28601e04c3fSmrg if (!rtblend->blend_enable) 28701e04c3fSmrg return; 28801e04c3fSmrg#endif 28901e04c3fSmrg 29001e04c3fSmrg cl_emit(&job->bcl, BLEND_CFG, config) { 29101e04c3fSmrg#if V3D_VERSION >= 40 29201e04c3fSmrg if (blend->independent_blend_enable) 29301e04c3fSmrg config.render_target_mask = 1 << rt; 29401e04c3fSmrg else 2959f464c52Smaya config.render_target_mask = (1 << V3D_MAX_DRAW_BUFFERS) - 1; 29601e04c3fSmrg#else 29701e04c3fSmrg assert(rt == 0); 29801e04c3fSmrg#endif 29901e04c3fSmrg 30001e04c3fSmrg config.color_blend_mode = rtblend->rgb_func; 30101e04c3fSmrg config.color_blend_dst_factor = 30201e04c3fSmrg v3d_factor(rtblend->rgb_dst_factor, 30301e04c3fSmrg v3d->blend_dst_alpha_one); 30401e04c3fSmrg config.color_blend_src_factor = 30501e04c3fSmrg v3d_factor(rtblend->rgb_src_factor, 30601e04c3fSmrg v3d->blend_dst_alpha_one); 30701e04c3fSmrg 30801e04c3fSmrg config.alpha_blend_mode = rtblend->alpha_func; 30901e04c3fSmrg config.alpha_blend_dst_factor = 31001e04c3fSmrg v3d_factor(rtblend->alpha_dst_factor, 31101e04c3fSmrg v3d->blend_dst_alpha_one); 31201e04c3fSmrg config.alpha_blend_src_factor = 31301e04c3fSmrg v3d_factor(rtblend->alpha_src_factor, 31401e04c3fSmrg v3d->blend_dst_alpha_one); 31501e04c3fSmrg } 31601e04c3fSmrg} 31701e04c3fSmrg 31801e04c3fSmrgstatic void 31901e04c3fSmrgemit_flat_shade_flags(struct v3d_job *job, 32001e04c3fSmrg int varying_offset, 32101e04c3fSmrg uint32_t varyings, 32201e04c3fSmrg enum V3DX(Varying_Flags_Action) lower, 32301e04c3fSmrg enum V3DX(Varying_Flags_Action) higher) 32401e04c3fSmrg{ 32501e04c3fSmrg cl_emit(&job->bcl, FLAT_SHADE_FLAGS, flags) { 32601e04c3fSmrg flags.varying_offset_v0 = varying_offset; 32701e04c3fSmrg flags.flat_shade_flags_for_varyings_v024 = varyings; 32801e04c3fSmrg flags.action_for_flat_shade_flags_of_lower_numbered_varyings = 32901e04c3fSmrg lower; 33001e04c3fSmrg flags.action_for_flat_shade_flags_of_higher_numbered_varyings = 33101e04c3fSmrg higher; 33201e04c3fSmrg } 33301e04c3fSmrg} 33401e04c3fSmrg 33501e04c3fSmrg#if V3D_VERSION >= 40 33601e04c3fSmrgstatic void 33701e04c3fSmrgemit_noperspective_flags(struct v3d_job *job, 33801e04c3fSmrg int varying_offset, 33901e04c3fSmrg uint32_t varyings, 34001e04c3fSmrg enum V3DX(Varying_Flags_Action) lower, 34101e04c3fSmrg enum V3DX(Varying_Flags_Action) higher) 34201e04c3fSmrg{ 34301e04c3fSmrg cl_emit(&job->bcl, NON_PERSPECTIVE_FLAGS, flags) { 34401e04c3fSmrg flags.varying_offset_v0 = varying_offset; 34501e04c3fSmrg flags.non_perspective_flags_for_varyings_v024 = varyings; 34601e04c3fSmrg flags.action_for_non_perspective_flags_of_lower_numbered_varyings = 34701e04c3fSmrg lower; 34801e04c3fSmrg flags.action_for_non_perspective_flags_of_higher_numbered_varyings = 34901e04c3fSmrg higher; 35001e04c3fSmrg } 35101e04c3fSmrg} 35201e04c3fSmrg 35301e04c3fSmrgstatic void 35401e04c3fSmrgemit_centroid_flags(struct v3d_job *job, 35501e04c3fSmrg int varying_offset, 35601e04c3fSmrg uint32_t varyings, 35701e04c3fSmrg enum V3DX(Varying_Flags_Action) lower, 35801e04c3fSmrg enum V3DX(Varying_Flags_Action) higher) 35901e04c3fSmrg{ 36001e04c3fSmrg cl_emit(&job->bcl, CENTROID_FLAGS, flags) { 36101e04c3fSmrg flags.varying_offset_v0 = varying_offset; 36201e04c3fSmrg flags.centroid_flags_for_varyings_v024 = varyings; 36301e04c3fSmrg flags.action_for_centroid_flags_of_lower_numbered_varyings = 36401e04c3fSmrg lower; 36501e04c3fSmrg flags.action_for_centroid_flags_of_higher_numbered_varyings = 36601e04c3fSmrg higher; 36701e04c3fSmrg } 36801e04c3fSmrg} 36901e04c3fSmrg#endif /* V3D_VERSION >= 40 */ 37001e04c3fSmrg 37101e04c3fSmrgstatic bool 37201e04c3fSmrgemit_varying_flags(struct v3d_job *job, uint32_t *flags, 37301e04c3fSmrg void (*flag_emit_callback)(struct v3d_job *job, 37401e04c3fSmrg int varying_offset, 37501e04c3fSmrg uint32_t flags, 37601e04c3fSmrg enum V3DX(Varying_Flags_Action) lower, 37701e04c3fSmrg enum V3DX(Varying_Flags_Action) higher)) 37801e04c3fSmrg{ 37901e04c3fSmrg struct v3d_context *v3d = job->v3d; 38001e04c3fSmrg bool emitted_any = false; 38101e04c3fSmrg 38201e04c3fSmrg for (int i = 0; i < ARRAY_SIZE(v3d->prog.fs->prog_data.fs->flat_shade_flags); i++) { 38301e04c3fSmrg if (!flags[i]) 38401e04c3fSmrg continue; 38501e04c3fSmrg 38601e04c3fSmrg if (emitted_any) { 38701e04c3fSmrg flag_emit_callback(job, i, flags[i], 38801e04c3fSmrg V3D_VARYING_FLAGS_ACTION_UNCHANGED, 38901e04c3fSmrg V3D_VARYING_FLAGS_ACTION_UNCHANGED); 39001e04c3fSmrg } else if (i == 0) { 39101e04c3fSmrg flag_emit_callback(job, i, flags[i], 39201e04c3fSmrg V3D_VARYING_FLAGS_ACTION_UNCHANGED, 39301e04c3fSmrg V3D_VARYING_FLAGS_ACTION_ZEROED); 39401e04c3fSmrg } else { 39501e04c3fSmrg flag_emit_callback(job, i, flags[i], 39601e04c3fSmrg V3D_VARYING_FLAGS_ACTION_ZEROED, 39701e04c3fSmrg V3D_VARYING_FLAGS_ACTION_ZEROED); 39801e04c3fSmrg } 39901e04c3fSmrg emitted_any = true; 40001e04c3fSmrg } 40101e04c3fSmrg 40201e04c3fSmrg return emitted_any; 40301e04c3fSmrg} 40401e04c3fSmrg 4057ec681f3Smrgstatic inline struct v3d_uncompiled_shader * 4067ec681f3Smrgget_tf_shader(struct v3d_context *v3d) 4077ec681f3Smrg{ 4087ec681f3Smrg if (v3d->prog.bind_gs) 4097ec681f3Smrg return v3d->prog.bind_gs; 4107ec681f3Smrg else 4117ec681f3Smrg return v3d->prog.bind_vs; 4127ec681f3Smrg} 4137ec681f3Smrg 41401e04c3fSmrgvoid 41501e04c3fSmrgv3dX(emit_state)(struct pipe_context *pctx) 41601e04c3fSmrg{ 41701e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 41801e04c3fSmrg struct v3d_job *job = v3d->job; 41901e04c3fSmrg bool rasterizer_discard = v3d->rasterizer->base.rasterizer_discard; 42001e04c3fSmrg 4217ec681f3Smrg if (v3d->dirty & (V3D_DIRTY_SCISSOR | V3D_DIRTY_VIEWPORT | 4227ec681f3Smrg V3D_DIRTY_RASTERIZER)) { 42301e04c3fSmrg float *vpscale = v3d->viewport.scale; 42401e04c3fSmrg float *vptranslate = v3d->viewport.translate; 42501e04c3fSmrg float vp_minx = -fabsf(vpscale[0]) + vptranslate[0]; 42601e04c3fSmrg float vp_maxx = fabsf(vpscale[0]) + vptranslate[0]; 42701e04c3fSmrg float vp_miny = -fabsf(vpscale[1]) + vptranslate[1]; 42801e04c3fSmrg float vp_maxy = fabsf(vpscale[1]) + vptranslate[1]; 42901e04c3fSmrg 43001e04c3fSmrg /* Clip to the scissor if it's enabled, but still clip to the 43101e04c3fSmrg * drawable regardless since that controls where the binner 43201e04c3fSmrg * tries to put things. 43301e04c3fSmrg * 43401e04c3fSmrg * Additionally, always clip the rendering to the viewport, 43501e04c3fSmrg * since the hardware does guardband clipping, meaning 43601e04c3fSmrg * primitives would rasterize outside of the view volume. 43701e04c3fSmrg */ 43801e04c3fSmrg uint32_t minx, miny, maxx, maxy; 43901e04c3fSmrg if (!v3d->rasterizer->base.scissor) { 44001e04c3fSmrg minx = MAX2(vp_minx, 0); 44101e04c3fSmrg miny = MAX2(vp_miny, 0); 44201e04c3fSmrg maxx = MIN2(vp_maxx, job->draw_width); 44301e04c3fSmrg maxy = MIN2(vp_maxy, job->draw_height); 44401e04c3fSmrg } else { 44501e04c3fSmrg minx = MAX2(vp_minx, v3d->scissor.minx); 44601e04c3fSmrg miny = MAX2(vp_miny, v3d->scissor.miny); 44701e04c3fSmrg maxx = MIN2(vp_maxx, v3d->scissor.maxx); 44801e04c3fSmrg maxy = MIN2(vp_maxy, v3d->scissor.maxy); 44901e04c3fSmrg } 45001e04c3fSmrg 45101e04c3fSmrg cl_emit(&job->bcl, CLIP_WINDOW, clip) { 45201e04c3fSmrg clip.clip_window_left_pixel_coordinate = minx; 45301e04c3fSmrg clip.clip_window_bottom_pixel_coordinate = miny; 45401e04c3fSmrg if (maxx > minx && maxy > miny) { 45501e04c3fSmrg clip.clip_window_width_in_pixels = maxx - minx; 45601e04c3fSmrg clip.clip_window_height_in_pixels = maxy - miny; 45701e04c3fSmrg } else if (V3D_VERSION < 41) { 45801e04c3fSmrg /* The HW won't entirely clip out when scissor 45901e04c3fSmrg * w/h is 0. Just treat it the same as 46001e04c3fSmrg * rasterizer discard. 46101e04c3fSmrg */ 46201e04c3fSmrg rasterizer_discard = true; 46301e04c3fSmrg clip.clip_window_width_in_pixels = 1; 46401e04c3fSmrg clip.clip_window_height_in_pixels = 1; 46501e04c3fSmrg } 46601e04c3fSmrg } 46701e04c3fSmrg 46801e04c3fSmrg job->draw_min_x = MIN2(job->draw_min_x, minx); 46901e04c3fSmrg job->draw_min_y = MIN2(job->draw_min_y, miny); 47001e04c3fSmrg job->draw_max_x = MAX2(job->draw_max_x, maxx); 47101e04c3fSmrg job->draw_max_y = MAX2(job->draw_max_y, maxy); 4727ec681f3Smrg 4737ec681f3Smrg if (!v3d->rasterizer->base.scissor) { 4747ec681f3Smrg job->scissor.disabled = true; 4757ec681f3Smrg } else if (!job->scissor.disabled && 4767ec681f3Smrg (v3d->dirty & V3D_DIRTY_SCISSOR)) { 4777ec681f3Smrg if (job->scissor.count < MAX_JOB_SCISSORS) { 4787ec681f3Smrg job->scissor.rects[job->scissor.count].min_x = 4797ec681f3Smrg v3d->scissor.minx; 4807ec681f3Smrg job->scissor.rects[job->scissor.count].min_y = 4817ec681f3Smrg v3d->scissor.miny; 4827ec681f3Smrg job->scissor.rects[job->scissor.count].max_x = 4837ec681f3Smrg v3d->scissor.maxx - 1; 4847ec681f3Smrg job->scissor.rects[job->scissor.count].max_y = 4857ec681f3Smrg v3d->scissor.maxy - 1; 4867ec681f3Smrg job->scissor.count++; 4877ec681f3Smrg } else { 4887ec681f3Smrg job->scissor.disabled = true; 4897ec681f3Smrg perf_debug("Too many scissor rects."); 4907ec681f3Smrg } 4917ec681f3Smrg } 49201e04c3fSmrg } 49301e04c3fSmrg 4947ec681f3Smrg if (v3d->dirty & (V3D_DIRTY_RASTERIZER | 4957ec681f3Smrg V3D_DIRTY_ZSA | 4967ec681f3Smrg V3D_DIRTY_BLEND | 4977ec681f3Smrg V3D_DIRTY_COMPILED_FS)) { 49801e04c3fSmrg cl_emit(&job->bcl, CFG_BITS, config) { 49901e04c3fSmrg config.enable_forward_facing_primitive = 50001e04c3fSmrg !rasterizer_discard && 50101e04c3fSmrg !(v3d->rasterizer->base.cull_face & 50201e04c3fSmrg PIPE_FACE_FRONT); 50301e04c3fSmrg config.enable_reverse_facing_primitive = 50401e04c3fSmrg !rasterizer_discard && 50501e04c3fSmrg !(v3d->rasterizer->base.cull_face & 50601e04c3fSmrg PIPE_FACE_BACK); 50701e04c3fSmrg /* This seems backwards, but it's what gets the 50801e04c3fSmrg * clipflat test to pass. 50901e04c3fSmrg */ 51001e04c3fSmrg config.clockwise_primitives = 51101e04c3fSmrg v3d->rasterizer->base.front_ccw; 51201e04c3fSmrg 51301e04c3fSmrg config.enable_depth_offset = 51401e04c3fSmrg v3d->rasterizer->base.offset_tri; 51501e04c3fSmrg 51601e04c3fSmrg /* V3D follows GL behavior where the sample mask only 51701e04c3fSmrg * applies when MSAA is enabled. Gallium has sample 51801e04c3fSmrg * mask apply anyway, and the MSAA blit shaders will 51901e04c3fSmrg * set sample mask without explicitly setting 52001e04c3fSmrg * rasterizer oversample. Just force it on here, 52101e04c3fSmrg * since the blit shaders are the only way to have 52201e04c3fSmrg * !multisample && samplemask != 0xf. 52301e04c3fSmrg */ 52401e04c3fSmrg config.rasterizer_oversample_mode = 52501e04c3fSmrg v3d->rasterizer->base.multisample || 52601e04c3fSmrg v3d->sample_mask != 0xf; 52701e04c3fSmrg 52801e04c3fSmrg config.direct3d_provoking_vertex = 52901e04c3fSmrg v3d->rasterizer->base.flatshade_first; 53001e04c3fSmrg 53101e04c3fSmrg config.blend_enable = v3d->blend->blend_enables; 53201e04c3fSmrg 53301e04c3fSmrg /* Note: EZ state may update based on the compiled FS, 53401e04c3fSmrg * along with ZSA 53501e04c3fSmrg */ 53601e04c3fSmrg config.early_z_updates_enable = 5377ec681f3Smrg (job->ez_state != V3D_EZ_DISABLED); 5387ec681f3Smrg if (v3d->zsa->base.depth_enabled) { 53901e04c3fSmrg config.z_updates_enable = 5407ec681f3Smrg v3d->zsa->base.depth_writemask; 54101e04c3fSmrg config.early_z_enable = 54201e04c3fSmrg config.early_z_updates_enable; 54301e04c3fSmrg config.depth_test_function = 5447ec681f3Smrg v3d->zsa->base.depth_func; 54501e04c3fSmrg } else { 54601e04c3fSmrg config.depth_test_function = PIPE_FUNC_ALWAYS; 54701e04c3fSmrg } 54801e04c3fSmrg 54901e04c3fSmrg config.stencil_enable = 55001e04c3fSmrg v3d->zsa->base.stencil[0].enabled; 5517ec681f3Smrg 5527ec681f3Smrg /* Use nicer line caps when line smoothing is 5537ec681f3Smrg * enabled 5547ec681f3Smrg */ 5557ec681f3Smrg config.line_rasterization = 5567ec681f3Smrg v3d_line_smoothing_enabled(v3d) ? 1 : 0; 55701e04c3fSmrg } 55801e04c3fSmrg 55901e04c3fSmrg } 56001e04c3fSmrg 5617ec681f3Smrg if (v3d->dirty & V3D_DIRTY_RASTERIZER && 56201e04c3fSmrg v3d->rasterizer->base.offset_tri) { 56301e04c3fSmrg if (job->zsbuf && 56401e04c3fSmrg job->zsbuf->format == PIPE_FORMAT_Z16_UNORM) { 56501e04c3fSmrg cl_emit_prepacked_sized(&job->bcl, 56601e04c3fSmrg v3d->rasterizer->depth_offset_z16, 56701e04c3fSmrg cl_packet_length(DEPTH_OFFSET)); 56801e04c3fSmrg } else { 56901e04c3fSmrg cl_emit_prepacked_sized(&job->bcl, 57001e04c3fSmrg v3d->rasterizer->depth_offset, 57101e04c3fSmrg cl_packet_length(DEPTH_OFFSET)); 57201e04c3fSmrg } 57301e04c3fSmrg } 57401e04c3fSmrg 5757ec681f3Smrg if (v3d->dirty & V3D_DIRTY_RASTERIZER) { 57601e04c3fSmrg cl_emit(&job->bcl, POINT_SIZE, point_size) { 57701e04c3fSmrg point_size.point_size = v3d->rasterizer->point_size; 57801e04c3fSmrg } 57901e04c3fSmrg 58001e04c3fSmrg cl_emit(&job->bcl, LINE_WIDTH, line_width) { 5817ec681f3Smrg line_width.line_width = v3d_get_real_line_width(v3d); 58201e04c3fSmrg } 58301e04c3fSmrg } 58401e04c3fSmrg 5857ec681f3Smrg if (v3d->dirty & V3D_DIRTY_VIEWPORT) { 58601e04c3fSmrg cl_emit(&job->bcl, CLIPPER_XY_SCALING, clip) { 58701e04c3fSmrg clip.viewport_half_width_in_1_256th_of_pixel = 58801e04c3fSmrg v3d->viewport.scale[0] * 256.0f; 58901e04c3fSmrg clip.viewport_half_height_in_1_256th_of_pixel = 59001e04c3fSmrg v3d->viewport.scale[1] * 256.0f; 59101e04c3fSmrg } 59201e04c3fSmrg 59301e04c3fSmrg cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) { 59401e04c3fSmrg clip.viewport_z_offset_zc_to_zs = 59501e04c3fSmrg v3d->viewport.translate[2]; 59601e04c3fSmrg clip.viewport_z_scale_zc_to_zs = 59701e04c3fSmrg v3d->viewport.scale[2]; 59801e04c3fSmrg } 59901e04c3fSmrg cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) { 60001e04c3fSmrg float z1 = (v3d->viewport.translate[2] - 60101e04c3fSmrg v3d->viewport.scale[2]); 60201e04c3fSmrg float z2 = (v3d->viewport.translate[2] + 60301e04c3fSmrg v3d->viewport.scale[2]); 60401e04c3fSmrg clip.minimum_zw = MIN2(z1, z2); 60501e04c3fSmrg clip.maximum_zw = MAX2(z1, z2); 60601e04c3fSmrg } 60701e04c3fSmrg 60801e04c3fSmrg cl_emit(&job->bcl, VIEWPORT_OFFSET, vp) { 60901e04c3fSmrg vp.viewport_centre_x_coordinate = 61001e04c3fSmrg v3d->viewport.translate[0]; 61101e04c3fSmrg vp.viewport_centre_y_coordinate = 61201e04c3fSmrg v3d->viewport.translate[1]; 61301e04c3fSmrg } 61401e04c3fSmrg } 61501e04c3fSmrg 6167ec681f3Smrg if (v3d->dirty & V3D_DIRTY_BLEND) { 61701e04c3fSmrg struct v3d_blend_state *blend = v3d->blend; 61801e04c3fSmrg 61901e04c3fSmrg if (blend->blend_enables) { 62001e04c3fSmrg#if V3D_VERSION >= 40 62101e04c3fSmrg cl_emit(&job->bcl, BLEND_ENABLES, enables) { 62201e04c3fSmrg enables.mask = blend->blend_enables; 62301e04c3fSmrg } 62401e04c3fSmrg#endif 62501e04c3fSmrg 62601e04c3fSmrg if (blend->base.independent_blend_enable) { 6279f464c52Smaya for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) 62801e04c3fSmrg emit_rt_blend(v3d, job, &blend->base, i); 62901e04c3fSmrg } else { 63001e04c3fSmrg emit_rt_blend(v3d, job, &blend->base, 0); 63101e04c3fSmrg } 63201e04c3fSmrg } 63301e04c3fSmrg } 63401e04c3fSmrg 6357ec681f3Smrg if (v3d->dirty & V3D_DIRTY_BLEND) { 63601e04c3fSmrg struct pipe_blend_state *blend = &v3d->blend->base; 63701e04c3fSmrg 63801e04c3fSmrg cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) { 63901e04c3fSmrg for (int i = 0; i < 4; i++) { 64001e04c3fSmrg int rt = blend->independent_blend_enable ? i : 0; 64101e04c3fSmrg int rt_mask = blend->rt[rt].colormask; 64201e04c3fSmrg 64301e04c3fSmrg mask.mask |= translate_colormask(v3d, rt_mask, 64401e04c3fSmrg i) << (4 * i); 64501e04c3fSmrg } 64601e04c3fSmrg } 64701e04c3fSmrg } 64801e04c3fSmrg 64901e04c3fSmrg /* GFXH-1431: On V3D 3.x, writing BLEND_CONFIG resets the constant 65001e04c3fSmrg * color. 65101e04c3fSmrg */ 6527ec681f3Smrg if (v3d->dirty & V3D_DIRTY_BLEND_COLOR || 6537ec681f3Smrg (V3D_VERSION < 41 && (v3d->dirty & V3D_DIRTY_BLEND))) { 65401e04c3fSmrg cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) { 65501e04c3fSmrg color.red_f16 = (v3d->swap_color_rb ? 65601e04c3fSmrg v3d->blend_color.hf[2] : 65701e04c3fSmrg v3d->blend_color.hf[0]); 65801e04c3fSmrg color.green_f16 = v3d->blend_color.hf[1]; 65901e04c3fSmrg color.blue_f16 = (v3d->swap_color_rb ? 66001e04c3fSmrg v3d->blend_color.hf[0] : 66101e04c3fSmrg v3d->blend_color.hf[2]); 66201e04c3fSmrg color.alpha_f16 = v3d->blend_color.hf[3]; 66301e04c3fSmrg } 66401e04c3fSmrg } 66501e04c3fSmrg 6667ec681f3Smrg if (v3d->dirty & (V3D_DIRTY_ZSA | V3D_DIRTY_STENCIL_REF)) { 66701e04c3fSmrg struct pipe_stencil_state *front = &v3d->zsa->base.stencil[0]; 66801e04c3fSmrg struct pipe_stencil_state *back = &v3d->zsa->base.stencil[1]; 66901e04c3fSmrg 67001e04c3fSmrg if (front->enabled) { 67101e04c3fSmrg cl_emit_with_prepacked(&job->bcl, STENCIL_CFG, 67201e04c3fSmrg v3d->zsa->stencil_front, config) { 67301e04c3fSmrg config.stencil_ref_value = 67401e04c3fSmrg v3d->stencil_ref.ref_value[0]; 67501e04c3fSmrg } 67601e04c3fSmrg } 67701e04c3fSmrg 67801e04c3fSmrg if (back->enabled) { 67901e04c3fSmrg cl_emit_with_prepacked(&job->bcl, STENCIL_CFG, 68001e04c3fSmrg v3d->zsa->stencil_back, config) { 68101e04c3fSmrg config.stencil_ref_value = 68201e04c3fSmrg v3d->stencil_ref.ref_value[1]; 68301e04c3fSmrg } 68401e04c3fSmrg } 68501e04c3fSmrg } 68601e04c3fSmrg 68701e04c3fSmrg#if V3D_VERSION < 40 68801e04c3fSmrg /* Pre-4.x, we have texture state that depends on both the sampler and 68901e04c3fSmrg * the view, so we merge them together at draw time. 69001e04c3fSmrg */ 6917ec681f3Smrg if (v3d->dirty & V3D_DIRTY_FRAGTEX) 6929f464c52Smaya emit_textures(v3d, &v3d->tex[PIPE_SHADER_FRAGMENT]); 69301e04c3fSmrg 6947ec681f3Smrg if (v3d->dirty & V3D_DIRTY_GEOMTEX) 6957ec681f3Smrg emit_textures(v3d, &v3d->tex[PIPE_SHADER_GEOMETRY]); 6967ec681f3Smrg 6977ec681f3Smrg if (v3d->dirty & V3D_DIRTY_VERTTEX) 6989f464c52Smaya emit_textures(v3d, &v3d->tex[PIPE_SHADER_VERTEX]); 69901e04c3fSmrg#endif 70001e04c3fSmrg 7017ec681f3Smrg if (v3d->dirty & V3D_DIRTY_FLAT_SHADE_FLAGS) { 70201e04c3fSmrg if (!emit_varying_flags(job, 70301e04c3fSmrg v3d->prog.fs->prog_data.fs->flat_shade_flags, 70401e04c3fSmrg emit_flat_shade_flags)) { 70501e04c3fSmrg cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags); 70601e04c3fSmrg } 70701e04c3fSmrg } 70801e04c3fSmrg 70901e04c3fSmrg#if V3D_VERSION >= 40 7107ec681f3Smrg if (v3d->dirty & V3D_DIRTY_NOPERSPECTIVE_FLAGS) { 71101e04c3fSmrg if (!emit_varying_flags(job, 71201e04c3fSmrg v3d->prog.fs->prog_data.fs->noperspective_flags, 71301e04c3fSmrg emit_noperspective_flags)) { 71401e04c3fSmrg cl_emit(&job->bcl, ZERO_ALL_NON_PERSPECTIVE_FLAGS, flags); 71501e04c3fSmrg } 71601e04c3fSmrg } 71701e04c3fSmrg 7187ec681f3Smrg if (v3d->dirty & V3D_DIRTY_CENTROID_FLAGS) { 71901e04c3fSmrg if (!emit_varying_flags(job, 72001e04c3fSmrg v3d->prog.fs->prog_data.fs->centroid_flags, 72101e04c3fSmrg emit_centroid_flags)) { 72201e04c3fSmrg cl_emit(&job->bcl, ZERO_ALL_CENTROID_FLAGS, flags); 72301e04c3fSmrg } 72401e04c3fSmrg } 72501e04c3fSmrg#endif 72601e04c3fSmrg 72701e04c3fSmrg /* Set up the transform feedback data specs (which VPM entries to 72801e04c3fSmrg * output to which buffers). 72901e04c3fSmrg */ 7307ec681f3Smrg if (v3d->dirty & (V3D_DIRTY_STREAMOUT | 7317ec681f3Smrg V3D_DIRTY_RASTERIZER | 7327ec681f3Smrg V3D_DIRTY_PRIM_MODE)) { 73301e04c3fSmrg struct v3d_streamout_stateobj *so = &v3d->streamout; 73401e04c3fSmrg if (so->num_targets) { 73501e04c3fSmrg bool psiz_per_vertex = (v3d->prim_mode == PIPE_PRIM_POINTS && 73601e04c3fSmrg v3d->rasterizer->base.point_size_per_vertex); 7377ec681f3Smrg struct v3d_uncompiled_shader *tf_shader = 7387ec681f3Smrg get_tf_shader(v3d); 73901e04c3fSmrg uint16_t *tf_specs = (psiz_per_vertex ? 7407ec681f3Smrg tf_shader->tf_specs_psiz : 7417ec681f3Smrg tf_shader->tf_specs); 74201e04c3fSmrg 74301e04c3fSmrg#if V3D_VERSION >= 40 7447ec681f3Smrg bool tf_enabled = v3d_transform_feedback_enabled(v3d); 74501e04c3fSmrg job->tf_enabled |= tf_enabled; 74601e04c3fSmrg 74701e04c3fSmrg cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) { 74801e04c3fSmrg tfe.number_of_16_bit_output_data_specs_following = 7497ec681f3Smrg tf_shader->num_tf_specs; 75001e04c3fSmrg tfe.enable = tf_enabled; 75101e04c3fSmrg }; 75201e04c3fSmrg#else /* V3D_VERSION < 40 */ 75301e04c3fSmrg cl_emit(&job->bcl, TRANSFORM_FEEDBACK_ENABLE, tfe) { 75401e04c3fSmrg tfe.number_of_32_bit_output_buffer_address_following = 75501e04c3fSmrg so->num_targets; 75601e04c3fSmrg tfe.number_of_16_bit_output_data_specs_following = 7577ec681f3Smrg tf_shader->num_tf_specs; 75801e04c3fSmrg }; 75901e04c3fSmrg#endif /* V3D_VERSION < 40 */ 7607ec681f3Smrg for (int i = 0; i < tf_shader->num_tf_specs; i++) { 76101e04c3fSmrg cl_emit_prepacked(&job->bcl, &tf_specs[i]); 76201e04c3fSmrg } 76301e04c3fSmrg } else { 76401e04c3fSmrg#if V3D_VERSION >= 40 76501e04c3fSmrg cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) { 76601e04c3fSmrg tfe.enable = false; 76701e04c3fSmrg }; 76801e04c3fSmrg#endif /* V3D_VERSION >= 40 */ 76901e04c3fSmrg } 77001e04c3fSmrg } 77101e04c3fSmrg 7727ec681f3Smrg /* Set up the transform feedback buffers. */ 7737ec681f3Smrg if (v3d->dirty & V3D_DIRTY_STREAMOUT) { 7747ec681f3Smrg struct v3d_uncompiled_shader *tf_shader = get_tf_shader(v3d); 77501e04c3fSmrg struct v3d_streamout_stateobj *so = &v3d->streamout; 77601e04c3fSmrg for (int i = 0; i < so->num_targets; i++) { 77701e04c3fSmrg const struct pipe_stream_output_target *target = 77801e04c3fSmrg so->targets[i]; 77901e04c3fSmrg struct v3d_resource *rsc = target ? 78001e04c3fSmrg v3d_resource(target->buffer) : NULL; 7817ec681f3Smrg struct pipe_shader_state *ss = &tf_shader->base; 7827ec681f3Smrg struct pipe_stream_output_info *info = &ss->stream_output; 78301e04c3fSmrg uint32_t offset = (v3d->streamout.offsets[i] * 78401e04c3fSmrg info->stride[i] * 4); 78501e04c3fSmrg 78601e04c3fSmrg#if V3D_VERSION >= 40 78701e04c3fSmrg if (!target) 78801e04c3fSmrg continue; 78901e04c3fSmrg 79001e04c3fSmrg cl_emit(&job->bcl, TRANSFORM_FEEDBACK_BUFFER, output) { 79101e04c3fSmrg output.buffer_address = 79201e04c3fSmrg cl_address(rsc->bo, 79301e04c3fSmrg target->buffer_offset + 79401e04c3fSmrg offset); 79501e04c3fSmrg output.buffer_size_in_32_bit_words = 79601e04c3fSmrg (target->buffer_size - offset) >> 2; 79701e04c3fSmrg output.buffer_number = i; 79801e04c3fSmrg } 79901e04c3fSmrg#else /* V3D_VERSION < 40 */ 80001e04c3fSmrg cl_emit(&job->bcl, TRANSFORM_FEEDBACK_OUTPUT_ADDRESS, output) { 80101e04c3fSmrg if (target) { 80201e04c3fSmrg output.address = 80301e04c3fSmrg cl_address(rsc->bo, 80401e04c3fSmrg target->buffer_offset + 80501e04c3fSmrg offset); 80601e04c3fSmrg } 80701e04c3fSmrg }; 80801e04c3fSmrg#endif /* V3D_VERSION < 40 */ 80901e04c3fSmrg if (target) { 8107ec681f3Smrg v3d_job_add_tf_write_resource(v3d->job, 8117ec681f3Smrg target->buffer); 81201e04c3fSmrg } 81301e04c3fSmrg /* XXX: buffer_size? */ 81401e04c3fSmrg } 81501e04c3fSmrg } 81601e04c3fSmrg 8177ec681f3Smrg if (v3d->dirty & V3D_DIRTY_OQ) { 81801e04c3fSmrg cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter) { 81901e04c3fSmrg if (v3d->active_queries && v3d->current_oq) { 82001e04c3fSmrg counter.address = cl_address(v3d->current_oq, 0); 82101e04c3fSmrg } 82201e04c3fSmrg } 82301e04c3fSmrg } 82401e04c3fSmrg 82501e04c3fSmrg#if V3D_VERSION >= 40 8267ec681f3Smrg if (v3d->dirty & V3D_DIRTY_SAMPLE_STATE) { 82701e04c3fSmrg cl_emit(&job->bcl, SAMPLE_STATE, state) { 82801e04c3fSmrg /* Note: SampleCoverage was handled at the 8297ec681f3Smrg * frontend level by converting to sample_mask. 83001e04c3fSmrg */ 83101e04c3fSmrg state.coverage = 1.0; 83201e04c3fSmrg state.mask = job->msaa ? v3d->sample_mask : 0xf; 83301e04c3fSmrg } 83401e04c3fSmrg } 83501e04c3fSmrg#endif 83601e04c3fSmrg} 837