Add basic supports of storage textures on OpenGL

This patch adds the basic supports of read-only and write-only storage
textures on OpenGL backend. Currently on OpenGL backend we only support
using either a layer of a texture or the entire texture as either read-
only or write-only storage texture.

BUG=dawn:267
TEST=dawn_end2end_tests

Change-Id: I235b98d8d961a17739ea35eec9726dcc80889c4b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22180
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Jiawei Shao
2020-05-29 07:51:08 +00:00
committed by Commit Bot service account
parent da6dccd7c5
commit 0e5301c23e
9 changed files with 115 additions and 42 deletions

View File

@@ -14,11 +14,54 @@
#include "dawn_native/opengl/BindGroupGL.h"
#include "dawn_native/Texture.h"
#include "dawn_native/opengl/BindGroupLayoutGL.h"
#include "dawn_native/opengl/DeviceGL.h"
namespace dawn_native { namespace opengl {
MaybeError ValidateGLBindGroupDescriptor(const BindGroupDescriptor* descriptor) {
const BindGroupLayoutBase::BindingMap& bindingMap = descriptor->layout->GetBindingMap();
for (uint32_t i = 0; i < descriptor->entryCount; ++i) {
const BindGroupEntry& entry = descriptor->entries[i];
const auto& it = bindingMap.find(BindingNumber(entry.binding));
BindingIndex bindingIndex = it->second;
ASSERT(bindingIndex < descriptor->layout->GetBindingCount());
const BindingInfo& bindingInfo = descriptor->layout->GetBindingInfo(bindingIndex);
switch (bindingInfo.type) {
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
ASSERT(entry.textureView != nullptr);
const uint32_t textureViewLayerCount = entry.textureView->GetLayerCount();
if (textureViewLayerCount != 1 &&
textureViewLayerCount !=
entry.textureView->GetTexture()->GetArrayLayers()) {
return DAWN_VALIDATION_ERROR(
"Currently the OpenGL backend only supports either binding a layer or "
"the entire texture as storage texture.");
}
} break;
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
break;
case wgpu::BindingType::StorageTexture:
default:
UNREACHABLE();
break;
}
}
return {};
}
BindGroup::BindGroup(Device* device, const BindGroupDescriptor* descriptor)
: BindGroupBase(this, device, descriptor) {
}

View File

@@ -23,6 +23,8 @@ namespace dawn_native { namespace opengl {
class BindGroupLayout;
class Device;
MaybeError ValidateGLBindGroupDescriptor(const BindGroupDescriptor* descriptor);
class BindGroup final : public BindGroupBase, public PlacementAllocated {
public:
BindGroup(Device* device, const BindGroupDescriptor* descriptor);

View File

@@ -312,9 +312,45 @@ namespace dawn_native { namespace opengl {
break;
}
case wgpu::BindingType::StorageTexture:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
TextureView* view =
ToBackend(group->GetBindingAsTextureView(bindingIndex));
Texture* texture = ToBackend(view->GetTexture());
GLuint handle = texture->GetHandle();
GLuint imageIndex = indices[bindingIndex];
GLenum access;
switch (bindingInfo.type) {
case wgpu::BindingType::ReadonlyStorageTexture:
access = GL_READ_ONLY;
break;
case wgpu::BindingType::WriteonlyStorageTexture:
access = GL_WRITE_ONLY;
break;
default:
UNREACHABLE();
break;
}
// OpenGL ES only supports either binding a layer or the entire texture
// in glBindImageTexture().
GLboolean isLayered;
if (view->GetLayerCount() == 1) {
isLayered = GL_FALSE;
} else if (texture->GetArrayLayers() == view->GetLayerCount()) {
isLayered = GL_TRUE;
} else {
UNREACHABLE();
}
gl.BindImageTexture(imageIndex, handle, view->GetBaseMipLevel(),
isLayered, view->GetBaseArrayLayer(), access,
texture->GetGLFormat().internalFormat);
break;
}
case wgpu::BindingType::StorageTexture:
UNREACHABLE();
break;

View File

@@ -94,6 +94,7 @@ namespace dawn_native { namespace opengl {
ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) {
DAWN_TRY(ValidateGLBindGroupDescriptor(descriptor));
return BindGroup::Create(this, descriptor);
}
ResultOrError<BindGroupLayoutBase*> Device::CreateBindGroupLayoutImpl(

View File

@@ -142,9 +142,16 @@ namespace dawn_native { namespace opengl {
// emulation
break;
case wgpu::BindingType::StorageTexture:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
GLint location = gl.GetUniformLocation(mProgram, name.c_str());
if (location != -1) {
gl.Uniform1i(location, indices[group][bindingIndex]);
}
break;
}
case wgpu::BindingType::StorageTexture:
UNREACHABLE();
break;

View File

@@ -26,6 +26,7 @@ namespace dawn_native { namespace opengl {
GLuint samplerIndex = 0;
GLuint sampledTextureIndex = 0;
GLuint ssboIndex = 0;
GLuint storageTextureIndex = 0;
for (uint32_t group : IterateBitSet(GetBindGroupLayoutsMask())) {
const BindGroupLayoutBase* bgl = GetBindGroupLayout(group);
@@ -53,9 +54,13 @@ namespace dawn_native { namespace opengl {
ssboIndex++;
break;
case wgpu::BindingType::StorageTexture:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
mIndexInfo[group][bindingIndex] = storageTextureIndex;
storageTextureIndex++;
break;
case wgpu::BindingType::StorageTexture:
UNREACHABLE();
break;

View File

@@ -176,12 +176,26 @@ namespace dawn_native { namespace opengl {
BindingNumber bindingNumber = it.first;
const auto& info = it.second;
uint32_t resourceId;
switch (info.type) {
// When the resource is a uniform or shader storage block, we should change the
// block name instead of the instance name.
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::UniformBuffer:
resourceId = info.base_type_id;
break;
default:
resourceId = info.id;
break;
}
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
mSpvcContext.SetName(info.base_type_id, GetBindingName(group, bindingNumber));
mSpvcContext.SetName(resourceId, GetBindingName(group, bindingNumber));
mSpvcContext.UnsetDecoration(info.id, shaderc_spvc_decoration_binding);
mSpvcContext.UnsetDecoration(info.id, shaderc_spvc_decoration_descriptorset);
} else {
compiler->set_name(info.base_type_id, GetBindingName(group, bindingNumber));
compiler->set_name(resourceId, GetBindingName(group, bindingNumber));
compiler->unset_decoration(info.id, spv::DecorationBinding);
compiler->unset_decoration(info.id, spv::DecorationDescriptorSet);
}