shared_image_gl_backing_produce_dawn_unittest.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/threading/thread_task_runner_handle.h"
  5. #include "build/build_config.h"
  6. #include "components/viz/test/test_gpu_service_holder.h"
  7. #include "gpu/GLES2/gl2extchromium.h"
  8. #include "gpu/command_buffer/client/gles2_implementation.h"
  9. #include "gpu/command_buffer/client/shared_image_interface.h"
  10. #include "gpu/command_buffer/client/webgpu_implementation.h"
  11. #include "gpu/command_buffer/common/mailbox.h"
  12. #include "gpu/command_buffer/common/shared_image_usage.h"
  13. #include "gpu/command_buffer/tests/webgpu_test.h"
  14. #include "gpu/ipc/gl_in_process_context.h"
  15. #include "testing/gmock/include/gmock/gmock.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. #include "ui/gfx/color_space.h"
  18. namespace gpu {
  19. namespace {
  20. class MockBufferMapCallback {
  21. public:
  22. MOCK_METHOD(void, Call, (WGPUBufferMapAsyncStatus status, void* userdata));
  23. };
  24. std::unique_ptr<testing::StrictMock<MockBufferMapCallback>>
  25. mock_buffer_map_callback;
  26. void ToMockBufferMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
  27. mock_buffer_map_callback->Call(status, userdata);
  28. }
  29. } // namespace
  30. class SharedImageGLBackingProduceDawnTest : public WebGPUTest {
  31. protected:
  32. void SetUp() override {
  33. WebGPUTest::SetUp();
  34. WebGPUTest::Options option;
  35. Initialize(option);
  36. if (ShouldSkipTest()) {
  37. return;
  38. }
  39. gpu::ContextCreationAttribs attributes;
  40. attributes.alpha_size = 8;
  41. attributes.depth_size = 24;
  42. attributes.red_size = 8;
  43. attributes.green_size = 8;
  44. attributes.blue_size = 8;
  45. attributes.stencil_size = 8;
  46. attributes.samples = 4;
  47. attributes.sample_buffers = 1;
  48. attributes.bind_generates_resource = false;
  49. gl_context_ = std::make_unique<GLInProcessContext>();
  50. ContextResult result = gl_context_->Initialize(
  51. GetGpuServiceHolder()->task_executor(), attributes,
  52. option.shared_memory_limits, /*image_factory=*/nullptr);
  53. ASSERT_EQ(result, ContextResult::kSuccess);
  54. mock_buffer_map_callback =
  55. std::make_unique<testing::StrictMock<MockBufferMapCallback>>();
  56. }
  57. void TearDown() override {
  58. WebGPUTest::TearDown();
  59. gl_context_.reset();
  60. mock_buffer_map_callback = nullptr;
  61. }
  62. bool ShouldSkipTest() {
  63. // Windows is the only platform enabled passthrough in this test.
  64. #if BUILDFLAG(IS_WIN)
  65. // Skip the test if there is no GPU service holder. It is not created if
  66. // Dawn is not supported on the platform (Win7).
  67. return GetGpuServiceHolder() == nullptr;
  68. #else
  69. return true;
  70. #endif // BUILDFLAG(IS_WIN)
  71. }
  72. gles2::GLES2Implementation* gl() { return gl_context_->GetImplementation(); }
  73. std::unique_ptr<GLInProcessContext> gl_context_;
  74. };
  75. // Tests using Associate/DissociateMailbox to share an image with Dawn.
  76. // For simplicity of the test the image is shared between a Dawn device and
  77. // itself: we render to it using the Dawn device, then re-associate it to a
  78. // Dawn texture and read back the values that were written.
  79. TEST_F(SharedImageGLBackingProduceDawnTest, Basic) {
  80. if (ShouldSkipTest())
  81. return;
  82. if (!WebGPUSupported()) {
  83. LOG(ERROR) << "Test skipped because WebGPU isn't supported";
  84. return;
  85. }
  86. if (!WebGPUSharedImageSupported()) {
  87. LOG(ERROR) << "Test skipped because WebGPUSharedImage isn't supported";
  88. return;
  89. }
  90. // Create the shared image
  91. SharedImageInterface* sii = gl_context_->GetSharedImageInterface();
  92. Mailbox gl_mailbox = sii->CreateSharedImage(
  93. viz::ResourceFormat::RGBA_8888, {1, 1}, gfx::ColorSpace::CreateSRGB(),
  94. kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, SHARED_IMAGE_USAGE_GLES2,
  95. kNullSurfaceHandle);
  96. SyncToken mailbox_produced_token = sii->GenVerifiedSyncToken();
  97. gl()->WaitSyncTokenCHROMIUM(mailbox_produced_token.GetConstData());
  98. GLuint texture =
  99. gl()->CreateAndTexStorage2DSharedImageCHROMIUM(gl_mailbox.name);
  100. gl()->BeginSharedImageAccessDirectCHROMIUM(
  101. texture, GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
  102. GLuint fbo = 0;
  103. gl()->GenFramebuffers(1, &fbo);
  104. gl()->BindFramebuffer(GL_FRAMEBUFFER, fbo);
  105. // Attach the texture to FBO.
  106. gl()->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  107. GL_TEXTURE_2D, /* Hard code */
  108. texture, 0);
  109. // Set the clear color to green.
  110. gl()->ClearColor(0.0f, 1.0f, 0.0f, 1.0f);
  111. gl()->Clear(GL_COLOR_BUFFER_BIT);
  112. gl()->EndSharedImageAccessDirectCHROMIUM(texture);
  113. SyncToken gl_op_token;
  114. gl()->GenUnverifiedSyncTokenCHROMIUM(gl_op_token.GetData());
  115. webgpu()->WaitSyncTokenCHROMIUM(gl_op_token.GetConstData());
  116. wgpu::Device device = GetNewDevice();
  117. {
  118. // Register the shared image as a Dawn texture in the wire.
  119. gpu::webgpu::ReservedTexture reservation =
  120. webgpu()->ReserveTexture(device.Get());
  121. webgpu()->AssociateMailbox(
  122. reservation.deviceId, reservation.deviceGeneration, reservation.id,
  123. reservation.generation, WGPUTextureUsage_CopySrc,
  124. webgpu::WEBGPU_MAILBOX_NONE, reinterpret_cast<GLbyte*>(&gl_mailbox));
  125. wgpu::Texture wgpu_texture = wgpu::Texture::Acquire(reservation.texture);
  126. // Copy the texture in a mappable buffer.
  127. wgpu::BufferDescriptor buffer_desc;
  128. buffer_desc.size = 4;
  129. buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  130. wgpu::Buffer readback_buffer = device.CreateBuffer(&buffer_desc);
  131. wgpu::ImageCopyTexture copy_src = {};
  132. copy_src.texture = wgpu_texture;
  133. copy_src.mipLevel = 0;
  134. copy_src.origin = {0, 0, 0};
  135. wgpu::ImageCopyBuffer copy_dst = {};
  136. copy_dst.buffer = readback_buffer;
  137. copy_dst.layout.offset = 0;
  138. copy_dst.layout.bytesPerRow = 256;
  139. wgpu::Extent3D copy_size = {1, 1, 1};
  140. wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
  141. encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);
  142. wgpu::CommandBuffer commands = encoder.Finish();
  143. wgpu::Queue queue = device.GetQueue();
  144. queue.Submit(1, &commands);
  145. webgpu()->DissociateMailbox(reservation.id, reservation.generation);
  146. // Map the buffer and assert the pixel is the correct value.
  147. readback_buffer.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapCallback,
  148. nullptr);
  149. EXPECT_CALL(*mock_buffer_map_callback,
  150. Call(WGPUBufferMapAsyncStatus_Success, nullptr))
  151. .Times(1);
  152. WaitForCompletion(device);
  153. const void* data = readback_buffer.GetConstMappedRange(0, 4);
  154. EXPECT_EQ(0xFF00FF00, *static_cast<const uint32_t*>(data));
  155. }
  156. }
  157. } // namespace gpu