beginRender( renderContext ) {

		const renderContextData = this.get( renderContext );

		const device = this.device;
		const occlusionQueryCount = renderContext.occlusionQueryCount;

		let occlusionQuerySet;

		if ( occlusionQueryCount > 0 ) {

			if ( renderContextData.currentOcclusionQuerySet ) renderContextData.currentOcclusionQuerySet.destroy();
			if ( renderContextData.currentOcclusionQueryBuffer ) renderContextData.currentOcclusionQueryBuffer.destroy();

			// Get a reference to the array of objects with queries. The renderContextData property
			// can be changed by another render pass before the buffer.mapAsyc() completes.
			renderContextData.currentOcclusionQuerySet = renderContextData.occlusionQuerySet;
			renderContextData.currentOcclusionQueryBuffer = renderContextData.occlusionQueryBuffer;
			renderContextData.currentOcclusionQueryObjects = renderContextData.occlusionQueryObjects;

			//

			occlusionQuerySet = device.createQuerySet( { type: 'occlusion', count: occlusionQueryCount, label: `occlusionQuerySet_${ renderContext.id }` } );

			renderContextData.occlusionQuerySet = occlusionQuerySet;
			renderContextData.occlusionQueryIndex = 0;
			renderContextData.occlusionQueryObjects = new Array( occlusionQueryCount );

			renderContextData.lastOcclusionObject = null;

		}

		let descriptor;

		if ( renderContext.textures === null ) {

			descriptor = this._getDefaultRenderPassDescriptor();

		} else {

			descriptor = this._getRenderPassDescriptor( renderContext, { loadOp: GPULoadOp.Load } );

		}

		this.initTimestampQuery( renderContext, descriptor );

		descriptor.occlusionQuerySet = occlusionQuerySet;

		const depthStencilAttachment = descriptor.depthStencilAttachment;

		if ( renderContext.textures !== null ) {

			const colorAttachments = descriptor.colorAttachments;

			for ( let i = 0; i < colorAttachments.length; i ++ ) {

				const colorAttachment = colorAttachments[ i ];

				if ( renderContext.clearColor ) {

					colorAttachment.clearValue = i === 0 ? renderContext.clearColorValue : { r: 0, g: 0, b: 0, a: 1 };
					colorAttachment.loadOp = GPULoadOp.Clear;

				} else {

					colorAttachment.loadOp = GPULoadOp.Load;

				}

				colorAttachment.storeOp = GPUStoreOp.Store;

			}

		} else {

			const colorAttachment = descriptor.colorAttachments[ 0 ];

			if ( renderContext.clearColor ) {

				colorAttachment.clearValue = renderContext.clearColorValue;
				colorAttachment.loadOp = GPULoadOp.Clear;

			} else {

				colorAttachment.loadOp = GPULoadOp.Load;

			}

		  	colorAttachment.storeOp = GPUStoreOp.Store;

		}

		//

		if ( renderContext.depth ) {

			if ( renderContext.clearDepth ) {

				depthStencilAttachment.depthClearValue = renderContext.clearDepthValue;
				depthStencilAttachment.depthLoadOp = GPULoadOp.Clear;

			} else {

				depthStencilAttachment.depthLoadOp = GPULoadOp.Load;

			}

		  depthStencilAttachment.depthStoreOp = GPUStoreOp.Store;

		}

		if ( renderContext.stencil ) {

		  if ( renderContext.clearStencil ) {

				depthStencilAttachment.stencilClearValue = renderContext.clearStencilValue;
				depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear;

			} else {

				depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;

			}

		  depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store;

		}

		//

		const encoder = device.createCommandEncoder( { label: 'renderContext_' + renderContext.id } );

		// shadow arrays - prepare bundle encoders for each camera in an array camera

		if ( this._isRenderCameraDepthArray( renderContext ) === true ) {

			const cameras = renderContext.camera.cameras;

			if ( ! renderContextData.layerDescriptors || renderContextData.layerDescriptors.length !== cameras.length ) {

				this._createDepthLayerDescriptors( renderContext, renderContextData, descriptor, cameras );

			} else {

				this._updateDepthLayerDescriptors( renderContext, renderContextData, cameras );

			}

			// Create bundle encoders for each layer
			renderContextData.bundleEncoders = [];
			renderContextData.bundleSets = [];

			// Create separate bundle encoders for each camera in the array
			for ( let i = 0; i < cameras.length; i ++ ) {

				const bundleEncoder = this.pipelineUtils.createBundleEncoder(
					renderContext,
					'renderBundleArrayCamera_' + i
				);

				// Initialize state tracking for this bundle
				const bundleSets = {
					attributes: {},
					bindingGroups: [],
					pipeline: null,
					index: null
				};

				renderContextData.bundleEncoders.push( bundleEncoder );
				renderContextData.bundleSets.push( bundleSets );

			}

			// We'll complete the bundles in finishRender
			renderContextData.currentPass = null;

		} else {

			const currentPass = encoder.beginRenderPass( descriptor );
			renderContextData.currentPass = currentPass;

			if ( renderContext.viewport ) {

				this.updateViewport( renderContext );

			}

			if ( renderContext.scissor ) {

				const { x, y, width, height } = renderContext.scissorValue;
				currentPass.setScissorRect( x, y, width, height );

			}

		}

		//

		renderContextData.descriptor = descriptor;
		renderContextData.encoder = encoder;
		renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null };
		renderContextData.renderBundles = [];

	}
This method is executed at the beginning of a render call and prepares
the WebGPU state for upcoming render calls

@param {RenderContext} renderContext - The render context.