blob: 297efecb587f2e17271d01079d200443ae837f6d [file] [log] [blame]
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// mtl_render_utils.h:
// Defines the class interface for RenderUtils.
//
#ifndef LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_
#define LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_
#import <Metal/Metal.h>
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/metal/mtl_command_buffer.h"
#include "libANGLE/renderer/metal/mtl_state_cache.h"
namespace rx
{
class BufferMtl;
class ContextMtl;
class DisplayMtl;
namespace mtl
{
struct ClearRectParams : public ClearOptions
{
gl::Rectangle clearArea;
bool flipY = false;
};
struct BlitParams
{
gl::Offset dstOffset;
// Destination texture needs to have viewport Y flipped?
// The difference between this param and unpackFlipY is that unpackFlipY is from
// glCopyImageCHROMIUM(), and dstFlipY controls whether the final viewport needs to be
// flipped when drawing to destination texture.
bool dstFlipY = false;
MTLColorWriteMask dstColorMask = MTLColorWriteMaskAll;
TextureRef src;
uint32_t srcLevel = 0;
gl::Rectangle srcRect;
bool srcYFlipped = false; // source texture has data flipped in Y direction
bool unpackFlipY = false; // flip texture data copying process in Y direction
bool unpackPremultiplyAlpha = false;
bool unpackUnmultiplyAlpha = false;
bool dstLuminance = false;
};
struct TriFanFromArrayParams
{
uint32_t firstVertex;
uint32_t vertexCount;
BufferRef dstBuffer;
// Must be multiples of kBufferSettingOffsetAlignment
uint32_t dstOffset;
};
struct IndexGenerationParams
{
gl::DrawElementsType srcType;
GLsizei indexCount;
const void *indices;
BufferRef dstBuffer;
uint32_t dstOffset;
};
class RenderUtils : public Context, angle::NonCopyable
{
public:
RenderUtils(DisplayMtl *display);
~RenderUtils() override;
angle::Result initialize();
void onDestroy();
// Clear current framebuffer
void clearWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const ClearRectParams &params);
// Blit texture data to current framebuffer
void blitWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const BlitParams &params);
angle::Result convertIndexBuffer(const gl::Context *context,
gl::DrawElementsType srcType,
uint32_t indexCount,
const BufferRef &srcBuffer,
uint32_t srcOffset,
const BufferRef &dstBuffer,
// Must be multiples of kBufferSettingOffsetAlignment
uint32_t dstOffset);
angle::Result generateTriFanBufferFromArrays(const gl::Context *context,
const TriFanFromArrayParams &params);
angle::Result generateTriFanBufferFromElementsArray(const gl::Context *context,
const IndexGenerationParams &params);
angle::Result generateLineLoopLastSegment(const gl::Context *context,
uint32_t firstVertex,
uint32_t lastVertex,
const BufferRef &dstBuffer,
uint32_t dstOffset);
angle::Result generateLineLoopLastSegmentFromElementsArray(const gl::Context *context,
const IndexGenerationParams &params);
angle::Result dispatchCompute(const gl::Context *context,
ComputeCommandEncoder *encoder,
id<MTLComputePipelineState> pipelineState,
size_t numThreads);
private:
// override ErrorHandler
void handleError(GLenum error,
const char *file,
const char *function,
unsigned int line) override;
void handleError(NSError *_Nullable error,
const char *file,
const char *function,
unsigned int line) override;
angle::Result initShaderLibrary();
void initClearResources();
void initBlitResources();
void setupClearWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const ClearRectParams &params);
void setupBlitWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const BlitParams &params);
id<MTLDepthStencilState> getClearDepthStencilState(const gl::Context *context,
const ClearRectParams &params);
id<MTLRenderPipelineState> getClearRenderPipelineState(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const ClearRectParams &params);
id<MTLRenderPipelineState> getBlitRenderPipelineState(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const BlitParams &params);
void setupBlitWithDrawUniformData(RenderCommandEncoder *cmdEncoder, const BlitParams &params);
void setupDrawCommonStates(RenderCommandEncoder *cmdEncoder);
AutoObjCPtr<id<MTLComputePipelineState>> getIndexConversionPipeline(
ContextMtl *context,
gl::DrawElementsType srcType,
uint32_t srcOffset);
AutoObjCPtr<id<MTLComputePipelineState>> getTriFanFromElemArrayGeneratorPipeline(
ContextMtl *context,
gl::DrawElementsType srcType,
uint32_t srcOffset);
angle::Result ensureTriFanFromArrayGeneratorInitialized(ContextMtl *context);
angle::Result generateTriFanBufferFromElementsArrayGPU(
const gl::Context *context,
gl::DrawElementsType srcType,
uint32_t indexCount,
const BufferRef &srcBuffer,
uint32_t srcOffset,
const BufferRef &dstBuffer,
// Must be multiples of kBufferSettingOffsetAlignment
uint32_t dstOffset);
angle::Result generateTriFanBufferFromElementsArrayCPU(const gl::Context *context,
const IndexGenerationParams &params);
angle::Result generateLineLoopLastSegmentFromElementsArrayCPU(
const gl::Context *context,
const IndexGenerationParams &params);
AutoObjCPtr<id<MTLLibrary>> mDefaultShaders = nil;
RenderPipelineCache mClearRenderPipelineCache;
RenderPipelineCache mBlitRenderPipelineCache;
RenderPipelineCache mBlitPremultiplyAlphaRenderPipelineCache;
RenderPipelineCache mBlitUnmultiplyAlphaRenderPipelineCache;
struct IndexConvesionPipelineCacheKey
{
gl::DrawElementsType srcType;
bool srcBufferOffsetAligned;
bool operator==(const IndexConvesionPipelineCacheKey &other) const;
bool operator<(const IndexConvesionPipelineCacheKey &other) const;
};
std::map<IndexConvesionPipelineCacheKey, AutoObjCPtr<id<MTLComputePipelineState>>>
mIndexConversionPipelineCaches;
std::map<IndexConvesionPipelineCacheKey, AutoObjCPtr<id<MTLComputePipelineState>>>
mTriFanFromElemArrayGeneratorPipelineCaches;
AutoObjCPtr<id<MTLComputePipelineState>> mTriFanFromArraysGeneratorPipeline;
};
} // namespace mtl
} // namespace rx
#endif /* LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_ */