OpenGL: Don't use glad to load OpenGL entrypoints

This makes the OpenGL entry points loaded at Adapter creation from the
getProcAddress passed in the DiscoveryOptions and update all GL calls in
the backend to go through the new OpenGLFunctions object.

A code generator is added that generates the function loader and list of
GL procs from Khronos' gl.xml file but we can't get rid of glad yet
because it is used to have the PROC typedefs and enum values.

BUG=dawn:165

Change-Id: I2a583d79752f55877fa4190846f5be16cf91651a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/7983
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez 2019-06-13 10:22:32 +00:00 committed by Commit Bot service account
parent 87ab2f96d9
commit df69f24824
22 changed files with 51252 additions and 286 deletions

View File

@ -44,6 +44,20 @@ dawn_json_generator("libdawn_native_utils_gen") {
]
}
if (dawn_enable_opengl) {
dawn_generator("libdawn_native_opengl_loader_gen") {
script = "generator/opengl_loader_generator.py"
args = [
"--gl-xml",
rebase_path("third_party/gl.xml", root_build_dir),
]
outputs = [
"dawn_native/opengl/OpenGLFunctionsBase_autogen.cpp",
"dawn_native/opengl/OpenGLFunctionsBase_autogen.h",
]
}
}
# Public libdawn_native headers so they can be publically visible for
# dependencies of libdawn_native
source_set("libdawn_native_headers") {
@ -261,7 +275,11 @@ source_set("libdawn_native_sources") {
}
if (dawn_enable_opengl) {
deps += [ "third_party:glad" ]
deps += [
":libdawn_native_opengl_loader_gen",
"third_party:glad",
]
sources += get_target_outputs(":libdawn_native_opengl_loader_gen")
sources += [
"src/dawn_native/opengl/BackendGL.cpp",
"src/dawn_native/opengl/BackendGL.h",
@ -274,6 +292,8 @@ source_set("libdawn_native_sources") {
"src/dawn_native/opengl/DeviceGL.cpp",
"src/dawn_native/opengl/DeviceGL.h",
"src/dawn_native/opengl/Forward.h",
"src/dawn_native/opengl/OpenGLFunctions.cpp",
"src/dawn_native/opengl/OpenGLFunctions.h",
"src/dawn_native/opengl/PersistentPipelineStateGL.cpp",
"src/dawn_native/opengl/PersistentPipelineStateGL.h",
"src/dawn_native/opengl/PipelineGL.cpp",

View File

@ -47,6 +47,11 @@ template("dawn_generator") {
generator_args += invoker.args
}
generator_args += [
"--template-dir",
rebase_path("${dawn_root}/generator/templates", root_build_dir),
]
# Use the Jinja2 version pulled from the DEPS file. We do it so we don't
# have version problems, and users don't have to install Jinja2.
jinja2_python_path = rebase_path("${dawn_jinja2_dir}/..")
@ -138,7 +143,6 @@ template("dawn_generator") {
# }
template("dawn_json_generator") {
dawn_generator(target_name) {
script = "${dawn_root}/generator/dawn_json_generator.py"
# The base arguments for the generator: from this dawn.json, generate this
@ -148,12 +152,10 @@ template("dawn_json_generator") {
rebase_path("${dawn_root}/dawn.json", root_build_dir),
"--wire-json",
rebase_path("${dawn_root}/dawn_wire.json", root_build_dir),
"--template-dir",
rebase_path("${dawn_root}/generator/templates", root_build_dir),
"--targets",
invoker.target,
]
forward_variables_from(invoker, "*", ["target"])
forward_variables_from(invoker, "*", [ "target" ])
}
}

View File

@ -44,7 +44,7 @@ import jinja2
# A custom Jinja2 template loader that removes the extra indentation
# of the template blocks so that the output is correctly indented
class PreprocessingLoader(jinja2.BaseLoader):
class _PreprocessingLoader(jinja2.BaseLoader):
def __init__(self, path):
self.path = path
@ -93,7 +93,7 @@ class PreprocessingLoader(jinja2.BaseLoader):
_FileOutput = namedtuple('FileOutput', ['name', 'content'])
def _do_renders(renders, template_dir):
loader = PreprocessingLoader(template_dir)
loader = _PreprocessingLoader(template_dir)
env = jinja2.Environment(loader=loader, lstrip_blocks=True, trim_blocks=True, line_comment_prefix='//*')
def do_assert(expr):

View File

@ -0,0 +1,117 @@
#!/usr/bin/env python2
# Copyright 2019 The Dawn Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os, sys
from collections import namedtuple
import xml.etree.ElementTree as etree
from generator_lib import Generator, run_generator, FileRender
class Proc:
def __init__(self, gl_name, proc_name=None):
assert(gl_name.startswith('gl'))
if proc_name == None:
proc_name = gl_name[2:]
self.gl_name = gl_name
self.proc_name = proc_name
def glProcName(self):
return self.gl_name
def ProcName(self):
return self.proc_name
def PFNPROCNAME(self):
return 'PFN' + self.gl_name.upper() + 'PROC'
def __repr__(self):
return 'Proc("{}", "{}")'.format(self.gl_name, self.proc_name)
Version = namedtuple('Version', ['major', 'minor'])
VersionProcBlock = namedtuple('ProcBlock', ['version', 'procs'])
HeaderProcBlock = namedtuple('ProcBlock', ['description', 'procs'])
def parse_version(version):
return Version(*map(int, version.split('.')))
def compute_params(root):
# Add proc blocks for OpenGL ES
gles_blocks = []
for gles_section in root.findall('''feature[@api='gles2']'''):
section_procs = []
for proc in gles_section.findall('./require/command'):
section_procs.append(Proc(proc.attrib['name']))
gles_blocks.append(VersionProcBlock(parse_version(gles_section.attrib['number']), section_procs))
# Get the list of all Desktop OpenGL function removed by the Core Profile.
core_removed_procs = set()
for removed_section in root.findall('feature/remove'):
assert(removed_section.attrib['profile'] == 'core')
for proc in removed_section.findall('./command'):
core_removed_procs.add(proc.attrib['name'])
# Add proc blocks for Desktop GL
desktop_gl_blocks = []
for gl_section in root.findall('''feature[@api='gl']'''):
section_procs = []
for proc in gl_section.findall('./require/command'):
if proc.attrib['name'] not in core_removed_procs:
section_procs.append(Proc(proc.attrib['name']))
desktop_gl_blocks.append(VersionProcBlock(parse_version(gl_section.attrib['number']), section_procs))
already_added_header_procs = set()
header_blocks = []
def add_header_block(description, procs):
block_procs = []
for proc in procs:
if not proc.glProcName() in already_added_header_procs:
already_added_header_procs.add(proc.glProcName())
block_procs.append(proc)
if len(block_procs) > 0:
header_blocks.append(HeaderProcBlock(description, block_procs))
for block in gles_blocks:
add_header_block('OpenGL ES {}.{}'.format(block.version.major, block.version.minor), block.procs)
for block in desktop_gl_blocks:
add_header_block('Desktop OpenGL {}.{}'.format(block.version.major, block.version.minor), block.procs)
return {
'gles_blocks': gles_blocks,
'desktop_gl_blocks': desktop_gl_blocks,
'header_blocks': header_blocks,
}
class OpenGLLoaderGenerator(Generator):
def get_description(self):
return 'Generates code to load OpenGL function pointers'
def add_commandline_arguments(self, parser):
parser.add_argument('--gl-xml', required=True, type=str, help ='The Khronos gl.xml to use.')
def get_file_renders(self, args):
params = compute_params(etree.parse(args.gl_xml).getroot())
return [
FileRender('opengl/OpenGLFunctionsBase.cpp', 'dawn_native/opengl/OpenGLFunctionsBase_autogen.cpp', [params]),
FileRender('opengl/OpenGLFunctionsBase.h', 'dawn_native/opengl/OpenGLFunctionsBase_autogen.h', [params]),
]
def get_dependencies(self, args):
return [os.path.abspath(args.gl_xml)]
if __name__ == '__main__':
sys.exit(run_generator(OpenGLLoaderGenerator()))

View File

@ -0,0 +1,54 @@
//* Copyright 2019 The Dawn Authors
//*
//* Licensed under the Apache License, Version 2.0 (the "License");
//* you may not use this file except in compliance with the License.
//* You may obtain a copy of the License at
//*
//* http://www.apache.org/licenses/LICENSE-2.0
//*
//* Unless required by applicable law or agreed to in writing, software
//* distributed under the License is distributed on an "AS IS" BASIS,
//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//* See the License for the specific language governing permissions and
//* limitations under the License.
#include "dawn_native/opengl/OpenGLFunctionsBase_autogen.h"
namespace dawn_native { namespace opengl {
template<typename T>
MaybeError OpenGLFunctionsBase::LoadProc(GetProcAddress getProc, T* memberProc, const char* name) {
*memberProc = reinterpret_cast<T>(getProc(name));
if (DAWN_UNLIKELY(memberProc == nullptr)) {
return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't load GL proc: ") + name);
}
return {};
}
MaybeError OpenGLFunctionsBase::LoadOpenGLESProcs(GetProcAddress getProc, int majorVersion, int minorVersion) {
{% for block in gles_blocks %}
// OpenGL ES {{block.version.major}}.{{block.version.minor}}
if (majorVersion > {{block.version.major}} || (majorVersion == {{block.version.major}} && minorVersion >= {{block.version.minor}})) {
{% for proc in block.procs %}
DAWN_TRY(LoadProc(getProc, &{{proc.ProcName()}}, "{{proc.glProcName()}}"));
{% endfor %}
}
{% endfor %}
return {};
}
MaybeError OpenGLFunctionsBase::LoadDesktopGLProcs(GetProcAddress getProc, int majorVersion, int minorVersion) {
{% for block in desktop_gl_blocks %}
// Desktop OpenGL {{block.version.major}}.{{block.version.minor}}
if (majorVersion > {{block.version.major}} || (majorVersion == {{block.version.major}} && minorVersion >= {{block.version.minor}})) {
{% for proc in block.procs %}
DAWN_TRY(LoadProc(getProc, &{{proc.ProcName()}}, "{{proc.glProcName()}}"));
{% endfor %}
}
{% endfor %}
return {};
}
}} // namespace dawn_native::opengl

View File

@ -0,0 +1,41 @@
//* Copyright 2019 The Dawn Authors
//*
//* Licensed under the Apache License, Version 2.0 (the "License");
//* you may not use this file except in compliance with the License.
//* You may obtain a copy of the License at
//*
//* http://www.apache.org/licenses/LICENSE-2.0
//*
//* Unless required by applicable law or agreed to in writing, software
//* distributed under the License is distributed on an "AS IS" BASIS,
//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//* See the License for the specific language governing permissions and
//* limitations under the License.
#include "dawn_native/Error.h"
#include <glad/glad.h>
namespace dawn_native { namespace opengl {
using GetProcAddress = void* (*) (const char*);
struct OpenGLFunctionsBase {
public:
{% for block in header_blocks %}
// {{block.description}}
{% for proc in block.procs %}
{{proc.PFNPROCNAME()}} {{proc.ProcName()}} = nullptr;
{% endfor %}
{% endfor%}
protected:
MaybeError LoadDesktopGLProcs(GetProcAddress getProc, int majorVersion, int minorVersion);
MaybeError LoadOpenGLESProcs(GetProcAddress getProc, int majorVersion, int minorVersion);
private:
template<typename T>
MaybeError LoadProc(GetProcAddress getProc, T* memberProc, const char* name);
};
}} // namespace dawn_native::opengl

View File

@ -23,26 +23,33 @@ namespace dawn_native { namespace opengl {
class Adapter : public AdapterBase {
public:
Adapter(InstanceBase* instance, const AdapterDiscoveryOptions* options)
: AdapterBase(instance, BackendType::OpenGL) {
// Use getProc to populate GLAD.
gladLoadGLLoader(reinterpret_cast<GLADloadproc>(options->getProc));
Adapter(InstanceBase* instance) : AdapterBase(instance, BackendType::OpenGL) {
}
MaybeError Initialize(const AdapterDiscoveryOptions* options) {
// Use getProc to populate the dispatch table
DAWN_TRY(mFunctions.Initialize(options->getProc));
// Set state that never changes between devices.
glEnable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
glEnable(GL_MULTISAMPLE);
mFunctions.Enable(GL_DEPTH_TEST);
mFunctions.Enable(GL_SCISSOR_TEST);
mFunctions.Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
mFunctions.Enable(GL_MULTISAMPLE);
mPCIInfo.name = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
mPCIInfo.name = reinterpret_cast<const char*>(mFunctions.GetString(GL_RENDERER));
return {};
}
virtual ~Adapter() = default;
~Adapter() override = default;
private:
OpenGLFunctions mFunctions;
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
// There is no limit on the number of devices created from this adapter because they can
// all share the same backing OpenGL context.
return {new Device(this, descriptor)};
return {new Device(this, descriptor, mFunctions)};
}
};
@ -58,9 +65,8 @@ namespace dawn_native { namespace opengl {
ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> Backend::DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) {
// TODO(cwallez@chromium.org): For now we can only create a single adapter because glad uses
// static variables to store the pointers to OpenGL procs. Also, if we could create
// multiple adapters, we would need to figure out what to do about MakeCurrent.
// TODO(cwallez@chromium.org): For now only create a single OpenGL adapter because don't
// know how to handle MakeCurrent.
if (mCreatedAdapter) {
return DAWN_VALIDATION_ERROR("The OpenGL backend can only create a single adapter");
}
@ -73,10 +79,12 @@ namespace dawn_native { namespace opengl {
return DAWN_VALIDATION_ERROR("AdapterDiscoveryOptions::getProc must be set");
}
std::vector<std::unique_ptr<AdapterBase>> adapters;
adapters.push_back(std::make_unique<Adapter>(GetInstance(), options));
std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(GetInstance());
DAWN_TRY(adapter->Initialize(options));
mCreatedAdapter = true;
std::vector<std::unique_ptr<AdapterBase>> adapters;
adapters.push_back(std::unique_ptr<AdapterBase>(adapter.release()));
return std::move(adapters);
}

View File

@ -22,9 +22,9 @@ namespace dawn_native { namespace opengl {
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
: BufferBase(device, descriptor) {
glGenBuffers(1, &mBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferData(GL_ARRAY_BUFFER, GetSize(), nullptr, GL_STATIC_DRAW);
device->gl.GenBuffers(1, &mBuffer);
device->gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
device->gl.BufferData(GL_ARRAY_BUFFER, GetSize(), nullptr, GL_STATIC_DRAW);
}
Buffer::~Buffer() {
@ -42,41 +42,51 @@ namespace dawn_native { namespace opengl {
}
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
void* data = gl.MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
*mappedPointer = reinterpret_cast<uint8_t*>(data);
return {};
}
MaybeError Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const void* data) {
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferSubData(GL_ARRAY_BUFFER, start, count, data);
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
gl.BufferSubData(GL_ARRAY_BUFFER, start, count, data);
return {};
}
void Buffer::MapReadAsyncImpl(uint32_t serial) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
// TODO(cwallez@chromium.org): this does GPU->CPU synchronization, we could require a high
// version of OpenGL that would let us map the buffer unsynchronized.
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
void* data = gl.MapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
CallMapReadCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize());
}
void Buffer::MapWriteAsyncImpl(uint32_t serial) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
// TODO(cwallez@chromium.org): this does GPU->CPU synchronization, we could require a high
// version of OpenGL that would let us map the buffer unsynchronized.
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
void* data = gl.MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
CallMapWriteCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize());
}
void Buffer::UnmapImpl() {
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glUnmapBuffer(GL_ARRAY_BUFFER);
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
gl.UnmapBuffer(GL_ARRAY_BUFFER);
}
void Buffer::DestroyImpl() {
glDeleteBuffers(1, &mBuffer);
ToBackend(GetDevice())->gl.DeleteBuffers(1, &mBuffer);
mBuffer = 0;
}

View File

@ -174,9 +174,9 @@ namespace dawn_native { namespace opengl {
mLastPipeline = pipeline;
}
void Apply() {
void Apply(const OpenGLFunctions& gl) {
if (mIndexBufferDirty && mIndexBuffer != nullptr) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->GetHandle());
gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->GetHandle());
mIndexBufferDirty = false;
}
@ -194,13 +194,13 @@ namespace dawn_native { namespace opengl {
auto formatType = VertexFormatType(attribute.format);
GLboolean normalized = VertexFormatIsNormalized(attribute.format);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
gl.BindBuffer(GL_ARRAY_BUFFER, buffer);
if (VertexFormatIsInt(attribute.format)) {
glVertexAttribIPointer(location, components, formatType, input.stride,
reinterpret_cast<void*>(static_cast<intptr_t>(
offset + attribute.offset)));
gl.VertexAttribIPointer(location, components, formatType, input.stride,
reinterpret_cast<void*>(static_cast<intptr_t>(
offset + attribute.offset)));
} else {
glVertexAttribPointer(
gl.VertexAttribPointer(
location, components, formatType, normalized, input.stride,
reinterpret_cast<void*>(
static_cast<intptr_t>(offset + attribute.offset)));
@ -224,7 +224,8 @@ namespace dawn_native { namespace opengl {
// Handles SetBindGroup commands with the specifics of translating to OpenGL texture and
// buffer units
void ApplyBindGroup(uint32_t index,
void ApplyBindGroup(const OpenGLFunctions& gl,
uint32_t index,
BindGroupBase* group,
PipelineLayout* pipelineLayout,
PipelineGL* pipeline) {
@ -238,8 +239,8 @@ namespace dawn_native { namespace opengl {
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint uboIndex = indices[bindingIndex];
glBindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, binding.offset,
binding.size);
gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, binding.offset,
binding.size);
} break;
case dawn::BindingType::Sampler: {
@ -248,7 +249,7 @@ namespace dawn_native { namespace opengl {
GLuint samplerIndex = indices[bindingIndex];
for (auto unit : pipeline->GetTextureUnitsForSampler(samplerIndex)) {
glBindSampler(unit, sampler);
gl.BindSampler(unit, sampler);
}
} break;
@ -259,8 +260,8 @@ namespace dawn_native { namespace opengl {
GLuint viewIndex = indices[bindingIndex];
for (auto unit : pipeline->GetTextureUnitsForTextureView(viewIndex)) {
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(target, handle);
gl.ActiveTexture(GL_TEXTURE0 + unit);
gl.BindTexture(target, handle);
}
} break;
@ -269,8 +270,8 @@ namespace dawn_native { namespace opengl {
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint ssboIndex = indices[bindingIndex];
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer,
binding.offset, binding.size);
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer,
binding.offset, binding.size);
} break;
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
@ -282,7 +283,8 @@ namespace dawn_native { namespace opengl {
}
}
void ResolveMultisampledRenderTargets(const BeginRenderPassCmd* renderPass) {
void ResolveMultisampledRenderTargets(const OpenGLFunctions& gl,
const BeginRenderPassCmd* renderPass) {
ASSERT(renderPass != nullptr);
GLuint readFbo = 0;
@ -292,8 +294,8 @@ namespace dawn_native { namespace opengl {
if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) {
if (readFbo == 0) {
ASSERT(writeFbo == 0);
glGenFramebuffers(1, &readFbo);
glGenFramebuffers(1, &writeFbo);
gl.GenFramebuffers(1, &readFbo);
gl.GenFramebuffers(1, &writeFbo);
}
const TextureBase* colorTexture =
@ -303,36 +305,36 @@ namespace dawn_native { namespace opengl {
ASSERT(renderPass->colorAttachments[i].view->GetBaseMipLevel() == 0);
GLuint colorHandle = ToBackend(colorTexture)->GetHandle();
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
ToBackend(colorTexture)->GetGLTarget(), colorHandle, 0);
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
ToBackend(colorTexture)->GetGLTarget(), colorHandle, 0);
const TextureBase* resolveTexture =
renderPass->colorAttachments[i].resolveTarget->GetTexture();
GLuint resolveTextureHandle = ToBackend(resolveTexture)->GetHandle();
GLuint resolveTargetMipmapLevel =
renderPass->colorAttachments[i].resolveTarget->GetBaseMipLevel();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, writeFbo);
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, writeFbo);
if (resolveTexture->GetArrayLayers() == 1) {
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, resolveTextureHandle,
resolveTargetMipmapLevel);
gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, resolveTextureHandle,
resolveTargetMipmapLevel);
} else {
GLuint resolveTargetArrayLayer =
renderPass->colorAttachments[i].resolveTarget->GetBaseArrayLayer();
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
resolveTextureHandle, resolveTargetMipmapLevel,
resolveTargetArrayLayer);
gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
resolveTextureHandle, resolveTargetMipmapLevel,
resolveTargetArrayLayer);
}
glBlitFramebuffer(0, 0, renderPass->width, renderPass->height, 0, 0,
renderPass->width, renderPass->height, GL_COLOR_BUFFER_BIT,
GL_NEAREST);
gl.BlitFramebuffer(0, 0, renderPass->width, renderPass->height, 0, 0,
renderPass->width, renderPass->height, GL_COLOR_BUFFER_BIT,
GL_NEAREST);
}
}
glDeleteFramebuffers(1, &readFbo);
glDeleteFramebuffers(1, &writeFbo);
gl.DeleteFramebuffers(1, &readFbo);
gl.DeleteFramebuffers(1, &writeFbo);
}
} // namespace
@ -345,6 +347,8 @@ namespace dawn_native { namespace opengl {
}
void CommandBuffer::Execute() {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
Command type;
while (mCommands.NextCommandId(&type)) {
switch (type) {
@ -361,13 +365,14 @@ namespace dawn_native { namespace opengl {
case Command::CopyBufferToBuffer: {
CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
glBindBuffer(GL_PIXEL_PACK_BUFFER, ToBackend(copy->source)->GetHandle());
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, ToBackend(copy->destination)->GetHandle());
glCopyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER,
copy->sourceOffset, copy->destinationOffset, copy->size);
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, ToBackend(copy->source)->GetHandle());
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER,
ToBackend(copy->destination)->GetHandle());
gl.CopyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER,
copy->sourceOffset, copy->destinationOffset, copy->size);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} break;
case Command::CopyBufferToTexture: {
@ -380,22 +385,22 @@ namespace dawn_native { namespace opengl {
GLenum target = texture->GetGLTarget();
auto format = texture->GetGLFormat();
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());
glActiveTexture(GL_TEXTURE0);
glBindTexture(target, texture->GetHandle());
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());
gl.ActiveTexture(GL_TEXTURE0);
gl.BindTexture(target, texture->GetHandle());
glPixelStorei(GL_UNPACK_ROW_LENGTH,
src.rowPitch / TextureFormatPixelSize(texture->GetFormat()));
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight);
gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
src.rowPitch / TextureFormatPixelSize(texture->GetFormat()));
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight);
switch (texture->GetDimension()) {
case dawn::TextureDimension::e2D:
if (texture->GetArrayLayers() > 1) {
glTexSubImage3D(
gl.TexSubImage3D(
target, dst.level, dst.origin.x, dst.origin.y, dst.slice,
copySize.width, copySize.height, 1, format.format, format.type,
reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
} else {
glTexSubImage2D(
gl.TexSubImage2D(
target, dst.level, dst.origin.x, dst.origin.y, copySize.width,
copySize.height, format.format, format.type,
reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
@ -405,10 +410,10 @@ namespace dawn_native { namespace opengl {
default:
UNREACHABLE();
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} break;
case Command::CopyTextureToBuffer: {
@ -423,21 +428,21 @@ namespace dawn_native { namespace opengl {
// The only way to move data from a texture to a buffer in GL is via
// glReadPixels with a pack buffer. Create a temporary FBO for the copy.
glBindTexture(target, texture->GetHandle());
gl.BindTexture(target, texture->GetHandle());
GLuint readFBO = 0;
glGenFramebuffers(1, &readFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
gl.GenFramebuffers(1, &readFBO);
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
switch (texture->GetDimension()) {
case dawn::TextureDimension::e2D:
if (texture->GetArrayLayers() > 1) {
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
texture->GetHandle(), src.level,
src.slice);
gl.FramebufferTextureLayer(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture->GetHandle(),
src.level, src.slice);
} else {
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture->GetHandle(),
src.level);
gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture->GetHandle(),
src.level);
}
break;
@ -445,19 +450,19 @@ namespace dawn_native { namespace opengl {
UNREACHABLE();
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
glPixelStorei(GL_PACK_ROW_LENGTH,
dst.rowPitch / TextureFormatPixelSize(texture->GetFormat()));
glPixelStorei(GL_PACK_IMAGE_HEIGHT, dst.imageHeight);
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
gl.PixelStorei(GL_PACK_ROW_LENGTH,
dst.rowPitch / TextureFormatPixelSize(texture->GetFormat()));
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.imageHeight);
ASSERT(copySize.depth == 1 && src.origin.z == 0);
void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
glReadPixels(src.origin.x, src.origin.y, copySize.width, copySize.height,
format.format, format.type, offset);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
gl.ReadPixels(src.origin.x, src.origin.y, copySize.width, copySize.height,
format.format, format.type, offset);
gl.PixelStorei(GL_PACK_ROW_LENGTH, 0);
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glDeleteFramebuffers(1, &readFBO);
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
gl.DeleteFramebuffers(1, &readFBO);
} break;
case Command::CopyTextureToTexture: {
@ -469,11 +474,11 @@ namespace dawn_native { namespace opengl {
Texture* srcTexture = ToBackend(src.texture.Get());
Texture* dstTexture = ToBackend(dst.texture.Get());
glCopyImageSubData(srcTexture->GetHandle(), srcTexture->GetGLTarget(),
src.level, src.origin.x, src.origin.y, src.slice,
dstTexture->GetHandle(), dstTexture->GetGLTarget(),
dst.level, dst.origin.x, dst.origin.y, dst.slice,
copySize.width, copySize.height, 1);
gl.CopyImageSubData(srcTexture->GetHandle(), srcTexture->GetGLTarget(),
src.level, src.origin.x, src.origin.y, src.slice,
dstTexture->GetHandle(), dstTexture->GetGLTarget(),
dst.level, dst.origin.x, dst.origin.y, dst.slice,
copySize.width, copySize.height, 1);
} break;
default: { UNREACHABLE(); } break;
@ -482,6 +487,7 @@ namespace dawn_native { namespace opengl {
}
void CommandBuffer::ExecuteComputePass() {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
ComputePipeline* lastPipeline = nullptr;
Command type;
@ -494,9 +500,9 @@ namespace dawn_native { namespace opengl {
case Command::Dispatch: {
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
glDispatchCompute(dispatch->x, dispatch->y, dispatch->z);
gl.DispatchCompute(dispatch->x, dispatch->y, dispatch->z);
// TODO(cwallez@chromium.org): add barriers to the API
glMemoryBarrier(GL_ALL_BARRIER_BITS);
gl.MemoryBarrier(GL_ALL_BARRIER_BITS);
} break;
case Command::DispatchIndirect: {
@ -505,10 +511,10 @@ namespace dawn_native { namespace opengl {
uint64_t indirectBufferOffset = dispatch->indirectOffset;
Buffer* indirectBuffer = ToBackend(dispatch->indirectBuffer.Get());
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, indirectBuffer->GetHandle());
glDispatchComputeIndirect(static_cast<GLintptr>(indirectBufferOffset));
gl.BindBuffer(GL_DISPATCH_INDIRECT_BUFFER, indirectBuffer->GetHandle());
gl.DispatchComputeIndirect(static_cast<GLintptr>(indirectBufferOffset));
// TODO(cwallez@chromium.org): add barriers to the API
glMemoryBarrier(GL_ALL_BARRIER_BITS);
gl.MemoryBarrier(GL_ALL_BARRIER_BITS);
} break;
case Command::SetComputePipeline: {
@ -519,7 +525,7 @@ namespace dawn_native { namespace opengl {
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
ApplyBindGroup(cmd->index, cmd->group.Get(),
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
ToBackend(lastPipeline->GetLayout()), lastPipeline);
} break;
@ -532,6 +538,7 @@ namespace dawn_native { namespace opengl {
}
void CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
GLuint fbo = 0;
// Create the framebuffer used for this render pass and calls the correct glDrawBuffers
@ -540,12 +547,12 @@ namespace dawn_native { namespace opengl {
// Windows/Intel. It should break any feedback loop before the clears, even if there
// shouldn't be any negative effects from this. Investigate whether it's actually
// needed.
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
// TODO(kainino@chromium.org): possible future optimization: create these framebuffers
// at Framebuffer build time (or maybe CommandBuffer build time) so they don't have to
// be created and destroyed at draw time.
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
gl.GenFramebuffers(1, &fbo);
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
// Mapping from attachmentSlot to GL framebuffer attachment points. Defaults to zero
// (GL_NONE).
@ -561,12 +568,12 @@ namespace dawn_native { namespace opengl {
// Attach color buffers.
if (textureView->GetTexture()->GetArrayLayers() == 1) {
GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target,
texture, textureView->GetBaseMipLevel());
gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target,
texture, textureView->GetBaseMipLevel());
} else {
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
texture, textureView->GetBaseMipLevel(),
textureView->GetBaseArrayLayer());
gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
texture, textureView->GetBaseMipLevel(),
textureView->GetBaseArrayLayer());
}
drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
attachmentCount = i + 1;
@ -579,7 +586,7 @@ namespace dawn_native { namespace opengl {
format == dawn::TextureFormat::R8Unorm ||
format == dawn::TextureFormat::B8G8R8A8Unorm);
}
glDrawBuffers(attachmentCount, drawBuffers.data());
gl.DrawBuffers(attachmentCount, drawBuffers.data());
if (renderPass->hasDepthStencilAttachment) {
TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get();
@ -601,7 +608,7 @@ namespace dawn_native { namespace opengl {
}
GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, target, texture, 0);
gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, target, texture, 0);
// TODO(kainino@chromium.org): the depth/stencil clears (later in
// this function) may be undefined for other texture formats.
@ -611,10 +618,10 @@ namespace dawn_native { namespace opengl {
// Set defaults for dynamic state before executing clears and commands.
PersistentPipelineState persistentPipelineState;
persistentPipelineState.SetDefaultState();
glBlendColor(0, 0, 0, 0);
glViewport(0, 0, renderPass->width, renderPass->height);
glScissor(0, 0, renderPass->width, renderPass->height);
persistentPipelineState.SetDefaultState(gl);
gl.BlendColor(0, 0, 0, 0);
gl.Viewport(0, 0, renderPass->width, renderPass->height);
gl.Scissor(0, 0, renderPass->width, renderPass->height);
// Clear framebuffer attachments as needed
{
@ -623,8 +630,8 @@ namespace dawn_native { namespace opengl {
// Load op - color
if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
glColorMaski(i, true, true, true, true);
glClearBufferfv(GL_COLOR, i, &attachmentInfo.clearColor.r);
gl.ColorMaski(i, true, true, true, true);
gl.ClearBufferfv(GL_COLOR, i, &attachmentInfo.clearColor.r);
}
}
@ -640,20 +647,20 @@ namespace dawn_native { namespace opengl {
(attachmentInfo.stencilLoadOp == dawn::LoadOp::Clear);
if (doDepthClear) {
glDepthMask(GL_TRUE);
gl.DepthMask(GL_TRUE);
}
if (doStencilClear) {
glStencilMask(GetStencilMaskFromStencilFormat(attachmentFormat));
gl.StencilMask(GetStencilMaskFromStencilFormat(attachmentFormat));
}
if (doDepthClear && doStencilClear) {
glClearBufferfi(GL_DEPTH_STENCIL, 0, attachmentInfo.clearDepth,
attachmentInfo.clearStencil);
gl.ClearBufferfi(GL_DEPTH_STENCIL, 0, attachmentInfo.clearDepth,
attachmentInfo.clearStencil);
} else if (doDepthClear) {
glClearBufferfv(GL_DEPTH, 0, &attachmentInfo.clearDepth);
gl.ClearBufferfv(GL_DEPTH, 0, &attachmentInfo.clearDepth);
} else if (doStencilClear) {
const GLint clearStencil = attachmentInfo.clearStencil;
glClearBufferiv(GL_STENCIL, 0, &clearStencil);
gl.ClearBufferiv(GL_STENCIL, 0, &clearStencil);
}
}
}
@ -670,32 +677,32 @@ namespace dawn_native { namespace opengl {
mCommands.NextCommand<EndRenderPassCmd>();
if (renderPass->sampleCount > 1) {
ResolveMultisampledRenderTargets(renderPass);
ResolveMultisampledRenderTargets(gl, renderPass);
}
glDeleteFramebuffers(1, &fbo);
gl.DeleteFramebuffers(1, &fbo);
return;
} break;
case Command::Draw: {
DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
inputBuffers.Apply();
inputBuffers.Apply(gl);
if (draw->firstInstance > 0) {
glDrawArraysInstancedBaseInstance(lastPipeline->GetGLPrimitiveTopology(),
draw->firstVertex, draw->vertexCount,
draw->instanceCount, draw->firstInstance);
gl.DrawArraysInstancedBaseInstance(
lastPipeline->GetGLPrimitiveTopology(), draw->firstVertex,
draw->vertexCount, draw->instanceCount, draw->firstInstance);
} else {
// This branch is only needed on OpenGL < 4.2
glDrawArraysInstanced(lastPipeline->GetGLPrimitiveTopology(),
draw->firstVertex, draw->vertexCount,
draw->instanceCount);
gl.DrawArraysInstanced(lastPipeline->GetGLPrimitiveTopology(),
draw->firstVertex, draw->vertexCount,
draw->instanceCount);
}
} break;
case Command::DrawIndexed: {
DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
inputBuffers.Apply();
inputBuffers.Apply(gl);
dawn::IndexFormat indexFormat =
lastPipeline->GetVertexInputDescriptor()->indexFormat;
@ -703,14 +710,14 @@ namespace dawn_native { namespace opengl {
GLenum formatType = IndexFormatType(indexFormat);
if (draw->firstInstance > 0) {
glDrawElementsInstancedBaseVertexBaseInstance(
gl.DrawElementsInstancedBaseVertexBaseInstance(
lastPipeline->GetGLPrimitiveTopology(), draw->indexCount, formatType,
reinterpret_cast<void*>(draw->firstIndex * formatSize +
indexBufferBaseOffset),
draw->instanceCount, draw->baseVertex, draw->firstInstance);
} else {
// This branch is only needed on OpenGL < 4.2
glDrawElementsInstancedBaseVertex(
gl.DrawElementsInstancedBaseVertex(
lastPipeline->GetGLPrimitiveTopology(), draw->indexCount, formatType,
reinterpret_cast<void*>(draw->firstIndex * formatSize +
indexBufferBaseOffset),
@ -720,20 +727,20 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndirect: {
DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
inputBuffers.Apply();
inputBuffers.Apply(gl);
uint64_t indirectBufferOffset = draw->indirectOffset;
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle());
glDrawArraysIndirect(
gl.BindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle());
gl.DrawArraysIndirect(
lastPipeline->GetGLPrimitiveTopology(),
reinterpret_cast<void*>(static_cast<intptr_t>(indirectBufferOffset)));
} break;
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = mCommands.NextCommand<DrawIndexedIndirectCmd>();
inputBuffers.Apply();
inputBuffers.Apply(gl);
dawn::IndexFormat indexFormat =
lastPipeline->GetVertexInputDescriptor()->indexFormat;
@ -742,8 +749,8 @@ namespace dawn_native { namespace opengl {
uint64_t indirectBufferOffset = draw->indirectOffset;
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle());
glDrawElementsIndirect(
gl.BindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle());
gl.DrawElementsIndirect(
lastPipeline->GetGLPrimitiveTopology(), formatType,
reinterpret_cast<void*>(static_cast<intptr_t>(indirectBufferOffset)));
} break;
@ -766,22 +773,22 @@ namespace dawn_native { namespace opengl {
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
persistentPipelineState.SetStencilReference(cmd->reference);
persistentPipelineState.SetStencilReference(gl, cmd->reference);
} break;
case Command::SetScissorRect: {
SetScissorRectCmd* cmd = mCommands.NextCommand<SetScissorRectCmd>();
glScissor(cmd->x, cmd->y, cmd->width, cmd->height);
gl.Scissor(cmd->x, cmd->y, cmd->width, cmd->height);
} break;
case Command::SetBlendColor: {
SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
glBlendColor(cmd->color.r, cmd->color.g, cmd->color.b, cmd->color.a);
gl.BlendColor(cmd->color.r, cmd->color.g, cmd->color.b, cmd->color.a);
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
ApplyBindGroup(cmd->index, cmd->group.Get(),
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
ToBackend(lastPipeline->GetLayout()), lastPipeline);
} break;

View File

@ -23,11 +23,11 @@ namespace dawn_native { namespace opengl {
PerStage<const ShaderModule*> modules(nullptr);
modules[dawn::ShaderStage::Compute] = ToBackend(descriptor->computeStage->module);
PipelineGL::Initialize(ToBackend(descriptor->layout), modules);
PipelineGL::Initialize(device->gl, ToBackend(descriptor->layout), modules);
}
void ComputePipeline::ApplyNow() {
PipelineGL::ApplyNow();
PipelineGL::ApplyNow(ToBackend(GetDevice())->gl);
}
}} // namespace dawn_native::opengl

View File

@ -31,8 +31,10 @@
namespace dawn_native { namespace opengl {
Device::Device(AdapterBase* adapter, const DeviceDescriptor* descriptor)
: DeviceBase(adapter, descriptor) {
Device::Device(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions)
: DeviceBase(adapter, descriptor), gl(functions) {
if (descriptor != nullptr) {
ApplyToggleOverrides(descriptor);
}
@ -102,7 +104,7 @@ namespace dawn_native { namespace opengl {
}
void Device::SubmitFenceSync() {
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
GLsync sync = gl.FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
mLastSubmittedSerial++;
mFencesInFlight.emplace(sync, mLastSubmittedSerial);
}
@ -130,12 +132,12 @@ namespace dawn_native { namespace opengl {
// Fence are added in order, so we can stop searching as soon
// as we see one that's not ready.
GLenum result = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
GLenum result = gl.ClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
if (result == GL_TIMEOUT_EXPIRED) {
continue;
}
glDeleteSync(sync);
gl.DeleteSync(sync);
mFencesInFlight.pop();

View File

@ -20,8 +20,7 @@
#include "common/Platform.h"
#include "dawn_native/Device.h"
#include "dawn_native/opengl/Forward.h"
#include "glad/glad.h"
#include "dawn_native/opengl/OpenGLFunctions.h"
#include <queue>
@ -34,9 +33,14 @@ namespace dawn_native { namespace opengl {
class Device : public DeviceBase {
public:
Device(AdapterBase* adapter, const DeviceDescriptor* descriptor);
Device(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions);
~Device();
// Contains all the OpenGL entry points, glDoFoo is called via device->gl.DoFoo.
const OpenGLFunctions gl;
void SubmitFenceSync();
// Dawn API

View File

@ -0,0 +1,59 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn_native/opengl/OpenGLFunctions.h"
#include <cctype>
namespace dawn_native { namespace opengl {
MaybeError OpenGLFunctions::Initialize(GetProcAddress getProc) {
PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(getProc("glGetString"));
if (getString == nullptr) {
return DAWN_CONTEXT_LOST_ERROR("Couldn't load glGetString");
}
std::string version = reinterpret_cast<const char*>(getString(GL_VERSION));
if (version.find("OpenGL ES") != std::string::npos) {
// ES spec states that the GL_VERSION string will be in the following format:
// "OpenGL ES N.M vendor-specific information"
mStandard = Standard::ES;
mMajorVersion = version[10] - '0';
mMinorVersion = version[12] - '0';
// The minor version shouldn't get to two digits.
ASSERT(version.size() <= 13 || !isdigit(version[13]));
DAWN_TRY(LoadOpenGLESProcs(getProc, mMajorVersion, mMinorVersion));
} else {
// OpenGL spec states the GL_VERSION string will be in the following format:
// <version number><space><vendor-specific information>
// The version number is either of the form major number.minor number or major
// number.minor number.release number, where the numbers all have one or more
// digits
mStandard = Standard::Desktop;
mMajorVersion = version[0] - '0';
mMinorVersion = version[2] - '0';
// The minor version shouldn't get to two digits.
ASSERT(version.size() <= 3 || !isdigit(version[3]));
DAWN_TRY(LoadDesktopGLProcs(getProc, mMajorVersion, mMinorVersion));
}
return {};
}
}} // namespace dawn_native::opengl

View File

@ -0,0 +1,39 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWNNATIVE_OPENGL_OPENGLFUNCTIONS_H_
#define DAWNNATIVE_OPENGL_OPENGLFUNCTIONS_H_
#include "dawn_native/opengl/OpenGLFunctionsBase_autogen.h"
namespace dawn_native { namespace opengl {
struct OpenGLFunctions : OpenGLFunctionsBase {
public:
MaybeError Initialize(GetProcAddress getProc);
private:
uint32_t mMajorVersion;
uint32_t mMinorVersion;
enum class Standard {
Desktop,
ES,
};
Standard mStandard;
};
}} // namespace dawn_native::opengl
#endif // DAWNNATIVE_OPENGL_OPENGLFUNCTIONS_H_

View File

@ -14,13 +14,16 @@
#include "dawn_native/opengl/PersistentPipelineStateGL.h"
#include "dawn_native/opengl/OpenGLFunctions.h"
namespace dawn_native { namespace opengl {
void PersistentPipelineState::SetDefaultState() {
CallGLStencilFunc();
void PersistentPipelineState::SetDefaultState(const OpenGLFunctions& gl) {
CallGLStencilFunc(gl);
}
void PersistentPipelineState::SetStencilFuncsAndMask(GLenum stencilBackCompareFunction,
void PersistentPipelineState::SetStencilFuncsAndMask(const OpenGLFunctions& gl,
GLenum stencilBackCompareFunction,
GLenum stencilFrontCompareFunction,
uint32_t stencilReadMask) {
if (mStencilBackCompareFunction == stencilBackCompareFunction &&
@ -32,23 +35,24 @@ namespace dawn_native { namespace opengl {
mStencilBackCompareFunction = stencilBackCompareFunction;
mStencilFrontCompareFunction = stencilFrontCompareFunction;
mStencilReadMask = stencilReadMask;
CallGLStencilFunc();
CallGLStencilFunc(gl);
}
void PersistentPipelineState::SetStencilReference(uint32_t stencilReference) {
void PersistentPipelineState::SetStencilReference(const OpenGLFunctions& gl,
uint32_t stencilReference) {
if (mStencilReference == stencilReference) {
return;
}
mStencilReference = stencilReference;
CallGLStencilFunc();
CallGLStencilFunc(gl);
}
void PersistentPipelineState::CallGLStencilFunc() {
glStencilFuncSeparate(GL_BACK, mStencilBackCompareFunction, mStencilReference,
mStencilReadMask);
glStencilFuncSeparate(GL_FRONT, mStencilFrontCompareFunction, mStencilReference,
mStencilReadMask);
void PersistentPipelineState::CallGLStencilFunc(const OpenGLFunctions& gl) {
gl.StencilFuncSeparate(GL_BACK, mStencilBackCompareFunction, mStencilReference,
mStencilReadMask);
gl.StencilFuncSeparate(GL_FRONT, mStencilFrontCompareFunction, mStencilReference,
mStencilReadMask);
}
}} // namespace dawn_native::opengl

View File

@ -21,16 +21,19 @@
namespace dawn_native { namespace opengl {
struct OpenGLFunctions;
class PersistentPipelineState {
public:
void SetDefaultState();
void SetStencilFuncsAndMask(GLenum stencilBackCompareFunction,
void SetDefaultState(const OpenGLFunctions& gl);
void SetStencilFuncsAndMask(const OpenGLFunctions& gl,
GLenum stencilBackCompareFunction,
GLenum stencilFrontCompareFunction,
uint32_t stencilReadMask);
void SetStencilReference(uint32_t stencilReference);
void SetStencilReference(const OpenGLFunctions& gl, uint32_t stencilReference);
private:
void CallGLStencilFunc();
void CallGLStencilFunc(const OpenGLFunctions& gl);
GLenum mStencilBackCompareFunction = GL_ALWAYS;
GLenum mStencilFrontCompareFunction = GL_ALWAYS;

View File

@ -17,7 +17,7 @@
#include "common/BitSetIterator.h"
#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/opengl/Forward.h"
#include "dawn_native/opengl/PersistentPipelineStateGL.h"
#include "dawn_native/opengl/OpenGLFunctions.h"
#include "dawn_native/opengl/PipelineLayoutGL.h"
#include "dawn_native/opengl/ShaderModuleGL.h"
@ -46,22 +46,24 @@ namespace dawn_native { namespace opengl {
PipelineGL::PipelineGL() {
}
void PipelineGL::Initialize(const PipelineLayout* layout,
void PipelineGL::Initialize(const OpenGLFunctions& gl,
const PipelineLayout* layout,
const PerStage<const ShaderModule*>& modules) {
auto CreateShader = [](GLenum type, const char* source) -> GLuint {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, nullptr);
glCompileShader(shader);
auto CreateShader = [](const OpenGLFunctions& gl, GLenum type,
const char* source) -> GLuint {
GLuint shader = gl.CreateShader(type);
gl.ShaderSource(shader, 1, &source, nullptr);
gl.CompileShader(shader);
GLint compileStatus = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
gl.GetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus == GL_FALSE) {
GLint infoLogLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
gl.GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 1) {
std::vector<char> buffer(infoLogLength);
glGetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]);
gl.GetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]);
std::cout << source << std::endl;
std::cout << "Program compilation failed:\n";
std::cout << buffer.data() << std::endl;
@ -70,7 +72,7 @@ namespace dawn_native { namespace opengl {
return shader;
};
mProgram = glCreateProgram();
mProgram = gl.CreateProgram();
dawn::ShaderStageBit activeStages = dawn::ShaderStageBit::None;
for (dawn::ShaderStage stage : IterateStages(kAllStages)) {
@ -80,27 +82,27 @@ namespace dawn_native { namespace opengl {
}
for (dawn::ShaderStage stage : IterateStages(activeStages)) {
GLuint shader = CreateShader(GLShaderType(stage), modules[stage]->GetSource());
glAttachShader(mProgram, shader);
GLuint shader = CreateShader(gl, GLShaderType(stage), modules[stage]->GetSource());
gl.AttachShader(mProgram, shader);
}
glLinkProgram(mProgram);
gl.LinkProgram(mProgram);
GLint linkStatus = GL_FALSE;
glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
gl.GetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_FALSE) {
GLint infoLogLength = 0;
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
gl.GetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 1) {
std::vector<char> buffer(infoLogLength);
glGetProgramInfoLog(mProgram, infoLogLength, nullptr, &buffer[0]);
gl.GetProgramInfoLog(mProgram, infoLogLength, nullptr, &buffer[0]);
std::cout << "Program link failed:\n";
std::cout << buffer.data() << std::endl;
}
}
glUseProgram(mProgram);
gl.UseProgram(mProgram);
// The uniforms are part of the program state so we can pre-bind buffer units, texture units
// etc.
@ -117,14 +119,14 @@ namespace dawn_native { namespace opengl {
std::string name = GetBindingName(group, binding);
switch (groupInfo.types[binding]) {
case dawn::BindingType::UniformBuffer: {
GLint location = glGetUniformBlockIndex(mProgram, name.c_str());
glUniformBlockBinding(mProgram, location, indices[group][binding]);
GLint location = gl.GetUniformBlockIndex(mProgram, name.c_str());
gl.UniformBlockBinding(mProgram, location, indices[group][binding]);
} break;
case dawn::BindingType::StorageBuffer: {
GLuint location = glGetProgramResourceIndex(
GLuint location = gl.GetProgramResourceIndex(
mProgram, GL_SHADER_STORAGE_BLOCK, name.c_str());
glShaderStorageBlockBinding(mProgram, location, indices[group][binding]);
gl.ShaderStorageBlockBinding(mProgram, location, indices[group][binding]);
} break;
case dawn::BindingType::Sampler:
@ -157,8 +159,8 @@ namespace dawn_native { namespace opengl {
GLuint textureUnit = layout->GetTextureUnitsUsed();
for (const auto& combined : combinedSamplersSet) {
std::string name = combined.GetName();
GLint location = glGetUniformLocation(mProgram, name.c_str());
glUniform1i(location, textureUnit);
GLint location = gl.GetUniformLocation(mProgram, name.c_str());
gl.Uniform1i(location, textureUnit);
GLuint samplerIndex =
indices[combined.samplerLocation.group][combined.samplerLocation.binding];
@ -187,8 +189,8 @@ namespace dawn_native { namespace opengl {
return mProgram;
}
void PipelineGL::ApplyNow() {
glUseProgram(mProgram);
void PipelineGL::ApplyNow(const OpenGLFunctions& gl) {
gl.UseProgram(mProgram);
}
}} // namespace dawn_native::opengl

View File

@ -23,7 +23,7 @@
namespace dawn_native { namespace opengl {
class Device;
struct OpenGLFunctions;
class PersistentPipelineState;
class PipelineLayout;
class ShaderModule;
@ -32,7 +32,9 @@ namespace dawn_native { namespace opengl {
public:
PipelineGL();
void Initialize(const PipelineLayout* layout, const PerStage<const ShaderModule*>& modules);
void Initialize(const OpenGLFunctions& gl,
const PipelineLayout* layout,
const PerStage<const ShaderModule*>& modules);
using BindingLocations =
std::array<std::array<GLint, kMaxBindingsPerGroup>, kMaxBindGroups>;
@ -41,7 +43,7 @@ namespace dawn_native { namespace opengl {
const std::vector<GLuint>& GetTextureUnitsForTextureView(GLuint index) const;
GLuint GetProgramHandle() const;
void ApplyNow();
void ApplyNow(const OpenGLFunctions& gl);
private:
GLuint mProgram;

View File

@ -90,23 +90,25 @@ namespace dawn_native { namespace opengl {
}
}
void ApplyColorState(uint32_t attachment, const ColorStateDescriptor* descriptor) {
void ApplyColorState(const OpenGLFunctions& gl,
uint32_t attachment,
const ColorStateDescriptor* descriptor) {
if (BlendEnabled(descriptor)) {
glEnablei(GL_BLEND, attachment);
glBlendEquationSeparatei(attachment, GLBlendMode(descriptor->colorBlend.operation),
GLBlendMode(descriptor->alphaBlend.operation));
glBlendFuncSeparatei(attachment,
GLBlendFactor(descriptor->colorBlend.srcFactor, false),
GLBlendFactor(descriptor->colorBlend.dstFactor, false),
GLBlendFactor(descriptor->alphaBlend.srcFactor, true),
GLBlendFactor(descriptor->alphaBlend.dstFactor, true));
gl.Enablei(GL_BLEND, attachment);
gl.BlendEquationSeparatei(attachment, GLBlendMode(descriptor->colorBlend.operation),
GLBlendMode(descriptor->alphaBlend.operation));
gl.BlendFuncSeparatei(attachment,
GLBlendFactor(descriptor->colorBlend.srcFactor, false),
GLBlendFactor(descriptor->colorBlend.dstFactor, false),
GLBlendFactor(descriptor->alphaBlend.srcFactor, true),
GLBlendFactor(descriptor->alphaBlend.dstFactor, true));
} else {
glDisablei(GL_BLEND, attachment);
gl.Disablei(GL_BLEND, attachment);
}
glColorMaski(attachment, descriptor->writeMask & dawn::ColorWriteMask::Red,
descriptor->writeMask & dawn::ColorWriteMask::Green,
descriptor->writeMask & dawn::ColorWriteMask::Blue,
descriptor->writeMask & dawn::ColorWriteMask::Alpha);
gl.ColorMaski(attachment, descriptor->writeMask & dawn::ColorWriteMask::Red,
descriptor->writeMask & dawn::ColorWriteMask::Green,
descriptor->writeMask & dawn::ColorWriteMask::Blue,
descriptor->writeMask & dawn::ColorWriteMask::Alpha);
}
GLuint OpenGLStencilOperation(dawn::StencilOperation stencilOperation) {
@ -132,43 +134,44 @@ namespace dawn_native { namespace opengl {
}
}
void ApplyDepthStencilState(const DepthStencilStateDescriptor* descriptor,
void ApplyDepthStencilState(const OpenGLFunctions& gl,
const DepthStencilStateDescriptor* descriptor,
PersistentPipelineState* persistentPipelineState) {
// Depth writes only occur if depth is enabled
if (descriptor->depthCompare == dawn::CompareFunction::Always &&
!descriptor->depthWriteEnabled) {
glDisable(GL_DEPTH_TEST);
gl.Disable(GL_DEPTH_TEST);
} else {
glEnable(GL_DEPTH_TEST);
gl.Enable(GL_DEPTH_TEST);
}
if (descriptor->depthWriteEnabled) {
glDepthMask(GL_TRUE);
gl.DepthMask(GL_TRUE);
} else {
glDepthMask(GL_FALSE);
gl.DepthMask(GL_FALSE);
}
glDepthFunc(ToOpenGLCompareFunction(descriptor->depthCompare));
gl.DepthFunc(ToOpenGLCompareFunction(descriptor->depthCompare));
if (StencilTestEnabled(descriptor)) {
glEnable(GL_STENCIL_TEST);
gl.Enable(GL_STENCIL_TEST);
} else {
glDisable(GL_STENCIL_TEST);
gl.Disable(GL_STENCIL_TEST);
}
GLenum backCompareFunction = ToOpenGLCompareFunction(descriptor->stencilBack.compare);
GLenum frontCompareFunction = ToOpenGLCompareFunction(descriptor->stencilFront.compare);
persistentPipelineState->SetStencilFuncsAndMask(
backCompareFunction, frontCompareFunction, descriptor->stencilReadMask);
gl, backCompareFunction, frontCompareFunction, descriptor->stencilReadMask);
glStencilOpSeparate(GL_BACK, OpenGLStencilOperation(descriptor->stencilBack.failOp),
OpenGLStencilOperation(descriptor->stencilBack.depthFailOp),
OpenGLStencilOperation(descriptor->stencilBack.passOp));
glStencilOpSeparate(GL_FRONT, OpenGLStencilOperation(descriptor->stencilFront.failOp),
OpenGLStencilOperation(descriptor->stencilFront.depthFailOp),
OpenGLStencilOperation(descriptor->stencilFront.passOp));
gl.StencilOpSeparate(GL_BACK, OpenGLStencilOperation(descriptor->stencilBack.failOp),
OpenGLStencilOperation(descriptor->stencilBack.depthFailOp),
OpenGLStencilOperation(descriptor->stencilBack.passOp));
gl.StencilOpSeparate(GL_FRONT, OpenGLStencilOperation(descriptor->stencilFront.failOp),
OpenGLStencilOperation(descriptor->stencilFront.depthFailOp),
OpenGLStencilOperation(descriptor->stencilFront.passOp));
glStencilMask(descriptor->stencilWriteMask);
gl.StencilMask(descriptor->stencilWriteMask);
}
} // anonymous namespace
@ -181,13 +184,14 @@ namespace dawn_native { namespace opengl {
modules[dawn::ShaderStage::Vertex] = ToBackend(descriptor->vertexStage->module);
modules[dawn::ShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
PipelineGL::Initialize(ToBackend(GetLayout()), modules);
PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), modules);
CreateVAOForVertexInput(descriptor->vertexInput);
}
RenderPipeline::~RenderPipeline() {
glDeleteVertexArrays(1, &mVertexArrayObject);
glBindVertexArray(0);
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
gl.DeleteVertexArrays(1, &mVertexArrayObject);
gl.BindVertexArray(0);
}
GLenum RenderPipeline::GetGLPrimitiveTopology() const {
@ -195,11 +199,14 @@ namespace dawn_native { namespace opengl {
}
void RenderPipeline::CreateVAOForVertexInput(const VertexInputDescriptor* vertexInput) {
glGenVertexArrays(1, &mVertexArrayObject);
glBindVertexArray(mVertexArrayObject);
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
gl.GenVertexArrays(1, &mVertexArrayObject);
gl.BindVertexArray(mVertexArrayObject);
for (uint32_t location : IterateBitSet(GetAttributesSetMask())) {
const auto& attribute = GetAttribute(location);
glEnableVertexAttribArray(location);
gl.EnableVertexAttribArray(location);
attributesUsingInput[attribute.inputSlot][location] = true;
auto input = GetInput(attribute.inputSlot);
@ -207,13 +214,13 @@ namespace dawn_native { namespace opengl {
if (input.stride == 0) {
// Emulate a stride of zero (constant vertex attribute) by
// setting the attribute instance divisor to a huge number.
glVertexAttribDivisor(location, 0xffffffff);
gl.VertexAttribDivisor(location, 0xffffffff);
} else {
switch (input.stepMode) {
case dawn::InputStepMode::Vertex:
break;
case dawn::InputStepMode::Instance:
glVertexAttribDivisor(location, 1);
gl.VertexAttribDivisor(location, 1);
break;
default:
UNREACHABLE();
@ -223,15 +230,16 @@ namespace dawn_native { namespace opengl {
}
void RenderPipeline::ApplyNow(PersistentPipelineState& persistentPipelineState) {
PipelineGL::ApplyNow();
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
PipelineGL::ApplyNow(gl);
ASSERT(mVertexArrayObject);
glBindVertexArray(mVertexArrayObject);
gl.BindVertexArray(mVertexArrayObject);
ApplyDepthStencilState(GetDepthStencilStateDescriptor(), &persistentPipelineState);
ApplyDepthStencilState(gl, GetDepthStencilStateDescriptor(), &persistentPipelineState);
for (uint32_t attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) {
ApplyColorState(attachmentSlot, GetColorStateDescriptor(attachmentSlot));
ApplyColorState(gl, attachmentSlot, GetColorStateDescriptor(attachmentSlot));
}
}

View File

@ -74,21 +74,23 @@ namespace dawn_native { namespace opengl {
Sampler::Sampler(Device* device, const SamplerDescriptor* descriptor)
: SamplerBase(device, descriptor) {
glGenSamplers(1, &mHandle);
glSamplerParameteri(mHandle, GL_TEXTURE_MAG_FILTER, MagFilterMode(descriptor->magFilter));
glSamplerParameteri(mHandle, GL_TEXTURE_MIN_FILTER,
MinFilterMode(descriptor->minFilter, descriptor->mipmapFilter));
glSamplerParameteri(mHandle, GL_TEXTURE_WRAP_R, WrapMode(descriptor->addressModeW));
glSamplerParameteri(mHandle, GL_TEXTURE_WRAP_S, WrapMode(descriptor->addressModeU));
glSamplerParameteri(mHandle, GL_TEXTURE_WRAP_T, WrapMode(descriptor->addressModeV));
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
glSamplerParameterf(mHandle, GL_TEXTURE_MIN_LOD, descriptor->lodMinClamp);
glSamplerParameterf(mHandle, GL_TEXTURE_MAX_LOD, descriptor->lodMaxClamp);
gl.GenSamplers(1, &mHandle);
gl.SamplerParameteri(mHandle, GL_TEXTURE_MAG_FILTER, MagFilterMode(descriptor->magFilter));
gl.SamplerParameteri(mHandle, GL_TEXTURE_MIN_FILTER,
MinFilterMode(descriptor->minFilter, descriptor->mipmapFilter));
gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_R, WrapMode(descriptor->addressModeW));
gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_S, WrapMode(descriptor->addressModeU));
gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_T, WrapMode(descriptor->addressModeV));
gl.SamplerParameterf(mHandle, GL_TEXTURE_MIN_LOD, descriptor->lodMinClamp);
gl.SamplerParameterf(mHandle, GL_TEXTURE_MAX_LOD, descriptor->lodMaxClamp);
if (ToOpenGLCompareFunction(descriptor->compareFunction) != GL_NEVER) {
glSamplerParameteri(mHandle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glSamplerParameteri(mHandle, GL_TEXTURE_COMPARE_FUNC,
ToOpenGLCompareFunction(descriptor->compareFunction));
gl.SamplerParameteri(mHandle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
gl.SamplerParameteri(mHandle, GL_TEXTURE_COMPARE_FUNC,
ToOpenGLCompareFunction(descriptor->compareFunction));
}
}

View File

@ -88,9 +88,9 @@ namespace dawn_native { namespace opengl {
}
}
GLuint GenTexture() {
GLuint GenTexture(const OpenGLFunctions& gl) {
GLuint handle = 0;
glGenTextures(1, &handle);
gl.GenTextures(1, &handle);
return handle;
}
@ -130,7 +130,9 @@ namespace dawn_native { namespace opengl {
// Texture
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
: Texture(device, descriptor, GenTexture(), TextureState::OwnedInternal) {
: Texture(device, descriptor, GenTexture(device->gl), TextureState::OwnedInternal) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
uint32_t width = GetSize().width;
uint32_t height = GetSize().height;
uint32_t levels = GetNumMipLevels();
@ -139,7 +141,7 @@ namespace dawn_native { namespace opengl {
auto formatInfo = GetGLFormatInfo(GetFormat());
glBindTexture(mTarget, mHandle);
gl.BindTexture(mTarget, mHandle);
// glTextureView() requires the value of GL_TEXTURE_IMMUTABLE_FORMAT for origtexture to be
// GL_TRUE, so the storage of the texture must be allocated with glTexStorage*D.
@ -148,14 +150,14 @@ namespace dawn_native { namespace opengl {
case dawn::TextureDimension::e2D:
if (arrayLayers > 1) {
ASSERT(!IsMultisampledTexture());
glTexStorage3D(mTarget, levels, formatInfo.internalFormat, width, height,
arrayLayers);
gl.TexStorage3D(mTarget, levels, formatInfo.internalFormat, width, height,
arrayLayers);
} else {
if (IsMultisampledTexture()) {
glTexStorage2DMultisample(mTarget, sampleCount, formatInfo.internalFormat,
width, height, true);
gl.TexStorage2DMultisample(mTarget, sampleCount, formatInfo.internalFormat,
width, height, true);
} else {
glTexStorage2D(mTarget, levels, formatInfo.internalFormat, width, height);
gl.TexStorage2D(mTarget, levels, formatInfo.internalFormat, width, height);
}
}
break;
@ -165,7 +167,7 @@ namespace dawn_native { namespace opengl {
// The texture is not complete if it uses mipmapping and not all levels up to
// MAX_LEVEL have been defined.
glTexParameteri(mTarget, GL_TEXTURE_MAX_LEVEL, levels - 1);
gl.TexParameteri(mTarget, GL_TEXTURE_MAX_LEVEL, levels - 1);
if (GetDevice()->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
static constexpr uint32_t MAX_TEXEL_SIZE = 16;
@ -175,7 +177,7 @@ namespace dawn_native { namespace opengl {
// TODO(natlee@microsoft.com): clear all subresources
for (uint32_t i = 0; i < GL_TEXTURE_MAX_LEVEL; i++) {
glClearTexImage(mHandle, i, formatInfo.format, formatInfo.type, clearColor);
gl.ClearTexImage(mHandle, i, formatInfo.format, formatInfo.type, clearColor);
}
}
}
@ -193,7 +195,7 @@ namespace dawn_native { namespace opengl {
}
void Texture::DestroyImpl() {
glDeleteTextures(1, &mHandle);
ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
mHandle = 0;
}
@ -222,20 +224,21 @@ namespace dawn_native { namespace opengl {
} else {
// glTextureView() is supported on OpenGL version >= 4.3
// TODO(jiawei.shao@intel.com): support texture view on OpenGL version <= 4.2
mHandle = GenTexture();
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
mHandle = GenTexture(gl);
const Texture* textureGL = ToBackend(texture);
TextureFormatInfo textureViewFormat = GetGLFormatInfo(descriptor->format);
glTextureView(mHandle, mTarget, textureGL->GetHandle(),
textureViewFormat.internalFormat, descriptor->baseMipLevel,
descriptor->mipLevelCount, descriptor->baseArrayLayer,
descriptor->arrayLayerCount);
gl.TextureView(mHandle, mTarget, textureGL->GetHandle(),
textureViewFormat.internalFormat, descriptor->baseMipLevel,
descriptor->mipLevelCount, descriptor->baseArrayLayer,
descriptor->arrayLayerCount);
mOwnsHandle = true;
}
}
TextureView::~TextureView() {
if (mOwnsHandle) {
glDeleteTextures(1, &mHandle);
ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
}
}

50579
third_party/gl.xml vendored Normal file

File diff suppressed because it is too large Load Diff