@@ -1046,6 +1046,137 @@ TEST_P(RendererTest, VertexBufferBuilder) {
1046
1046
ASSERT_EQ (vertex_builder.GetVertexCount (), 4u );
1047
1047
}
1048
1048
1049
+ TEST_P (RendererTest, StencilMask) {
1050
+ using VS = BoxFadeVertexShader;
1051
+ using FS = BoxFadeFragmentShader;
1052
+ auto context = GetContext ();
1053
+ ASSERT_TRUE (context);
1054
+ using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1055
+ auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor (*context);
1056
+ ASSERT_TRUE (desc.has_value ());
1057
+
1058
+ // Vertex buffer.
1059
+ VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1060
+ vertex_builder.SetLabel (" Box" );
1061
+ vertex_builder.AddVertices ({
1062
+ {{100 , 100 , 0.0 }, {0.0 , 0.0 }}, // 1
1063
+ {{800 , 100 , 0.0 }, {1.0 , 0.0 }}, // 2
1064
+ {{800 , 800 , 0.0 }, {1.0 , 1.0 }}, // 3
1065
+ {{100 , 100 , 0.0 }, {0.0 , 0.0 }}, // 1
1066
+ {{800 , 800 , 0.0 }, {1.0 , 1.0 }}, // 3
1067
+ {{100 , 800 , 0.0 }, {0.0 , 1.0 }}, // 4
1068
+ });
1069
+ auto vertex_buffer =
1070
+ vertex_builder.CreateVertexBuffer (*context->GetResourceAllocator ());
1071
+ ASSERT_TRUE (vertex_buffer);
1072
+
1073
+ desc->SetSampleCount (SampleCount::kCount4 );
1074
+
1075
+ auto bridge = CreateTextureForFixture (" bay_bridge.jpg" );
1076
+ auto boston = CreateTextureForFixture (" boston.jpg" );
1077
+ ASSERT_TRUE (bridge && boston);
1078
+ auto sampler = context->GetSamplerLibrary ()->GetSampler ({});
1079
+ ASSERT_TRUE (sampler);
1080
+
1081
+ static int stencil_reference_write = 0xFF ;
1082
+ static int stencil_reference_read = 0x1 ;
1083
+ std::vector<uint8_t > stencil_contents;
1084
+ static int last_stencil_contents_reference_value = 0 ;
1085
+ Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
1086
+ auto buffer = context->CreateCommandBuffer ();
1087
+ if (!buffer) {
1088
+ return false ;
1089
+ }
1090
+ buffer->SetLabel (" Playground Command Buffer" );
1091
+
1092
+ {
1093
+ // Configure the stencil attachment for the test.
1094
+ RenderTarget::AttachmentConfig stencil_config;
1095
+ stencil_config.load_action = LoadAction::kLoad ;
1096
+ stencil_config.store_action = StoreAction::kDontCare ;
1097
+ stencil_config.storage_mode = StorageMode::kHostVisible ;
1098
+ render_target.SetupStencilAttachment (*context,
1099
+ render_target.GetRenderTargetSize (),
1100
+ true , " stencil" , stencil_config);
1101
+ // Fill the stencil buffer with an checkerboard pattern.
1102
+ const auto target_width = render_target.GetRenderTargetSize ().width ;
1103
+ const auto target_height = render_target.GetRenderTargetSize ().height ;
1104
+ const size_t target_size = target_width * target_height;
1105
+ if (stencil_contents.size () != target_size ||
1106
+ last_stencil_contents_reference_value != stencil_reference_write) {
1107
+ stencil_contents.resize (target_size);
1108
+ last_stencil_contents_reference_value = stencil_reference_write;
1109
+ for (int y = 0 ; y < target_height; y++) {
1110
+ for (int x = 0 ; x < target_width; x++) {
1111
+ const auto index = y * target_width + x;
1112
+ const auto kCheckSize = 64 ;
1113
+ const auto value =
1114
+ (((y / kCheckSize ) + (x / kCheckSize )) % 2 == 0 ) *
1115
+ stencil_reference_write;
1116
+ stencil_contents[index] = value;
1117
+ }
1118
+ }
1119
+ }
1120
+ if (!render_target.GetStencilAttachment ()->texture ->SetContents (
1121
+ stencil_contents.data (), stencil_contents.size (), 0 , false )) {
1122
+ VALIDATION_LOG << " Could not upload stencil contents to device memory" ;
1123
+ return false ;
1124
+ }
1125
+ auto pass = buffer->CreateRenderPass (render_target);
1126
+ if (!pass) {
1127
+ return false ;
1128
+ }
1129
+ pass->SetLabel (" Stencil Buffer" );
1130
+ ImGui::Begin (" Controls" , nullptr , ImGuiWindowFlags_AlwaysAutoResize);
1131
+ ImGui::SliderInt (" Stencil Write Value" , &stencil_reference_write, 0 ,
1132
+ 0xFF );
1133
+ ImGui::SliderInt (" Stencil Compare Value" , &stencil_reference_read, 0 ,
1134
+ 0xFF );
1135
+ ImGui::End ();
1136
+ StencilAttachmentDescriptor front_and_back;
1137
+ front_and_back.stencil_compare = CompareFunction::kGreater ;
1138
+ desc->SetStencilAttachmentDescriptors (front_and_back);
1139
+ auto pipeline = context->GetPipelineLibrary ()->GetPipeline (desc).Get ();
1140
+
1141
+ assert (pipeline && pipeline->IsValid ());
1142
+
1143
+ Command cmd;
1144
+ cmd.label = " Box" ;
1145
+ cmd.pipeline = pipeline;
1146
+ cmd.stencil_reference = stencil_reference_read;
1147
+
1148
+ cmd.BindVertices (vertex_buffer);
1149
+
1150
+ VS::UniformBuffer uniforms;
1151
+ uniforms.mvp = Matrix::MakeOrthographic (pass->GetRenderTargetSize ()) *
1152
+ Matrix::MakeScale (GetContentScale ());
1153
+ VS::BindUniformBuffer (
1154
+ cmd, pass->GetTransientsBuffer ().EmplaceUniform (uniforms));
1155
+
1156
+ FS::FrameInfo frame_info;
1157
+ frame_info.current_time = GetSecondsElapsed ();
1158
+ frame_info.cursor_position = GetCursorPosition ();
1159
+ frame_info.window_size .x = GetWindowSize ().width ;
1160
+ frame_info.window_size .y = GetWindowSize ().height ;
1161
+
1162
+ FS::BindFrameInfo (cmd,
1163
+ pass->GetTransientsBuffer ().EmplaceUniform (frame_info));
1164
+ FS::BindContents1 (cmd, boston, sampler);
1165
+ FS::BindContents2 (cmd, bridge, sampler);
1166
+ if (!pass->AddCommand (std::move (cmd))) {
1167
+ return false ;
1168
+ }
1169
+ pass->EncodeCommands ();
1170
+ }
1171
+
1172
+ if (!buffer->SubmitCommands ()) {
1173
+ return false ;
1174
+ }
1175
+ return true ;
1176
+ };
1177
+ OpenPlaygroundHere (callback);
1178
+ }
1179
+
1049
1180
} // namespace testing
1050
1181
} // namespace impeller
1051
1182
0 commit comments