Compare commits
1 Commits
bjd/backen
...
pf/add-fil
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4261577724 |
@@ -474,7 +474,12 @@ constexpr std::string_view to_string(DescriptorType type) noexcept {
|
||||
|
||||
enum class DescriptorFlags : uint8_t {
|
||||
NONE = 0x00,
|
||||
DYNAMIC_OFFSET = 0x01
|
||||
|
||||
// Indicate a UNIFORM_BUFFER will have dynamic offsets.
|
||||
DYNAMIC_OFFSET = 0x01,
|
||||
|
||||
// To indicate a texture/sampler type should be unfiltered.
|
||||
UNFILTERABLE = 0x02,
|
||||
};
|
||||
|
||||
using descriptor_set_t = uint8_t;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "WebGPUDescriptorSetLayout.h"
|
||||
#include "WebGPUConstants.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
@@ -117,10 +118,10 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
samplerEntryInfo.binding = samplerEntry.binding;
|
||||
samplerEntry.visibility = wEntry.visibility;
|
||||
wEntry.texture.multisampled = isMultiSampledTypeDescriptor(fEntry.type);
|
||||
// TODO: Set once we have the filtering values
|
||||
if (isDepthDescriptor(fEntry.type)) {
|
||||
samplerEntry.sampler.type = wgpu::SamplerBindingType::Comparison;
|
||||
} else if (isIntDescriptor(fEntry.type)) {
|
||||
} else if (isIntDescriptor(fEntry.type) ||
|
||||
any(fEntry.flags & DescriptorFlags::UNFILTERABLE)) {
|
||||
samplerEntry.sampler.type = wgpu::SamplerBindingType::NonFiltering;
|
||||
} else {
|
||||
samplerEntry.sampler.type = wgpu::SamplerBindingType::Filtering;
|
||||
@@ -151,8 +152,11 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
if (isDepthDescriptor(fEntry.type)) {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Depth;
|
||||
} else if (isFloatDescriptor(fEntry.type)) {
|
||||
// TODO: Set once we have the filtering values
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Float;
|
||||
if (any(fEntry.flags & DescriptorFlags::UNFILTERABLE)) {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::UnfilterableFloat;
|
||||
} else {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Float;
|
||||
}
|
||||
} else if (isIntDescriptor(fEntry.type)) {
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Sint;
|
||||
} else if (isUnsignedIntDescriptor(fEntry.type)) {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "CommandStreamDispatcher.h"
|
||||
#include "DriverBase.h"
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include "webgpu/WebGPUConstants.h"
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
@@ -1166,6 +1167,7 @@ void WebGPUDriver::updateDescriptorSetBuffer(Handle<HwDescriptorSet> descriptorS
|
||||
void WebGPUDriver::updateDescriptorSetTexture(Handle<HwDescriptorSet> descriptorSetHandle,
|
||||
const backend::descriptor_binding_t binding, Handle<HwTexture> textureHandle,
|
||||
const SamplerParams params) {
|
||||
|
||||
auto bindGroup = handleCast<WebGPUDescriptorSet>(descriptorSetHandle);
|
||||
auto texture = handleCast<WebGPUTexture>(textureHandle);
|
||||
|
||||
|
||||
@@ -91,16 +91,20 @@ void WebGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor&
|
||||
.clearValue = { params.clearColor.r, params.clearColor.g, params.clearColor.b,
|
||||
params.clearColor.a } });
|
||||
|
||||
bool const depthReadonly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
|
||||
|
||||
if (defaultDepthStencilTextureView) {
|
||||
mDepthStencilAttachmentDescriptor = {
|
||||
.view = defaultDepthStencilTextureView,
|
||||
.depthLoadOp =
|
||||
WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH),
|
||||
.depthStoreOp =
|
||||
WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH),
|
||||
.depthLoadOp = depthReadonly ? wgpu::LoadOp::Undefined
|
||||
: WebGPURenderTarget::getLoadOperation(params,
|
||||
TargetBufferFlags::DEPTH),
|
||||
.depthStoreOp = depthReadonly ? wgpu::StoreOp::Undefined
|
||||
: WebGPURenderTarget::getStoreOperation(params,
|
||||
TargetBufferFlags::DEPTH),
|
||||
.depthClearValue = static_cast<float>(params.clearDepth),
|
||||
.depthReadOnly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0,
|
||||
.depthReadOnly = depthReadonly,
|
||||
.stencilLoadOp = wgpu::LoadOp::Undefined,
|
||||
.stencilStoreOp = wgpu::StoreOp::Undefined,
|
||||
.stencilClearValue = params.clearStencil,
|
||||
@@ -156,14 +160,19 @@ void WebGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor&
|
||||
customDepthTextureView ? customDepthTextureView : customStencilTextureView;
|
||||
|
||||
if (hasDepth) {
|
||||
bool const depthReadonly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
|
||||
|
||||
|
||||
mDepthStencilAttachmentDescriptor.depthLoadOp =
|
||||
depthReadonly ? wgpu::LoadOp::Undefined :
|
||||
WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH);
|
||||
mDepthStencilAttachmentDescriptor.depthStoreOp =
|
||||
depthReadonly ? wgpu::StoreOp::Undefined :
|
||||
WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH);
|
||||
mDepthStencilAttachmentDescriptor.depthClearValue =
|
||||
static_cast<float>(params.clearDepth);
|
||||
mDepthStencilAttachmentDescriptor.depthReadOnly =
|
||||
(params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
|
||||
mDepthStencilAttachmentDescriptor.depthReadOnly = depthReadonly;
|
||||
} else {
|
||||
mDepthStencilAttachmentDescriptor.depthLoadOp = wgpu::LoadOp::Undefined;
|
||||
mDepthStencilAttachmentDescriptor.depthStoreOp = wgpu::StoreOp::Undefined;
|
||||
|
||||
@@ -481,6 +481,7 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener,
|
||||
uint8_t fieldType = 0;
|
||||
uint8_t fieldFormat = 0;
|
||||
uint8_t fieldPrecision = 0;
|
||||
bool fieldUnfilterable = false;
|
||||
bool fieldMultisample = false;
|
||||
|
||||
if (!unflattener.read(&fieldName)) {
|
||||
@@ -503,6 +504,10 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!unflattener.read(&fieldUnfilterable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!unflattener.read(&fieldMultisample)) {
|
||||
return false;
|
||||
}
|
||||
@@ -512,6 +517,7 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener,
|
||||
SamplerInterfaceBlock::Type(fieldType),
|
||||
SamplerInterfaceBlock::Format(fieldFormat),
|
||||
SamplerInterfaceBlock::Precision(fieldPrecision),
|
||||
fieldUnfilterable,
|
||||
fieldMultisample);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : float,
|
||||
|
||||
@@ -4,7 +4,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: medium
|
||||
precision: medium,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : float4,
|
||||
|
||||
@@ -9,7 +9,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : float4,
|
||||
@@ -77,4 +78,3 @@ fragment {
|
||||
postProcess.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: medium
|
||||
precision: medium,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : float2,
|
||||
|
||||
@@ -9,7 +9,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: medium
|
||||
precision: medium,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : float2,
|
||||
|
||||
@@ -5,7 +5,8 @@ material {
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high,
|
||||
multisample : true
|
||||
multisample : true,
|
||||
unfilterable: true
|
||||
}
|
||||
],
|
||||
outputs : [
|
||||
|
||||
@@ -4,7 +4,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -4,7 +4,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -4,7 +4,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
}
|
||||
],
|
||||
variables : [
|
||||
|
||||
@@ -4,7 +4,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -4,7 +4,8 @@ material {
|
||||
{
|
||||
type : sampler2d,
|
||||
name : depth,
|
||||
precision: high
|
||||
precision: high,
|
||||
unfilterable: true
|
||||
},
|
||||
{
|
||||
type : mat4,
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
Type type; // type of this sampler
|
||||
Format format; // format of this sampler
|
||||
Precision precision; // precision of this sampler
|
||||
bool unfilterable; // whether the sampling should be unfiltered.
|
||||
bool multisample; // multisample capable
|
||||
ShaderStageFlags stages; // stages the sampler can be accessed from
|
||||
};
|
||||
@@ -83,6 +84,7 @@ public:
|
||||
Type type; // type of this sampler
|
||||
Format format; // format of this sampler
|
||||
Precision precision; // precision of this sampler
|
||||
bool unfilterable = false; // whether the sampling should be unfiltered.
|
||||
bool multisample = false; // multisample capable
|
||||
ShaderStageFlags stages =
|
||||
ShaderStageFlags::ALL_SHADER_STAGE_FLAGS; // shader stages using this sampler
|
||||
@@ -95,7 +97,8 @@ public:
|
||||
|
||||
// Add a sampler
|
||||
Builder& add(std::string_view samplerName, Binding binding, Type type, Format format,
|
||||
Precision precision = Precision::MEDIUM, bool multisample = false,
|
||||
Precision precision = Precision::MEDIUM, bool unfilterable = false,
|
||||
bool multisample = false,
|
||||
ShaderStageFlags stages = ShaderStageFlags::ALL_SHADER_STAGE_FLAGS) noexcept;
|
||||
|
||||
// Add multiple samplers
|
||||
|
||||
@@ -50,12 +50,12 @@ SamplerInterfaceBlock::Builder::stageFlags(backend::ShaderStageFlags stageFlags)
|
||||
}
|
||||
|
||||
SamplerInterfaceBlock::Builder& SamplerInterfaceBlock::Builder::add(std::string_view samplerName,
|
||||
Binding binding, Type type, Format format, Precision precision, bool multisample,
|
||||
ShaderStageFlags stages) noexcept {
|
||||
Binding binding, Type type, Format format, Precision precision, bool unfilterable,
|
||||
bool multisample, ShaderStageFlags stages) noexcept {
|
||||
mEntries.push_back({
|
||||
{ samplerName.data(), samplerName.size() }, // name
|
||||
{ }, // uniform name
|
||||
binding, type, format, precision, multisample, stages });
|
||||
{ samplerName.data(), samplerName.size() }, // name
|
||||
{}, // uniform name
|
||||
binding, type, format, precision, unfilterable, multisample, stages });
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -65,8 +65,9 @@ SamplerInterfaceBlock SamplerInterfaceBlock::Builder::build() {
|
||||
|
||||
SamplerInterfaceBlock::Builder& SamplerInterfaceBlock::Builder::add(
|
||||
std::initializer_list<ListEntry> list) noexcept {
|
||||
for (auto& e : list) {
|
||||
add(e.name, e.binding, e.type, e.format, e.precision, e.multisample, e.stages);
|
||||
for (auto& e: list) {
|
||||
add(e.name, e.binding, e.type, e.format, e.precision, e.unfilterable, e.multisample,
|
||||
e.stages);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -323,8 +323,8 @@ public:
|
||||
*/
|
||||
MaterialBuilder& parameter(const char* name, SamplerType samplerType,
|
||||
SamplerFormat format = SamplerFormat::FLOAT,
|
||||
ParameterPrecision precision = ParameterPrecision::DEFAULT, bool multisample = false,
|
||||
const char* transformName = "",
|
||||
ParameterPrecision precision = ParameterPrecision::DEFAULT, bool unfilterable = false,
|
||||
bool multisample = false, const char* transformName = "",
|
||||
ShaderStageFlags stages = ShaderStageFlags::ALL_SHADER_STAGE_FLAGS);
|
||||
|
||||
MaterialBuilder& buffer(filament::BufferInterfaceBlock bib);
|
||||
@@ -658,9 +658,17 @@ public:
|
||||
|
||||
// Sampler
|
||||
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p,
|
||||
bool ms, const char* tn, ShaderStageFlags s)
|
||||
: name(paramName), size(1), precision(p), samplerType(t), format(f),
|
||||
parameterType(SAMPLER), multisample(ms), transformName(tn), stages(s) { }
|
||||
bool unfilterable, bool ms, const char* tn, ShaderStageFlags s)
|
||||
: name(paramName),
|
||||
size(1),
|
||||
precision(p),
|
||||
samplerType(t),
|
||||
format(f),
|
||||
parameterType(SAMPLER),
|
||||
unfilterable(unfilterable),
|
||||
multisample(ms),
|
||||
transformName(tn),
|
||||
stages(s) {}
|
||||
|
||||
// Uniform
|
||||
Parameter(const char* paramName, UniformType t, size_t typeSize, ParameterPrecision p)
|
||||
@@ -676,8 +684,9 @@ public:
|
||||
ParameterPrecision precision;
|
||||
SamplerType samplerType;
|
||||
SubpassType subpassType;
|
||||
SamplerFormat format;
|
||||
bool multisample;
|
||||
SamplerFormat format = SamplerFormat::INT; // 0 of the enum
|
||||
bool unfilterable = false;
|
||||
bool multisample = false;
|
||||
utils::CString transformName;
|
||||
ShaderStageFlags stages;
|
||||
enum {
|
||||
|
||||
@@ -300,19 +300,19 @@ MaterialBuilder& MaterialBuilder::parameter(const char* name, UniformType const
|
||||
return parameter(name, 1, type, precision);
|
||||
}
|
||||
|
||||
|
||||
MaterialBuilder& MaterialBuilder::parameter(const char* name, SamplerType samplerType,
|
||||
SamplerFormat format, ParameterPrecision precision, bool multisample,
|
||||
SamplerFormat format, ParameterPrecision precision, bool unfilterable, bool multisample,
|
||||
const char* transformName, ShaderStageFlags stages) {
|
||||
FILAMENT_CHECK_PRECONDITION(!multisample ||
|
||||
(format != SamplerFormat::SHADOW &&
|
||||
(samplerType == SamplerType::SAMPLER_2D ||
|
||||
samplerType == SamplerType::SAMPLER_2D_ARRAY)))
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
!multisample || (format != SamplerFormat::SHADOW &&
|
||||
(samplerType == SamplerType::SAMPLER_2D ||
|
||||
samplerType == SamplerType::SAMPLER_2D_ARRAY)))
|
||||
<< "multisample samplers only possible with SAMPLER_2D or SAMPLER_2D_ARRAY,"
|
||||
" as long as type is not SHADOW";
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT) << "Too many parameters";
|
||||
mParameters[mParameterCount++] = { name, samplerType, format, precision, multisample, transformName, stages };
|
||||
mParameters[mParameterCount++] = { name, samplerType, format, precision, unfilterable,
|
||||
multisample, transformName, stages };
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -639,10 +639,12 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept {
|
||||
assert_invariant(!param.isSubpass());
|
||||
if (param.isSampler()) {
|
||||
sbb.add({ param.name.data(), param.name.size() }, binding, param.samplerType,
|
||||
param.format, param.precision, param.multisample, param.stages);
|
||||
param.format, param.precision, param.unfilterable, param.multisample,
|
||||
param.stages);
|
||||
if (!param.transformName.empty()) {
|
||||
ibb.add({{{ param.transformName.data(), param.transformName.size() }, uint8_t(binding),
|
||||
0, UniformType::MAT3, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }});
|
||||
ibb.add({ { { param.transformName.data(), param.transformName.size() },
|
||||
uint8_t(binding), 0, UniformType::MAT3, Precision::DEFAULT,
|
||||
FeatureLevel::FEATURE_LEVEL_0 } });
|
||||
}
|
||||
binding++;
|
||||
} else if (param.isUniform()) {
|
||||
|
||||
@@ -77,6 +77,7 @@ void MaterialSamplerInterfaceBlockChunk::flatten(Flattener& f) {
|
||||
f.writeUint8(static_cast<uint8_t>(sInfo.type));
|
||||
f.writeUint8(static_cast<uint8_t>(sInfo.format));
|
||||
f.writeUint8(static_cast<uint8_t>(sInfo.precision));
|
||||
f.writeBool(sInfo.unfilterable);
|
||||
f.writeBool(sInfo.multisample);
|
||||
}
|
||||
}
|
||||
@@ -230,7 +231,11 @@ void MaterialDescriptorSetLayoutChunk::flatten(Flattener& f) {
|
||||
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
|
||||
f.writeUint8(uint8_t(entry.stages));
|
||||
f.writeUint8(entry.binding);
|
||||
f.writeUint8(uint8_t(DescriptorFlags::NONE));
|
||||
if (entry.unfilterable) {
|
||||
f.writeUint8(uint8_t(DescriptorFlags::UNFILTERABLE));
|
||||
} else {
|
||||
f.writeUint8(uint8_t(DescriptorFlags::NONE));
|
||||
}
|
||||
f.writeUint16(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,8 +383,10 @@ ViewerGui::ViewerGui(filament::Engine* engine, filament::Scene* scene, filament:
|
||||
mSettings.view.vsmShadowOptions.anisotropy = 0;
|
||||
mSettings.view.dithering = Dithering::TEMPORAL;
|
||||
mSettings.view.antiAliasing = AntiAliasing::FXAA;
|
||||
mSettings.view.msaa = { .enabled = true, .sampleCount = 4 };
|
||||
mSettings.view.ssao.enabled = true;
|
||||
// mSettings.view.msaa = { .enabled = true, .sampleCount = 4 };
|
||||
mSettings.view.msaa = { .enabled = false, .sampleCount = 4 };
|
||||
// mSettings.view.ssao.enabled = true;
|
||||
mSettings.view.ssao.enabled = false;
|
||||
mSettings.view.bloom.enabled = true;
|
||||
|
||||
DebugRegistry& debug = mEngine->getDebugRegistry();
|
||||
|
||||
@@ -185,6 +185,13 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
|
||||
}
|
||||
}
|
||||
|
||||
const JsonishValue* unfilterableValue = jsonObject.getValue("unfilterable");
|
||||
if (unfilterableValue) {
|
||||
if (unfilterableValue->getType() != JsonishValue::BOOL) {
|
||||
std::cerr << "parameters: unfilterable must be a BOOL." << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const JsonishValue* multiSampleValue = jsonObject.getValue("multisample");
|
||||
if (multiSampleValue) {
|
||||
if (multiSampleValue->getType() != JsonishValue::BOOL) {
|
||||
@@ -260,6 +267,7 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
|
||||
auto precision = precisionValue ? Enums::toEnum<ParameterPrecision>(
|
||||
precisionValue->toJsonString()->getString()) : ParameterPrecision::DEFAULT;
|
||||
|
||||
auto unfilterable = unfilterableValue ? unfilterableValue->toJsonBool()->getBool() : false;
|
||||
auto multisample = multiSampleValue ? multiSampleValue->toJsonBool()->getBool() : false;
|
||||
|
||||
if (stages == ShaderStageFlags::NONE) {
|
||||
@@ -276,10 +284,11 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
|
||||
return false;
|
||||
}
|
||||
auto transformName = transformNameValue->toJsonString()->getString();
|
||||
builder.parameter(nameString.c_str(), type, format, precision, multisample,
|
||||
transformName.c_str(), stages);
|
||||
builder.parameter(nameString.c_str(), type, format, precision, unfilterable,
|
||||
multisample, transformName.c_str(), stages);
|
||||
} else {
|
||||
builder.parameter(nameString.c_str(), type, format, precision, multisample, "", stages);
|
||||
builder.parameter(nameString.c_str(), type, format, precision, unfilterable,
|
||||
multisample, "", stages);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user