浏览代码

Vulkan: Framebuffer work

Panagiotis Christopoulos Charitos 9 年之前
父节点
当前提交
e6536f1447

+ 0 - 1
include/anki/gr/Enums.h

@@ -276,7 +276,6 @@ enum class AttachmentLoadOperation : U8
 enum class AttachmentStoreOperation : U8
 {
 	STORE,
-	RESOLVE_MSAA,
 	DONT_CARE
 };
 

+ 3 - 3
include/anki/gr/Framebuffer.h

@@ -58,7 +58,7 @@ class FramebufferInitInfo
 {
 public:
 	Array<Attachment, MAX_COLOR_ATTACHMENTS> m_colorAttachments;
-	U32 m_colorAttachmentsCount = 0;
+	U32 m_colorAttachmentCount = 0;
 	Attachment m_depthStencilAttachment;
 
 	FramebufferInitInfo() = default;
@@ -72,12 +72,12 @@ public:
 
 	FramebufferInitInfo& operator=(const FramebufferInitInfo& b)
 	{
-		for(U i = 0; i < b.m_colorAttachmentsCount; i++)
+		for(U i = 0; i < b.m_colorAttachmentCount; i++)
 		{
 			m_colorAttachments[i] = b.m_colorAttachments[i];
 		}
 
-		m_colorAttachmentsCount = b.m_colorAttachmentsCount;
+		m_colorAttachmentCount = b.m_colorAttachmentCount;
 		m_depthStencilAttachment = b.m_depthStencilAttachment;
 		return *this;
 	}

+ 6 - 0
include/anki/gr/vulkan/Common.h

@@ -65,6 +65,12 @@ inline ANKI_USE_RESULT VkColorComponentFlags convertColorWriteMask(ColorBit ak)
 {
 	return static_cast<U>(ak);
 }
+
+/// Convert load op.
+ANKI_USE_RESULT VkAttachmentLoadOp convertLoadOp(AttachmentLoadOperation ak);
+
+/// Convert store op.
+ANKI_USE_RESULT VkAttachmentStoreOp convertStoreOp(AttachmentStoreOperation ak);
 /// @}
 
 } // end namespace anki

+ 16 - 0
include/anki/gr/vulkan/FramebufferImpl.h

