Skip to content
This repository has been archived by the owner on Aug 1, 2019. It is now read-only.

Sampler descriptor #195

Merged
merged 8 commits into from
May 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions examples/HelloTriangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ void initTextures() {
.SetAllowedUsage(nxt::TextureUsageBit::TransferDst | nxt::TextureUsageBit::Sampled)
.GetResult();

sampler = device.CreateSamplerBuilder()
.SetFilterMode(nxt::FilterMode::Linear, nxt::FilterMode::Linear, nxt::FilterMode::Linear)
.GetResult();
nxt::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
sampler = device.CreateSampler(&samplerDesc);

// Initialize the texture with arbitrary data until we can load images
std::vector<uint8_t> data(4 * 1024 * 1024, 0);
Expand Down
5 changes: 2 additions & 3 deletions examples/RenderToTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@ void initTextures() {
.GetResult();
renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();

samplerPost = device.CreateSamplerBuilder()
.SetFilterMode(nxt::FilterMode::Linear, nxt::FilterMode::Linear, nxt::FilterMode::Linear)
.GetResult();
nxt::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
samplerPost = device.CreateSampler(&samplerDesc);
}

void initPipeline() {
Expand Down
25 changes: 10 additions & 15 deletions examples/glTFViewer/glTFViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,15 +336,15 @@ namespace {
const auto& iSamplerID = s.first;
const auto& iSampler = s.second;

auto magFilter = nxt::FilterMode::Nearest;
auto minFilter = nxt::FilterMode::Nearest;
auto mipmapFilter = nxt::FilterMode::Nearest;
nxt::SamplerDescriptor desc = utils::GetDefaultSamplerDescriptor();
// TODO: wrap modes

switch (iSampler.magFilter) {
case gl::Nearest:
magFilter = nxt::FilterMode::Nearest;
desc.magFilter = nxt::FilterMode::Nearest;
break;
case gl::Linear:
magFilter = nxt::FilterMode::Linear;
desc.magFilter = nxt::FilterMode::Linear;
break;
default:
fprintf(stderr, "unsupported magFilter %d\n", iSampler.magFilter);
Expand All @@ -354,12 +354,12 @@ namespace {
case gl::Nearest:
case gl::NearestMipmapNearest:
case gl::NearestMipmapLinear:
minFilter = nxt::FilterMode::Nearest;
desc.minFilter = nxt::FilterMode::Nearest;
break;
case gl::Linear:
case gl::LinearMipmapNearest:
case gl::LinearMipmapLinear:
minFilter = nxt::FilterMode::Linear;
desc.minFilter = nxt::FilterMode::Linear;
break;
default:
fprintf(stderr, "unsupported minFilter %d\n", iSampler.magFilter);
Expand All @@ -368,20 +368,15 @@ namespace {
switch (iSampler.minFilter) {
case gl::NearestMipmapNearest:
case gl::LinearMipmapNearest:
mipmapFilter = nxt::FilterMode::Nearest;
desc.mipmapFilter = nxt::FilterMode::Nearest;
break;
case gl::NearestMipmapLinear:
case gl::LinearMipmapLinear:
mipmapFilter = nxt::FilterMode::Linear;
desc.mipmapFilter = nxt::FilterMode::Linear;
break;
}

auto oSampler = device.CreateSamplerBuilder()
.SetFilterMode(magFilter, minFilter, mipmapFilter)
// TODO: wrap modes
.GetResult();

samplers[iSamplerID] = std::move(oSampler);
samplers[iSamplerID] = device.CreateSampler(&desc);
}
}

Expand Down
38 changes: 35 additions & 3 deletions generator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ def __init__(self, name, record):
self.native_methods = []
self.built_type = None

class StructureMember:
def __init__(self, name, typ, annotation):
self.name = name
self.type = typ
self.annotation = annotation
self.length = None

class StructureType(Type):
def __init__(self, name, record):
Type.__init__(self, name, record)
self.extensible = record.get("extensible", False)
self.members = []

############################################################
# PARSE
############################################################
Expand All @@ -112,9 +125,13 @@ def make_method(record):
arguments_by_name[arg.name.canonical_case()] = arg

for (arg, a) in zip(arguments, record.get('args', [])):
assert(arg.annotation == 'value' or 'length' in a)
if arg.annotation != 'value':
if a['length'] == 'strlen':
if not 'length' in a:
if arg.type.category == 'structure':
arg.length = "constant_one"
else:
assert(false)
elif a['length'] == 'strlen':
arg.length = 'strlen'
else:
arg.length = arguments_by_name[a['length']]
Expand All @@ -133,13 +150,21 @@ def make_method(record):
break
assert(obj.built_type != None)

def link_structure(struct, types):
def make_member(m):
return StructureMember(Name(m['name']), types[m['type']], m.get('annotation', 'value'))

# TODO([email protected]): Handle pointer members and their length
struct.members = [make_member(m) for m in struct.record['members']]

def parse_json(json):
category_to_parser = {
'bitmask': BitmaskType,
'enum': EnumType,
'native': NativeType,
'natively defined': NativelyDefined,
'object': ObjectType,
'structure': StructureType,
}

types = {}
Expand All @@ -159,6 +184,9 @@ def parse_json(json):
for obj in by_category['object']:
link_object(obj, types)

for struct in by_category['structure']:
link_structure(struct, types)

for category in by_category.keys():
by_category[category] = sorted(by_category[category], key=lambda typ: typ.name.canonical_case())

Expand Down Expand Up @@ -434,7 +462,11 @@ def main():
backend_params = {
'namespace': backend,
}
renders.append(FileRender('BackendProcTable.cpp', backend + '/ProcTable.' + extension, base_backend_params + [backend_params]))
renders.append(FileRender('backend/ProcTable.cpp', 'backend/' + backend + '/ProcTable.' + extension, base_backend_params + [backend_params]))

if 'backend_utils' in targets:
renders.append(FileRender('backend/ValidationUtils.h', 'backend/ValidationUtils_autogen.h', base_backend_params))
renders.append(FileRender('backend/ValidationUtils.cpp', 'backend/ValidationUtils_autogen.cpp', base_backend_params))

if 'wire' in targets:
renders.append(FileRender('wire/WireCmd.h', 'wire/WireCmd_autogen.h', base_backend_params))
Expand Down
11 changes: 11 additions & 0 deletions generator/templates/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@

{% endfor %}

{% for type in by_category["structure"] %}
typedef struct {
{% if type.extensible %}
const void* nextInChain;
{% endif %}
{% for member in type.members %}
{{as_annotated_cType(member)}};
{% endfor %}
} {{as_cType(type.name)}};
{% endfor %}

// Custom types depending on the target language
typedef uint64_t nxtCallbackUserdata;
typedef void (*nxtDeviceErrorCallback)(const char* message, nxtCallbackUserdata userdata);
Expand Down
19 changes: 19 additions & 0 deletions generator/templates/apicpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ namespace nxt {
{% endfor %}


{% for type in by_category["structure"] %}
{% set CppType = as_cppType(type.name) %}
{% set CType = as_cType(type.name) %}

static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");

{% if type.extensible %}
static_assert(offsetof({{CppType}}, nextInChain) == offsetof({{CType}}, nextInChain),
"offsetof mismatch for {{CppType}}::nextInChain");
{% endif %}
{% for member in type.members %}
{% set memberName = member.name.camelCase() %}
static_assert(offsetof({{CppType}}, {{memberName}}) == offsetof({{CType}}, {{memberName}}),
"offsetof mismatch for {{CppType}}::{{memberName}}");
{% endfor %}

{% endfor %}

{% for type in by_category["object"] %}
{% set CppType = as_cppType(type.name) %}
{% set CType = as_cType(type.name) %}
Expand Down
12 changes: 12 additions & 0 deletions generator/templates/apicpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ namespace nxt {
class {{as_cppType(type.name)}};
{% endfor %}

{% for type in by_category["structure"] %}
struct {{as_cppType(type.name)}} {
{% if type.extensible %}
const void* nextInChain = nullptr;
{% endif %}
{% for member in type.members %}
{{as_annotated_cppType(member)}};
{% endfor %}
};

{% endfor %}

template<typename Derived, typename CType>
class ObjectBase {
public:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,14 @@

#include "common/Assert.h"

#include "backend/ValidationUtils_autogen.h"
#include "backend/{{namespace}}/GeneratedCodeIncludes.h"

namespace backend {
namespace {{namespace}} {

namespace {

//* Helper functions to check the value of enums
{% for type in by_category["enum"] %}
{% set cType = as_cType(type.name) %}
bool CheckEnum{{cType}}({{cType}} value) {
switch (value) {
{% for value in type.values %}
case {{as_cEnum(type.name, value.name)}}:
return true;
{% endfor %}
default:
return false;
}
}
{% endfor %}

{% for type in by_category["bitmask"] %}
{% set cType = as_cType(type.name) %}
bool CheckBitmask{{cType}}({{cType}} value) {
return (value & ~{{type.full_mask}}) == 0;
}
{% endfor %}

{% set methodsWithExtraValidation = (
"CommandBufferBuilderGetResult",
"QueueSubmit",
Expand All @@ -70,6 +49,8 @@ namespace {{namespace}} {
{%- if not loop.first %}, {% endif -%}
{%- if arg.type.category in ["enum", "bitmask"] -%}
static_cast<nxt::{{as_cppType(arg.type.name)}}>({{as_varName(arg.name)}})
{%- elif arg.type.category == "structure" and arg.annotation != "value" -%}
reinterpret_cast<const nxt::{{as_cppType(arg.type.name)}}*>({{as_varName(arg.name)}})
{%- else -%}
{{as_varName(arg.name)}}
{%- endif -%}
Expand Down Expand Up @@ -100,10 +81,9 @@ namespace {{namespace}} {
{% endif %}
bool error = false;
{% for arg in method.arguments %}
{% if arg.type.category == "enum" %}
if (!CheckEnum{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) error = true;;
{% elif arg.type.category == "bitmask" %}
if (!CheckBitmask{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) error = true;
{% set cppType = as_cppType(arg.type.name) %}
{% if arg.type.category in ["enum", "bitmask"] %}
if (!IsValid{{cppType}}(static_cast<nxt::{{cppType}}>({{as_varName(arg.name)}}))) error = true;
{% else %}
(void) {{as_varName(arg.name)}};
{% endif %}
Expand Down Expand Up @@ -169,6 +149,8 @@ namespace {{namespace}} {
{%- if not loop.first %}, {% endif -%}
{%- if arg.type.category in ["enum", "bitmask"] -%}
static_cast<nxt::{{as_cppType(arg.type.name)}}>({{as_varName(arg.name)}})
{%- elif arg.type.category == "structure" and arg.annotation != "value" -%}
reinterpret_cast<const nxt::{{as_cppType(arg.type.name)}}*>({{as_varName(arg.name)}})
{%- else -%}
{{as_varName(arg.name)}}
{%- endif -%}
Expand Down
40 changes: 40 additions & 0 deletions generator/templates/backend/ValidationUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//* Copyright 2018 The NXT 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 "backend/ValidationUtils_autogen.h"

namespace backend {

{% for type in by_category["enum"] %}
bool IsValid{{type.name.CamelCase()}}(nxt::{{as_cppType(type.name)}} value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this be a "<" since our enums should be contiguous? Maybe with some extra asserts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping that the switch would be future proof for when we start to have sparse enums for extensions. Compilers do a good job of optimizing this pattern when it is dense, see https://godbolt.org/g/HjWVZH
WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM.

switch (value) {
{% for value in type.values %}
case nxt::{{as_cppType(type.name)}}::{{as_cppEnum(value.name)}}:
return true;
{% endfor %}
default:
return false;
}
}

{% endfor %}

{% for type in by_category["bitmask"] %}
bool IsValid{{type.name.CamelCase()}}(nxt::{{as_cppType(type.name)}} value) {
return (value & static_cast<nxt::{{as_cppType(type.name)}}>(~{{type.full_mask}})) == 0;
}

{% endfor %}

} // namespace backend
29 changes: 29 additions & 0 deletions generator/templates/backend/ValidationUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//* Copyright 2018 The NXT 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 BACKEND_VALIDATIONUTILS_H_
#define BACKEND_VALIDATIONUTILS_H_

#include "nxt/nxtcpp.h"

namespace backend {

// Helper functions to check the value of enums and bitmasks
{% for type in by_category["enum"] + by_category["bitmask"] %}
bool IsValid{{type.name.CamelCase()}}(nxt::{{as_cppType(type.name)}} value);
{% endfor %}

} // namespace backend

#endif // BACKEND_VALIDATIONUTILS_H_
2 changes: 2 additions & 0 deletions generator/templates/wire/WireClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ namespace wire {
{% set argName = as_varName(arg.name) %}
{% if arg.length == "strlen" %}
memcpy(allocCmd->GetPtr_{{argName}}(), {{argName}}, allocCmd->{{argName}}Strlen + 1);
{% elif arg.length == "constant_one" %}
memcpy(allocCmd->GetPtr_{{argName}}(), {{argName}}, sizeof(*{{argName}}));
{% elif arg.type.category == "object" %}
auto {{argName}}Storage = reinterpret_cast<uint32_t*>(allocCmd->GetPtr_{{argName}}());
for (size_t i = 0; i < {{as_varName(arg.length.name)}}; i++) {
Expand Down
4 changes: 4 additions & 0 deletions generator/templates/wire/WireCmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace wire {
{% for arg in method.arguments if arg.annotation != "value" %}
{% if arg.length == "strlen" %}
result += {{as_varName(arg.name)}}Strlen + 1;
{% elif arg.length == "constant_one" %}
result += sizeof({{as_cType(arg.type.name)}});
{% elif arg.type.category == "object" %}
result += {{as_varName(arg.length.name)}} * sizeof(uint32_t);
{% else %}
Expand All @@ -53,6 +55,8 @@ namespace wire {
{% endif %}
{% if arg.length == "strlen" %}
ptr += {{as_varName(arg.name)}}Strlen + 1;
{% elif arg.length == "constant_one" %}
ptr += sizeof({{as_cType(arg.type.name)}});
{% elif arg.type.category == "object" %}
ptr += {{as_varName(arg.length.name)}} * sizeof(uint32_t);
{% else %}
Expand Down
Loading