Metal: Stencil texture view support #107971
|
@ -691,7 +691,7 @@ class Texture : NonCopyable {
|
|||
eGPUTextureFormat format = GPU_texture_format(tx_);
|
||||
for (auto i : IndexRange(mip_len)) {
|
||||
mip_views_.append(
|
||||
GPU_texture_create_view(name_, tx_, format, i, 1, 0, 9999, cube_as_array));
|
||||
GPU_texture_create_view(name_, tx_, format, i, 1, 0, 9999, cube_as_array, false));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -726,7 +726,7 @@ class Texture : NonCopyable {
|
|||
eGPUTextureFormat format = GPU_texture_format(tx_);
|
||||
for (auto i : IndexRange(layer_len)) {
|
||||
layer_views_.append(
|
||||
GPU_texture_create_view(name_, tx_, format, 0, 9999, i, 1, cube_as_array));
|
||||
GPU_texture_create_view(name_, tx_, format, 0, 9999, i, 1, cube_as_array, false));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -742,8 +742,8 @@ class Texture : NonCopyable {
|
|||
{
|
||||
if (stencil_view_ == nullptr) {
|
||||
eGPUTextureFormat format = GPU_texture_format(tx_);
|
||||
stencil_view_ = GPU_texture_create_view(name_, tx_, format, 0, 9999, 0, 9999, cube_as_array);
|
||||
GPU_texture_stencil_texture_mode_set(stencil_view_, true);
|
||||
stencil_view_ = GPU_texture_create_view(
|
||||
name_, tx_, format, 0, 9999, 0, 9999, cube_as_array, true);
|
||||
}
|
||||
return stencil_view_;
|
||||
}
|
||||
|
|
|
@ -700,6 +700,13 @@ void GPU_texture_free(GPUTexture *texture);
|
|||
* \note If \a cube_as_array is true, then the created view will be a 2D array texture instead of a
|
||||
* cube-map texture or cube-map-array texture.
|
||||
*
|
||||
* For Depth-Stencil texture view formats:
|
||||
* \note If \a use_stencil is true, the texture is expected to be bound to a UINT sampler and will
|
||||
* return the stencil value (in a range of [0..255]) as the first component.
|
||||
* \note If \a use_stencil is false (default), the texture is expected to be bound to a DEPTH
|
||||
* sampler and will return the normalized depth value (in a range of [0..1]) as the first
|
||||
* component.
|
||||
*
|
||||
* TODO(fclem): Target conversion (ex: Texture 2D as Texture 2D Array) is not implemented yet.
|
||||
*/
|
||||
GPUTexture *GPU_texture_create_view(const char *name,
|
||||
|
@ -709,7 +716,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
|
|||
int mip_len,
|
||||
int layer_start,
|
||||
int layer_len,
|
||||
bool cube_as_array);
|
||||
bool cube_as_array,
|
||||
bool use_stencil);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -908,16 +916,6 @@ void GPU_texture_extend_mode(GPUTexture *texture, GPUSamplerExtendMode extend_mo
|
|||
*/
|
||||
void GPU_texture_swizzle_set(GPUTexture *texture, const char swizzle[4]);
|
||||
|
||||
/**
|
||||
* Set a depth-stencil texture read mode.
|
||||
*
|
||||
* If \a use_stencil is true, the texture is expected to be bound to a UINT sampler and will return
|
||||
* the stencil value (in a range of [0..255]) as the first component.
|
||||
* If \a use_stencil is false, the texture is expected to be bound to a DEPTH sampler and will
|
||||
* return the normalized depth value (in a range of [0..1]) as the first component.
|
||||
*/
|
||||
void GPU_texture_stencil_texture_mode_set(GPUTexture *texture, bool use_stencil);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -139,7 +139,8 @@ bool Texture::init_view(GPUTexture *src_,
|
|||
int mip_len,
|
||||
int layer_start,
|
||||
int layer_len,
|
||||
bool cube_as_array)
|
||||
bool cube_as_array,
|
||||
bool use_stencil)
|
||||
{
|
||||
const Texture *src = unwrap(src_);
|
||||
w_ = src->w_;
|
||||
|
@ -172,7 +173,7 @@ bool Texture::init_view(GPUTexture *src_,
|
|||
type_ = (type_ & ~GPU_TEXTURE_CUBE) | GPU_TEXTURE_2D_ARRAY;
|
||||
}
|
||||
sampler_state = src->sampler_state;
|
||||
return this->init_internal(src_, mip_start, layer_start);
|
||||
return this->init_internal(src_, mip_start, layer_start, use_stencil);
|
||||
}
|
||||
|
||||
void Texture::usage_set(eGPUTextureUsage usage_flags)
|
||||
|
@ -454,7 +455,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
|
|||
int mip_len,
|
||||
int layer_start,
|
||||
int layer_len,
|
||||
bool cube_as_array)
|
||||
bool cube_as_array,
|
||||
bool use_stencil)
|
||||
{
|
||||
BLI_assert(mip_len > 0);
|
||||
BLI_assert(layer_len > 0);
|
||||
|
@ -469,7 +471,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
|
|||
mip_len,
|
||||
layer_start,
|
||||
layer_len,
|
||||
cube_as_array);
|
||||
cube_as_array,
|
||||
use_stencil);
|
||||
return wrap(view);
|
||||
}
|
||||
|
||||
|
@ -665,12 +668,6 @@ void GPU_texture_swizzle_set(GPUTexture *tex, const char swizzle[4])
|
|||
reinterpret_cast<Texture *>(tex)->swizzle_set(swizzle);
|
||||
}
|
||||
|
||||
void GPU_texture_stencil_texture_mode_set(GPUTexture *tex, bool use_stencil)
|
||||
{
|
||||
BLI_assert(GPU_texture_has_stencil_format(tex) || !use_stencil);
|
||||
reinterpret_cast<Texture *>(tex)->stencil_texture_mode_set(use_stencil);
|
||||
}
|
||||
|
||||
void GPU_texture_free(GPUTexture *tex_)
|
||||
{
|
||||
Texture *tex = reinterpret_cast<Texture *>(tex_);
|
||||
|
|
|
@ -139,13 +139,13 @@ class Texture {
|
|||
int mip_len,
|
||||
int layer_start,
|
||||
int layer_len,
|
||||
bool cube_as_array);
|
||||
bool cube_as_array,
|
||||
bool use_stencil);
|
||||
|
||||
virtual void generate_mipmap() = 0;
|
||||
virtual void copy_to(Texture *tex) = 0;
|
||||
virtual void clear(eGPUDataFormat format, const void *data) = 0;
|
||||
virtual void swizzle_set(const char swizzle_mask[4]) = 0;
|
||||
virtual void stencil_texture_mode_set(bool use_stencil) = 0;
|
||||
virtual void mip_range_set(int min, int max) = 0;
|
||||
virtual void *read(int mip, eGPUDataFormat format) = 0;
|
||||
|
||||
|
@ -313,7 +313,10 @@ class Texture {
|
|||
protected:
|
||||
virtual bool init_internal() = 0;
|
||||
virtual bool init_internal(GPUVertBuf *vbo) = 0;
|
||||
virtual bool init_internal(GPUTexture *src, int mip_offset, int layer_offset) = 0;
|
||||
virtual bool init_internal(GPUTexture *src,
|
||||
int mip_offset,
|
||||
int layer_offset,
|
||||
bool use_stencil) = 0;
|
||||
};
|
||||
|
||||
/* Syntactic sugar. */
|
||||
|
|
|
@ -219,6 +219,7 @@ class MTLTexture : public Texture {
|
|||
MTLTextureSwizzleChannels mtl_swizzle_mask_;
|
||||
bool mip_range_dirty_ = false;
|
||||
|
||||
bool texture_view_stencil_ = false;
|
||||
int mip_texture_base_level_ = 0;
|
||||
int mip_texture_max_level_ = 1000;
|
||||
int mip_texture_base_layer_ = 0;
|
||||
|
@ -256,9 +257,6 @@ class MTLTexture : public Texture {
|
|||
void copy_to(Texture *dst) override;
|
||||
void clear(eGPUDataFormat format, const void *data) override;
|
||||
void swizzle_set(const char swizzle_mask[4]) override;
|
||||
void stencil_texture_mode_set(bool use_stencil) override{
|
||||
/* TODO(Metal): implement. */
|
||||
};
|
||||
void mip_range_set(int min, int max) override;
|
||||
void *read(int mip, eGPUDataFormat type) override;
|
||||
|
||||
|
@ -285,7 +283,8 @@ class MTLTexture : public Texture {
|
|||
bool init_internal(GPUVertBuf *vbo) override;
|
||||
bool init_internal(GPUTexture *src,
|
||||
int mip_offset,
|
||||
int layer_offset) override; /* Texture View */
|
||||
int layer_offset,
|
||||
bool use_stencil) override; /* Texture View */
|
||||
|
||||
private:
|
||||
/* Common Constructor, default initialization. */
|
||||
|
@ -516,6 +515,32 @@ inline std::string tex_data_format_to_msl_texture_template_type(eGPUDataFormat t
|
|||
return "";
|
||||
}
|
||||
|
||||
/* Fetch Metal texture type from GPU texture type. */
|
||||
inline MTLTextureType to_metal_type(eGPUTextureType type)
|
||||
{
|
||||
switch (type) {
|
||||
case GPU_TEXTURE_1D:
|
||||
return MTLTextureType1D;
|
||||
case GPU_TEXTURE_2D:
|
||||
return MTLTextureType2D;
|
||||
case GPU_TEXTURE_3D:
|
||||
return MTLTextureType3D;
|
||||
case GPU_TEXTURE_CUBE:
|
||||
return MTLTextureTypeCube;
|
||||
case GPU_TEXTURE_BUFFER:
|
||||
return MTLTextureTypeTextureBuffer;
|
||||
case GPU_TEXTURE_1D_ARRAY:
|
||||
return MTLTextureType1DArray;
|
||||
case GPU_TEXTURE_2D_ARRAY:
|
||||
return MTLTextureType2DArray;
|
||||
case GPU_TEXTURE_CUBE_ARRAY:
|
||||
return MTLTextureTypeCubeArray;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
return MTLTextureType2D;
|
||||
}
|
||||
|
||||
/* Determine whether format is writable or not. Use mtl_format_get_writeable_view_format(..) for
|
||||
* these. */
|
||||
inline bool mtl_format_is_writable(MTLPixelFormat format)
|
||||
|
|
|
@ -159,14 +159,35 @@ void gpu::MTLTexture::bake_mip_swizzle_view()
|
|||
break;
|
||||
}
|
||||
|
||||
/* Determine texture view format. If texture view is used as a stencil view, we instead provide
|
||||
* the equivalent format for performing stencil reads/samples. */
|
||||
MTLPixelFormat texture_view_pixel_format = texture_.pixelFormat;
|
||||
if (texture_view_stencil_) {
|
||||
switch (texture_view_pixel_format) {
|
||||
case MTLPixelFormatDepth24Unorm_Stencil8:
|
||||
texture_view_pixel_format = MTLPixelFormatX24_Stencil8;
|
||||
break;
|
||||
case MTLPixelFormatDepth32Float_Stencil8:
|
||||
texture_view_pixel_format = MTLPixelFormatX32_Stencil8;
|
||||
break;
|
||||
default:
|
||||
BLI_assert_msg(false, "Texture format does not support stencil views.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: Texture type for cube maps can be overriden as a 2D array. This is done
|
||||
* via modifying this textures type flags. */
|
||||
MTLTextureType texture_view_texture_type = to_metal_type(type_);
|
||||
|
||||
int range_len = min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1,
|
||||
texture_.mipmapLevelCount - mip_texture_base_level_);
|
||||
BLI_assert(range_len > 0);
|
||||
BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount);
|
||||
BLI_assert(mip_texture_base_layer_ < num_slices);
|
||||
mip_swizzle_view_ = [texture_
|
||||
newTextureViewWithPixelFormat:texture_.pixelFormat
|
||||
textureType:texture_.textureType
|
||||
newTextureViewWithPixelFormat:texture_view_pixel_format
|
||||
textureType:texture_view_texture_type
|
||||
levels:NSMakeRange(mip_texture_base_level_, range_len)
|
||||
slices:NSMakeRange(mip_texture_base_layer_, num_slices)
|
||||
swizzle:mtl_swizzle_mask_];
|
||||
|
@ -1810,7 +1831,10 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool gpu::MTLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset)
|
||||
bool gpu::MTLTexture::init_internal(GPUTexture *src,
|
||||
int mip_offset,
|
||||
int layer_offset,
|
||||
bool use_stencil)
|
||||
{
|
||||
BLI_assert(src);
|
||||
|
||||
|
@ -1841,6 +1865,13 @@ bool gpu::MTLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_o
|
|||
is_baked_ = true;
|
||||
is_dirty_ = false;
|
||||
|
||||
/* Stencil view support. */
|
||||
texture_view_stencil_ = false;
|
||||
if (use_stencil) {
|
||||
BLI_assert(ELEM(format_, GPU_DEPTH24_STENCIL8, GPU_DEPTH32F_STENCIL8));
|
||||
texture_view_stencil_ = true;
|
||||
}
|
||||
|
||||
/* Bake mip swizzle view. */
|
||||
bake_mip_swizzle_view();
|
||||
return true;
|
||||
|
|
|
@ -178,7 +178,7 @@ bool GLTexture::init_internal(GPUVertBuf *vbo)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset)
|
||||
bool GLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset, bool use_stencil)
|
||||
{
|
||||
BLI_assert(GLContext::texture_storage_support);
|
||||
|
||||
|
@ -197,6 +197,11 @@ bool GLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset)
|
|||
|
||||
debug::object_label(GL_TEXTURE, tex_id_, name_);
|
||||
|
||||
/* Stencil view support. */
|
||||
if (ELEM(format_, GPU_DEPTH24_STENCIL8, GPU_DEPTH32F_STENCIL8)) {
|
||||
stencil_texture_mode_set(use_stencil);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ class GLTexture : public Texture {
|
|||
void copy_to(Texture *dst) override;
|
||||
void clear(eGPUDataFormat format, const void *data) override;
|
||||
void swizzle_set(const char swizzle_mask[4]) override;
|
||||
void stencil_texture_mode_set(bool use_stencil) override;
|
||||
void mip_range_set(int min, int max) override;
|
||||
void *read(int mip, eGPUDataFormat type) override;
|
||||
|
||||
|
@ -117,10 +116,11 @@ class GLTexture : public Texture {
|
|||
/** Return true on success. */
|
||||
bool init_internal(GPUVertBuf *vbo) override;
|
||||
/** Return true on success. */
|
||||
bool init_internal(GPUTexture *src, int mip_offset, int layer_offset) override;
|
||||
bool init_internal(GPUTexture *src, int mip_offset, int layer_offset, bool use_stencil) override;
|
||||
|
||||
private:
|
||||
bool proxy_check(int mip);
|
||||
void stencil_texture_mode_set(bool use_stencil);
|
||||
void update_sub_direct_state_access(
|
||||
int mip, int offset[3], int extent[3], GLenum gl_format, GLenum gl_type, const void *data);
|
||||
GPUFrameBuffer *framebuffer_get();
|
||||
|
|
|
@ -62,8 +62,6 @@ void VKTexture::clear(eGPUDataFormat format, const void *data)
|
|||
|
||||
void VKTexture::swizzle_set(const char /*swizzle_mask*/[4]) {}
|
||||
|
||||
void VKTexture::stencil_texture_mode_set(bool /*use_stencil*/) {}
|
||||
|
||||
void VKTexture::mip_range_set(int /*min*/, int /*max*/) {}
|
||||
|
||||
void *VKTexture::read(int mip, eGPUDataFormat format)
|
||||
|
@ -181,7 +179,10 @@ bool VKTexture::init_internal(GPUVertBuf * /*vbo*/)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool VKTexture::init_internal(GPUTexture * /*src*/, int /*mip_offset*/, int /*layer_offset*/)
|
||||
bool VKTexture::init_internal(GPUTexture * /*src*/,
|
||||
int /*mip_offset*/,
|
||||
int /*layer_offset*/,
|
||||
bool /*use_stencil*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ class VKTexture : public Texture {
|
|||
void copy_to(Texture *tex) override;
|
||||
void clear(eGPUDataFormat format, const void *data) override;
|
||||
void swizzle_set(const char swizzle_mask[4]) override;
|
||||
void stencil_texture_mode_set(bool use_stencil) override;
|
||||
void mip_range_set(int min, int max) override;
|
||||
void *read(int mip, eGPUDataFormat format) override;
|
||||
void update_sub(
|
||||
|
@ -68,7 +67,7 @@ class VKTexture : public Texture {
|
|||
protected:
|
||||
bool init_internal() override;
|
||||
bool init_internal(GPUVertBuf *vbo) override;
|
||||
bool init_internal(GPUTexture *src, int mip_offset, int layer_offset) override;
|
||||
bool init_internal(GPUTexture *src, int mip_offset, int layer_offset, bool use_stencil) override;
|
||||
|
||||
private:
|
||||
/** Is this texture already allocated on device. */
|
||||
|
|
Loading…
Reference in New Issue