@@ -10,6 +10,9 @@
 namespace anki
 {
 
+// Forward
+class Attachment;
+
 /// @addtogroup vulkan
 /// @{
 
@@ -17,12 +20,25 @@ namespace anki
 class FramebufferImpl : public VulkanObject
 {
 public:
+	VkFramebuffer m_framebuffer = VK_NULL_HANDLE;
+	VkRenderPass m_renderPass = VK_NULL_HANDLE;
+
 	FramebufferImpl(GrManager* manager)
 		: VulkanObject(manager)
 	{
 	}
 
 	~FramebufferImpl();
+
+	void init(const FramebufferInitInfo& init);
+
+private:
+	void initRenderPass(const FramebufferInitInfo& init);
+
+	void setupAttachmentDescriptor(
+		const Attachment& in, VkAttachmentDescription& out, Bool depthStencil);
+
+	void initFramebuffer(const FramebufferInitInfo& init);
 };
 /// @}
 

+ 4 - 4
include/anki/gr/vulkan/PipelineImpl.h

@@ -57,11 +57,11 @@ private:
 	initTessellationState(const TessellationStateInfo& t,
 		VkPipelineTessellationStateCreateInfo& ci);
 
-	ANKI_USE_RESULT VkPipelineViewportStateCreateInfo*
-	initViewportState(VkPipelineViewportStateCreateInfo& ci);
+	ANKI_USE_RESULT VkPipelineViewportStateCreateInfo* initViewportState(
+		VkPipelineViewportStateCreateInfo& ci);
 
-	ANKI_USE_RESULT VkPipelineRasterizationStateCreateInfo*
-	initRasterizerState(const RasterizerStateInfo& r, 
+	ANKI_USE_RESULT VkPipelineRasterizationStateCreateInfo* initRasterizerState(
+		const RasterizerStateInfo& r,
 		VkPipelineRasterizationStateCreateInfo& ci);
 
 	ANKI_USE_RESULT VkPipelineMultisampleStateCreateInfo* initMsState(

+ 5 - 5
src/gr/gl/FramebufferImpl.cpp

@@ -21,7 +21,7 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 	ANKI_ASSERT(!isCreated());
 	m_in = init;
 
-	if(m_in.m_colorAttachmentsCount == 0
+	if(m_in.m_colorAttachmentCount == 0
 		&& !m_in.m_depthStencilAttachment.m_texture.isCreated())
 	{
 		m_bindDefault = true;
@@ -36,7 +36,7 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 	glBindFramebuffer(target, m_glName);
 
 	// Attach color
-	for(U i = 0; i < m_in.m_colorAttachmentsCount; i++)
+	for(U i = 0; i < m_in.m_colorAttachmentCount; i++)
 	{
 		const Attachment& att = m_in.m_colorAttachments[i];
 		const GLenum binding = GL_COLOR_ATTACHMENT0 + i;
@@ -157,9 +157,9 @@ void FramebufferImpl::bind(const GlState& state)
 		glBindFramebuffer(GL_FRAMEBUFFER, m_glName);
 
 		// Set the draw buffers
-		if(m_in.m_colorAttachmentsCount)
+		if(m_in.m_colorAttachmentCount)
 		{
-			glDrawBuffers(m_in.m_colorAttachmentsCount, &m_drawBuffers[0]);
+			glDrawBuffers(m_in.m_colorAttachmentCount, &m_drawBuffers[0]);
 		}
 
 		// Invalidate
@@ -171,7 +171,7 @@ void FramebufferImpl::bind(const GlState& state)
 		}
 
 		// Clear buffers
-		for(U i = 0; i < m_in.m_colorAttachmentsCount; i++)
+		for(U i = 0; i < m_in.m_colorAttachmentCount; i++)
 		{
 			const Attachment& att = m_in.m_colorAttachments[i];
 

+ 43 - 0
src/gr/vulkan/Common.cpp

@@ -443,4 +443,47 @@ VkBlendOp convertBlendFunc(BlendFunction ak)
 	return out;
 }
 
+//==============================================================================
+VkAttachmentLoadOp convertLoadOp(AttachmentLoadOperation ak)
+{
+	VkAttachmentLoadOp out = VK_ATTACHMENT_LOAD_OP_MAX_ENUM;
+
+	switch(ak)
+	{
+	case AttachmentLoadOperation::LOAD:
+		out = VK_ATTACHMENT_LOAD_OP_LOAD;
+		break;
+	case AttachmentLoadOperation::CLEAR:
+		out = VK_ATTACHMENT_LOAD_OP_CLEAR;
+		break;
+	case AttachmentLoadOperation::DONT_CARE:
+		out = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+		break;
+	default:
+		ANKI_ASSERT(0);
+	}
+
+	return out;
+}
+
+//==============================================================================
+VkAttachmentStoreOp convertStoreOp(AttachmentStoreOperation ak)
+{
+	VkAttachmentStoreOp out = VK_ATTACHMENT_STORE_OP_MAX_ENUM;
+
+	switch(ak)
+	{
+	case AttachmentStoreOperation::STORE:
+		out = VK_ATTACHMENT_STORE_OP_STORE;
+		break;
+	case AttachmentStoreOperation::DONT_CARE:
+		out = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+		break;
+	default:
+		ANKI_ASSERT(0);
+	}
+
+	return out;
+}
+
 } // end namespace anki

+ 138 - 0
src/gr/vulkan/FramebufferImpl.cpp

@@ -4,3 +4,141 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/gr/vulkan/FramebufferImpl.h>
+#include <anki/gr/Framebuffer.h>
+
+namespace anki
+{
+
+//==============================================================================
+FramebufferImpl::~FramebufferImpl()
+{
+	if(m_framebuffer)
+	{
+		vkDestroyFramebuffer(getDevice(), m_framebuffer, nullptr);
+	}
+
+	if(m_renderPass)
+	{
+		vkDestroyRenderPass(getDevice(), m_renderPass, nullptr);
+	}
+}
+
+//==============================================================================
+void FramebufferImpl::init(const FramebufferInitInfo& init)
+{
+	initRenderPass(init);
+	initFramebuffer(init);
+}
+
+//==============================================================================
+void FramebufferImpl::setupAttachmentDescriptor(
+	const Attachment& att, VkAttachmentDescription& desc, Bool depthStencil)
+{
+	VkImageLayout initLayout = (depthStencil)
+		? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
+		: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+	ANKI_VK_MEMSET_DBG(desc);
+	desc.flags = 0;
+	desc.format = convertFormat(att.m_format);
+	desc.samples = VK_SAMPLE_COUNT_1_BIT;
+	desc.loadOp = convertLoadOp(att.m_loadOperation);
+	desc.storeOp = convertStoreOp(att.m_storeOperation);
+	desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+	desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+	desc.initialLayout = (att.m_loadOperation == AttachmentLoadOperation::LOAD)
+		? initLayout
+		: VK_IMAGE_LAYOUT_UNDEFINED;
+	desc.finalLayout = (att.m_storeOperation == AttachmentStoreOperation::STORE)
+		? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+		: VK_IMAGE_LAYOUT_UNDEFINED;
+}
+
+//==============================================================================
+void FramebufferImpl::initRenderPass(const FramebufferInitInfo& init)
+{
+	VkRenderPassCreateInfo ci;
+	ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+	ci.pNext = nullptr;
+	ci.flags = 0;
+
+	// First setup the attachments
+	ci.attachmentCount = 0;
+	Array<VkAttachmentDescription, MAX_COLOR_ATTACHMENTS + 1>
+		attachmentDescriptions;
+	Array<VkAttachmentReference, MAX_COLOR_ATTACHMENTS> references;
+	Bool hasDepthStencil = init.m_depthStencilAttachment.m_format.m_components
+		!= ComponentFormat::NONE;
+
+	for(U i = 0; i < init.m_colorAttachmentCount; ++i)
+	{
+		setupAttachmentDescriptor(
+			init.m_colorAttachments[i], attachmentDescriptions[i], false);
+
+		references[i].attachment = i;
+		references[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+		++ci.attachmentCount;
+	}
+
+	VkAttachmentReference dsReference = {0, VK_IMAGE_LAYOUT_UNDEFINED};
+	if(hasDepthStencil)
+	{
+		setupAttachmentDescriptor(init.m_depthStencilAttachment,
+			attachmentDescriptions[ci.attachmentCount],
+			true);
+
+		dsReference.attachment = ci.attachmentCount;
+		dsReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+		++ci.attachmentCount;
+	}
+
+	// Setup the render pass
+	ci.pAttachments = &attachmentDescriptions[0];
+
+	// Subpass
+	VkSubpassDescription spass;
+	ANKI_VK_MEMSET_DBG(spass);
+	spass.flags = 0;
+	spass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+	spass.inputAttachmentCount = 0;
+	spass.pInputAttachments = nullptr;
+	spass.colorAttachmentCount = init.m_colorAttachmentCount;
+	spass.pColorAttachments =
+		(init.m_colorAttachmentCount) ? &references[0] : nullptr;
+	spass.pResolveAttachments = nullptr;
+	spass.pDepthStencilAttachment = (hasDepthStencil) ? &dsReference : nullptr;
+	spass.preserveAttachmentCount = 0;
+	spass.pPreserveAttachments = nullptr;
+
+	ci.subpassCount = 1;
+	ci.pSubpasses = &spass;
+	ci.dependencyCount = 0;
+	ci.pDependencies = nullptr;
+
+	ANKI_VK_CHECK(vkCreateRenderPass(getDevice(), &ci, nullptr, &m_renderPass));
+}
+
+//==============================================================================
+void FramebufferImpl::initFramebuffer(const FramebufferInitInfo& init)
+{
+	Bool hasDepthStencil = init.m_depthStencilAttachment.m_format.m_components
+		!= ComponentFormat::NONE;
+
+	VkFramebufferCreateInfo ci;
+	ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+	ci.pNext = nullptr;
+	ci.flags = 0;
+	ci.renderPass = m_renderPass;
+	ci.attachmentCount =
+		init.m_colorAttachmentCount + ((hasDepthStencil) ? 1 : 0);
+
+	// TODO set views
+	// TODO set size and the rest
+
+	ANKI_VK_CHECK(
+		vkCreateFramebuffer(getDevice(), &ci, nullptr, &m_framebuffer));
+}
+
+} // end namespace anki

+ 3 - 3
src/gr/vulkan/GrManagerImpl.cpp

@@ -85,7 +85,7 @@ void GrManagerImpl::initGlobalDsetLayout()
 	ci.pNext = nullptr;
 	ci.flags = 0;
 
-	const U BINDING_COUNT = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS 
+	const U BINDING_COUNT = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS
 		+ MAX_STORAGE_BUFFER_BINDINGS;
 	ci.bindingCount = BINDING_COUNT;
 
@@ -142,8 +142,8 @@ void GrManagerImpl::initGlobalDsetLayout()
 //==============================================================================
 void GrManagerImpl::initGlobalPplineLayout()
 {
-	Array<VkDescriptorSetLayout, MAX_RESOURCE_GROUPS> sets = {{
-		m_globalDescriptorSetLayout, m_globalDescriptorSetLayout}};
+	Array<VkDescriptorSetLayout, MAX_RESOURCE_GROUPS> sets = {
+		{m_globalDescriptorSetLayout, m_globalDescriptorSetLayout}};
 
 	VkPipelineLayoutCreateInfo ci;
 	ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;

+ 19 - 11
src/gr/vulkan/PipelineImpl.cpp

@@ -29,7 +29,7 @@ public:
 	VkPipelineRasterizationStateCreateInfo m_rast;
 	VkPipelineMultisampleStateCreateInfo m_ms;
 	VkPipelineDepthStencilStateCreateInfo m_ds;
-	Array<VkPipelineColorBlendAttachmentState, MAX_COLOR_ATTACHMENTS> 
+	Array<VkPipelineColorBlendAttachmentState, MAX_COLOR_ATTACHMENTS>
 		m_attachments;
 	VkPipelineColorBlendStateCreateInfo m_color;
 	VkPipelineDynamicStateCreateInfo m_dyn;
@@ -77,6 +77,15 @@ static const FilledGraphicsPipelineCreateInfo FILLED;
 // PipelineImpl                                                                =
 //==============================================================================
 
+//==============================================================================
+PipelineImpl::~PipelineImpl()
+{
+	if(m_handle)
+	{
+		vkDestroyPipeline(getDevice(), m_handle, nullptr);
+	}
+}
+
 //==============================================================================
 void PipelineImpl::initGraphics(const PipelineInitInfo& init)
 {
@@ -87,10 +96,10 @@ void PipelineImpl::initGraphics(const PipelineInitInfo& init)
 
 	// Init sub-states
 	ci.pVertexInputState = initVertexStage(init.m_vertex, ci.m_vertex);
-	ci.pInputAssemblyState = initInputAssemblyState(
-		init.m_inputAssembler, ci.m_ia);
-	ci.pTessellationState = initTessellationState(
-		init.m_tessellation, ci.m_tess);
+	ci.pInputAssemblyState =
+		initInputAssemblyState(init.m_inputAssembler, ci.m_ia);
+	ci.pTessellationState =
+		initTessellationState(init.m_tessellation, ci.m_tess);
 	ci.pViewportState = initViewportState(ci.m_vp);
 	ci.pRasterizationState = initRasterizerState(init.m_rasterizer, ci.m_rast);
 	ci.pMultisampleState = initMsState(ci.m_ms);
@@ -121,7 +130,7 @@ void PipelineImpl::initCompute(const PipelineInitInfo& init)
 	stage.pNext = nullptr;
 	stage.flags = 0;
 	stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
-	stage.module = 
+	stage.module =
 		init.m_shaders[ShaderType::COMPUTE]->getImplementation().m_handle;
 	stage.pName = "main";
 	stage.pSpecializationInfo = nullptr;
@@ -267,10 +276,9 @@ VkPipelineMultisampleStateCreateInfo* PipelineImpl::initMsState(
 
 //==============================================================================
 VkPipelineDepthStencilStateCreateInfo* PipelineImpl::initDsState(
-	const DepthStencilStateInfo& ds,
-	VkPipelineDepthStencilStateCreateInfo& ci)
+	const DepthStencilStateInfo& ds, VkPipelineDepthStencilStateCreateInfo& ci)
 {
-	ci.depthTestEnable = ds.m_depthCompareFunction != CompareOperation::ALWAYS 
+	ci.depthTestEnable = ds.m_depthCompareFunction != CompareOperation::ALWAYS
 		|| ds.m_depthWriteEnabled;
 	ci.depthWriteEnable = ds.m_depthWriteEnabled;
 	ci.depthCompareOp = convertCompareOp(ds.m_depthCompareFunction);
@@ -289,11 +297,11 @@ VkPipelineColorBlendStateCreateInfo* PipelineImpl::initColorState(
 
 	for(U i = 0; i < ci.attachmentCount; ++i)
 	{
-		VkPipelineColorBlendAttachmentState& out = 
+		VkPipelineColorBlendAttachmentState& out =
 			const_cast<VkPipelineColorBlendAttachmentState&>(
 				ci.pAttachments[i]);
 		const ColorAttachmentStateInfo& in = c.m_attachments[i];
-		out.blendEnable = !(in.m_srcBlendMethod == BlendMethod::ONE 
+		out.blendEnable = !(in.m_srcBlendMethod == BlendMethod::ONE
 			&& in.m_dstBlendMethod == BlendMethod::ZERO);
 		out.srcColorBlendFactor = convertBlendMethod(in.m_srcBlendMethod);
 		out.dstColorBlendFactor = convertBlendMethod(in.m_dstBlendMethod);

+ 1 - 1
src/renderer/Bloom.cpp

@@ -31,7 +31,7 @@ Error Bloom::initFb(FramebufferPtr& fb, TexturePtr& rt)
 
 	// Create FB
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = rt;
 	fbInit.m_colorAttachments[0].m_loadOperation =
 		AttachmentLoadOperation::DONT_CARE;

+ 1 - 1
src/renderer/Dbg.cpp

@@ -49,7 +49,7 @@ Error Dbg::init(const ConfigSet& initializer)
 
 	// Chose the correct color FAI
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_depthStencilAttachment.m_texture = m_r->getMs().getDepthRt();
 	fbInit.m_depthStencilAttachment.m_loadOperation =
 		AttachmentLoadOperation::LOAD;

+ 1 - 1
src/renderer/DownscaleBlur.cpp

@@ -47,7 +47,7 @@ Error DownscaleBlur::initSubpass(U idx, const UVec2& inputTexSize)
 
 	// FB
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = m_r->getIs().getRt();
 	fbInit.m_colorAttachments[0].m_loadOperation =
 		AttachmentLoadOperation::DONT_CARE;

+ 1 - 1
src/renderer/Fs.cpp

@@ -35,7 +35,7 @@ Error Fs::init(const ConfigSet&)
 		m_rt);
 
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = m_rt;
 	fbInit.m_colorAttachments[0].m_loadOperation =
 		AttachmentLoadOperation::CLEAR;

+ 1 - 1
src/renderer/Ir.cpp

@@ -292,7 +292,7 @@ Error Ir::renderReflection(RenderingContext& ctx,
 		cmdb->bindResourceGroup(m_computeIrradianceResources, 0, &dinf);
 
 		FramebufferInitInfo fbinit;
-		fbinit.m_colorAttachmentsCount = 1;
+		fbinit.m_colorAttachmentCount = 1;
 		fbinit.m_colorAttachments[0].m_texture = m_irradianceCubemapArr;
 		fbinit.m_colorAttachments[0].m_arrayIndex = cubemapIdx;
 		fbinit.m_colorAttachments[0].m_faceIndex = i;

+ 1 - 1
src/renderer/Is.cpp

@@ -422,7 +422,7 @@ Error Is::initInternal(const ConfigSet& config)
 		m_rt);
 
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = m_rt;
 	fbInit.m_colorAttachments[0].m_loadOperation =
 		AttachmentLoadOperation::DONT_CARE;

+ 1 - 1
src/renderer/Ms.cpp

@@ -71,7 +71,7 @@ Error Ms::createRt(U32 samples)
 #endif
 
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = ATTACHMENT_COUNT;
+	fbInit.m_colorAttachmentCount = ATTACHMENT_COUNT;
 	fbInit.m_colorAttachments[0].m_texture = m_rt0;
 	fbInit.m_colorAttachments[0].m_loadOperation = loadop;
 	fbInit.m_colorAttachments[0].m_clearValue.m_colorf = {{1.0, 0.0, 0.0, 0.0}};

+ 1 - 1
src/renderer/Pps.cpp

@@ -49,7 +49,7 @@ Error Pps::initInternal(const ConfigSet& config)
 		m_rt);
 
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = m_rt;
 	fbInit.m_colorAttachments[0].m_loadOperation =
 		AttachmentLoadOperation::DONT_CARE;

+ 1 - 1
src/renderer/Ssao.cpp

@@ -70,7 +70,7 @@ Error Ssao::createFb(FramebufferPtr& fb, TexturePtr& rt)
 
 	// Create FB
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = rt;
 	fbInit.m_colorAttachments[0].m_loadOperation =
 		AttachmentLoadOperation::DONT_CARE;

+ 1 - 1
src/renderer/Upsample.cpp

@@ -80,7 +80,7 @@ Error Upsample::init(const ConfigSet& config)
 
 	// Create FB
 	FramebufferInitInfo fbInit;
-	fbInit.m_colorAttachmentsCount = 1;
+	fbInit.m_colorAttachmentCount = 1;
 	fbInit.m_colorAttachments[0].m_texture = m_r->getIs().getRt();
 	fbInit.m_colorAttachments[0].m_loadOperation =
 		AttachmentLoadOperation::LOAD;