protected override Number4 GetLinear(
            SamplerState samplerState, ITextureMipMap mipMap, 
            ref Number4 texCoords)
        {
            int intTexelX = (int) texCoords.Float0;
            int intTexelY = (int) texCoords.Float1;

            float fracX = texCoords.Float0 - intTexelX;
            float fracY = texCoords.Float1 - intTexelY;

            texCoords.Int0 = intTexelX;
            texCoords.Int1 = intTexelY;
            var c00 = GetColor(samplerState, mipMap, ref texCoords);

            texCoords.Int0 = intTexelX + 1;
            texCoords.Int1 = intTexelY;
            var c10 = GetColor(samplerState, mipMap, ref texCoords);

            texCoords.Int0 = intTexelX;
            texCoords.Int1 = intTexelY + 1;
            var c01 = GetColor(samplerState, mipMap, ref texCoords);

            texCoords.Int0 = intTexelX + 1;
            texCoords.Int1 = intTexelY + 1;
            var c11 = GetColor(samplerState, mipMap, ref texCoords);

            var cMinV = Number4.Lerp(ref c00, ref c10, fracX);
            var cMaxV = Number4.Lerp(ref c01, ref c11, fracX);

            return Number4.Lerp(ref cMinV, ref cMaxV, fracY);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="samplerState"></param>
        /// <param name="location"></param>
        /// <param name="lod">A number that specifies the mipmap level. If the value is &lt;=0, the zero'th (biggest map)
        /// is used. The fractional value (if supplied) is used to interpolate between two mipmap levels.</param>
        /// <returns></returns>
        public Number4 SampleLevel(
            ITexture texture, SamplerState samplerState,
            ref Number4 location,
            float lod)
        {
            // TODO: Don't always pass minifying=true to GetFilteredColor.

            switch (samplerState.Filter)
            {
                case Filter.MinPointMagLinearMipPoint:
                case Filter.MinLinearMagMipPoint:
                case Filter.MinMagLinearMipPoint:
                case Filter.MinMagMipPoint:
                {
                    // Calculate nearest mipmap level.
                    var nearestLevel = MathUtility.Round(lod);
                    return GetFilteredColor(texture, samplerState, true, nearestLevel, ref location);
                }
                case Filter.MinLinearMagPointMipLinear:
                case Filter.MinMagMipLinear:
                case Filter.MinMagPointMipLinear:
                case Filter.MinPointMagMipLinear:
                {
                    // Calculate nearest two levels and linearly filter between them.
                    var nearestLevelInt = (int) lod;
                    var d = lod - nearestLevelInt;
                    var c1 = GetFilteredColor(texture, samplerState, true, nearestLevelInt, ref location);
                    var c2 = GetFilteredColor(texture, samplerState, true, nearestLevelInt + 1, ref location);
                    return Number4.Lerp(ref c1, ref c2, d);
                }
                default:
                    throw new NotSupportedException();
            }
        }
		public VirtualMachine(BytecodeContainer bytecode, int numContexts)
		{
            if (bytecode.Shader.Version.ProgramType == ProgramType.PixelShader && numContexts % 4 != 0)
                throw new ArgumentOutOfRangeException("numContexts", "numContexts must be a multiple of 4 for pixel shaders.");

			_bytecode = bytecode;

			var instructionTokens = bytecode.Shader.Tokens.OfType<InstructionToken>().ToArray();
			var branchingInstructions = ExplicitBranchingRewriter.Rewrite(instructionTokens);
			var controlFlowGraph = ControlFlowGraph.FromInstructions(branchingInstructions);
            _executableInstructions = ExecutableInstructionRewriter.Rewrite(controlFlowGraph).ToArray();

			_requiredRegisters = RequiredRegisters.FromShader(bytecode.Shader);

			_executionContexts = new ExecutionContext[numContexts];
			for (int i = 0; i < _executionContexts.Length; i++)
				_executionContexts[i] = new ExecutionContext(this, i, _requiredRegisters);

            ConstantBuffers = new Number4[_requiredRegisters.ConstantBuffers.Count][];
            for (int i = 0; i < _requiredRegisters.ConstantBuffers.Count; i++)
                ConstantBuffers[i] = new Number4[_requiredRegisters.ConstantBuffers[i]];

		    TextureSamplers = new TextureSampler[_requiredRegisters.Resources.Count];
			for (int i = 0; i < _requiredRegisters.Resources.Count; i++)
				TextureSamplers[i] = TextureSamplerFactory.Create(_requiredRegisters.Resources[i]);

            Textures = new ITexture[_requiredRegisters.Resources.Count];
            Samplers = new SamplerState[_requiredRegisters.Samplers];
		}
 protected override Number4 GetNearestNeighbor(
     SamplerState samplerState, ITextureMipMap mipMap, 
     ref Number4 texCoords)
 {
     texCoords.Int0 = MathUtility.Floor(texCoords.Float0);
     texCoords.Int1 = MathUtility.Floor(texCoords.Float1);
     return GetColor(samplerState, mipMap, ref texCoords);
 }
 public Number4 SampleGrad(
     ITexture texture, SamplerState samplerState,
     ref Number4 location,
     ref Number4 ddx, ref Number4 ddy)
 {
     var lod = CalculateLevelOfDetail(texture, samplerState, ref ddx, ref ddy);
     return SampleLevel(texture, samplerState, ref location, lod);
 }
        private static Number4 GetColor(SamplerState samplerState, ITextureMipMap mipMap, ref Number4 texCoords)
        {
            if (!GetTextureAddress(texCoords.Int0, mipMap.Width, samplerState.AddressU, out texCoords.Int0))
                return samplerState.BorderColor;
            if (!GetTextureAddress(texCoords.Int1, mipMap.Height, samplerState.AddressV, out texCoords.Int1))
                return samplerState.BorderColor;

            return mipMap.GetData(ref texCoords);
        }
        private Number4 GetFilteredColor(
            ITexture texture, SamplerState samplerState, bool minifying, int level,
            ref Number4 location)
        {
            var clampedLevel = MathUtility.Clamp(level, 0, texture.MipMapCount - 1);

            ITextureMipMap mipMap;
            Number4 texCoords;
            GetMipMapAndTransformedCoordinates(
                texture, ref location, clampedLevel,
                out mipMap, out texCoords);

            // Minifying
            if (minifying)
                switch (samplerState.Filter)
                {
                    case Filter.MinMagMipPoint:
                    case Filter.MinMagPointMipLinear:
                    case Filter.MinPointMagLinearMipPoint:
                    case Filter.MinPointMagMipLinear:
                        return GetNearestNeighbor(samplerState, mipMap, ref texCoords);
                    case Filter.MinLinearMagMipPoint:
                    case Filter.MinLinearMagPointMipLinear:
                    case Filter.MinMagLinearMipPoint:
                    case Filter.MinMagMipLinear:
                        return GetLinear(samplerState, mipMap, ref texCoords);
                    default:
                        throw new NotSupportedException();
                }

            // Magnifying
            switch (samplerState.Filter)
            {
                case Filter.MinLinearMagMipPoint:
                case Filter.MinLinearMagPointMipLinear:
                case Filter.MinMagMipPoint:
                case Filter.MinMagPointMipLinear:
                    return GetNearestNeighbor(samplerState, mipMap, ref texCoords);
                case Filter.MinMagLinearMipPoint:
                case Filter.MinMagMipLinear:
                case Filter.MinPointMagLinearMipPoint:
                case Filter.MinPointMagMipLinear:
                    return GetLinear(samplerState, mipMap, ref texCoords);
                default:
                    throw new NotSupportedException();
            }
        }
        public override float CalculateLevelOfDetail(
            ITexture texture, SamplerState samplerState, 
            ref Number4 ddx, ref Number4 ddy)
        {
            var mostDetailedMipMap = texture.GetMipMap(0, 0);
            int width = mostDetailedMipMap.Width;
            int height = mostDetailedMipMap.Height;
            float xBound2 = width * width;
            float yBound2 = height * height;

            float dudx2 = ddx.Float0 * ddx.Float0 * xBound2;
            float dvdx2 = ddx.Float1 * ddx.Float1 * yBound2;
            float dudy2 = ddy.Float0 * ddy.Float0 * xBound2;
            float dvdy2 = ddy.Float1 * ddy.Float1 * yBound2;

            // Proportional to the amount of a texel on display in a single pixel
            float pixelSizeTexelRatio2 = Math.Max(dudx2 + dvdx2, dudy2 + dvdy2);

            // Uses formula for p410 of Essential Mathematics for Games and Interactive Applications
            float result = 0.5f * MathUtility.Log2(pixelSizeTexelRatio2);

            // Clamp to >= 0.
            return Math.Max(result, 0.0f);
        }
 public abstract float CalculateLevelOfDetail(
     ITexture texture, SamplerState samplerState,
     ref Number4 ddx, ref Number4 ddy);
 protected abstract Number4 GetLinear(
     SamplerState samplerState, ITextureMipMap mipMap, 
     ref Number4 texCoords);
 protected abstract Number4 GetNearestNeighbor(
     SamplerState samplerState, ITextureMipMap mipMap, 
     ref Number4 texCoords);
		public void SetSampler(RegisterIndex registerIndex, SamplerState sampler)
		{
			Samplers[registerIndex.Index1D] = sampler;
		}