This adds support to the mesa state tracker for ARB_texture_multisample.
hardware doesn't seem to use a different texture instructions, so
I don't think we need to create one for TGSI at this time.
Thanks to Marek for fixes to sample number picking.
v2: idr pointed out a bug in how we picked the max sample counts,
use new internal format chooser interface to pick proper answers.
v3: use st_choose_format directly, it was okay, fix anding of masks.
Reviewed-by: Marek Olšák <maraeo@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);
if (!strb->surface ||
+ strb->surface->texture->nr_samples != strb->Base.NumSamples ||
strb->surface->format != format ||
strb->surface->texture != resource ||
strb->surface->width != rtt_width ||
if (st->ctx->Multisample.SampleCoverageInvert)
sample_mask = ~sample_mask;
}
- /* TODO merge with app-supplied sample mask */
+ if (st->ctx->Multisample.SampleMask)
+ sample_mask &= st->ctx->Multisample.SampleMaskValue;
}
/* mask off unused bits or don't care? */
* Create texture to hold bitmap pattern.
*/
pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
- 0, width, height, 1, 1,
+ 0, width, height, 1, 1, 0,
PIPE_BIND_SAMPLER_VIEW);
if (!pt) {
_mesa_unmap_pbo_source(ctx, unpack);
cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
st->bitmap.tex_format, 0,
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
- 1, 1,
+ 1, 1, 0,
PIPE_BIND_SAMPLER_VIEW);
}
struct pipe_resource *pt;
pt = st_texture_create(st, st->internal_target, texFormat, 0,
- width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW);
+ width, height, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
return pt;
}
strb->rtt_level = att->TextureLevel;
strb->rtt_face = att->CubeMapFace;
strb->rtt_slice = att->Zoffset;
-
+ rb->NumSamples = texImage->NumSamples;
rb->Width = texImage->Width2;
rb->Height = texImage->Height2;
rb->_BaseFormat = texImage->_BaseFormat;
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
case GL_TEXTURE_EXTERNAL_OES:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
return PIPE_TEXTURE_2D;
case GL_TEXTURE_RECTANGLE_NV:
case GL_PROXY_TEXTURE_RECTANGLE_NV:
return PIPE_TEXTURE_1D_ARRAY;
case GL_TEXTURE_2D_ARRAY_EXT:
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
return PIPE_TEXTURE_2D_ARRAY;
case GL_TEXTURE_BUFFER:
return PIPE_BUFFER;
ptWidth,
ptHeight,
ptDepth,
- ptLayers,
+ ptLayers, 0,
bindings);
stObj->lastLevel = lastLevel;
ptWidth,
ptHeight,
ptDepth,
- ptLayers,
+ ptLayers, 0,
bindings);
return stImage->pt != NULL;
}
GLuint face;
struct st_texture_image *firstImage;
enum pipe_format firstImageFormat;
- GLuint ptWidth, ptHeight, ptDepth, ptLayers;
+ GLuint ptWidth, ptHeight, ptDepth, ptLayers, ptNumSamples;
if (_mesa_is_texture_complete(tObj, &tObj->Sampler)) {
/* The texture is complete and we know exactly how many mipmap levels
/* convert GL dims to Gallium dims */
st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth,
&ptWidth, &ptHeight, &ptDepth, &ptLayers);
+ ptNumSamples = firstImage->base.NumSamples;
}
/* If we already have a gallium texture, check that it matches the texture
stObj->pt->width0 != ptWidth ||
stObj->pt->height0 != ptHeight ||
stObj->pt->depth0 != ptDepth ||
+ stObj->pt->nr_samples != ptNumSamples ||
stObj->pt->array_size != ptLayers)
{
/* The gallium texture does not match the Mesa texture so delete the
ptWidth,
ptHeight,
ptDepth,
- ptLayers,
+ ptLayers, ptNumSamples,
bindings);
if (!stObj->pt) {
GLsizei height, GLsizei depth)
{
const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
+ struct gl_texture_image *texImage = texObj->Image[0][0];
struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(texObj);
+ struct pipe_screen *screen = st->pipe->screen;
GLuint ptWidth, ptHeight, ptDepth, ptLayers, bindings;
enum pipe_format fmt;
GLint level;
+ int num_samples = texImage->NumSamples;
assert(levels > 0);
stObj->depth0 = depth;
stObj->lastLevel = levels - 1;
- fmt = st_mesa_format_to_pipe_format(texObj->Image[0][0]->TexFormat);
+ fmt = st_mesa_format_to_pipe_format(texImage->TexFormat);
bindings = default_bindings(st, fmt);
+ /* Raise the sample count if the requested one is unsupported. */
+ if (num_samples > 1) {
+ boolean found = FALSE;
+
+ for (; num_samples <= ctx->Const.MaxSamples; num_samples++) {
+ if (screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
+ num_samples,
+ PIPE_BIND_SAMPLER_VIEW)) {
+ /* Update the sample count in gl_texture_image as well. */
+ texImage->NumSamples = num_samples;
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ return GL_FALSE;
+ }
+ }
+
st_gl_texture_dims_to_pipe_dims(texObj->Target,
width, height, depth,
&ptWidth, &ptHeight, &ptDepth, &ptLayers);
ptWidth,
ptHeight,
ptDepth,
- ptLayers,
+ ptLayers, num_samples,
bindings);
if (!stObj->pt)
return GL_FALSE;
#include "st_context.h"
#include "st_extensions.h"
-
+#include "st_format.h"
static int _min(int a, int b)
{
{ o(MESA_texture_array), PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS },
{ o(OES_standard_derivatives), PIPE_CAP_SM3 },
- { o(ARB_texture_cube_map_array), PIPE_CAP_CUBE_MAP_ARRAY }
+ { o(ARB_texture_cube_map_array), PIPE_CAP_CUBE_MAP_ARRAY },
+ { o(ARB_texture_multisample), PIPE_CAP_TEXTURE_MULTISAMPLE }
};
/* Required: render target and sampler support */
/* Maximum sample count. */
for (i = 16; i > 0; --i) {
- if (screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_UNORM,
- PIPE_TEXTURE_2D, i,
- PIPE_BIND_RENDER_TARGET)) {
+ enum pipe_format pformat = st_choose_format(st, GL_RGBA,
+ GL_NONE, GL_NONE,
+ PIPE_TEXTURE_2D, i,
+ PIPE_BIND_RENDER_TARGET, FALSE);
+ if (pformat != PIPE_FORMAT_NONE) {
ctx->Const.MaxSamples = i;
+ ctx->Const.MaxColorTextureSamples = i;
+ break;
+ }
+ }
+ for (i = ctx->Const.MaxSamples; i > 0; --i) {
+ enum pipe_format pformat = st_choose_format(st, GL_DEPTH_STENCIL,
+ GL_NONE, GL_NONE,
+ PIPE_TEXTURE_2D, i,
+ PIPE_BIND_DEPTH_STENCIL, FALSE);
+ if (pformat != PIPE_FORMAT_NONE) {
+ ctx->Const.MaxDepthTextureSamples = i;
+ break;
+ }
+ }
+ for (i = ctx->Const.MaxSamples; i > 0; --i) {
+ enum pipe_format pformat = st_choose_format(st, GL_RGBA_INTEGER,
+ GL_NONE, GL_NONE,
+ PIPE_TEXTURE_2D, i,
+ PIPE_BIND_RENDER_TARGET, FALSE);
+ if (pformat != PIPE_FORMAT_NONE) {
+ ctx->Const.MaxIntegerSamples = i;
break;
}
}
oldTex->height0,
oldTex->depth0,
oldTex->array_size,
+ 0,
oldTex->bind);
/* This will copy the old texture's base image into the new texture
void
glsl_to_tgsi_visitor::visit(ir_texture *ir)
{
- st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset;
+ st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset, sample_index;
st_dst_reg result_dst, coord_dst, cube_sc_dst;
glsl_to_tgsi_instruction *inst = NULL;
unsigned opcode = TGSI_OPCODE_NOP;
*/
coord = get_temp(glsl_type::vec4_type);
coord_dst = st_dst_reg(coord);
+ coord_dst.writemask = (1 << ir->coordinate->type->vector_elements) - 1;
emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result);
}
}
break;
case ir_txf_ms:
- assert(!"Unexpected ir_txf_ms opcode");
+ opcode = TGSI_OPCODE_TXF;
+ ir->lod_info.sample_index->accept(this);
+ sample_index = this->result;
break;
case ir_lod:
assert(!"Unexpected ir_lod opcode");
}
}
- if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB ||
+ if (ir->op == ir_txf_ms) {
+ coord_dst.writemask = WRITEMASK_W;
+ emit(ir, TGSI_OPCODE_MOV, coord_dst, sample_index);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ } else if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB ||
opcode == TGSI_OPCODE_TXF) {
/* TGSI stores LOD or LOD bias in the last channel of the coords. */
coord_dst.writemask = WRITEMASK_W;
case GLSL_SAMPLER_DIM_EXTERNAL:
inst->tex_target = TEXTURE_EXTERNAL_INDEX;
break;
+ case GLSL_SAMPLER_DIM_MS:
+ inst->tex_target = (sampler_type->sampler_array)
+ ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
+ break;
default:
assert(!"Should not get here.");
}
}
switch( textarget ) {
+ case TEXTURE_2D_MULTISAMPLE_INDEX: return TGSI_TEXTURE_2D_MSAA;
+ case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY_MSAA;
case TEXTURE_BUFFER_INDEX: return TGSI_TEXTURE_BUFFER;
case TEXTURE_1D_INDEX: return TGSI_TEXTURE_1D;
case TEXTURE_2D_INDEX: return TGSI_TEXTURE_2D;
GLuint height0,
GLuint depth0,
GLuint layers,
+ GLuint nr_samples,
GLuint bind )
{
struct pipe_resource pt, *newtex;
pt.usage = PIPE_USAGE_DEFAULT;
pt.bind = bind;
pt.flags = 0;
+ pt.nr_samples = nr_samples;
newtex = screen->resource_create(screen, &pt);
case GL_TEXTURE_RECTANGLE:
case GL_PROXY_TEXTURE_RECTANGLE:
case GL_TEXTURE_EXTERNAL_OES:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_2D_MULTISAMPLE:
assert(depthIn == 1);
*widthOut = widthIn;
*heightOut = heightIn;
*layersOut = 6;
break;
case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
case GL_PROXY_TEXTURE_2D_ARRAY:
+ case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
*widthOut = widthIn;
*heightOut = heightIn;
*depthOut = 1;
/* create texture for color map/table */
pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
- texSize, texSize, 1, 1, PIPE_BIND_SAMPLER_VIEW);
+ texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
return pt;
}
GLuint height0,
GLuint depth0,
GLuint layers,
+ GLuint nr_samples,
GLuint tex_usage );