Add storage texture case reading from read-only then writing into write-only
This case verifies that reading from one read-only storage texture then writing into another write-only storage texture in one dispatch are supported in compute shader. Bug: dawn:458 Change-Id: If1b4c13da067fa39b45a378b54c22a4162695c8d Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23040 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
parent
90ad1a34dd
commit
667238b97d
|
@ -154,15 +154,16 @@ class StorageTextureTests : public DawnTest {
|
|||
|
||||
std::string GetGLSLImageDeclaration(wgpu::TextureFormat format,
|
||||
std::string accessQualifier,
|
||||
bool is2DArray) {
|
||||
bool is2DArray,
|
||||
uint32_t binding) {
|
||||
std::ostringstream ostream;
|
||||
ostream << "layout(set = 0, binding = 0, " << utils::GetGLSLImageFormatQualifier(format)
|
||||
<< ") uniform " << accessQualifier << " "
|
||||
<< utils::GetColorTextureComponentTypePrefix(format) << "image2D";
|
||||
ostream << "layout(set = 0, binding = " << binding << ", "
|
||||
<< utils::GetGLSLImageFormatQualifier(format) << ") uniform " << accessQualifier
|
||||
<< " " << utils::GetColorTextureComponentTypePrefix(format) << "image2D";
|
||||
if (is2DArray) {
|
||||
ostream << "Array";
|
||||
}
|
||||
ostream << " storageImage;";
|
||||
ostream << " storageImage" << binding << ";";
|
||||
return ostream.str();
|
||||
}
|
||||
|
||||
|
@ -273,13 +274,13 @@ class StorageTextureTests : public DawnTest {
|
|||
|
||||
const char* prefix = utils::GetColorTextureComponentTypePrefix(format);
|
||||
|
||||
ostream << GetGLSLImageDeclaration(format, "readonly", is2DArray) << "\n"
|
||||
ostream << GetGLSLImageDeclaration(format, "readonly", is2DArray, 0) << "\n"
|
||||
<< GetGLSLComparisonFunction(format) << "bool doTest() {\n";
|
||||
if (is2DArray) {
|
||||
ostream << R"(ivec3 size = imageSize(storageImage);
|
||||
ostream << R"(ivec3 size = imageSize(storageImage0);
|
||||
const uint layerCount = size.z;)";
|
||||
} else {
|
||||
ostream << R"(ivec2 size = imageSize(storageImage);
|
||||
ostream << R"(ivec2 size = imageSize(storageImage0);
|
||||
const uint layerCount = 1;)";
|
||||
}
|
||||
ostream << R"(for (uint layer = 0; layer < layerCount; ++layer) {
|
||||
|
@ -288,7 +289,7 @@ class StorageTextureTests : public DawnTest {
|
|||
uint value = )"
|
||||
<< kComputeExpectedValueGLSL << ";\n"
|
||||
<< prefix << "vec4 expected = " << GetExpectedPixelValue(format) << ";\n"
|
||||
<< prefix << R"(vec4 pixel = imageLoad(storageImage, )";
|
||||
<< prefix << R"(vec4 pixel = imageLoad(storageImage0, )";
|
||||
if (is2DArray) {
|
||||
ostream << "ivec3(x, y, layer));";
|
||||
} else {
|
||||
|
@ -314,16 +315,16 @@ class StorageTextureTests : public DawnTest {
|
|||
|
||||
ostream << R"(
|
||||
#version 450
|
||||
)" << GetGLSLImageDeclaration(format, "writeonly", is2DArray)
|
||||
)" << GetGLSLImageDeclaration(format, "writeonly", is2DArray, 0)
|
||||
<< R"(
|
||||
void main() {
|
||||
)";
|
||||
if (is2DArray) {
|
||||
ostream << R"(ivec3 size = imageSize(storageImage);
|
||||
ostream << R"(ivec3 size = imageSize(storageImage0);
|
||||
const uint layerCount = size.z;
|
||||
)";
|
||||
} else {
|
||||
ostream << R"(ivec2 size = imageSize(storageImage);
|
||||
ostream << R"(ivec2 size = imageSize(storageImage0);
|
||||
const uint layerCount = 1;
|
||||
)";
|
||||
}
|
||||
|
@ -340,7 +341,7 @@ class StorageTextureTests : public DawnTest {
|
|||
ostream << "ivec2 texcoord = ivec2(x, y);\n";
|
||||
}
|
||||
|
||||
ostream << R"( imageStore(storageImage, texcoord, expected);
|
||||
ostream << R"( imageStore(storageImage0, texcoord, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -349,6 +350,44 @@ class StorageTextureTests : public DawnTest {
|
|||
return ostream.str();
|
||||
}
|
||||
|
||||
std::string CommonReadWriteTestCode(wgpu::TextureFormat format, bool is2DArray = false) {
|
||||
std::ostringstream ostream;
|
||||
|
||||
ostream << R"(
|
||||
#version 450
|
||||
)" << GetGLSLImageDeclaration(format, "writeonly", is2DArray, 0)
|
||||
<< GetGLSLImageDeclaration(format, "readonly", is2DArray, 1) << R"(
|
||||
void main() {
|
||||
)";
|
||||
if (is2DArray) {
|
||||
ostream << R"(ivec3 size = imageSize(storageImage0);
|
||||
const uint layerCount = size.z;
|
||||
)";
|
||||
} else {
|
||||
ostream << R"(ivec2 size = imageSize(storageImage0);
|
||||
const uint layerCount = 1;
|
||||
)";
|
||||
}
|
||||
|
||||
ostream << R"(for (uint layer = 0; layer < layerCount; ++layer) {
|
||||
for (uint y = 0; y < size.y; ++y) {
|
||||
for (uint x = 0; x < size.x; ++x) {)"
|
||||
"\n";
|
||||
if (is2DArray) {
|
||||
ostream << "ivec3 texcoord = ivec3(x, y, layer);\n";
|
||||
} else {
|
||||
ostream << "ivec2 texcoord = ivec2(x, y);\n";
|
||||
}
|
||||
|
||||
ostream
|
||||
<< R"( imageStore(storageImage0, texcoord, imageLoad(storageImage1, texcoord));
|
||||
}
|
||||
}
|
||||
}
|
||||
})";
|
||||
return ostream.str();
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> GetExpectedData(wgpu::TextureFormat format,
|
||||
uint32_t arrayLayerCount = 1) {
|
||||
const uint32_t texelSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
|
||||
|
@ -570,6 +609,25 @@ class StorageTextureTests : public DawnTest {
|
|||
queue.Submit(1, &commandBuffer);
|
||||
}
|
||||
|
||||
void ReadWriteIntoStorageTextureInComputePass(wgpu::Texture readonlyStorageTexture,
|
||||
wgpu::Texture writeonlyStorageTexture,
|
||||
const char* computeShader) {
|
||||
// Create a compute pipeline that writes the expected pixel values into the storage texture.
|
||||
wgpu::ComputePipeline pipeline = CreateComputePipeline(computeShader);
|
||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(
|
||||
device, pipeline.GetBindGroupLayout(0),
|
||||
{{0, writeonlyStorageTexture.CreateView()}, {1, readonlyStorageTexture.CreateView()}});
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::ComputePassEncoder computePassEncoder = encoder.BeginComputePass();
|
||||
computePassEncoder.SetBindGroup(0, bindGroup);
|
||||
computePassEncoder.SetPipeline(pipeline);
|
||||
computePassEncoder.Dispatch(1);
|
||||
computePassEncoder.EndPass();
|
||||
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
||||
queue.Submit(1, &commandBuffer);
|
||||
}
|
||||
|
||||
void CheckOutputStorageTexture(wgpu::Texture writeonlyStorageTexture,
|
||||
wgpu::TextureFormat format,
|
||||
uint32_t arrayLayerCount = 1) {
|
||||
|
@ -818,6 +876,45 @@ TEST_P(StorageTextureTests, WriteonlyStorageTextureInComputeShader) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that reading from one read-only storage texture then writing into another write-only storage
|
||||
// texture in one dispatch are supported in compute shader.
|
||||
TEST_P(StorageTextureTests, ReadWriteDifferentStorageTextureInOneDispatchInComputeShader) {
|
||||
// When we run dawn_end2end_tests with "--use-spvc-parser", extracting the binding type of a
|
||||
// read-only image will always return shaderc_spvc_binding_type_writeonly_storage_texture.
|
||||
// TODO(jiawei.shao@intel.com): enable this test when we specify "--use-spvc-parser" after the
|
||||
// bug in spvc parser is fixed.
|
||||
DAWN_SKIP_TEST_IF(IsD3D12() && IsSpvcParserBeingUsed());
|
||||
|
||||
for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
|
||||
if (!utils::TextureFormatSupportsStorageTexture(format)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO(jiawei.shao@intel.com): investigate why this test fails with RGBA8Snorm on Linux
|
||||
// Intel OpenGL driver.
|
||||
if (format == wgpu::TextureFormat::RGBA8Snorm && IsIntel() && IsOpenGL() && IsLinux()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare the read-only storage texture.
|
||||
const std::vector<uint8_t> kInitialTextureData = GetExpectedData(format);
|
||||
wgpu::Texture readonlyStorageTexture =
|
||||
CreateTextureWithTestData(kInitialTextureData, format);
|
||||
|
||||
// Prepare the write-only storage texture.
|
||||
wgpu::Texture writeonlyStorageTexture =
|
||||
CreateTexture(format, wgpu::TextureUsage::Storage | wgpu::TextureUsage::CopySrc);
|
||||
|
||||
// Write the expected pixel values into the write-only storage texture.
|
||||
const std::string computeShader = CommonReadWriteTestCode(format);
|
||||
ReadWriteIntoStorageTextureInComputePass(readonlyStorageTexture, writeonlyStorageTexture,
|
||||
computeShader.c_str());
|
||||
|
||||
// Verify the pixel data in the write-only storage texture is expected.
|
||||
CheckOutputStorageTexture(writeonlyStorageTexture, format);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that write-only storage textures are supported in fragment shader.
|
||||
TEST_P(StorageTextureTests, WriteonlyStorageTextureInFragmentShader) {
|
||||
// When we run dawn_end2end_tests with "--use-spvc-parser", extracting the binding type of a
|
||||
|
|
Loading…
Reference in New Issue