From 837143bb124457f30413d906f1d13706f1c7ea21 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 25 Nov 2023 16:58:09 -0500 Subject: [PATCH] naga-agal: Fix handling of sampler overrides After some testing, and looking at OpenFL, I believe I've determined the correct behavior for AGAL sampling: Each time a Context3D.setProgram or Context3D.setSamplerStateAt call is made, the sampler config for the used texture slot(s) is updated with the new wrapping/filter behavior. For setProgram, this comes from all of the 'tex' opcodes used within the program. However, when the 'ignoresampler' flag is set in a 'tex' opcode, the setProgram call does *not* override the existing sampler config. As a result, that program will sample with the behavior determined by the most recent setSamplerStateAt or setProgram call involving the used texture slot(s). Previously, we were always overriding the opcode sampler config with the values from Context3D.setSamplerStateAt. However, I didn't realize that the order of the calls matter, so none of my tests ended up observing the effect of 'ignoresampler'. We now need to process AGAL bytecode twice - a quick initial parse to determine the sampler configs (which need to be updated when we call 'setProgram'), and a second time when to build the Naga module (which needs to wait until we have the vertex attributes available, which can be changed by ActionScript after setting the program). --- render/naga-agal/src/builder.rs | 151 +++++++++++----- render/naga-agal/src/lib.rs | 17 +- render/naga-agal/src/types.rs | 12 +- .../snapshots/wgsl__complex_raytrace-2.snap | 3 +- render/naga-agal/tests/wgsl.rs | 2 +- render/wgpu/src/context3d/current_pipeline.rs | 30 +++- render/wgpu/src/context3d/shader_pair.rs | 18 +- .../stage3d_ignore_sampler_override/Test.as | 169 ++++++++++++++++++ .../output.expected.png | Bin 0 -> 42766 bytes .../output.txt | 0 .../stage3d_ignore_sampler_override/test.fla | Bin 0 -> 4343 bytes .../stage3d_ignore_sampler_override/test.swf | Bin 0 -> 11790 bytes .../stage3d_ignore_sampler_override/test.toml | 9 + .../com/adobe/utils/AGALMiniAssembler.as | 2 +- 14 files changed, 350 insertions(+), 63 deletions(-) create mode 100644 tests/tests/swfs/avm2/stage3d_ignore_sampler_override/Test.as create mode 100644 tests/tests/swfs/avm2/stage3d_ignore_sampler_override/output.expected.png create mode 100644 tests/tests/swfs/avm2/stage3d_ignore_sampler_override/output.txt create mode 100755 tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.fla create mode 100644 tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.swf create mode 100644 tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.toml diff --git a/render/naga-agal/src/builder.rs b/render/naga-agal/src/builder.rs index bf99d83d4..3031fb4c7 100644 --- a/render/naga-agal/src/builder.rs +++ b/render/naga-agal/src/builder.rs @@ -15,7 +15,8 @@ use num_traits::FromPrimitive; use crate::varying::VaryingRegisters; use crate::{ - types::*, Error, ShaderType, VertexAttributeFormat, MAX_VERTEX_ATTRIBUTES, SHADER_ENTRY_POINT, + types::*, Error, ShaderType, VertexAttributeFormat, MAX_TEXTURES, MAX_VERTEX_ATTRIBUTES, + SHADER_ENTRY_POINT, }; const VERTEX_PROGRAM_CONTANTS: u64 = 128; @@ -52,6 +53,15 @@ struct TextureSamplers { repeat_u_clamp_v_nearest: Handle, } +#[derive(Copy, Clone)] +struct TextureBindingData { + // The `Expression::GlobalVariable` corresponding to the texture that we loaded. + expr: Handle, + // The sample config values extracted from the opcode + // (which may override or be overridden by values set by Context3D.setSamplerStateAt) + sampler_config: SamplerConfig, +} + pub(crate) struct NagaBuilder<'a> { pub(crate) module: Module, pub(crate) func: Function, @@ -74,9 +84,9 @@ pub(crate) struct NagaBuilder<'a> { pub(crate) varying_registers: VaryingRegisters, // Whenever we encounter a texture load at a particular index - // for the first time, we store an `Expression::GlobalVariable` - // here corresponding to the texture that we loaded. - texture_bindings: [Option>; 8], + // for the first time, we store the expression we generate, + // as well as the sampler parameters used. + texture_bindings: [Option; MAX_TEXTURES], // Whenever we read from a particular temporary register // for the first time, we create a new local variable @@ -263,7 +273,7 @@ impl VertexAttributeFormat { pub struct ShaderConfig<'a> { pub shader_type: ShaderType, pub vertex_attributes: &'a [Option; 8], - pub sampler_overrides: &'a [Option; 8], + pub sampler_configs: &'a [SamplerConfig; 8], pub version: AgalVersion, } @@ -273,12 +283,14 @@ pub enum AgalVersion { Agal2, } +struct ParsedBytecode { + version: AgalVersion, + shader_type: ShaderType, + operations: Vec<(Opcode, DestField, SourceField, Source2)>, +} + impl<'a> NagaBuilder<'a> { - pub fn process_agal( - mut agal: &[u8], - vertex_attributes: &[Option; MAX_VERTEX_ATTRIBUTES], - sampler_overrides: &[Option; 8], - ) -> Result { + fn parse_bytecode(mut agal: &[u8]) -> Result { let data = &mut agal; let mut header = [0; 7]; @@ -305,12 +317,7 @@ impl<'a> NagaBuilder<'a> { _ => return Err(Error::InvalidShaderType(header[6])), }; - let mut builder = NagaBuilder::new(ShaderConfig { - shader_type, - vertex_attributes, - sampler_overrides, - version, - }); + let mut operations = Vec::new(); while !data.is_empty() { let mut token = [0; 24]; @@ -331,7 +338,63 @@ impl<'a> NagaBuilder<'a> { token[16..24].try_into().unwrap(), ))?) }; + operations.push((opcode, dest, source1, source2)) + } + Ok(ParsedBytecode { + version, + shader_type, + operations, + }) + } + pub fn extract_sampler_configs(agal: &[u8]) -> Result<[Option; MAX_TEXTURES]> { + let parsed = Self::parse_bytecode(agal)?; + let mut sampler_configs = [None; MAX_TEXTURES]; + for (_opcode, _dest, _source1, source2) in parsed.operations { + if let Source2::Sampler(sampler_field) = source2 { + // When the 'ignore_sampler' field is set, we do not update the sampler config. + // The existing sampler value will end up getting used + // (which comes from a previous Context3D.setSamplerStateAt + // or Context3D.setProgram call) + if sampler_field.special.ignore_sampler { + continue; + } + + let sampler_config = SamplerConfig { + wrapping: sampler_field.wrapping, + filter: sampler_field.filter, + mipmap: sampler_field.mipmap, + }; + let index = sampler_field.reg_num as usize; + if sampler_configs[index].is_none() { + sampler_configs[index] = Some(sampler_config); + } else if sampler_configs[index] != Some(sampler_config) { + return Err(Error::SamplerConfigMismatch { + texture: index, + old: sampler_configs[index].unwrap(), + new: sampler_config, + }); + } + } + } + + Ok(sampler_configs) + } + + pub fn build_module( + agal: &[u8], + vertex_attributes: &[Option; MAX_VERTEX_ATTRIBUTES], + sampler_configs: &[SamplerConfig; 8], + ) -> Result { + let parsed = Self::parse_bytecode(agal)?; + let mut builder = NagaBuilder::new(ShaderConfig { + shader_type: parsed.shader_type, + vertex_attributes, + sampler_configs, + version: parsed.version, + }); + + for (opcode, dest, source1, source2) in parsed.operations { builder.process_opcode(&opcode, &dest, &source1, &source2)?; } builder.finish() @@ -737,8 +800,13 @@ impl<'a> NagaBuilder<'a> { fn emit_texture_load( &mut self, index: usize, - dimension: Dimension, + sampler_field: &SamplerField, ) -> Result> { + let sampler_config = SamplerConfig { + wrapping: sampler_field.wrapping, + filter: sampler_field.filter, + mipmap: sampler_field.mipmap, + }; if self.texture_bindings[index].is_none() { let global_var = self.module.global_variables.append( GlobalVariable { @@ -750,7 +818,7 @@ impl<'a> NagaBuilder<'a> { }), // Note - we assume that a given texture is always sampled with the same dimension // (2d or cube) - ty: match dimension { + ty: match sampler_field.dimension { Dimension::TwoD => self.image2d, Dimension::Cube => self.imagecube, }, @@ -758,13 +826,25 @@ impl<'a> NagaBuilder<'a> { }, Span::UNDEFINED, ); - self.texture_bindings[index] = Some( - self.func + self.texture_bindings[index] = Some(TextureBindingData { + expr: self + .func .expressions .append(Expression::GlobalVariable(global_var), Span::UNDEFINED), - ); + sampler_config, + }); } - Ok(self.texture_bindings[index].unwrap()) + let data = self.texture_bindings[index].as_ref().unwrap(); + // AGAL requires that a given texture ID always be sampled with the same settings + // within a program + if data.sampler_config != sampler_config { + return Err(Error::SamplerConfigMismatch { + texture: index, + old: data.sampler_config, + new: sampler_config, + }); + } + Ok(self.texture_bindings[index].unwrap().expr) } fn emit_source_field_load( @@ -1145,25 +1225,12 @@ impl<'a> NagaBuilder<'a> { panic!("Invalid sample register type {:?}", sampler_field); } - let mut filter = sampler_field.filter; - let mut wrapping = sampler_field.wrapping; - - // See https://github.com/openfl/openfl/issues/1332 - - // FIXME - Flash Player seems to unconditionally use sampler overrides, - // regardless of whether or not `ignore_sampler` is set. I haven't - // found any real SWFs that use it, so let's panic so that get - // get a bug report if it ever happens. - if sampler_field.special.ignore_sampler { - panic!("Found ignore_sampler in {:?}", sampler_field); - } - - if let Some(sampler_override) = - &self.shader_config.sampler_overrides[texture_id as usize] - { - filter = sampler_override.filter; - wrapping = sampler_override.wrapping; - } + // Always take filter/wrapping from the shader config, which takes into account both the values + // from the opcode and any Context3D.setSamplerStateAt calls. + // FIXME - refactor this to just bind the correct sampler at the proper index from the wgpu side. + let sampler_config = self.shader_config.sampler_configs[texture_id as usize]; + let filter = sampler_config.filter; + let wrapping = sampler_config.wrapping; let sampler_binding = match (filter, wrapping) { (Filter::Linear, Wrapping::Clamp) => texture_samplers.clamp_linear, @@ -1229,7 +1296,7 @@ impl<'a> NagaBuilder<'a> { } }; - let image = self.emit_texture_load(texture_id as usize, sampler_field.dimension)?; + let image = self.emit_texture_load(texture_id as usize, sampler_field)?; let tex = self.evaluate_expr(Expression::ImageSample { image, sampler: sampler_binding, diff --git a/render/naga-agal/src/lib.rs b/render/naga-agal/src/lib.rs index 7090b96ca..b5eb4ada0 100644 --- a/render/naga-agal/src/lib.rs +++ b/render/naga-agal/src/lib.rs @@ -29,6 +29,11 @@ pub enum Error { ReadError(std::io::Error), InvalidOpcode(u32), InvalidVersion(u32), + SamplerConfigMismatch { + texture: usize, + old: SamplerConfig, + new: SamplerConfig, + }, } impl From for Error { @@ -43,7 +48,7 @@ pub enum ShaderType { Fragment, } -pub use types::{Filter, Mipmap, SamplerOverride, Wrapping}; +pub use types::{Filter, Mipmap, SamplerConfig, Wrapping}; /** * Compiles an Adobe AGAL shader to a Naga Module. @@ -93,7 +98,13 @@ pub use types::{Filter, Mipmap, SamplerOverride, Wrapping}; pub fn agal_to_naga( agal: &[u8], vertex_attributes: &[Option; MAX_VERTEX_ATTRIBUTES], - sampler_overrides: &[Option; MAX_TEXTURES], + sampler_configs: &[SamplerConfig; MAX_TEXTURES], ) -> Result { - NagaBuilder::process_agal(agal, vertex_attributes, sampler_overrides) + NagaBuilder::build_module(agal, vertex_attributes, sampler_configs) +} + +pub fn extract_sampler_configs( + agal: &[u8], +) -> Result<[Option; MAX_TEXTURES], Error> { + NagaBuilder::extract_sampler_configs(agal) } diff --git a/render/naga-agal/src/types.rs b/render/naga-agal/src/types.rs index db6eefc68..db933e39a 100644 --- a/render/naga-agal/src/types.rs +++ b/render/naga-agal/src/types.rs @@ -186,12 +186,22 @@ pub struct SamplerField { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct SamplerOverride { +pub struct SamplerConfig { pub wrapping: Wrapping, pub filter: Filter, pub mipmap: Mipmap, } +impl Default for SamplerConfig { + fn default() -> Self { + SamplerConfig { + wrapping: Wrapping::Clamp, + filter: Filter::Nearest, + mipmap: Mipmap::Disable, + } + } +} + impl SamplerField { pub fn parse(val: u64) -> Result { let reg_num = (val & 0xFFFF) as u16; diff --git a/render/naga-agal/tests/snapshots/wgsl__complex_raytrace-2.snap b/render/naga-agal/tests/snapshots/wgsl__complex_raytrace-2.snap index 5cbd9265e..cc6c01006 100644 --- a/render/naga-agal/tests/snapshots/wgsl__complex_raytrace-2.snap +++ b/render/naga-agal/tests/snapshots/wgsl__complex_raytrace-2.snap @@ -1,6 +1,5 @@ --- source: render/naga-agal/tests/wgsl.rs -assertion_line: 105 expression: output --- struct FragmentOutput { @@ -2675,7 +2674,7 @@ fn main(@location(0) param: vec4) -> FragmentOutput { } } let _e5727: vec4 = temporary9_; - let _e5731: vec4 = textureSample(texture0_, sampler2_, _e5727.xyzz.xyz); + let _e5731: vec4 = textureSample(texture0_, sampler3_, _e5727.xyzz.xyz); temporary1_ = _e5731; let _e5732: vec4 = temporary11_; let _e5736: vec4 = constant_registers[16u]; diff --git a/render/naga-agal/tests/wgsl.rs b/render/naga-agal/tests/wgsl.rs index fb8ad99fe..d148cd07c 100644 --- a/render/naga-agal/tests/wgsl.rs +++ b/render/naga-agal/tests/wgsl.rs @@ -22,7 +22,7 @@ pub fn to_wgsl(module: &Module) -> String { // Making this a macro gives us a better span in 'inta' macro_rules! test_shader { ($shader:expr, $attrs:expr, $shader_type:expr $(,)?) => { - let module = agal_to_naga(&$shader, $attrs, &[None; 8]).unwrap(); + let module = agal_to_naga(&$shader, $attrs, &[Default::default(); 8]).unwrap(); let output = to_wgsl(&module); insta::assert_display_snapshot!(output); }; diff --git a/render/wgpu/src/context3d/current_pipeline.rs b/render/wgpu/src/context3d/current_pipeline.rs index bea87fa1d..1b1611a92 100644 --- a/render/wgpu/src/context3d/current_pipeline.rs +++ b/render/wgpu/src/context3d/current_pipeline.rs @@ -1,5 +1,5 @@ use naga::valid::{Capabilities, ValidationFlags, Validator}; -use naga_agal::{Filter, SamplerOverride, Wrapping}; +use naga_agal::{Filter, SamplerConfig, Wrapping}; use ruffle_render::backend::{ Context3DTextureFilter, Context3DTriangleFace, Context3DVertexBufferFormat, Context3DWrapMode, Texture, @@ -84,7 +84,13 @@ pub struct CurrentPipeline { dirty: Cell, - sampler_override: [Option; 8], + // Sampler configuration information for each texture slot. + // This is updated by `Context3D.setSamplerStateAt`, as well + // as in `Context3D.setProgram` (based on the sampling opcodes + // in the program). All texture slots have a sampler set by default + // (which allows rendering with an 'ignoresampler' tex opcode, + // and no calls to Context3D.setSamplerStateAt) + sampler_configs: [SamplerConfig; 8], } #[derive(Clone)] @@ -159,12 +165,20 @@ impl CurrentPipeline { target_format: TextureFormat::Rgba8Unorm, - sampler_override: [None; 8], + sampler_configs: [SamplerConfig::default(); 8], } } pub fn set_shaders(&mut self, shaders: Option>) { self.dirty.set(true); self.shaders = shaders; + if let Some(shaders) = &self.shaders { + for (i, sampler_config) in shaders.fragment_sampler_configs().iter().enumerate() { + // When we call `Context3D.setProgram`, sampler configs from the fragment shader override + // any previously set sampler configs (if 'ignoresampler' was set in the program, then the corresponding + // array entry will be `None`). + self.sampler_configs[i] = sampler_config.unwrap_or(self.sampler_configs[i]); + } + } } pub fn update_texture_at(&mut self, index: usize, texture: Option) { @@ -325,7 +339,7 @@ impl CurrentPipeline { descriptors, ShaderCompileData { vertex_attributes: agal_attributes, - sampler_overrides: self.sampler_override, + sampler_configs: self.sampler_configs, bound_textures: self.bound_textures.clone(), }, ); @@ -538,7 +552,7 @@ impl CurrentPipeline { wrap: ruffle_render::backend::Context3DWrapMode, filter: ruffle_render::backend::Context3DTextureFilter, ) { - let sampler_override = SamplerOverride { + let sampler_config = SamplerConfig { wrapping: match wrap { Context3DWrapMode::Clamp => Wrapping::Clamp, Context3DWrapMode::Repeat => Wrapping::Repeat, @@ -553,10 +567,8 @@ impl CurrentPipeline { // FIXME - implement this mipmap: naga_agal::Mipmap::Disable, }; - if self.sampler_override[sampler] != Some(sampler_override) { - self.dirty.set(true); - self.sampler_override[sampler] = Some(sampler_override); - } + self.dirty.set(true); + self.sampler_configs[sampler] = sampler_config; } } diff --git a/render/wgpu/src/context3d/shader_pair.rs b/render/wgpu/src/context3d/shader_pair.rs index ba684689a..ecafcbbc5 100644 --- a/render/wgpu/src/context3d/shader_pair.rs +++ b/render/wgpu/src/context3d/shader_pair.rs @@ -1,5 +1,5 @@ use lru::LruCache; -use naga_agal::{SamplerOverride, VertexAttributeFormat}; +use naga_agal::{SamplerConfig, VertexAttributeFormat}; use ruffle_render::backend::ShaderModule; use std::{ borrow::Cow, @@ -22,7 +22,9 @@ use crate::descriptors::Descriptors; pub struct ShaderPairAgal { vertex_bytecode: Vec, + fragment_bytecode: Vec, + fragment_sampler_configs: [Option; 8], // Caches compiled wgpu shader modules. The cache key represents all of the data // that we need to pass to `naga_agal::agal_to_naga` to compile a shader. compiled: RefCell>, @@ -38,14 +40,22 @@ pub struct CompiledShaderProgram { impl ShaderPairAgal { pub fn new(vertex_bytecode: Vec, fragment_bytecode: Vec) -> Self { + let fragment_sampler_configs = + naga_agal::extract_sampler_configs(&fragment_bytecode).unwrap(); + Self { vertex_bytecode, fragment_bytecode, + fragment_sampler_configs, // TODO - figure out a good size for this cache. compiled: RefCell::new(LruCache::new(NonZeroUsize::new(2).unwrap())), } } + pub fn fragment_sampler_configs(&self) -> &[Option; 8] { + &self.fragment_sampler_configs + } + pub fn compile( &self, descriptors: &Descriptors, @@ -58,7 +68,7 @@ impl ShaderPairAgal { let vertex_naga_module = naga_agal::agal_to_naga( &self.vertex_bytecode, &data.vertex_attributes, - &data.sampler_overrides, + &data.sampler_configs, ) .unwrap(); let vertex_module = @@ -72,7 +82,7 @@ impl ShaderPairAgal { let fragment_naga_module = naga_agal::agal_to_naga( &self.fragment_bytecode, &data.vertex_attributes, - &data.sampler_overrides, + &data.sampler_configs, ) .unwrap(); let fragment_module = @@ -200,7 +210,7 @@ impl ShaderPairAgal { #[derive(Hash, Eq, PartialEq, Clone)] pub struct ShaderCompileData { - pub sampler_overrides: [Option; 8], + pub sampler_configs: [SamplerConfig; 8], pub vertex_attributes: [Option; MAX_VERTEX_ATTRIBUTES], pub bound_textures: [Option; 8], } diff --git a/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/Test.as b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/Test.as new file mode 100644 index 000000000..4f19533c5 --- /dev/null +++ b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/Test.as @@ -0,0 +1,169 @@ +package { + import com.adobe.utils.AGALMiniAssembler; + + import flash.display.Sprite; + import flash.display.Stage3D; + import flash.display.StageAlign; + import flash.display.StageScaleMode; + import flash.display3D.Context3D; + import flash.display3D.Context3DBlendFactor; + import flash.display3D.Context3DCompareMode; + import flash.display3D.Context3DProgramType; + import flash.display3D.Context3DRenderMode; + import flash.display3D.Context3DStencilAction; + import flash.display3D.Context3DTriangleFace; + import flash.display3D.Context3DVertexBufferFormat; + import flash.display3D.Context3DTextureFilter; + import flash.display3D.Context3DWrapMode; + import flash.display3D.IndexBuffer3D; + import flash.display3D.Program3D; + import flash.display3D.VertexBuffer3D; + import flash.events.Event; + import flash.events.KeyboardEvent; + import flash.events.MouseEvent; + import flash.events.TimerEvent; + import flash.geom.Rectangle; + import flash.text.TextField; + import flash.text.TextFormat; + import flash.ui.Keyboard; + import flash.utils.Timer; + import flash.display.MovieClip; + import flash.display.Stage; + import flash.display.BitmapData; + import flash.display.Bitmap; + + // Based on example from https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display3D/Context3D.html#setStencilActions + public class Test extends MovieClip { + public const viewWidth:Number = 500; + public const viewHeight:Number = 600; + + private var stage3D:Stage3D; + private var renderContext:Context3D; + private var indexList:IndexBuffer3D; + private var vertexes:VertexBuffer3D; + + private const VERTEX_SHADER:String = + "add op, va0, vc0 \n" + // copy position to output with offset vector + "mov v0, va1"; // copy uv to varying variable v0 + + private const FRAGMENT_SHADER:String = + "tex oc, v0, fs0 <2d,clamp,linear,mipnone,ignoresampler>"; + + + private const FRAGMENT_SHADER_REPEAT:String = + "tex oc, v0, fs0 <2d,repeat,linear,mipnone>"; + + private var vertexAssembly:AGALMiniAssembler = new AGALMiniAssembler(false); + private var fragmentAssembly:AGALMiniAssembler = new AGALMiniAssembler(false); + private var fragmentAssemblyRepeat:AGALMiniAssembler = new AGALMiniAssembler(false); + private var programPair:Program3D; + + public function Test() { + stage3D = this.stage.stage3Ds[0]; + + // Add event listener before requesting the context + stage3D.addEventListener(Event.CONTEXT3D_CREATE, contextCreated); + stage3D.requestContext3D(Context3DRenderMode.AUTO, "standard"); + + // Compile shaders + vertexAssembly.assemble(Context3DProgramType.VERTEX, VERTEX_SHADER, 2); + fragmentAssembly.assemble(Context3DProgramType.FRAGMENT, FRAGMENT_SHADER, 2); + fragmentAssemblyRepeat.assemble(Context3DProgramType.FRAGMENT, FRAGMENT_SHADER_REPEAT, 2); + } + + // Note, context3DCreate event can happen at any time, such as when the hardware resources are taken by another process + private function contextCreated(event:Event):void { + renderContext = Stage3D(event.target).context3D; + + renderContext.enableErrorChecking = true; // Can slow rendering - only turn on when developing/testing + renderContext.configureBackBuffer(viewWidth, viewHeight, 4, false); + + // Create vertex index list for the triangles + var triangles:Vector. = Vector.([0, 3, 2, + 0, 1, 3, + ]); + indexList = renderContext.createIndexBuffer(triangles.length); + indexList.uploadFromVector(triangles, 0, triangles.length); + + // Create vertexes + const dataPerVertex:int = 5; + var vertexData:Vector. = Vector.( + [ + // x, y, z u, v + -.1, .1, 0, 0, 2, + .1, .1, 0, 2, 2, + -.1, -.1, 0, 0, 0, + .1, -.1, 0, 2, 0 + ]); + vertexes = renderContext.createVertexBuffer(vertexData.length / dataPerVertex, dataPerVertex); + vertexes.uploadFromVector(vertexData, 0, vertexData.length / dataPerVertex); + + // Identify vertex data inputs for vertex program + renderContext.setVertexBufferAt(0, vertexes, 0, Context3DVertexBufferFormat.FLOAT_3); // va0 is position + renderContext.setVertexBufferAt(1, vertexes, 3, Context3DVertexBufferFormat.FLOAT_2); // va1 is texture uv coords + + const size = 4; + var redGreen = new BitmapData(size, size, true, 0x0); + redGreen.fillRect(new Rectangle(0, 0, size / 2, size / 2), 0xFFFF0000); + redGreen.fillRect(new Rectangle(size / 2, 0, size / 2, size / 2), 0xFF00FF00); + redGreen.fillRect(new Rectangle(0, size / 2, size / 2, size / 2), 0xFF0000FF); + redGreen.fillRect(new Rectangle(size / 2, size / 2, size / 2, size / 2), 0xFFFF00FF); + + var redGreenTexture = renderContext.createTexture(size, size, "bgra", false); + redGreenTexture.uploadFromBitmapData(redGreen); + + // This modification is done after 'redGreenTexture.uploadFromBitmapData(redGreen)', + // so it should have no effect. + redGreen.fillRect(new Rectangle(0, 0, size, size), 0); + + // Upload programs to render context + programPair = renderContext.createProgram(); + programPair.upload(vertexAssembly.agalcode, fragmentAssembly.agalcode); + + var repeatProgram = renderContext.createProgram(); + repeatProgram.upload(vertexAssembly.agalcode, fragmentAssemblyRepeat.agalcode); + + // Clear, setting stencil to 0 + renderContext.clear(.3, .3, .3, 1, 1, 0); + + var offsetVec = Vector.([-0.7, 0.7, 0, 0]); + // FIXME - implement and test anisotropic filters + + renderContext.setTextureAt(0, redGreenTexture); + + for each (var mode in [0, 1, 2, 3, 4, 5]) { + for each (var textureFilter in [Context3DTextureFilter.NEAREST, Context3DTextureFilter.LINEAR]) { + for each (var wrapMode in [Context3DWrapMode.CLAMP, Context3DWrapMode.CLAMP_U_REPEAT_V, Context3DWrapMode.REPEAT, Context3DWrapMode.REPEAT_U_CLAMP_V]) { + if (mode == 0) { + renderContext.setProgram(programPair); + } else if (mode == 1) { + renderContext.setSamplerStateAt(0, wrapMode, textureFilter, "mipnone"); + renderContext.setProgram(repeatProgram); + renderContext.setProgram(programPair); + } else if (mode == 2) { + renderContext.setSamplerStateAt(0, wrapMode, textureFilter, "mipnone"); + renderContext.setProgram(programPair); + } else if (mode == 3) { + renderContext.setSamplerStateAt(0, wrapMode, textureFilter, "mipnone"); + renderContext.setProgram(repeatProgram); + } else if (mode == 4) { + renderContext.setSamplerStateAt(0, wrapMode, textureFilter, "mipnone"); + renderContext.setProgram(programPair); + } else if (mode == 5) { + renderContext.setProgram(repeatProgram); + renderContext.setSamplerStateAt(0, wrapMode, textureFilter, "mipnone"); + } + renderContext.setProgramConstantsFromVector("vertex", 0, offsetVec); + renderContext.drawTriangles(indexList, 0, 2); + + offsetVec[0] += 0.3; + } + } + offsetVec[1] += -0.3; + offsetVec[0] = -0.7; + } + + renderContext.present(); + } + } +} diff --git a/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/output.expected.png b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/output.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..7f43fc40b28746d0fa057017caaf944601bc0ebd GIT binary patch literal 42766 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 VIQ;hEGYIf!+2WNiS1h7&{trJCz9awu literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/output.txt b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/output.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.fla b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.fla new file mode 100755 index 0000000000000000000000000000000000000000..f01a7d779729593a8ea3f90b9b30d7d8ab748dd6 GIT binary patch literal 4343 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 literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.swf b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..77a8f9931dd6d64ea983b94d5881dc02abc7e899 GIT binary patch literal 11790 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 wliVF_lKV2G6-XHp{@oQakH1E?YFl+MQMIRF3v literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.toml b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.toml new file mode 100644 index 000000000..afd6e2b10 --- /dev/null +++ b/tests/tests/swfs/avm2/stage3d_ignore_sampler_override/test.toml @@ -0,0 +1,9 @@ +num_frames = 1 + +[image_comparisons.output] +tolerance = 1 +# FIXME - investigate why this is so high +max_outliers = 1935 + +[player_options] +with_renderer = { optional = true, sample_count = 1 } \ No newline at end of file diff --git a/tests/tests/swfs/stage3d/shared/com/adobe/utils/AGALMiniAssembler.as b/tests/tests/swfs/stage3d/shared/com/adobe/utils/AGALMiniAssembler.as index f9ee69d41..bafe82618 100644 --- a/tests/tests/swfs/stage3d/shared/com/adobe/utils/AGALMiniAssembler.as +++ b/tests/tests/swfs/stage3d/shared/com/adobe/utils/AGALMiniAssembler.as @@ -372,7 +372,7 @@ package com.adobe.utils if ( optfound == null ) { // todo check that it's a number... - //trace( "Warning, unknown sampler option: "+opts[k] ); + trace( "Warning, unknown sampler option: "+opts[k] ); bias = Number(opts[k]); if ( verbose ) trace( " bias: " + bias );