diff --git a/pxr/imaging/hdSt/domeLightComputations.cpp b/pxr/imaging/hdSt/domeLightComputations.cpp index 773f052700..d370645b6f 100644 --- a/pxr/imaging/hdSt/domeLightComputations.cpp +++ b/pxr/imaging/hdSt/domeLightComputations.cpp @@ -137,6 +137,7 @@ HdSt_DomeLightComputationGPU::Execute( static_cast(resourceRegistry); constexpr int localSize = 8; + const bool hasUniforms = _roughness >= 0.0f; HdStGLSLProgramSharedPtr const computeProgram = HdStGLSLProgram::GetComputeProgram( @@ -149,6 +150,17 @@ HdSt_DomeLightComputationGPU::Execute( computeDesc.shaderStage = HgiShaderStageCompute; computeDesc.computeDescriptor.localSize = GfVec3i(localSize, localSize, 1); + + HgiShaderFunctionAddTexture(&computeDesc, "inTexture"); + HgiShaderFunctionAddWritableTexture(&computeDesc, "outTexture", + 2, HgiFormatFloat16Vec4); + if (hasUniforms) { + HgiShaderFunctionAddConstantParam( + &computeDesc, "inRoughness", HdStTokens->_float); + } + HgiShaderFunctionAddStageInput( + &computeDesc, "hd_GlobalInvocationID", "uvec3", + HgiShaderKeywordTokens->hdGlobalInvocationID); }); if (!TF_VERIFY(computeProgram)) { return; @@ -249,8 +261,6 @@ HdSt_DomeLightComputationGPU::Execute( uniform.roughness = _roughness; - bool hasUniforms = uniform.roughness >= 0.0f; - HgiComputePipelineDesc desc; desc.debugName = "DomeLightComputation"; desc.shaderProgram = computeProgram->GetProgram(); diff --git a/pxr/imaging/hdSt/shaders/domeLight.glslfx b/pxr/imaging/hdSt/shaders/domeLight.glslfx index b655a854c9..ab0e2ba4b4 100644 --- a/pxr/imaging/hdSt/shaders/domeLight.glslfx +++ b/pxr/imaging/hdSt/shaders/domeLight.glslfx @@ -51,13 +51,10 @@ const float PI = 3.1415926536; -layout(binding = 0) uniform sampler2D inTexture; -layout(rgba16f, binding = 1) uniform image2D outTexture; - // compute texture coords based on the size of the output image/texture vec2 GetTexCoords(ivec2 outCoords) { - vec2 outDims = imageSize(outTexture); + vec2 outDims = HdGetSize_outTexture(); // apply a (0.5, 0.5) offset to use pixel centers and not pixel corners vec2 texCoords = (outCoords + vec2(0.5, 0.5)) / outDims; return texCoords; @@ -67,7 +64,7 @@ vec2 GetTexCoords(ivec2 outCoords) vec3 SampleEnvMapLod(vec3 sampleVec, float sampleLod) { vec2 coord = vec2((atan(sampleVec.z, sampleVec.x) + PI) / (2.0 * PI), acos(sampleVec.y) / PI); - return textureLod(inTexture, coord, sampleLod).rgb; + return HdTextureLod_inTexture(coord, sampleLod).rgb; } // compute world position from texture coords @@ -124,7 +121,7 @@ vec3 SampleEnvMap(vec3 sampleVec) { // sample from a mipmap level of the environment map determined by the // size of the environment map and the number of samples we are taking - ivec2 inDims = textureSize(inTexture, 0); + ivec2 inDims = HdGetSize_inTexture(); float mipLevel = ceil(log2(inDims.x * deltaPhi/(2.0 * PI)) * 2.0f); return SampleEnvMapLod(sampleVec, mipLevel); @@ -155,22 +152,18 @@ vec3 ComputeIrradiance(vec3 inPos) void main(void) { - ivec2 outCoords = ivec2(gl_GlobalInvocationID.xy); + ivec2 outCoords = ivec2(hd_GlobalInvocationID.xy); vec2 texCoords = GetTexCoords(outCoords); vec3 pos3D = GetWorldPos(texCoords); vec4 outColor = vec4(ComputeIrradiance(pos3D), 1.0); - imageStore(outTexture, outCoords, outColor); + HdSet_outTexture(outCoords, outColor); } --- -------------------------------------------------------------------------- -- glsl DomeLight.Prefilter -layout(std140, binding=0) uniform Uniforms { - float roughness; -} uniforms; - // Normal Distribution function float Distribution_GGX(float dotNH, float roughness) { @@ -186,7 +179,7 @@ vec3 PrefilterEnvMap(vec3 R, float roughness) vec3 V = R; vec3 color = vec3(0.0); float totalWeight = 0.0; - float envMapDim = float(textureSize(inTexture, 0).s); + float envMapDim = float(HdGetSize_inTexture().s); const uint numSamples = 1024u; for (uint i = 0u; i < numSamples; i++) { vec2 Xi = Hammersley2d(i, numSamples); @@ -218,21 +211,19 @@ vec3 PrefilterEnvMap(vec3 R, float roughness) void main(void) { - ivec2 outCoords = ivec2(gl_GlobalInvocationID.xy); + ivec2 outCoords = ivec2(hd_GlobalInvocationID.xy); vec2 texCoords = GetTexCoords(outCoords); vec3 pos3D = GetWorldPos(texCoords); vec3 R = normalize(pos3D); - vec4 outColor = vec4(PrefilterEnvMap(R, uniforms.roughness), 1.0); + vec4 outColor = vec4(PrefilterEnvMap(R, inRoughness), 1.0); - imageStore(outTexture, outCoords, outColor); + HdSet_outTexture(outCoords, outColor); } --- -------------------------------------------------------------------------- -- glsl DomeLight.BRDF -uniform int sampleLevel = 0; - float Geometry_SchlicksmithGGX(float dotNL, float dotNV, float roughness) { float k = (roughness * roughness) / 2.0; @@ -274,11 +265,11 @@ vec2 ComputeBRDF(float NoV, float roughness) void main(void) { - ivec2 outCoords = ivec2(gl_GlobalInvocationID.xy); + ivec2 outCoords = ivec2(hd_GlobalInvocationID.xy); vec2 texCoords = GetTexCoords(outCoords); // texCoords.x represents N dot E and texCoords.y represents roughness vec4 outColor = vec4(ComputeBRDF(texCoords.x, texCoords.y), 0.0, 1.0); - imageStore(outTexture, outCoords, outColor); + HdSet_outTexture(outCoords, outColor); } diff --git a/pxr/imaging/hgi/shaderFunctionDesc.cpp b/pxr/imaging/hgi/shaderFunctionDesc.cpp index df5c5e0203..dd117b1298 100644 --- a/pxr/imaging/hgi/shaderFunctionDesc.cpp +++ b/pxr/imaging/hgi/shaderFunctionDesc.cpp @@ -28,6 +28,7 @@ PXR_NAMESPACE_OPEN_SCOPE HgiShaderFunctionTextureDesc::HgiShaderFunctionTextureDesc() : dimensions(2) , format(HgiFormatInvalid) + , writable(false) { } @@ -67,7 +68,8 @@ bool operator==( { return lhs.nameInShader == rhs.nameInShader && lhs.dimensions == rhs.dimensions && - lhs.format == rhs.format; + lhs.format == rhs.format && + lhs.writable == rhs.writable; } bool operator!=( @@ -156,7 +158,7 @@ bool operator==( lhs.constantParams == rhs.constantParams && lhs.stageInputs == rhs.stageInputs && lhs.stageOutputs == rhs.stageOutputs && - lhs.computeDescriptor == rhs.computeDescriptor; + lhs.computeDescriptor == rhs.computeDescriptor && lhs.tessellationDescriptor == rhs.tessellationDescriptor; } @@ -178,6 +180,23 @@ HgiShaderFunctionAddTexture( texDesc.nameInShader = nameInShader; texDesc.dimensions = dimensions; texDesc.format = format; + texDesc.writable = false; + + desc->textures.push_back(std::move(texDesc)); +} + +void +HgiShaderFunctionAddWritableTexture( + HgiShaderFunctionDesc * const desc, + const std::string &nameInShader, + const uint32_t dimensions /* = 2 */, + const HgiFormat &format /* = HgiFormatFloat32Vec4*/) +{ + HgiShaderFunctionTextureDesc texDesc; + texDesc.nameInShader = nameInShader; + texDesc.dimensions = dimensions; + texDesc.format = format; + texDesc.writable = true; desc->textures.push_back(std::move(texDesc)); } diff --git a/pxr/imaging/hgi/shaderFunctionDesc.h b/pxr/imaging/hgi/shaderFunctionDesc.h index 693601fab2..9c7a07d2f4 100644 --- a/pxr/imaging/hgi/shaderFunctionDesc.h +++ b/pxr/imaging/hgi/shaderFunctionDesc.h @@ -48,6 +48,8 @@ PXR_NAMESPACE_OPEN_SCOPE ///
  • format /// Format of the texture. This is required in APIs where sampler types depend /// on the texture (e.g., GL)
  • +///
  • writable +/// Whether the texture is writable.
  • /// /// struct HgiShaderFunctionTextureDesc @@ -58,6 +60,7 @@ struct HgiShaderFunctionTextureDesc std::string nameInShader; uint32_t dimensions; HgiFormat format; + bool writable; }; using HgiShaderFunctionTextureDescVector = @@ -293,6 +296,15 @@ HgiShaderFunctionAddTexture( uint32_t dimensions = 2, const HgiFormat &format = HgiFormatFloat32Vec4); +/// Adds writable texture descriptor to given shader function descriptor. +HGI_API +void +HgiShaderFunctionAddWritableTexture( + HgiShaderFunctionDesc *desc, + const std::string &nameInShader, + uint32_t dimensions = 2, + const HgiFormat &format = HgiFormatFloat32Vec4); + /// Adds buffer descriptor to given shader function descriptor. HGI_API void diff --git a/pxr/imaging/hgi/types.cpp b/pxr/imaging/hgi/types.cpp index 0f563f1d0f..62205d9d23 100644 --- a/pxr/imaging/hgi/types.cpp +++ b/pxr/imaging/hgi/types.cpp @@ -191,6 +191,64 @@ HgiGetDataSize( bpt; } +HgiFormat +HgiGetComponentBaseFormat( + const HgiFormat f) +{ + switch(f) { + case HgiFormatUNorm8: + case HgiFormatUNorm8Vec2: + case HgiFormatUNorm8Vec4: + case HgiFormatUNorm8Vec4srgb: + case HgiFormatBC7UNorm8Vec4: + case HgiFormatBC7UNorm8Vec4srgb: + case HgiFormatBC1UNorm8Vec4: + case HgiFormatBC3UNorm8Vec4: + return HgiFormatUNorm8; + case HgiFormatSNorm8: + case HgiFormatSNorm8Vec2: + case HgiFormatSNorm8Vec4: + return HgiFormatSNorm8; + case HgiFormatFloat16: + case HgiFormatFloat16Vec2: + case HgiFormatFloat16Vec3: + case HgiFormatFloat16Vec4: + return HgiFormatFloat16; + case HgiFormatInt16: + case HgiFormatInt16Vec2: + case HgiFormatInt16Vec3: + case HgiFormatInt16Vec4: + return HgiFormatInt16; + case HgiFormatUInt16: + case HgiFormatUInt16Vec2: + case HgiFormatUInt16Vec3: + case HgiFormatUInt16Vec4: + return HgiFormatUInt16; + case HgiFormatFloat32: + case HgiFormatFloat32Vec2: + case HgiFormatFloat32Vec3: + case HgiFormatFloat32Vec4: + return HgiFormatFloat32; + case HgiFormatInt32: + case HgiFormatInt32Vec2: + case HgiFormatInt32Vec3: + case HgiFormatInt32Vec4: + return HgiFormatInt32; + case HgiFormatFloat32UInt8: + return HgiFormatFloat32UInt8; + case HgiFormatBC6FloatVec3: + return HgiFormatBC6FloatVec3; + case HgiFormatBC6UFloatVec3: + return HgiFormatBC6UFloatVec3; + case HgiFormatCount: + case HgiFormatInvalid: + TF_CODING_ERROR("Invalid Format"); + return HgiFormatInvalid; + } + TF_CODING_ERROR("Missing Format"); + return HgiFormatInvalid; +} + uint16_t _ComputeNumMipLevels(const GfVec3i &dimensions) { diff --git a/pxr/imaging/hgi/types.h b/pxr/imaging/hgi/types.h index 0c913a1913..7a7b678b91 100644 --- a/pxr/imaging/hgi/types.h +++ b/pxr/imaging/hgi/types.h @@ -169,6 +169,12 @@ size_t HgiGetDataSize( HgiFormat f, const GfVec3i &dimensions); +/// Returns the scalar type of the format, in the form of an HgiFormat, if +/// possible. +HGI_API +HgiFormat HgiGetComponentBaseFormat( + HgiFormat f); + /// Returns mip infos. /// /// If dataByteSize is specified, the levels stops when the total memory diff --git a/pxr/imaging/hgiGL/conversions.cpp b/pxr/imaging/hgiGL/conversions.cpp index 6ef1865f2a..1a2a513090 100644 --- a/pxr/imaging/hgiGL/conversions.cpp +++ b/pxr/imaging/hgiGL/conversions.cpp @@ -226,6 +226,45 @@ _primitiveTypeTable[HgiPrimitiveTypeCount][2] = {HgiPrimitiveTypePatchList, GL_PATCHES} }; +static const std::string +_imageLayoutFormatTable[HgiFormatCount][2] = +{ + {"HgiFormatUNorm8", "r8"}, + {"HgiFormatUNorm8Vec2", "rg8"}, + {"HgiFormatUNorm8Vec4", "rgba8"}, + {"HgiFormatSNorm8", "r8_snorm"}, + {"HgiFormatSNorm8Vec2", "rg8_snorm"}, + {"HgiFormatSNorm8Vec4", "rgba8_snorm"}, + {"HgiFormatFloat16", "r16f"}, + {"HgiFormatFloat16Vec2", "rg16f"}, + {"HgiFormatFloat16Vec3", ""}, + {"HgiFormatFloat16Vec4", "rgba16f"}, + {"HgiFormatFloat32", "r32f"}, + {"HgiFormatFloat32Vec2", "rg32f"}, + {"HgiFormatFloat32Vec3", ""}, + {"HgiFormatFloat32Vec4", "rgba32f" }, + {"HgiFormatInt16", "r16i"}, + {"HgiFormatInt16Vec2", "rg16i"}, + {"HgiFormatInt16Vec3", ""}, + {"HgiFormatInt16Vec4", "rgba16i"}, + {"HgiFormatUInt16", "r16ui"}, + {"HgiFormatUInt16Vec2", "rg16ui"}, + {"HgiFormatUInt16Vec3", ""}, + {"HgiFormatUInt16Vec4", "rgba16ui"}, + {"HgiFormatInt32", "r32i"}, + {"HgiFormatInt32Vec2", "rg32i"}, + {"HgiFormatInt32Vec3", ""}, + {"HgiFormatInt32Vec4", "rgba32i"}, + {"HgiFormatUNorm8Vec4srgb", ""}, + {"HgiFormatBC6FloatVec3", ""}, + {"HgiFormatBC6UFloatVec3", ""}, + {"HgiFormatBC7UNorm8Vec4", ""}, + {"HgiFormatBC7UNorm8Vec4srgb", ""}, + {"HgiFormatBC1UNorm8Vec4", ""}, + {"HgiFormatBC3UNorm8Vec4", ""}, + {"HgiFormatFloat32UInt8", ""}, +}; + void HgiGLConversions::GetFormat( HgiFormat inFormat, @@ -385,4 +424,16 @@ HgiGLConversions::GetPrimitiveType(HgiPrimitiveType pt) return _primitiveTypeTable[pt][1]; } +std::string +HgiGLConversions::GetImageLayoutFormatQualifier(HgiFormat inFormat) +{ + const std::string layoutQualifier = _imageLayoutFormatTable[inFormat][1]; + if (layoutQualifier.empty()) { + TF_WARN("Given HgiFormat is not a supported image unit format, " + "defaulting to rgba16f"); + return _imageLayoutFormatTable[9][1]; + } + return layoutQualifier; +} + PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/hgiGL/conversions.h b/pxr/imaging/hgiGL/conversions.h index ffa6c355f5..b6d6b668c9 100644 --- a/pxr/imaging/hgiGL/conversions.h +++ b/pxr/imaging/hgiGL/conversions.h @@ -89,6 +89,9 @@ class HgiGLConversions final HGIGL_API static GLenum GetPrimitiveType(HgiPrimitiveType pt); + + HGIGL_API + static std::string GetImageLayoutFormatQualifier(HgiFormat inFormat); }; diff --git a/pxr/imaging/hgiGL/shaderGenerator.cpp b/pxr/imaging/hgiGL/shaderGenerator.cpp index 9b5b9f0c8a..1b580a6359 100644 --- a/pxr/imaging/hgiGL/shaderGenerator.cpp +++ b/pxr/imaging/hgiGL/shaderGenerator.cpp @@ -24,6 +24,7 @@ #include "pxr/imaging/garch/glApi.h" #include "pxr/imaging/hgiGL/shaderGenerator.h" +#include "pxr/imaging/hgiGL/conversions.h" #include "pxr/imaging/hgi/tokens.h" PXR_NAMESPACE_OPEN_SCOPE @@ -106,18 +107,26 @@ void HgiGLShaderGenerator::_WriteTextures( const HgiShaderFunctionTextureDescVector &textures) { - //Extract texture descriptors and add appropriate texture sections - for(size_t i=0; ipush_back( std::make_unique( textureDescription.nameInShader, i, textureDescription.dimensions, textureDescription.format, + textureDescription.writable, attrs)); } } diff --git a/pxr/imaging/hgiGL/shaderSection.cpp b/pxr/imaging/hgiGL/shaderSection.cpp index 62ffb0a885..2dd83064ca 100644 --- a/pxr/imaging/hgiGL/shaderSection.cpp +++ b/pxr/imaging/hgiGL/shaderSection.cpp @@ -188,6 +188,7 @@ HgiGLTextureShaderSection::HgiGLTextureShaderSection( const unsigned int layoutIndex, const unsigned int dimensions, const HgiFormat format, + const bool writable, const HgiShaderSectionAttributeVector &attributes, const std::string &defaultValue) : HgiGLShaderSection( identifier, @@ -196,6 +197,7 @@ HgiGLTextureShaderSection::HgiGLTextureShaderSection( defaultValue) , _dimensions(dimensions) , _format(format) + , _writable(writable) { } @@ -216,7 +218,11 @@ _GetTextureTypePrefix(HgiFormat const &format) void HgiGLTextureShaderSection::_WriteSamplerType(std::ostream &ss) const { - ss << _GetTextureTypePrefix(_format) << "sampler" << _dimensions << "D"; + if (_writable) { + ss << "image" << _dimensions << "D"; + } else { + ss << _GetTextureTypePrefix(_format) << "sampler" << _dimensions << "D"; + } } void @@ -244,38 +250,87 @@ HgiGLTextureShaderSection::VisitGlobalMemberDeclarations(std::ostream &ss) bool HgiGLTextureShaderSection::VisitGlobalFunctionDefinitions(std::ostream &ss) { - //Write a function that let's you query the texture with HdGet_texName(uv) - //Used to unify texture sampling across platforms that depend on samplers - //and don't store textures in global space - _WriteSampledDataType(ss); // e.g., vec4, ivec4, uvec4 - ss << " HdGet_"; - WriteIdentifier(ss); - ss << "(vec" << _dimensions - << " uv) {\n"; - ss << " "; - _WriteSampledDataType(ss); - ss << " result = texture("; - WriteIdentifier(ss); - ss << ", uv);\n"; - ss << " return result;\n"; - ss << "}"; - - //Same except for texelfetch - if(_dimensions != 2) { - return true; + // Used to unify texture sampling and writing across platforms that depend + // on samplers and don't store textures in global space. + + const std::string intType = _dimensions == 1 ? + "int" : + "ivec" + std::to_string(_dimensions); + + if (_writable) { + // Write a function that lets you write to the texture with + // HdSet_texName(uv, data). + ss << "void HdSet_"; + WriteIdentifier(ss); + ss << "(" << intType << " uv, vec4 data) {\n"; + ss << " "; + ss << "imageStore("; + WriteIdentifier(ss); + ss << ", uv, data);\n"; + ss << "}\n"; + + // HdGetSize_texName() + ss << intType << " HdGetSize_"; + WriteIdentifier(ss); + ss << "() {\n"; + ss << " "; + ss << "return imageSize("; + WriteIdentifier(ss); + ss << ");\n"; + ss << "}\n"; + } else { + // Write a function that lets you query the texture with + // HdGet_texName(uv). + const std::string floatType = _dimensions == 1 ? + "float" : + "vec" + std::to_string(_dimensions); + + _WriteSampledDataType(ss); // e.g., vec4, ivec4, uvec4 + ss << " HdGet_"; + WriteIdentifier(ss); + ss << "(" << floatType << " uv) {\n"; + ss << " "; + _WriteSampledDataType(ss); + ss << " result = texture("; + WriteIdentifier(ss); + ss << ", uv);\n"; + ss << " return result;\n"; + ss << "}\n"; + + // HdGetSize_texName() + ss << intType << " HdGetSize_"; + WriteIdentifier(ss); + ss << "() {\n"; + ss << " "; + ss << "return textureSize("; + WriteIdentifier(ss); + ss << ", 0);\n"; + ss << "}\n"; + + // HdTextureLod_texName() + _WriteSampledDataType(ss); + ss << " HdTextureLod_"; + WriteIdentifier(ss); + ss << "(" << floatType << " coord, float lod) {\n"; + ss << " "; + ss << "return textureLod("; + WriteIdentifier(ss); + ss << ", coord, lod);\n"; + ss << "}\n"; + + // HdTexelFetch_texName() + _WriteSampledDataType(ss); + ss << " HdTexelFetch_"; + WriteIdentifier(ss); + ss << "(" << intType << " coord) {\n"; + ss << " "; + _WriteSampledDataType(ss); + ss << " result = texelFetch("; + WriteIdentifier(ss); + ss << ", coord, 0);\n"; + ss << " return result;\n"; + ss << "}\n"; } - - _WriteSampledDataType(ss); - ss << " HdTexelFetch_"; - WriteIdentifier(ss); - ss << "(ivec2 coord) {\n"; - ss << " "; - _WriteSampledDataType(ss); - ss << " result = texelFetch("; - WriteIdentifier(ss); - ss << ", coord, 0);\n"; - ss << " return result;\n"; - ss << "}\n"; return true; } diff --git a/pxr/imaging/hgiGL/shaderSection.h b/pxr/imaging/hgiGL/shaderSection.h index 96d4b77e77..1a7c377c09 100644 --- a/pxr/imaging/hgiGL/shaderSection.h +++ b/pxr/imaging/hgiGL/shaderSection.h @@ -174,6 +174,7 @@ class HgiGLTextureShaderSection final: public HgiGLShaderSection const uint32_t layoutIndex, const uint32_t dimensions, const HgiFormat format, + const bool writable, const HgiShaderSectionAttributeVector &attributes, const std::string &defaultValue = std::string()); @@ -199,6 +200,7 @@ class HgiGLTextureShaderSection final: public HgiGLShaderSection const uint32_t _dimensions; const HgiFormat _format; + const bool _writable; static const std::string _storageQualifier; }; diff --git a/pxr/imaging/hgiMetal/hgi.mm b/pxr/imaging/hgiMetal/hgi.mm index 5625a00b7d..9376337ca8 100644 --- a/pxr/imaging/hgiMetal/hgi.mm +++ b/pxr/imaging/hgiMetal/hgi.mm @@ -101,7 +101,11 @@ HgiMetal::IsBackendSupported() const { // Want Metal 2.0 and Metal Shading Language 2.2 or higher. - return (@available(macOS 10.15, ios 13.0, *)); + if (@available(macOS 10.15, ios 13.0, *)) { + return true; + } + + return false; } id diff --git a/pxr/imaging/hgiMetal/shaderGenerator.mm b/pxr/imaging/hgiMetal/shaderGenerator.mm index b5d99f693c..f462c29b88 100644 --- a/pxr/imaging/hgiMetal/shaderGenerator.mm +++ b/pxr/imaging/hgiMetal/shaderGenerator.mm @@ -783,6 +783,9 @@ void _Init( texName, textureAttributes, samplerSection, + textures[i].dimensions, + textures[i].format, + textures[i].writable, std::string()); //fx texturing struct depends on the sampler diff --git a/pxr/imaging/hgiMetal/shaderSection.h b/pxr/imaging/hgiMetal/shaderSection.h index 728c6c1160..960d068687 100644 --- a/pxr/imaging/hgiMetal/shaderSection.h +++ b/pxr/imaging/hgiMetal/shaderSection.h @@ -170,8 +170,10 @@ class HgiMetalTextureShaderSection final const std::string &samplerSharedIdentifier, const HgiShaderSectionAttributeVector &attributes, const HgiMetalSamplerShaderSection *samplerShaderSectionDependency, - const std::string &defaultValue = std::string(), - uint32_t dimension = 2); + uint32_t dimensions, + HgiFormat format, + bool writable, + const std::string &defaultValue = std::string()); HGIMETAL_API void WriteType(std::ostream& ss) const override; @@ -187,9 +189,13 @@ class HgiMetalTextureShaderSection final const HgiMetalTextureShaderSection&) = delete; HgiMetalTextureShaderSection(const HgiMetalTextureShaderSection&) = delete; + const std::string _samplerSharedIdentifier; const HgiMetalSamplerShaderSection* const _samplerShaderSectionDependency; const uint32_t _dimensionsVar; - const std::string _samplerSharedIdentifier; + const HgiFormat _format; + const bool _writable; + std::string _baseType; + std::string _returnType; }; /// \class HgiMetalBufferShaderSection diff --git a/pxr/imaging/hgiMetal/shaderSection.mm b/pxr/imaging/hgiMetal/shaderSection.mm index 6edadaba68..ea5d18c449 100644 --- a/pxr/imaging/hgiMetal/shaderSection.mm +++ b/pxr/imaging/hgiMetal/shaderSection.mm @@ -131,22 +131,60 @@ const std::string &samplerSharedIdentifier, const HgiShaderSectionAttributeVector &attributes, const HgiMetalSamplerShaderSection *samplerShaderSectionDependency, - const std::string &defaultValue, - uint32_t dimension) + uint32_t dimensions, + HgiFormat format, + bool writable, + const std::string &defaultValue) : HgiMetalShaderSection( "textureBind_" + samplerSharedIdentifier, attributes, defaultValue) - , _samplerShaderSectionDependency(samplerShaderSectionDependency) - , _dimensionsVar(dimension) , _samplerSharedIdentifier(samplerSharedIdentifier) -{ + , _samplerShaderSectionDependency(samplerShaderSectionDependency) + , _dimensionsVar(dimensions) + , _format(format) + , _writable(writable) +{ + HgiFormat baseFormat = HgiGetComponentBaseFormat(_format); + + switch (baseFormat) { + case HgiFormatFloat32: + _baseType = "float"; + _returnType = "vec"; + break; + case HgiFormatFloat16: + _baseType = "half"; + _returnType = "vec"; + break; + case HgiFormatInt32: + _baseType = "int32_t"; + _returnType = "ivec"; + break; + case HgiFormatInt16: + _baseType = "int16_t"; + _returnType = "ivec"; + break; + case HgiFormatUInt16: + _baseType = "uint16_t"; + _returnType = "uvec"; + break; + default: + TF_CODING_ERROR("Invalid Format"); + _baseType = "float"; + _returnType = "vec"; + break; + } } void HgiMetalTextureShaderSection::WriteType(std::ostream& ss) const { - ss << "texture" << _dimensionsVar << "d"; + ss << "texture" << _dimensionsVar << "d"; + ss << "<" << _baseType; + if (_writable) { + ss << ", access::write"; + } + ss << ">"; } bool @@ -160,33 +198,111 @@ bool HgiMetalTextureShaderSection::VisitScopeFunctionDefinitions(std::ostream &ss) { - const std::string defValue = _GetDefaultValue().empty() - ? "0.0f" - : _GetDefaultValue(); + const std::string intType = _dimensionsVar == 1 ? + "uint" : "uint" + std::to_string(_dimensionsVar); - ss << "#define HdGetSampler_" << _samplerSharedIdentifier - << "() "; - WriteIdentifier(ss); - ss << "\n"; + if (_writable) { + // Write a function that lets you write to the texture with + // HdSet_texName(uv, data). + ss << "void HdSet_" << _samplerSharedIdentifier; + ss << "(" << intType << " coord, float4 data) {\n"; + ss << " "; + WriteIdentifier(ss); + ss << ".write(data, coord);\n"; + ss << "}\n"; + + // HdGetSize_texName() + ss << intType; + ss << " HdGet_" << _samplerSharedIdentifier << "Size() { \n"; + ss << " "; + if (_dimensionsVar == 1) { + ss << "return "; + WriteIdentifier(ss); + ss << ".get_width();\n"; + } else if (_dimensionsVar == 2) { + ss << "return " << intType << "("; + WriteIdentifier(ss); + ss << ".get_width(), "; + WriteIdentifier(ss); + ss << ".get_height());\n"; + } else if (_dimensionsVar == 3) { + ss << "return " << intType << "("; + WriteIdentifier(ss); + ss << ".get_width(), "; + WriteIdentifier(ss); + ss << ".get_height(), "; + WriteIdentifier(ss); + ss << ".get_depth());\n"; + } + ss << "}\n"; + } else { + const std::string defValue = _GetDefaultValue().empty() + ? "0.0f" + : _GetDefaultValue(); + + ss << "#define HdGetSampler_" << _samplerSharedIdentifier + << "() "; + WriteIdentifier(ss); + ss << "\n"; - ss << "vec4 HdGet_" << _samplerSharedIdentifier - << "(vec2 coord) {\n"; - ss << " vec4 result = is_null_texture("; - WriteIdentifier(ss); - ss << ") ? "<< defValue << ": "; - WriteIdentifier(ss); - ss << ".sample("; - _samplerShaderSectionDependency->WriteIdentifier(ss); - ss << ", coord);\n"; - ss << " return result;\n"; - ss << "}\n"; - - ss << "vec4 HdTexelFetch_" - << _samplerSharedIdentifier << "(ivec2 coord) {\n"; - ss << " vec4 result = " << "textureBind_" << _samplerSharedIdentifier - << ".read(ushort2(coord.x, coord.y));\n"; - ss << " return result;\n"; - ss << "}\n"; + ss << "vec4 HdGet_" << _samplerSharedIdentifier + << "(vec2 coord) {\n"; + ss << " vec4 result = is_null_texture("; + WriteIdentifier(ss); + ss << ") ? "<< defValue << ": "; + WriteIdentifier(ss); + ss << ".sample("; + _samplerShaderSectionDependency->WriteIdentifier(ss); + ss << ", coord);\n"; + ss << " return result;\n"; + ss << "}\n"; + + // HdGetSize_texName() + ss << intType; + ss << " HdGetSize_" << _samplerSharedIdentifier << "() { \n"; + ss << " "; + if (_dimensionsVar == 1) { + ss << "return "; + WriteIdentifier(ss); + ss << ".get_width();\n"; + } else if (_dimensionsVar == 2) { + ss << "return " << intType << "("; + WriteIdentifier(ss); + ss << ".get_width(), "; + WriteIdentifier(ss); + ss << ".get_height());\n"; + } else if (_dimensionsVar == 3) { + ss << "return " << intType << "("; + WriteIdentifier(ss); + ss << ".get_width(), "; + WriteIdentifier(ss); + ss << ".get_height(), "; + WriteIdentifier(ss); + ss << ".get_depth());\n"; + } + ss << "}\n"; + + // HdTextureLod_texName() + ss << "vec4 HdTextureLod_" << _samplerSharedIdentifier + << "(vec2 coord, float lod) {\n"; + ss << " vec4 result = is_null_texture("; + WriteIdentifier(ss); + ss << ") ? "<< defValue << ": "; + WriteIdentifier(ss); + ss << ".sample("; + _samplerShaderSectionDependency->WriteIdentifier(ss); + ss << ", coord, level(lod));\n"; + ss << " return result;\n"; + ss << "}\n"; + + // HdTexelFetch_texName() + ss << "vec4 HdTexelFetch_" + << _samplerSharedIdentifier << "(ivec2 coord) {\n"; + ss << " vec4 result = " << "textureBind_" << _samplerSharedIdentifier + << ".read(ushort2(coord.x, coord.y));\n"; + ss << " return result;\n"; + ss << "}\n"; + } return true; } diff --git a/pxr/imaging/hgiVulkan/conversions.cpp b/pxr/imaging/hgiVulkan/conversions.cpp index a76704eb0b..d640ef21b3 100644 --- a/pxr/imaging/hgiVulkan/conversions.cpp +++ b/pxr/imaging/hgiVulkan/conversions.cpp @@ -324,6 +324,45 @@ _primitiveTypeTable[HgiPrimitiveTypeCount][2] = }; static_assert(HgiPrimitiveTypeCount==5, ""); +static const std::string +_imageLayoutFormatTable[HgiFormatCount][2] = +{ + {"HgiFormatUNorm8", "r8"}, + {"HgiFormatUNorm8Vec2", "rg8"}, + {"HgiFormatUNorm8Vec4", "rgba8"}, + {"HgiFormatSNorm8", "r8_snorm"}, + {"HgiFormatSNorm8Vec2", "rg8_snorm"}, + {"HgiFormatSNorm8Vec4", "rgba8_snorm"}, + {"HgiFormatFloat16", "r16f"}, + {"HgiFormatFloat16Vec2", "rg16f"}, + {"HgiFormatFloat16Vec3", ""}, + {"HgiFormatFloat16Vec4", "rgba16f"}, + {"HgiFormatFloat32", "r32f"}, + {"HgiFormatFloat32Vec2", "rg32f"}, + {"HgiFormatFloat32Vec3", ""}, + {"HgiFormatFloat32Vec4", "rgba32f" }, + {"HgiFormatInt16", "r16i"}, + {"HgiFormatInt16Vec2", "rg16i"}, + {"HgiFormatInt16Vec3", ""}, + {"HgiFormatInt16Vec4", "rgba16i"}, + {"HgiFormatUInt16", "r16ui"}, + {"HgiFormatUInt16Vec2", "rg16ui"}, + {"HgiFormatUInt16Vec3", ""}, + {"HgiFormatUInt16Vec4", "rgba16ui"}, + {"HgiFormatInt32", "r32i"}, + {"HgiFormatInt32Vec2", "rg32i"}, + {"HgiFormatInt32Vec3", ""}, + {"HgiFormatInt32Vec4", "rgba32i"}, + {"HgiFormatUNorm8Vec4srgb", ""}, + {"HgiFormatBC6FloatVec3", ""}, + {"HgiFormatBC6UFloatVec3", ""}, + {"HgiFormatBC7UNorm8Vec4", ""}, + {"HgiFormatBC7UNorm8Vec4srgb", ""}, + {"HgiFormatBC1UNorm8Vec4", ""}, + {"HgiFormatBC3UNorm8Vec4", ""}, + {"HgiFormatFloat32UInt8", ""}, +}; + VkFormat HgiVulkanConversions::GetFormat(HgiFormat inFormat) { @@ -530,4 +569,16 @@ HgiVulkanConversions::GetPrimitiveType(HgiPrimitiveType pt) return VkPrimitiveTopology(_primitiveTypeTable[pt][1]); } +std::string +HgiVulkanConversions::GetImageLayoutFormatQualifier(HgiFormat inFormat) +{ + const std::string layoutQualifier = _imageLayoutFormatTable[inFormat][1]; + if (layoutQualifier.empty()) { + TF_WARN("Given HgiFormat is not a supported image unit format, " + "defaulting to rgba16f"); + return _imageLayoutFormatTable[9][1]; + } + return layoutQualifier; +} + PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/hgiVulkan/conversions.h b/pxr/imaging/hgiVulkan/conversions.h index ea78bbedf3..136ee5c7f2 100644 --- a/pxr/imaging/hgiVulkan/conversions.h +++ b/pxr/imaging/hgiVulkan/conversions.h @@ -112,6 +112,9 @@ class HgiVulkanConversions final HGIVULKAN_API static VkPrimitiveTopology GetPrimitiveType(HgiPrimitiveType pt); + + HGIVULKAN_API + static std::string GetImageLayoutFormatQualifier(HgiFormat inFormat); }; diff --git a/pxr/imaging/hgiVulkan/shaderGenerator.cpp b/pxr/imaging/hgiVulkan/shaderGenerator.cpp index 9a463523e1..7e6d5d7588 100644 --- a/pxr/imaging/hgiVulkan/shaderGenerator.cpp +++ b/pxr/imaging/hgiVulkan/shaderGenerator.cpp @@ -23,6 +23,7 @@ // #include "pxr/imaging/hgiVulkan/shaderGenerator.h" +#include "pxr/imaging/hgiVulkan/conversions.h" #include "pxr/imaging/hgi/tokens.h" PXR_NAMESPACE_OPEN_SCOPE @@ -99,17 +100,25 @@ void HgiVulkanShaderGenerator::_WriteTextures( const HgiShaderFunctionTextureDescVector& textures) { - for(const HgiShaderFunctionTextureDesc& desc : textures) { - const HgiShaderSectionAttributeVector attrs = { + for (const HgiShaderFunctionTextureDesc& desc : textures) { + HgiShaderSectionAttributeVector attrs = { HgiShaderSectionAttribute{ "binding", std::to_string(_bindIndex)}}; + if (desc.writable) { + attrs.insert(attrs.begin(), HgiShaderSectionAttribute{ + HgiVulkanConversions::GetImageLayoutFormatQualifier( + desc.format), + ""}); + } + GetShaderSections()->push_back( std::make_unique( desc.nameInShader, _bindIndex, desc.dimensions, + desc.writable, attrs)); // In Vulkan buffers and textures cannot have the same binding index. diff --git a/pxr/imaging/hgiVulkan/shaderSection.cpp b/pxr/imaging/hgiVulkan/shaderSection.cpp index 3db5b6e272..21bf1f639f 100644 --- a/pxr/imaging/hgiVulkan/shaderSection.cpp +++ b/pxr/imaging/hgiVulkan/shaderSection.cpp @@ -181,6 +181,7 @@ HgiVulkanTextureShaderSection::HgiVulkanTextureShaderSection( const std::string &identifier, const unsigned int layoutIndex, const unsigned int dimensions, + const bool writable, const HgiShaderSectionAttributeVector &attributes, const std::string &defaultValue) : HgiVulkanShaderSection( identifier, @@ -188,6 +189,7 @@ HgiVulkanTextureShaderSection::HgiVulkanTextureShaderSection( "uniform", defaultValue) , _dimensions(dimensions) + , _writable(writable) { } @@ -212,32 +214,81 @@ HgiVulkanTextureShaderSection::VisitGlobalMemberDeclarations(std::ostream &ss) bool HgiVulkanTextureShaderSection::VisitGlobalFunctionDefinitions(std::ostream &ss) { - //Write a function that let's you query the texture with HDGet_texName(uv) - //Used to unify texture sampling across platforms that depend on samplers - //and don't store textures in global space - ss << "vec4 HdGet_"; - WriteIdentifier(ss); - ss << "(vec" << _dimensions - << " uv) {\n"; - ss << " vec4 result = texture("; - WriteIdentifier(ss); - ss << ", uv);\n"; - ss << " return result;\n"; - ss << "}"; - - //Same except for texelfetch - if(_dimensions != 2) { - return true; + // Used to unify texture sampling and writing across platforms that depend + // on samplers and don't store textures in global space. + + const std::string intType = _dimensions == 1 ? + "int" : + "ivec" + std::to_string(_dimensions); + + if (_writable) { + // Write a function that lets you write to the texture with + // HdSet_texName(uv, data). + ss << "void HdSet_"; + WriteIdentifier(ss); + ss << "(" << intType << " uv, vec4 data) {\n"; + ss << " "; + ss << "imageStore("; + WriteIdentifier(ss); + ss << ", uv, data);\n"; + ss << "}\n"; + + // HdGetSize_texName() + ss << intType << " HdGetSize_"; + WriteIdentifier(ss); + ss << "() {\n"; + ss << " "; + ss << "return imageSize("; + WriteIdentifier(ss); + ss << ");\n"; + ss << "}\n"; + } else { + // Write a function that lets you query the texture with + // HdGet_texName(uv). + const std::string floatType = _dimensions == 1 ? + "float" : + "vec" + std::to_string(_dimensions); + + ss << "vec4 HdGet_"; + WriteIdentifier(ss); + ss << "(" << floatType << " uv) {\n"; + ss << " "; + ss << "vec4 result = texture("; + WriteIdentifier(ss); + ss << ", uv);\n"; + ss << " return result;\n"; + ss << "}\n"; + + // HdGetSize_texName() + ss << intType << " HdGetSize_"; + WriteIdentifier(ss); + ss << "() {\n"; + ss << " "; + ss << "return textureSize("; + WriteIdentifier(ss); + ss << ", 0);\n"; + ss << "}\n"; + + // HdTextureLod_texName() + ss << "vec4 HdTextureLod_"; + WriteIdentifier(ss); + ss << "(" << floatType << " coord, float lod) {\n"; + ss << " "; + ss << "return textureLod("; + WriteIdentifier(ss); + ss << ", coord, lod);\n"; + ss << "}\n"; + + // HdTexelFetch_texName() + ss << "vec4 HdTexelFetch_"; + WriteIdentifier(ss); + ss << "(" << intType << " coord) {\n"; + ss << " vec4 result = texelFetch("; + WriteIdentifier(ss); + ss << ", coord, 0);\n"; + ss << " return result;\n"; + ss << "}\n"; } - - ss << "vec4 HdTexelFetch_"; - WriteIdentifier(ss); - ss << "(ivec2 coord) {\n"; - ss << " vec4 result = texelFetch("; - WriteIdentifier(ss); - ss << ", coord, 0);\n"; - ss << " return result;\n"; - ss << "}\n"; return true; } diff --git a/pxr/imaging/hgiVulkan/shaderSection.h b/pxr/imaging/hgiVulkan/shaderSection.h index 0387246c20..ad2eaf3baa 100644 --- a/pxr/imaging/hgiVulkan/shaderSection.h +++ b/pxr/imaging/hgiVulkan/shaderSection.h @@ -172,6 +172,7 @@ class HgiVulkanTextureShaderSection final: public HgiVulkanShaderSection const std::string &identifier, const uint32_t layoutIndex, const uint32_t dimensions, + const bool writable, const HgiShaderSectionAttributeVector &attributes, const std::string &defaultValue = std::string()); @@ -193,6 +194,7 @@ class HgiVulkanTextureShaderSection final: public HgiVulkanShaderSection HgiVulkanTextureShaderSection(const HgiVulkanTextureShaderSection&) = delete; const uint32_t _dimensions; + const bool _writable; }; /// \class HgiVulkanBufferShaderSection