/** * Check if there are any resources that are both bound to a render target * and bound as a shader resource for the given type of shader. */ boolean svga_check_sampler_framebuffer_resource_collision(struct svga_context *svga, enum pipe_shader_type shader) { struct svga_surface *surf; unsigned i; for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) { surf = svga_surface(svga->curr.framebuffer.cbufs[i]); if (surf && svga_check_sampler_view_resource_collision(svga, surf->handle, shader)) { return TRUE; } } surf = svga_surface(svga->curr.framebuffer.zsbuf); if (surf && svga_check_sampler_view_resource_collision(svga, surf->handle, shader)) { return TRUE; } return FALSE; }
/** * Create a DX RenderTarget/DepthStencil View for the given surface, * if needed. */ struct pipe_surface * svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) { enum pipe_error ret = PIPE_OK; unsigned shader; assert(svga_have_vgpu10(svga)); /** * DX spec explicitly specifies that no resource can be bound to a render * target view and a shader resource view simultanously. * So first check if the resource bound to this surface view collides with * a sampler view. If so, then we will clone this surface view and its * associated resource. We will then use the cloned surface view for * render target. */ for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) { SVGA_DBG(DEBUG_VIEWS, "same resource used in shaderResource and renderTarget 0x%x\n", s->handle); s = create_backed_surface_view(svga, s); if (!s) return NULL; break; } } if (s->view_id == SVGA3D_INVALID_ID) { SVGA3dResourceType resType; SVGA3dRenderTargetViewDesc desc; desc.tex.mipSlice = s->real_level; desc.tex.firstArraySlice = s->real_layer + s->real_zslice; desc.tex.arraySize = s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1; s->view_id = util_bitmask_add(svga->surface_view_id_bm); switch (s->base.texture->target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_1D_ARRAY: resType = SVGA3D_RESOURCE_TEXTURE1D; break; case PIPE_TEXTURE_RECT: case PIPE_TEXTURE_2D: case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_CUBE: /* drawing to cube map is treated as drawing to 2D array */ resType = SVGA3D_RESOURCE_TEXTURE2D; break; case PIPE_TEXTURE_3D: resType = SVGA3D_RESOURCE_TEXTURE3D; break; default: assert(!"Unexpected texture target"); resType = SVGA3D_RESOURCE_TEXTURE2D; } if (util_format_is_depth_or_stencil(s->base.format)) { ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, s->view_id, s->handle, s->key.format, resType, &desc); } else { ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, s->view_id, s->handle, s->key.format, resType, &desc); } if (ret != PIPE_OK) { util_bitmask_clear(svga->surface_view_id_bm, s->view_id); s->view_id = SVGA3D_INVALID_ID; return NULL; } } return &s->base; }