diff --git a/src/api/include/projectM-4/parameters.h b/src/api/include/projectM-4/parameters.h index f68e10ad8..5bd7d901d 100644 --- a/src/api/include/projectM-4/parameters.h +++ b/src/api/include/projectM-4/parameters.h @@ -227,6 +227,34 @@ PROJECTM_EXPORT void projectm_set_mesh_size(projectm_handle instance, size_t wid */ PROJECTM_EXPORT void projectm_get_mesh_size(projectm_handle instance, size_t* width, size_t* height); +/** + * @brief Applies a sub-texel offset for main texture lookups in the warp shader. + * + * Original Milkdrop uses 0.5 here, but it doesn't seem to be required in OpenGL as this value + * introduces a slight warp drift to the top left. As this may be vendor-specific, this value can + * be configured externally to fix any possible drift. + * + * @param instance The projectM instance handle. + * @param offset_X The offset in texels in the horizontal direction. Milkdrop uses 0.5, default in projectM is 0.0. + * @param offset_y The offset in texels in the vertical direction. Milkdrop uses 0.5, default in projectM is 0.0. + * @since 4.2.0 + */ +PROJECTM_EXPORT void projectm_set_texel_offset(projectm_handle instance, float offset_X, float offset_y); + +/** + * @brief Retrieves the current sub-texel offsets for main texture lookups in the warp shader. + * + * Original Milkdrop uses 0.5 here, but it doesn't seem to be required in OpenGL as this value + * introduces a slight warp drift to the top left. As this may be vendor-specific, this value can + * be configured externally to fix any possible drift. + * + * @param instance The projectM instance handle. + * @param offset_X A valid pointer to a float variable that will receive the currently set horizontal texel offset. + * @param offset_y A valid pointer to a float variable that will receive the currently set vertical texel offset. + * @since 4.2.0 + */ +PROJECTM_EXPORT void projectm_get_texel_offset(projectm_handle instance, float* offset_X, float* offset_y); + /** * @brief Sets the current/average frames per second. * diff --git a/src/libprojectM/MilkdropPreset/Border.cpp b/src/libprojectM/MilkdropPreset/Border.cpp index 8ed978c13..10dd8c9d9 100644 --- a/src/libprojectM/MilkdropPreset/Border.cpp +++ b/src/libprojectM/MilkdropPreset/Border.cpp @@ -37,6 +37,7 @@ void Border::Draw(const PerFrameContext& presetPerFrameContext) auto shader = m_presetState.untexturedShader.lock(); shader->Bind(); shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformFloat("vertex_point_size", 1.0f); m_borderMesh.Bind(); diff --git a/src/libprojectM/MilkdropPreset/CustomShape.cpp b/src/libprojectM/MilkdropPreset/CustomShape.cpp index ae30b7ea1..4f9a0f3ac 100644 --- a/src/libprojectM/MilkdropPreset/CustomShape.cpp +++ b/src/libprojectM/MilkdropPreset/CustomShape.cpp @@ -223,8 +223,7 @@ void CustomShape::Draw() auto shader = m_presetState.untexturedShader.lock(); shader->Bind(); shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); - - m_outlineMesh.Bind(); + shader->SetUniformFloat("vertex_point_size", 1.0f); glVertexAttrib4f(1, static_cast(*m_perFrameContext.border_r), diff --git a/src/libprojectM/MilkdropPreset/CustomWaveform.cpp b/src/libprojectM/MilkdropPreset/CustomWaveform.cpp index 0b62ec28f..3ca7bbe75 100644 --- a/src/libprojectM/MilkdropPreset/CustomWaveform.cpp +++ b/src/libprojectM/MilkdropPreset/CustomWaveform.cpp @@ -76,6 +76,9 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext) int const maxSampleCount{m_spectrum ? Audio::SpectrumSamples : Audio::WaveformSamples}; + int sampleCount = std::min(maxSampleCount, static_cast(*m_perFrameContext.samples)); + sampleCount -= m_sep; + // Initialize and execute per-frame code LoadPerFrameEvaluationVariables(presetPerFrameContext); m_perFrameContext.ExecutePerFrameCode(); @@ -83,8 +86,7 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext) // Copy Q and T vars to per-point context InitPerPointEvaluationVariables(); - int sampleCount = std::min(maxSampleCount, static_cast(*m_perFrameContext.samples)); - sampleCount -= m_sep; + sampleCount = std::min(maxSampleCount, static_cast(*m_perFrameContext.samples)); // If there aren't enough samples to draw a single line or dot, skip drawing the waveform. if ((m_useDots && sampleCount < 1) || sampleCount < 2) @@ -104,7 +106,7 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext) // PCM data smoothing const int offset1 = m_spectrum ? 0 : (maxSampleCount - sampleCount) / 2 - m_sep / 2; const int offset2 = m_spectrum ? 0 : (maxSampleCount - sampleCount) / 2 + m_sep / 2; - const int t = m_spectrum ? static_cast(static_cast(maxSampleCount - m_sep) / static_cast(sampleCount)) : 1; + const float t = m_spectrum ? static_cast(maxSampleCount - m_sep) / static_cast(sampleCount) : 1.0f; const float mix1 = std::pow(m_smoothing * 0.98f, 0.5f); const float mix2 = 1.0f - mix1; @@ -175,6 +177,7 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext) auto shader = m_presetState.untexturedShader.lock(); shader->Bind(); shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformFloat("vertex_point_size", m_drawThick ? 2.0f : 1.0f); auto iterations = (m_drawThick && !m_useDots) ? 4 : 1; diff --git a/src/libprojectM/MilkdropPreset/DarkenCenter.cpp b/src/libprojectM/MilkdropPreset/DarkenCenter.cpp index c550afc3e..1bd1d8a12 100644 --- a/src/libprojectM/MilkdropPreset/DarkenCenter.cpp +++ b/src/libprojectM/MilkdropPreset/DarkenCenter.cpp @@ -42,6 +42,7 @@ void DarkenCenter::Draw() auto shader = m_presetState.untexturedShader.lock(); shader->Bind(); shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformFloat("vertex_point_size", 1.0f); m_mesh.Draw(); diff --git a/src/libprojectM/MilkdropPreset/Filters.cpp b/src/libprojectM/MilkdropPreset/Filters.cpp index c84d9784b..e5d8702df 100644 --- a/src/libprojectM/MilkdropPreset/Filters.cpp +++ b/src/libprojectM/MilkdropPreset/Filters.cpp @@ -29,6 +29,7 @@ void Filters::Draw() auto shader = m_presetState.untexturedShader.lock(); shader->Bind(); shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformFloat("vertex_point_size", 1.0f); glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0); diff --git a/src/libprojectM/MilkdropPreset/MilkdropShader.cpp b/src/libprojectM/MilkdropPreset/MilkdropShader.cpp index 345ef69ff..f2b203fe3 100644 --- a/src/libprojectM/MilkdropPreset/MilkdropShader.cpp +++ b/src/libprojectM/MilkdropPreset/MilkdropShader.cpp @@ -371,11 +371,22 @@ void MilkdropShader::PreprocessPresetShader(std::string& program) { if (m_type == ShaderType::WarpShader) { - program.replace(int(found), 11, "void PS(float4 _vDiffuse : COLOR, float4 _uv : TEXCOORD0, float2 _rad_ang : TEXCOORD1, out float4 _return_value : COLOR0, out float4 _mv_tex_coords : COLOR1)\n"); + program.replace(int(found), 11, R"( +void PS(float4 _vDiffuse : COLOR, + float4 _uv : TEXCOORD0, + float2 _rad_ang : TEXCOORD1, + out float4 _return_value : COLOR0, + out float4 _mv_tex_coords : COLOR1) +)"); } else { - program.replace(int(found), 11, "void PS(float4 _vDiffuse : COLOR, float2 _uv : TEXCOORD0, float2 _rad_ang : TEXCOORD1, out float4 _return_value : COLOR)\n"); + program.replace(int(found), 11, R"( +void PS(float4 _vDiffuse : COLOR, + float2 _uv : TEXCOORD0, + float2 _rad_ang : TEXCOORD1, + out float4 _return_value : COLOR) +)"); } } else diff --git a/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp b/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp index bb9bd8d85..8241910a1 100644 --- a/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp +++ b/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp @@ -308,8 +308,8 @@ void PerPixelMesh::WarpedBlit(const PresetState& presetState, }; // Texel alignment - glm::vec2 const texelOffsets{0.5f / static_cast(presetState.renderContext.viewportSizeX), - 0.5f / static_cast(presetState.renderContext.viewportSizeY)}; + glm::vec2 const texelOffsets{presetState.renderContext.texelOffsetX / static_cast(presetState.renderContext.viewportSizeX), + presetState.renderContext.texelOffsetY / static_cast(presetState.renderContext.viewportSizeY)}; // Decay float decay = std::min(static_cast(*perFrameContext.decay), 1.0f); diff --git a/src/libprojectM/MilkdropPreset/Waveform.cpp b/src/libprojectM/MilkdropPreset/Waveform.cpp index caaca5987..0277d10c4 100644 --- a/src/libprojectM/MilkdropPreset/Waveform.cpp +++ b/src/libprojectM/MilkdropPreset/Waveform.cpp @@ -41,7 +41,8 @@ void Waveform::Draw(const PerFrameContext& presetPerFrameContext) auto shader = m_presetState.untexturedShader.lock(); shader->Bind(); - shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjectionFlipped); + shader->SetUniformFloat("vertex_point_size", 1.0f); // Additive wave drawing (vice overwrite) if (m_presetState.additiveWaves) diff --git a/src/libprojectM/MilkdropPreset/Waveforms/Line.cpp b/src/libprojectM/MilkdropPreset/Waveforms/Line.cpp index 01271180a..a180baaeb 100644 --- a/src/libprojectM/MilkdropPreset/Waveforms/Line.cpp +++ b/src/libprojectM/MilkdropPreset/Waveforms/Line.cpp @@ -17,7 +17,7 @@ void Line::GenerateVertices(const PresetState& presetState, const PerFrameContex m_wave1Vertices.resize(m_samples); - ClipWaveformEdges(1.57f + m_mysteryWaveParam); + ClipWaveformEdges(1.57f * m_mysteryWaveParam); for (int i = 0; i < m_samples; i++) { diff --git a/src/libprojectM/MilkdropPreset/Waveforms/WaveformMath.cpp b/src/libprojectM/MilkdropPreset/Waveforms/WaveformMath.cpp index f33e3d1ea..f3e50f211 100644 --- a/src/libprojectM/MilkdropPreset/Waveforms/WaveformMath.cpp +++ b/src/libprojectM/MilkdropPreset/Waveforms/WaveformMath.cpp @@ -71,7 +71,7 @@ auto WaveformMath::GetVertices(const PresetState& presetState, m_mysteryWaveParam = static_cast(*presetPerFrameContext.wave_mystery); - if (UsesNormalizedMysteryParam() && (m_mysteryWaveParam < 1.0f || m_mysteryWaveParam > 1.0f)) + if (UsesNormalizedMysteryParam() && (m_mysteryWaveParam < -1.0f || m_mysteryWaveParam > 1.0f)) { m_mysteryWaveParam = m_mysteryWaveParam * 0.5f + 0.5f; m_mysteryWaveParam -= std::floor(m_mysteryWaveParam); diff --git a/src/libprojectM/ProjectM.cpp b/src/libprojectM/ProjectM.cpp index 495c5d4b7..dc73ea0f2 100644 --- a/src/libprojectM/ProjectM.cpp +++ b/src/libprojectM/ProjectM.cpp @@ -455,6 +455,18 @@ void ProjectM::SetMeshSize(uint32_t meshResolutionX, uint32_t meshResolutionY) m_meshY = std::max(8u, std::min(400u, m_meshY)); } +void ProjectM::TexelOffsets(float& texelOffsetX, float& texelOffsetY) const +{ + texelOffsetX = m_texelOffsetX; + texelOffsetY = m_texelOffsetY; +} + +void ProjectM::SetTexelOffsets(float texelOffsetX, float texelOffsetY) +{ + m_texelOffsetX = texelOffsetX; + m_texelOffsetY = texelOffsetY; +} + auto ProjectM::PCM() -> libprojectM::Audio::PCM& { return m_audioStorage; @@ -493,8 +505,13 @@ auto ProjectM::GetRenderContext() -> Renderer::RenderContext ctx.aspectY = (m_windowWidth > m_windowHeight) ? static_cast(m_windowHeight) / static_cast(m_windowWidth) : 1.0f; ctx.invAspectX = 1.0f / ctx.aspectX; ctx.invAspectY = 1.0f / ctx.aspectY; + ctx.perPixelMeshX = static_cast(m_meshX); ctx.perPixelMeshY = static_cast(m_meshY); + + ctx.texelOffsetX = m_texelOffsetX; + ctx.texelOffsetY = m_texelOffsetY; + ctx.textureManager = m_textureManager.get(); ctx.shaderCache = m_shaderCache.get(); diff --git a/src/libprojectM/ProjectM.hpp b/src/libprojectM/ProjectM.hpp index a718d500a..f83f9c49b 100644 --- a/src/libprojectM/ProjectM.hpp +++ b/src/libprojectM/ProjectM.hpp @@ -177,6 +177,10 @@ class PROJECTM_EXPORT ProjectM void SetMeshSize(uint32_t meshResolutionX, uint32_t meshResolutionY); + void TexelOffsets(float& texelOffsetX, float& texelOffsetY) const; + + void SetTexelOffsets(float texelOffsetX, float texelOffsetY); + void Touch(float touchX, float touchY, int pressure, int touchType); void TouchDrag(float touchX, float touchY, int pressure); @@ -265,6 +269,8 @@ class PROJECTM_EXPORT ProjectM bool m_aspectCorrection{true}; //!< If true, corrects aspect ratio for non-rectangular windows. float m_easterEgg{1.0}; //!< Random preset duration modifier. See TimeKeeper class. float m_previousFrameVolume{}; //!< Volume in previous frame, used for hard cuts. + float m_texelOffsetX{0.0}; //!< Horizontal warp shader texel offset + float m_texelOffsetY{0.0}; //!< Vertical warp shader texel offset std::vector m_textureSearchPaths; ///!< List of paths to search for texture files diff --git a/src/libprojectM/ProjectMCWrapper.cpp b/src/libprojectM/ProjectMCWrapper.cpp index 5119314cf..e0d9f1325 100644 --- a/src/libprojectM/ProjectMCWrapper.cpp +++ b/src/libprojectM/ProjectMCWrapper.cpp @@ -273,6 +273,18 @@ void projectm_get_mesh_size(projectm_handle instance, size_t* width, size_t* hei *height = static_cast(h); } +void projectm_set_texel_offsete(projectm_handle instance, float offset_X, float offset_y) +{ + auto projectMInstance = handle_to_instance(instance); + projectMInstance->SetTexelOffsets(offset_X, offset_y); +} + +void projectm_get_texel_offsete(projectm_handle instance, float* offset_X, float* offset_y) +{ + auto projectMInstance = handle_to_instance(instance); + projectMInstance->TexelOffsets(*offset_X, *offset_y); +} + void projectm_set_mesh_size(projectm_handle instance, size_t width, size_t height) { auto projectMInstance = handle_to_instance(instance); diff --git a/src/libprojectM/Renderer/RenderContext.hpp b/src/libprojectM/Renderer/RenderContext.hpp index 895a36b85..bd8adb472 100644 --- a/src/libprojectM/Renderer/RenderContext.hpp +++ b/src/libprojectM/Renderer/RenderContext.hpp @@ -31,6 +31,9 @@ class RenderContext int perPixelMeshX{64}; //!< Per-pixel/per-vertex mesh X resolution. int perPixelMeshY{48}; //!< Per-pixel/per-vertex mesh Y resolution. + float texelOffsetX{0.0f}; //!< Horizontal texel offset in the warp shader. + float texelOffsetY{0.0f}; //!< Vertical texel offset in the warp shader. + TextureManager* textureManager{nullptr}; //!< Holds all loaded textures for shader access. ShaderCache* shaderCache{nullptr}; //!< The shader chace of this projectM instance. }; diff --git a/src/libprojectM/Renderer/TextureSamplerDescriptor.cpp b/src/libprojectM/Renderer/TextureSamplerDescriptor.cpp index b9a7870f9..25efe8e39 100644 --- a/src/libprojectM/Renderer/TextureSamplerDescriptor.cpp +++ b/src/libprojectM/Renderer/TextureSamplerDescriptor.cpp @@ -20,71 +20,71 @@ TextureSamplerDescriptor::TextureSamplerDescriptor(const std::shared_ptr bool { - return m_texture.expired() || m_sampler.expired(); + return m_texture->Empty(); } void TextureSamplerDescriptor::Bind(GLint unit, const Shader& shader) const { - auto texture = m_texture.lock(); - auto sampler = m_sampler.lock(); - if (texture && sampler) + if (m_texture && m_sampler) { - texture->Bind(unit, sampler); + m_texture->Bind(unit, m_sampler); shader.SetUniformInt(std::string("sampler_" + m_samplerName).c_str(), unit); // Might be setting this more than once if the texture is used with different wrap/filter modes, but this rarely happens. - shader.SetUniformFloat4(std::string("texsize_" + m_sizeName).c_str(), {texture->Width(), - texture->Height(), - 1.0f / static_cast(texture->Width()), - 1.0f / static_cast(texture->Height())}); + shader.SetUniformFloat4(std::string("texsize_" + m_sizeName).c_str(), {m_texture->Width(), + m_texture->Height(), + 1.0f / static_cast(m_texture->Width()), + 1.0f / static_cast(m_texture->Height())}); // Bind shorthand random texture size uniform if (m_sizeName.substr(0, 4) == "rand" && m_sizeName.length() > 7 && m_sizeName.at(6) == '_') { - shader.SetUniformFloat4(std::string("texsize_" + m_sizeName.substr(0, 6)).c_str(), {texture->Width(), - texture->Height(), - 1.0f / static_cast(texture->Width()), - 1.0f / static_cast(texture->Height())}); + shader.SetUniformFloat4(std::string("texsize_" + m_sizeName.substr(0, 6)).c_str(), {m_texture->Width(), + m_texture->Height(), + 1.0f / static_cast(m_texture->Width()), + 1.0f / static_cast(m_texture->Height())}); } } } void TextureSamplerDescriptor::Unbind(GLint unit) { - auto texture = m_texture.lock(); - if (texture) + if (m_texture) { - texture->Unbind(unit); + m_texture->Unbind(unit); } Sampler::Unbind(unit); } auto TextureSamplerDescriptor::Texture() const -> std::shared_ptr { - return m_texture.lock(); + return m_texture; } -void TextureSamplerDescriptor::Texture(std::weak_ptr texture) +void TextureSamplerDescriptor::Texture(const std::shared_ptr& texture) { m_texture = texture; } +void TextureSamplerDescriptor::Texture(const std::weak_ptr& texture) +{ + m_texture = texture.lock(); +} + auto TextureSamplerDescriptor::Sampler() const -> std::shared_ptr { - return m_sampler.lock(); + return m_sampler; } auto TextureSamplerDescriptor::SamplerDeclaration() const -> std::string { - auto texture = m_texture.lock(); - auto sampler = m_sampler.lock(); - if (!texture || !sampler) + if (!m_texture || !m_sampler) { return {}; } std::string declaration = "uniform "; - if (texture->Type() == GL_TEXTURE_3D) + if (m_texture->Type() == GL_TEXTURE_3D) { declaration.append("sampler3D sampler_"); } @@ -109,9 +109,7 @@ auto TextureSamplerDescriptor::SamplerDeclaration() const -> std::string auto TextureSamplerDescriptor::TexSizeDeclaration() const -> std::string { - auto texture = m_texture.lock(); - auto sampler = m_sampler.lock(); - if (!texture || !sampler) + if (!m_texture || !m_sampler) { return {}; } diff --git a/src/libprojectM/Renderer/TextureSamplerDescriptor.hpp b/src/libprojectM/Renderer/TextureSamplerDescriptor.hpp index 40deba8ec..0e4d7997c 100644 --- a/src/libprojectM/Renderer/TextureSamplerDescriptor.hpp +++ b/src/libprojectM/Renderer/TextureSamplerDescriptor.hpp @@ -1,6 +1,10 @@ #pragma once +#include "Renderer/Sampler.hpp" #include "Renderer/Shader.hpp" +#include "Renderer/Texture.hpp" + +#include namespace libprojectM { namespace Renderer { @@ -65,11 +69,17 @@ class TextureSamplerDescriptor */ auto Texture() const -> std::shared_ptr; + /** + * @brief Updates the internal texture with a new one. + * @param texture A shared pointer to the new texture. + */ + void Texture(const std::shared_ptr& texture); + /** * @brief Updates the internal texture with a new one. * @param texture A weak pointer to the new texture. */ - void Texture(std::weak_ptr texture); + void Texture(const std::weak_ptr& texture); /** * @brief Returns a pointer to the stored sampler. @@ -96,8 +106,8 @@ class TextureSamplerDescriptor void TryUpdate(TextureManager& textureManager); private: - std::weak_ptr m_texture; //!< A weak reference to the texture. - std::weak_ptr m_sampler; //!< A weak reference to the sampler. + std::shared_ptr m_texture; //!< A reference to the texture. + std::shared_ptr m_sampler; //!< A reference to the sampler. std::string m_samplerName; //!< The name of the texture sampler as referenced in the shader. std::string m_sizeName; //!< The name of the "texsize_" uniform as referenced in the shader. bool m_updateFailed{false}; //!< Set to true if the update try failed, e.g. texture could not be loaded. diff --git a/src/libprojectM/projectM4Config.cmake.in b/src/libprojectM/projectM4Config.cmake.in index 00244c4df..883a6738b 100644 --- a/src/libprojectM/projectM4Config.cmake.in +++ b/src/libprojectM/projectM4Config.cmake.in @@ -13,7 +13,11 @@ if(NOT "@ENABLE_EMSCRIPTEN@") # ENABLE_EMSCRIPTEN endif() endif() if("@ENABLE_BOOST_FILESYSTEM@") # ENABLE_BOOST_FILESYSTEM - find_dependency(Boost COMPONENTS Filesystem) + if(POLICY CMP0167) + cmake_policy(SET CMP0167 NEW) + endif() + + find_dependency(Boost CONFIG NO_MODULE COMPONENTS Filesystem) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Windows") find_dependency(GLEW) diff --git a/vendor/hlslparser/src/GLSLGenerator.cpp b/vendor/hlslparser/src/GLSLGenerator.cpp index c8afbd797..c913e8268 100644 --- a/vendor/hlslparser/src/GLSLGenerator.cpp +++ b/vendor/hlslparser/src/GLSLGenerator.cpp @@ -119,7 +119,7 @@ GLSLGenerator::GLSLGenerator() : #else m_version = Version_330; #endif - + m_versionLegacy = false; m_inAttribPrefix = NULL; m_outAttribPrefix = NULL; @@ -244,7 +244,7 @@ bool GLSLGenerator::Generate(HLSLTree* tree, Target target, Version version, con m_writer.WriteLine(0, "precision highp float;"); } else if (m_version == Version_300_ES) - { + { m_writer.WriteLine(0, "#version 300 es"); m_writer.WriteLine(0, "precision highp float;"); m_writer.WriteLine(0, "precision highp sampler3D;"); @@ -257,10 +257,25 @@ bool GLSLGenerator::Generate(HLSLTree* tree, Target target, Version version, con // Output the special function used to access rows in a matrix. m_writer.WriteLine(0, "vec2 %s(mat2 m, int i) { return vec2( m[0][i], m[1][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec2 %s(mat2 m, float i_float) { int i=int(i_float); return vec2( m[0][i], m[1][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec2 %s(mat2x3 m, int i) { return vec2( m[0][i], m[1][i]); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec2 %s(mat2x3 m, float i_float) { int i=int(i_float); return vec2( m[0][i], m[1][i]); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec2 %s(mat2x4 m, int i) { return vec2( m[0][i], m[1][i]); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec2 %s(mat2x4 m, float i_float) { int i=int(i_float); return vec2( m[0][i], m[1][i]); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec3 %s(mat3 m, int i) { return vec3( m[0][i], m[1][i], m[2][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec3 %s(mat3 m, float i_float) { int i=int(i_float); return vec3( m[0][i], m[1][i], m[2][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec3 %s(mat3x2 m, int i) { return vec3( m[0][i], m[1][i], m[2][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec3 %s(mat3x2 m, float i_float) { int i=int(i_float); return vec3( m[0][i], m[1][i], m[2][i] ); }", m_matrixRowFunction); m_writer.WriteLine(0, "vec3 %s(mat3x4 m, int i) { return vec3( m[0][i], m[1][i], m[2][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec3 %s(mat3x4 m, float i_float) { int i=int(i_float); return vec3( m[0][i], m[1][i], m[2][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec4 %s(mat4 m, int i) { return vec4( m[0][i], m[1][i], m[2][i], m[3][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec4 %s(mat4 m, float i_float) { int i=int(i_float); return vec4( m[0][i], m[1][i], m[2][i], m[3][i] ); }", m_matrixRowFunction); m_writer.WriteLine(0, "vec4 %s(mat4x3 m, int i) { return vec4( m[0][i], m[1][i], m[2][i], m[3][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec4 %s(mat4x3 m, float i_float) { int i=int(i_float); return vec4( m[0][i], m[1][i], m[2][i], m[3][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec4 %s(mat4x2 m, int i) { return vec4( m[0][i], m[1][i], m[2][i], m[3][i] ); }", m_matrixRowFunction); + m_writer.WriteLine(0, "vec4 %s(mat4x2 m, float i_float) { int i=int(i_float); return vec4( m[0][i], m[1][i], m[2][i], m[3][i] ); }", m_matrixRowFunction); // Output the special function used to do matrix cast for OpenGL 2.0 if (m_versionLegacy) @@ -405,13 +420,13 @@ bool GLSLGenerator::Generate(HLSLTree* tree, Target target, Version version, con * domain. To do this, we bail out to a separate function that piecewise-defines * a polynomial that qualitatively matches what we see under DX9. The DX9 * implementation itself is unknown, so this is only a rough match. - * + * * We also implement this as a separate function because we need to evaluate the * argument multiple times. If the argument expression involves side-effects * (such as post-increment or -decrement) the result would not be what we expect * if we evaluated this equation as a macro in OutputExpression. */ - m_writer.WriteLine(0, "float %s(float x) { if (abs(x) > 1.0) { return 0.39269908169872415*(4-sign(x)*(abs(x) - 3.0)*(abs(x) - 3.0)); } else { return acos(x); } }", m_acosFunction); + m_writer.WriteLine(0, "float %s(float x) { if (abs(x) > 1.0) { return 0.39269908169872415*(4.0-sign(x)*(abs(x) - 3.0)*(abs(x) - 3.0)); } else { return acos(x); } }", m_acosFunction); m_writer.WriteLine(0, "vec2 %s(vec2 x) { vec2 ret; ret.x = %s(x.x); ret.y = %s(x.y); return ret; }", m_acosFunction, m_acosFunction, m_acosFunction); m_writer.WriteLine(0, "vec3 %s(vec3 x) { vec3 ret; ret.x = %s(x.x); ret.y = %s(x.y); ret.z = %s(x.z); return ret; }", m_acosFunction, m_acosFunction, m_acosFunction, m_acosFunction); m_writer.WriteLine(0, "vec4 %s(vec4 x) { vec4 ret; ret.x = %s(x.x); ret.y = %s(x.y); ret.z = %s(x.z); ret.w = %s(x.w); return ret; }", m_acosFunction, m_acosFunction, m_acosFunction, m_acosFunction, m_acosFunction); @@ -532,7 +547,7 @@ void GLSLGenerator::OutputExpressionList(HLSLExpression* expression, HLSLArgumen { m_writer.Write(", "); } - + HLSLType* expectedType = NULL; if (argument != NULL) { @@ -1013,16 +1028,60 @@ void GLSLGenerator::OutputExpression(HLSLExpression* expression, const HLSLType* Error("%s expects 2 arguments", functionName); return; } + /* See rsqrt above regarding abs(). Note that this behaves * as expected on some drivers but not others, so we add * the abs() call for compatibility across drivers. + * + * There's one special case though: if the exponent is a literal "1" (or "1.0"), + * don't use pow() at all, just return the base (arg 1) unchanged, even if negative. + * This is probably due to an HLSL compiler optimization which does the same thing. + * When not optimized, pow(x, 1) with a negative value of x would return NaN instead. */ - m_writer.Write("pow(abs("); - OutputExpression(argument[0], &functionCall->function->returnType); - m_writer.Write("),"); - OutputExpression(argument[1], &functionCall->function->returnType); - m_writer.Write(")"); - handled = true; + if (argument[1]->nodeType == HLSLNodeType_LiteralExpression) + { + HLSLLiteralExpression* literalExpression = static_cast(argument[1]); + float value = 0.0; + bool found = false; + switch (literalExpression->type) + { + case HLSLBaseType_Float: + value = literalExpression->fValue; + found = true; + break; + case HLSLBaseType_Int: + case HLSLBaseType_Uint: + value = literalExpression->iValue; + found = true; + break; + case HLSLBaseType_Bool: + value = literalExpression->bValue; + found = true; + break; + default: + break; + } + + // Replace the function call with just arg 1. + if (found && value == 1.0) + { + m_writer.Write("("); + OutputExpression(argument[0], &functionCall->function->returnType); + m_writer.Write(")"); + handled = true; + } + } + + // Other cases, including variable exponent arguments, will still call pow(). + if (!handled) + { + m_writer.Write("pow(abs("); + OutputExpression(argument[0], &functionCall->function->returnType); + m_writer.Write("),"); + OutputExpression(argument[1], &functionCall->function->returnType); + m_writer.Write(")"); + handled = true; + } } else if (String_Equal(functionName, "ldexp")) { @@ -1158,7 +1217,7 @@ void GLSLGenerator::OutputIdentifier(const char* name) { name = m_asinFunction; } - else + else { // The identifier could be a GLSL reserved word (if it's not also a HLSL reserved word). name = GetSafeIdentifierName(name); @@ -2140,7 +2199,7 @@ void GLSLGenerator::Error(const char* format, ...) va_start(arg, format); Log_ErrorArgList(format, arg); va_end(arg); -} +} const char* GLSLGenerator::GetSafeIdentifierName(const char* name) const { diff --git a/vendor/hlslparser/src/HLSLParser.cpp b/vendor/hlslparser/src/HLSLParser.cpp index 358df2770..aaf73007c 100644 --- a/vendor/hlslparser/src/HLSLParser.cpp +++ b/vendor/hlslparser/src/HLSLParser.cpp @@ -36,7 +36,7 @@ enum CompareFunctionsResult Function2Better }; - + /** This structure stores a HLSLFunction-like declaration for an intrinsic function */ struct Intrinsic { @@ -103,7 +103,7 @@ struct Intrinsic HLSLFunction function; HLSLArgument argument[4]; }; - + Intrinsic SamplerIntrinsic(const char* name, HLSLBaseType returnType, HLSLBaseType arg1, HLSLBaseType samplerType, HLSLBaseType arg2) { Intrinsic i(name, returnType, arg1, arg2); @@ -113,7 +113,7 @@ Intrinsic SamplerIntrinsic(const char* name, HLSLBaseType returnType, HLSLBaseTy -static const int _numberTypeRank[NumericType_Count][NumericType_Count] = +static const int _numberTypeRank[NumericType_Count][NumericType_Count] = { //F B I U { 0, 4, 4, 4 }, // NumericType_Float @@ -261,7 +261,7 @@ static const EffectState samplerStates[] = { {"MipMapLodBias", 8, floatValues}, {"MaxMipLevel", 9, integerValues}, {"MaxAnisotropy", 10, integerValues}, - {"sRGBTexture", 11, booleanValues}, + {"sRGBTexture", 11, booleanValues}, }; static const EffectState effectStates[] = { @@ -415,7 +415,7 @@ static const EffectState pipelineStates[] = { #define SAMPLER_INTRINSIC_FUNCTION(name, sampler, arg1) \ Intrinsic( name, HLSLBaseType_Float4, sampler, arg1) #endif - + const Intrinsic _intrinsic[] = { INTRINSIC_FLOAT1_FUNCTION( "abs" ), @@ -478,6 +478,11 @@ const Intrinsic _intrinsic[] = Intrinsic( "length", HLSLBaseType_Float, HLSLBaseType_Float3 ), Intrinsic( "length", HLSLBaseType_Float, HLSLBaseType_Float4 ), + Intrinsic( "fwidth", HLSLBaseType_Float, HLSLBaseType_Float ), + Intrinsic( "fwidth", HLSLBaseType_Float, HLSLBaseType_Float2 ), + Intrinsic( "fwidth", HLSLBaseType_Float, HLSLBaseType_Float3 ), + Intrinsic( "fwidth", HLSLBaseType_Float, HLSLBaseType_Float4 ), + Intrinsic( "distance", HLSLBaseType_Float, HLSLBaseType_Float , HLSLBaseType_Float ), Intrinsic( "distance", HLSLBaseType_Float, HLSLBaseType_Float2, HLSLBaseType_Float2 ), Intrinsic( "distance", HLSLBaseType_Float, HLSLBaseType_Float3, HLSLBaseType_Float3 ), @@ -617,10 +622,10 @@ const Intrinsic _intrinsic[] = INTRINSIC_FLOAT1_FUNCTION( "log" ), INTRINSIC_FLOAT1_FUNCTION( "log2" ), INTRINSIC_FLOAT1_FUNCTION( "log10" ), - + INTRINSIC_FLOAT1_FUNCTION( "ddx" ), INTRINSIC_FLOAT1_FUNCTION( "ddy" ), - + INTRINSIC_FLOAT1_FUNCTION( "sign" ), INTRINSIC_FLOAT2_FUNCTION( "step" ), INTRINSIC_FLOAT2_FUNCTION( "reflect" ), @@ -657,15 +662,15 @@ const Intrinsic _intrinsic[] = Intrinsic("asuint", HLSLBaseType_Uint, HLSLBaseType_Float), SAMPLER_INTRINSIC_FUNCTION("tex2D", HLSLBaseType_Sampler2D, HLSLBaseType_Float2), - + Intrinsic("tex2Dproj", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float4), SAMPLER_INTRINSIC_FUNCTION("tex2Dlod", HLSLBaseType_Sampler2D, HLSLBaseType_Float4), - + Intrinsic("tex2Dlod", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float4, HLSLBaseType_Int2), // With offset. SAMPLER_INTRINSIC_FUNCTION("tex2Dbias", HLSLBaseType_Sampler2D, HLSLBaseType_Float4), - + Intrinsic("tex2Dgrad", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float2, HLSLBaseType_Float2, HLSLBaseType_Float2), Intrinsic("tex2Dgather", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float2, HLSLBaseType_Int), Intrinsic("tex2Dgather", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float2, HLSLBaseType_Int2, HLSLBaseType_Int), // With offset. @@ -718,7 +723,7 @@ const int _binaryOpPriority[] = // IC: I'm not sure this table is right, but any errors should be caught by the backend compiler. // Also, this is operator dependent. The type resulting from (float4 * float4x4) is not the same as (float4 + float4x4). // We should probably distinguish between component-wise operator and only allow same dimensions -HLSLBaseType _binaryOpTypeLookup[HLSLBaseType_NumericCount][HLSLBaseType_NumericCount] = +HLSLBaseType _binaryOpTypeLookup[HLSLBaseType_NumericCount][HLSLBaseType_NumericCount] = { { // float HLSLBaseType_Float, HLSLBaseType_Float2, HLSLBaseType_Float3, HLSLBaseType_Float4, @@ -1001,7 +1006,7 @@ static const char* GetBinaryOpName(HLSLBinaryOp binaryOp) * 4.) Conversion + scalar dimension promotion * 5.) Truncation (vector -> scalar or lower component vector, matrix -> scalar or lower component matrix) * 6.) Conversion + truncation - */ + */ static int GetTypeCastRank(HLSLTree * tree, const HLSLType& srcType, const HLSLType& dstType) { /*if (srcType.array != dstType.array || srcType.arraySize != dstType.arraySize) @@ -1039,7 +1044,7 @@ static int GetTypeCastRank(HLSLTree * tree, const HLSLType& srcType, const HLSLT { return srcType.samplerType == dstType.samplerType ? 0 : -1; } - + return 0; } @@ -1081,7 +1086,7 @@ static int GetTypeCastRank(HLSLTree * tree, const HLSLType& srcType, const HLSLT } return result; - + } static bool GetFunctionCallCastRanks(HLSLTree* tree, const HLSLFunctionCall* call, const HLSLFunction* function, int* rankBuffer) @@ -1095,7 +1100,7 @@ static bool GetFunctionCallCastRanks(HLSLTree* tree, const HLSLFunctionCall* cal const HLSLExpression* expression = call->argument; const HLSLArgument* argument = function->argument; - + for (int i = 0; i < call->numArguments; ++i) { int rank = GetTypeCastRank(tree, expression->expressionType, argument->type); @@ -1105,7 +1110,7 @@ static bool GetFunctionCallCastRanks(HLSLTree* tree, const HLSLFunctionCall* cal } rankBuffer[i] = rank; - + argument = argument->nextArgument; expression = expression->nextExpression; } @@ -1129,7 +1134,7 @@ struct CompareRanks }; static CompareFunctionsResult CompareFunctions(HLSLTree* tree, const HLSLFunctionCall* call, const HLSLFunction* function1, const HLSLFunction* function2) -{ +{ #if defined _WIN32 && !defined alloca int* function1Ranks = static_cast(_alloca(sizeof(int) * call->numArguments)); @@ -1161,7 +1166,7 @@ static CompareFunctionsResult CompareFunctions(HLSLTree* tree, const HLSLFunctio std::sort(function1Ranks, function1Ranks + call->numArguments, CompareRanks()); std::sort(function2Ranks, function2Ranks + call->numArguments, CompareRanks()); - + for (int i = 0; i < call->numArguments; ++i) { if (function1Ranks[i] < function2Ranks[i]) @@ -1242,7 +1247,7 @@ static bool GetBinaryOpResultType(HLSLBinaryOp binaryOp, const HLSLType& type1, result.array = false; result.arraySize = NULL; result.flags = (type1.flags & type2.flags) & HLSLTypeFlag_Const; // Propagate constness. - + return result.baseType != HLSLBaseType_Unknown; } @@ -1358,7 +1363,7 @@ bool HLSLParser::ParseTopLevel(HLSLStatement*& statement) int line = GetLineNumber(); const char* fileName = GetFileName(); - + HLSLType type; //HLSLBaseType type; //const char* typeName = NULL; @@ -1390,7 +1395,7 @@ bool HLSLParser::ParseTopLevel(HLSLStatement*& statement) structure->name = structName; m_userTypes.PushBack(structure); - + HLSLStructField* lastField = NULL; // Add the struct to our list of user defined types. @@ -1544,7 +1549,7 @@ bool HLSLParser::ParseTopLevel(HLSLStatement*& statement) // Note, no semi-colon at the end of a function declaration. statement = function; - + return true; } else @@ -1693,7 +1698,7 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur } HLSLAttribute * attributes = NULL; - ParseAttributeBlock(attributes); // @@ Leak if not assigned to node? + ParseAttributeBlock(attributes); // @@ Leak if not assigned to node? #if 0 // @@ Work in progress. // Static statements: @if only for now. @@ -1704,9 +1709,9 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur //HLSLIfStatement* ifStatement = m_tree->AddNode(fileName, line); //ifStatement->isStatic = true; //ifStatement->attributes = attributes; - + HLSLExpression * condition = NULL; - + m_allowUndeclaredIdentifiers = true; // Not really correct... better to push to stack? if (!Expect('(') || !ParseExpression(condition) || !Expect(')')) { @@ -1714,25 +1719,25 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur return false; } m_allowUndeclaredIdentifiers = false; - + if ((condition->expressionType.flags & HLSLTypeFlag_Const) == 0) { m_tokenizer.Error("Syntax error: @if condition is not constant"); return false; } - + int conditionValue; if (!m_tree->GetExpressionValue(condition, conditionValue)) { m_tokenizer.Error("Syntax error: Cannot evaluate @if condition"); return false; } - + if (!conditionValue) m_disableSemanticValidation = true; - + HLSLStatement * ifStatements = NULL; HLSLStatement * elseStatements = NULL; - + if (!ParseStatementOrBlock(ifStatements, returnType, /*scoped=*/false)) { m_disableSemanticValidation = false; @@ -1741,7 +1746,7 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur if (Accept(HLSLToken_Else)) { if (conditionValue) m_disableSemanticValidation = true; - + if (!ParseStatementOrBlock(elseStatements, returnType, /*scoped=*/false)) { m_disableSemanticValidation = false; @@ -1749,12 +1754,12 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur } } m_disableSemanticValidation = false; - + if (conditionValue) statement = ifStatements; else statement = elseStatements; - + // @@ Free the pruned statements? - + return true; } else { @@ -1762,7 +1767,7 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur } } #endif - + // If statement. if (Accept(HLSLToken_If)) { @@ -1783,7 +1788,7 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur } return true; } - + // For statement. if (Accept(HLSLToken_For)) { @@ -2184,15 +2189,15 @@ bool HLSLParser::AcceptAssign(HLSLBinaryOp& binaryOp) else if (Accept(HLSLToken_MinusEqual)) { binaryOp = HLSLBinaryOp_SubAssign; - } + } else if (Accept(HLSLToken_TimesEqual)) { binaryOp = HLSLBinaryOp_MulAssign; - } + } else if (Accept(HLSLToken_DivideEqual)) { binaryOp = HLSLBinaryOp_DivAssign; - } + } else { return false; @@ -2242,10 +2247,10 @@ bool HLSLParser::ParseBinaryExpression(int priority, HLSLExpression*& expression return false; } - + // Propagate constness. binaryExpression->expressionType.flags = (expression->expressionType.flags | expression2->expressionType.flags) & HLSLTypeFlag_Const; - + expression = binaryExpression; } else if (_conditionalOpPriority > priority && Accept('?')) @@ -2253,7 +2258,7 @@ bool HLSLParser::ParseBinaryExpression(int priority, HLSLExpression*& expression HLSLConditionalExpression* conditionalExpression = m_tree->AddNode(fileName, line); conditionalExpression->condition = expression; - + HLSLExpression* expression1 = NULL; HLSLExpression* expression2 = NULL; if (!ParseBinaryExpression(_conditionalOpPriority, expression1) || !Expect(':') || !ParseBinaryExpression(_conditionalOpPriority, expression2)) @@ -2311,7 +2316,7 @@ bool HLSLParser::ParsePartialConstructor(HLSLExpression*& expression, HLSLBaseTy if (!ParseExpressionList(')', false, constructorExpression->argument, numArguments)) { return false; - } + } constructorExpression->expressionType = constructorExpression->type; constructorExpression->expressionType.flags = HLSLTypeFlag_Const; expression = constructorExpression; @@ -2336,7 +2341,7 @@ bool HLSLParser::ParseTerminalExpression(HLSLExpression*& expression, char& need } if (unaryOp == HLSLUnaryOp_BitNot) { - if (unaryExpression->expression->expressionType.baseType < HLSLBaseType_FirstInteger || + if (unaryExpression->expression->expressionType.baseType < HLSLBaseType_FirstInteger || unaryExpression->expression->expressionType.baseType > HLSLBaseType_LastInteger) { const char * typeName = GetTypeName(unaryExpression->expression->expressionType); @@ -2359,7 +2364,7 @@ bool HLSLParser::ParseTerminalExpression(HLSLExpression*& expression, char& need } unaryExpression->expressionType = HLSLType(HLSLBaseType_Bool); - + // Propagate constness. unaryExpression->expressionType.flags = unaryExpression->expression->expressionType.flags & HLSLTypeFlag_Const; } @@ -2395,7 +2400,7 @@ bool HLSLParser::ParseTerminalExpression(HLSLExpression*& expression, char& need expression = unaryExpression; return true; } - + // Expressions inside parenthesis or casts. char expressionEndChar = 0; if (Accept('(')) @@ -2426,7 +2431,7 @@ bool HLSLParser::ParseTerminalExpression(HLSLExpression*& expression, char& need castingExpression->expressionType = type; return Expect(')') && ParseExpression(castingExpression->expression); } - + int numArguments = 0; if (!ParseExpressionList(expressionEndChar, false, expression, numArguments)) { @@ -2447,7 +2452,7 @@ bool HLSLParser::ParseTerminalExpression(HLSLExpression*& expression, char& need // Terminal values. float fValue = 0.0f; int iValue = 0; - + if (AcceptFloat(fValue)) { HLSLLiteralExpression* literalExpression = m_tree->AddNode(fileName, line); @@ -2728,7 +2733,7 @@ bool HLSLParser::ParseArgumentList(HLSLArgument*& firstArgument, int& numArgumen { const char* fileName = GetFileName(); int line = GetLineNumber(); - + HLSLArgument* lastArgument = NULL; numArguments = 0; @@ -3000,7 +3005,7 @@ const EffectState* GetEffectState(const char* name, bool isSamplerState, bool is { const EffectState* validStates = effectStates; int count = sizeof(effectStates)/sizeof(effectStates[0]); - + if (isPipeline) { validStates = pipelineStates; @@ -3016,7 +3021,7 @@ const EffectState* GetEffectState(const char* name, bool isSamplerState, bool is // Case insensitive comparison. for (int i = 0; i < count; i++) { - if (String_EqualNoCase(name, validStates[i].name)) + if (String_EqualNoCase(name, validStates[i].name)) { return &validStates[i]; } @@ -3028,12 +3033,12 @@ const EffectState* GetEffectState(const char* name, bool isSamplerState, bool is static const EffectStateValue* GetStateValue(const char* name, const EffectState* state) { // Case insensitive comparison. - for (int i = 0; ; i++) + for (int i = 0; ; i++) { const EffectStateValue & value = state->values[i]; if (value.name == NULL) break; - if (String_EqualNoCase(name, value.name)) + if (String_EqualNoCase(name, value.name)) { return &value; } @@ -3099,7 +3104,7 @@ bool HLSLParser::ParseStateValue(const EffectState * state, HLSLStateAssignment* const bool expectsFloat = state->values == floatValues; const bool expectsBoolean = state->values == booleanValues; - if (!expectsExpression && !expectsInteger && !expectsFloat && !expectsBoolean) + if (!expectsExpression && !expectsInteger && !expectsFloat && !expectsBoolean) { if (m_tokenizer.GetToken() != HLSLToken_Identifier) { @@ -3176,7 +3181,7 @@ bool HLSLParser::ParseStateValue(const EffectState * state, HLSLStateAssignment* return false; } } - else + else { // Expect one of the allowed values. const EffectStateValue * stateValue = GetStateValue(m_tokenizer.GetIdentifier(), state); @@ -3233,7 +3238,7 @@ bool HLSLParser::ParseAttributeList(HLSLAttribute*& firstAttribute) { const char* fileName = GetFileName(); int line = GetLineNumber(); - + HLSLAttribute * lastAttribute = firstAttribute; do { const char * identifier = NULL; @@ -3242,12 +3247,12 @@ bool HLSLParser::ParseAttributeList(HLSLAttribute*& firstAttribute) } HLSLAttribute * attribute = m_tree->AddNode(fileName, line); - + if (strcmp(identifier, "unroll") == 0) attribute->attributeType = HLSLAttributeType_Unroll; else if (strcmp(identifier, "flatten") == 0) attribute->attributeType = HLSLAttributeType_Flatten; else if (strcmp(identifier, "branch") == 0) attribute->attributeType = HLSLAttributeType_Branch; else if (strcmp(identifier, "nofastmath") == 0) attribute->attributeType = HLSLAttributeType_NoFastMath; - + // @@ parse arguments, () not required if attribute constructor has no arguments. if (firstAttribute == NULL) @@ -3259,7 +3264,7 @@ bool HLSLParser::ParseAttributeList(HLSLAttribute*& firstAttribute) lastAttribute->nextAttribute = attribute; } lastAttribute = attribute; - + } while(Accept(',')); return true; @@ -3339,7 +3344,7 @@ bool HLSLParser::ParseStage(HLSLStatement*& statement) bool HLSLParser::Parse(const char* fileName, const char* buffer, size_t length) -{ +{ HLSLRoot* root = m_tree->GetRoot(); HLSLStatement* lastStatement = NULL; @@ -3352,7 +3357,7 @@ bool HLSLParser::Parse(const char* fileName, const char* buffer, size_t length) return false; } if (statement != NULL) - { + { if (lastStatement == NULL) { root->statement = statement; @@ -3556,7 +3561,7 @@ bool HLSLParser::ApplyPreprocessor(const char* fileName, const char* buffer, siz m_tokenizer.Next(); } - if (valueProcessed == "main") + if (valueProcessed == "main") { valueProcessed = "sampler_fw_main"; } @@ -3854,12 +3859,12 @@ bool HLSLParser::AcceptTypeModifier(int& flags) bool HLSLParser::AcceptInterpolationModifier(int& flags) { if (Accept("linear")) - { - flags |= HLSLTypeFlag_Linear; + { + flags |= HLSLTypeFlag_Linear; return true; } else if (Accept("centroid")) - { + { flags |= HLSLTypeFlag_Centroid; return true; } @@ -3908,7 +3913,7 @@ bool HLSLParser::AcceptType(bool allowVoid, HLSLType& type/*, bool acceptFlags*/ case HLSLToken_Double1x1: type.baseType = HLSLBaseType_Float; break; - case HLSLToken_Float2: + case HLSLToken_Float2: case HLSLToken_Float2x1: case HLSLToken_Half2: case HLSLToken_Half2x1: @@ -4041,7 +4046,7 @@ bool HLSLParser::AcceptType(bool allowVoid, HLSLType& type/*, bool acceptFlags*/ if (type.baseType != HLSLBaseType_Void) { m_tokenizer.Next(); - + if (IsSamplerType(type.baseType)) { // Parse optional sampler type. @@ -4058,7 +4063,7 @@ bool HLSLParser::AcceptType(bool allowVoid, HLSLType& type/*, bool acceptFlags*/ return false; } m_tokenizer.Next(); - + if (!Expect('>')) { m_tokenizer.Error("Syntax error: '>' expected for sampler type"); @@ -4303,7 +4308,7 @@ const HLSLFunction* HLSLParser::MatchFunctionCall(const HLSLFunctionCall* functi if (function->name == name) { nameMatches = true; - + CompareFunctionsResult result = CompareFunctions( m_tree, functionCall, function, matchedFunction ); if (result == Function1Better) { @@ -4454,7 +4459,7 @@ bool HLSLParser::GetMemberType(const HLSLType& objectType, HLSLMemberAccess * me static const HLSLBaseType intType[] = { HLSLBaseType_Int, HLSLBaseType_Int2, HLSLBaseType_Int3, HLSLBaseType_Int4 }; static const HLSLBaseType uintType[] = { HLSLBaseType_Uint, HLSLBaseType_Uint2, HLSLBaseType_Uint3, HLSLBaseType_Uint4 }; static const HLSLBaseType boolType[] = { HLSLBaseType_Bool, HLSLBaseType_Bool2, HLSLBaseType_Bool3, HLSLBaseType_Bool4 }; - + switch (baseTypeDescriptions[objectType.baseType].numericType) { case NumericType_Float: @@ -4474,7 +4479,7 @@ bool HLSLParser::GetMemberType(const HLSLType& objectType, HLSLMemberAccess * me } memberAccess->swizzle = true; - + return true; }